Easy GUIs for Python Programs

I recently got more interested in python after some MOOC classes on AI. I hadn’t really used it much since my thesis work which allowed users to write Jython scripts to control robots in my robotics simulator.  Since then I did a little webscraping project here or there but nothing big.

There was an annoying set of issues I had with python, one of which was that I couldn’t slap together GUIs as fast as I’d like to. I admit, Java had me spoiled with the wysiwyg builders in netbeans and eclipse. I honestly would gravitate to processing if I needed an interface, but now I’ve come across a stupid-simple GUI library for python called PySimpleGUI.

Basically this is a wrapper around the tKinter library (though QT and other graphics libs are available as well).  Much of setting up a GUI is done in a few lines of code. There’s a large number of example programs and a good bit of documentation. It’s slightly annoying but also awesome that the entire doc are in one giant webpage so no matter what you want, simply ctrl+f to find it on that page. Their gihub page is very insightful as well with insightful gems of example code in the issues section.  My dude even has a youtube channel full of great tutorials and explanations. I recommend getting up to speed with it starting with this playlist.

It’s as easy as installing the library:

pip install pysimplegui

One of the key features of PySimpleGUI is its simplicity. It abstracts away many of the complexities of GUI programming, making it easy for even beginners to create visually appealing and functional GUI applications. PySimpleGUI also offers a wide range of customization options, allowing users to tailor the appearance and behavior of their GUI applications to meet their specific needs.

In addition to its simplicity and customization capabilities, PySimpleGUI is also highly portable. It is compatible with multiple operating systems, including Windows, Linux, and macOS, and can be used with both Python 2 and Python 3. This makes it an excellent choice for developing GUI applications that need to be compatible with a variety of platforms.

PySimpleGUI lays out windows in a very simple grid form that is controlled by lists.  Let’s write an example to see how this works:

Check out the code below:

This is a simple converter from inches to centimeters.  Looking at the “layout” variable you can see a list which has 3 elements.

TextOutput, TextInput, Button

This is the order the elements will appear on the main screen. If I wanted to add a second row, I could simply make this a 2D list, each row containing a new line of elements in the GUI window.  For example the following puts the “OK” button on the next line down:

layout = [ [sg.Text('Enter inches'), sg.InputText(key = 'inputValue') ] , [sg.Ok()] ]

When GUI items like buttons, etc. are activated by the user, a message is sent to the “window.read()” function. You can then run if-else statements to do different things based on which button was pressed.

Of course it can get into much more complicated territory, but since there are so many example programs doing pretty much anything you can think of in one way or another it is easy to see how this library can be applied nearly anything written in python. Examples include a “how do I” app that basically tells you how to do anything you type in the question box, games like Uno and Chess, Matplotlib for graphing, even integrating with AI programs and making desktop widgets.

I’ve written a couple apps with it now for personal and professional use and I’m hooked. Definitely give it a try!

You can use trinket.io/pygame or replit.com to edit basic programs in your browwser online, but to run this code on your own computer, I use vscode. Here’s a quick tutorial on how to get that installed and set up in 5 minutes).

Overall, PySimpleGUI is a powerful and easy-to-use Python library that enables developers to create professional-quality GUI applications with minimal effort. Its simplicity, customization options, and portability make it a great choice for a wide range of projects, from small utility programs to large-scale applications.

DIY Soldermask Showdown

banner

Once you fabricate a PCB, it pretty much instantly begins to oxidize. PCBs created in industry are coated with a couple of things to protect them from this oxidation and short circuits. The first is called a soldermask, which is a type of epoxy that literally coats the entire circuit board. If you’ve ever seen a circuit board, you’ve seen the soldermask. It is typically GREEN but can be different colors. For example, official arduinos typically have a Teal BLUE soldermask. Sparkfun uses RED. OSHPark uses Purple.

You can see below just how badly the copper oxidizes after being touched an exposed over time.

unprotected

There are multiple ways to add a soldermask to a PCB. My new favorite method is using Kapton tape (explained at the end of this page), but I have tried and compared a lot of different solutions below.

Epoxy-based:
In industry, they use a specially designed paint or epoxy that is cured with ultraviolet light. This allows them to cover all the traces (the wires) but leave the pads visible so you can solder components on the board. Some folks have tutorials out there showing how to do this, but it is messy and uses nasty chemicals.

Dry-Film Soldermask:
You can also buy sheets of “dry film soldermask” which has the epoxy deposited as a flexible sheet that you adhere to the PCB, then use a photolithography method to harden it with UV light.  This allows you to remove the softer material on the pads you will solder the components to. This material is not readily available, but you can find it from electronics suppliers online. Here’s an excellent tutorial on how to do this process at home.

Tinning Traces:
Another option to protect the traces from oxidizing is to tin them. Tin doesn’t oxidize as badly as copper. Essentially you can deposit tin on all the copper surfaces using a chemical deposition (electroless). This is actually done to the solder pads on commercial PCBs, but it can be done to the entire PCB. The biggest issue with this method is that it doesn’t prevent short circuits because it doesn’t add a layer of insulation to the traces. Again, it uses nasty chemicals.

Conformal Coating:
There is a conformal coating that can be painted or sprayed on a PCB after soldering the components.  It coats everything. While it has been formulated for electrical characteristics, etc. I personally don’t like this option. There are Acrylic, polyurethane, and silicone based products, which you can solder through, but it only comes in clear (you though you can see it in UV light).

DIY – Nail Polish:
When I did FabAcademy in 2014, I milled a ton of PCBs. They always oxidized really badly. Some would be useless within a month.  I began painting finished boards with fingernail polish. I only painted the traces in case I needed to resolder the components. (The soldered areas do not oxidize like the copper traces). This option isn’t great because fingernail polish isn’t designed for electronics, or being touched with a soldering iron, but it works and I have boards that are almost 10 years old that look brand new. This is probably one of the easiest solutions due to availability and color selection.

Lacquer:
Another thing I tried more recently was to spray the PCB with colored lacquer, then using either a laser to etch off the lacquer on the solder pads with a laser, or to just solder it directly (the lacquer melts only when touched with a soldering iron).  I don’t really know the chemistry here so when you laser it or solder it, I don’t know how safe it is. I don’t see how much different it can be from the conformal coating you can buy. A bonus with Lacquer is that you can get lots of colors, though I recommend avoiding anything with glitter, pearl, or metal flakes in it.

Both nail polish and lacquer do allow multiple colors, but neither are designed for electronics. Here you can see the left board is almost 8 years old but has had its traces painted with clear nail polish for protection. The red board is from my previous article in 2021.

paint and lacquer

 

The best solution I’ve come up with is to mill or etch a circuit board, then export the pads layer of the design to an SVG. From here it can be cut by a laser or a vinyl cutting machine into Kapton tape. Once cut, the tape can be applied to the PCB and pressed down hard. Since kapton tape is heat resistant, it can withhold under a bit of soldering. It also has excellent electrical properties (resistance, capacitance, and inductance).  It is actually used for a substrate material for flexible electrical circuits.

UV Curable Dry Film Conformal Coating Nail Polish Lacquer Kapton Tape
Cheap

Availability

Safety

Designed for
Electronics

Ease of Use

Clean

Speed

Special Equipment

Ok, so Kapton tape wins. How do you cut and apply the kapton? We tried a couple of things and both worked.

Firstly, I told Garrett (who is taking FabAcademy in our lab this semester) about my idea and asked if he’d play with the kapton tape and the laser to find out what settings to use. He set about finding the best settings. He first used it to make a solderpaste stencil for his own project. Apparently on a 120 watt epilog, for the size holes we needed, about 6-7% power worked well.

We tried a couple of methods. First we placed the tape on cardboard, cut it, then peeled and stuck it to the PCB. This worked fine, but was a little tough to unstick and weed. This is likely the method I’ll use in the future though.

The second attempt we got cocky and just stuck the tape on the PCB and lasered it directly.

kapton1    kapton weeded

It is easier to line up with the cameras on the laser, but even when we placed the PCB directly under the camera (to avoid aberration of the fisheye lens) we still didn’t get the best alignment. It was good enough to solder though. You can see the finished product at the top of this page.

offset      stuffed1

Using VSCode and Mkdocs to make a static website

For FabAcademy, students have to post each of their assignments on a website. The website must be a static HTML site hosted on Gitlab (though this method works for github too).  There are a lot of ways to generate static sites, but maybe one of the simplest seems to be to use mkdocs.

I made a video tutorial showing the steps required to get up and running quickly with this method. Just a couple of tweaks required here… In the video I apparently missed a couple of steps. If you have trouble getting python from within VScode’s terminal to work, you need to set the path in VSCode’s settings as well as the PATH environment variable in windows.  VSCode’s tutorial on installing python and selecting the proper python interpreter shares some steps to help you debug if you have this issue.

The second thing you might have to do is set your name and email in git. Try this:

git config --global user.email "<your email here>"
git config --global user.name "<your name here>"

The other steps in the video should get you going.

I will say I did thi

Setting OBS to Start and Stop Recording Automatically

(Video at the end…) OBS is a great tool for capturing screencasts for classes and such. I also use it sometimes to capture zoom and webex chats when I want the entire screen recorded full-sized. (By default those apps record and show other things like chat on the screen which isn’t useful for me). Sometimes I’m in class when my webchats start, so I wanted to automate the recording setup just like you used to be able to do with old VHS tapes on a VCR.  Simply program the start time and the stop time (assuming your VCR didn’t just flash 12:00 forever because you never figured out how to set the clock on the thing).  Of course you have to have your chat already started and opened on the screen you wish to record before you start OBS or you won’t record anything but a blank desktop with no sound… ask me how I know.  it works better with dual monitors and muting the external microphone inputs.

OBS has a STOP feature built-in. Simply open OBS and go to Tools–>Output Timer and you can set a time limit for how long you want it to record for.  I also check the box for “start every time” when I set it up this way.

The tricky part is STARTING the recording. Since OBS doesn’t run as a background process, it can’t just open itself and do whatever it wants. That’s just not safe. The work-around for this is to create a Windows Task that will do it for you. Windows Tasks are incredibly helpful. It’s like a cron job on linux. Even windows itself uses this tool for checking for updates and running virus scans for you.  To access it, simply click your windows icon and type “task scheduler”

Once it loads, you’ll need to doubleclick the “Task Schedule Library” in the left pane. If you don’t doubleclick it, then you won’t have the ability to create a task. Kind of a bad design in my opinion, but easy enough to work around.

Click Action–>Create Basic Task to open the wizard for you. It’ll walk you through the steps for setting the trigger you want. (In my case, I just want it to be a timed trigger at a certain date, but you can have it repeating, or based on a user’s action, or even every time you login. I set the time for about 5 minutes before the start time of my webchat.

 

Then it asks for what action it should perform when this task is triggered.  This is where we will tell it to open OBS and start the recording. To figure out what to type here, you’ll click your windows icon and type “OBS” but instead of opening it, right-click the icon and select “open file location” This will open the start menu folder.  Right click the OBS icon and click “properties”

Copy and paste the “Target” to the task Scheduler’s “”Program/Script” box.

Then copy and paste the “Start- in” path to the Task Scheduler’s “start in” box. But you have to remove the quotation marks on this one or it will not work!

Finally, you’ll need to type in some arguments for the Task Scheduler. Type:

--startrecording -m

 

The -m is there to allow multiple OBS windows to run at the same time in case for some reason you forget to close the previous one. Without this in the command, OBS will just give an error if another window is already opened.

Click OK to finish this task.  You will then be able to find your new task in the Scheduler’s window. If it is a long time before your trigger point, you can test it by right-clicking and selecting “run” and it should immediately open OBS and start recording.  If this doesn’t happen, then go back and make sure you don’t have quotation marks on the “Start in” function of the task.

I had a bit of trouble setting this up on my older laptop for some reason. I just could not get it to run directly from Task Scheduler. Instead, I wrote a windows batch script with the command in it, then passed the path to it as an argument to the “cmd” command (the windows command terminal/console).  Worked like a charm. First, open notepad and enter the following:

"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\OBS Studio\OBS Studio (64bit).lnk" --startrecording -m

and save this file as “obsScript.bat”  The icon should change from a notepad file to a script icon as shown below.

If you can’t get it to change even by adding “.bat” to the file name, then you need to show file extensions in windows. Open any folder, click View–>Show filename Extensions as shown below then change the filename.

Once this batch script is created, simply create a task for it like we tried to do above, but the path to the program/script should point to our new batch script.

Remember, you can always doubleclick the task in the schedule window to edit the different features. The command itself is listed under the “Actions” and the time is set under the “Triggers” tab.

When you run it, you should see the black command window pop up with the command, then OBS should start.

COMMON QUESTIONS:

Question: I want it to stream instead of record
Answer: Then use –startstreaming instead of –startrecording

Question: How can I make it record multiple times without opening a new window each time?
Answer: There are a couple of ways to do this.  The easiest is to close the window first.

Question: How do I make it automatically close the OBS window when done recording?
Answer: Schedule a “taskkill” command in the scheduler. This is like using the task manager to kill an app. You’ll need to know the time that you want it to end.  The command might be:

taskkill \IM obs.exe

If that doesn’t work, add a “\F” to the end of that line to force-close the program.

Question: How can I start a recording automatically when a call stats on zoom or other services?
Answer: You might be able to do this in TaskScheduler, but I did find a solution script for the program AutoHotKey on the OBS forum that checks to see if zoom is started.

Question: It doesn’t work, even with the batch script. What do?
Answer: You need to be in an Admin account in windows for it to work.

Question: I only have one screen. Wheen OBS starts it hides the content I am trying to record. What d?
Answer: In OBS Open Settings, under General tab > System Tray, select “Minimize to system tray when started”

Here’s the video showing the whole setup. You’re welcome!

 

SAMD11C Multi-use board

I finally got a chance to play with the SAMD11C chips FabAcademy has been recommending for a while. I also wanted to learn to use KiCAD a bit more so I made a multi-use board with the SAMD11C which can be used for UART, UPDI programmer, and as a FreeDAP board. You can find all of my files for this project, including the firmware at my FabAcademy gitlab page.

I will be making a modification of the board Quentin designed.

I designed the board in KiCAD by modifying another of Quentin’s boards, the SAMD11C dev kit with USB-A connector.

To fabricate a PCB, I’ll use the Roland SRM-20 mill as well as my shapeoko/X-carve using Fab Mods.

The steps in this project are:

  1. Download my board files, code, and hex from here.
  2. Mill the PCB with Roland or other CNC
  3. Populate (stuff) the board with components
  4. Flash firmware to the chip
  5. Use this new board as a programmer or USB/UART

Milling a board on the SRM-20 through Fab Mods:

I’ve posted a more detailed explanation of exporting from KiCAD to a milling machine in this previous post.  Be sure to check that out when you get to that part of the process.

Go to http://mods.cba.mit.edu/

Right click anywhere on the screen and select “program” then “open server program” and search for Roland→SRM-20 → PCB png. To use any other CNC (Shapeoko, Xcarve, 3018, etc.) you can select G-code→ mill 2D PCB png. This will accept in a PNG image file and generate the cut file you will send to your machine.

clip_image001

Then we’ll modify this to save a file for us.

clip_image002

 

If your X, Y, and Z, look like the GIF above, you’ll do an “air cut”.  An “air cut” is a test that runs the same code, just offset in the Z axis  (and this case X and Y as well) just to make sure everything will cut as you would expect. Then you’ll regenerate your cut file by changing the X, Y and Z defaults to 0s in mods before exporting your cutfile again.

 

Once the board is cut, it must be populated… Break out the old iron and solder up the design. If you don’t have a switch like the one I used, you can simply install some male headers and use a jumper to select the voltage. The SAMD doesn’t have a lot of external accessories which makes this part a good bit easier than say some of the older FabISP designs.

Once populated, the board needs to have firmware flashed to it. For this step, I will use the Atmel ICE programmer and a windows computer.

First download windows version of edbg which is the debugger tool we’ll use to download the firmware.

https://taradov.com/bin/edbg/

I downloaded it to my desktop.

Then download the binary of the firmware. I am using the SAMD11C arduino bootloader core firmware so I can use the chip with the Arduino IDE and libraries. (This bootloader seems to eat up a good bit of memory, even on these ARM devices).

Connect up the atmel ICE programmer to the SAMD board. I used figure 3-8 from the atmel ice manual to figure out the pinout because we are using the Serial-Wire debug (SWD) pinout.

Above you can see the specific pins for programming the firmware with the Atmel ICE. Pin 1 is Target Voltage (Vcc), pin 2 is SWDIO, pin 3 is GND, and pin 4 is SWDCLK. Pin 10 is the Reset.

Here are the pins and usage of the board:

Finally you’ll need to open the command prompt in windows, cd to the directory you downloaded these files to and run the following command (assuming you went with the 2nd firmware option above):

edbg-windows-r24.exe -bpv -e -t samd11 -f sam_ba_Generic_D11C14A_SAMD11C14A.bin

You should see:

Debugger: ATMEL Atmel-ICE CMSIS-DAP J42700050854 01.00.0021 (SJ)

Clock frequency: 16.0 MHz

Target: SAM D11C14A (Rev B)

Erasing... done.

Programming.... done.

Verification.... done.

The first time I did it I got this error:

Debugger: ATMEL Atmel-ICE CMSIS-DAP J42700050854 01.00.0021 (SJ)

Clock frequency: 16.0 MHz

Error: invalid response during transfer (count = 0/1, status = 0)

I unplugged everything, replugged it and tried again and it worked.

This firmware only allows arduino to program the chip via USB. Let’s now install the correct board info to arduino so we can do that.

In the arduino software, go to File→Preferences and click the icon next to “Additional Boards” and paste the following:

https://www.mattairtech.com/software/arduino/package_MattairTech_index.json

 

Then you need to install the SAMD boards. In Arduino go to Tools→Boards→Board manager

Search for “SAMD” and install the “MattairTech” one only.

Once this is installed (it will take a bit of time) We can write some arduino code to run on our new board. Let’s start with a blinky program. Looking at the pinout of the SAMD11C, we can choose a pin to connect an LED to on a breadboard.

(Image source: https://gitlab.fabcloud.org/pub/helloworld/index/-/tree/master/SAMDino.%20Hello%20SAMD11C14 )

 

You better make sure that you always use “INTERNAL_USB_CALIBRATED_OSCILLATOR” when you plan to keep this plugged into the USB port for power, or “INTERNAL_OSCILLATOR” when you want tit to be standalone. If you select the other two options, you’ll have to reprogram the firmware with the ICE or a DAP.  It basically bricks the chip if you tell it to use an external crystal but don’t add a xtal to your design.

Arduino file to be serial print to test. The pinout is simple. Each output uses the same pin number as the SAMD chip output. This is unlike a normal Arduino.

ATsamD11C14A Arduino pinout

   0 -------------------
  5 | A5                 A4 | 4
  8 | A8 (XIN)        A2 | 2
  9 | A9 (XOUT)   Vdd |
14 | A14             Gnd |
15 | A15             A25 | 25
28 | A28/RST     A24 | 24
30 | A30            A31 | 31
    -------------------

 

You can download this code to test your board (whether you have a working LED or not). Once this uploads, open the serial terminal and you should see “hello”

 

void setup() {
   SerialUSB.begin(0);
}

void loop() {
      SerialUSB.println("hello"); //Send stuff from USB to serial port
} //end loop

If you want to test to make sure that your board can now be programmed from the Arduino IDE, you can flash the built-in LED on pin 2 with this code:

int led = 2;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

The following Arduino file makes this board into a UPDI programmer when you add a jumper to the appropriate pins (see above). Simply take data from the USB serial port and put it on the output serial port and vice versa.

 

void setup() {
  
   SerialUSB.begin(0);
   Serial1.begin(57600, SERIAL_8E2); //Adjust baud rate and use SERIAL_8N1 for regular serial port usage
}

void loop() {
   if (SerialUSB.available()) {
      Serial1.write((char) SerialUSB.read()); //Send stuff from Serial port to USB
   }
   if (Serial1.available()) {
      SerialUSB.write((char) Serial1.read()); //Send stuff from USB to serial port
   }
} //end loop

 

Program a target board over UPDI:

Once you have downloaded the above serial code to your board, you can use it to program attiny412 or attiny1614 chips over UPDI.

  1. First, you want to get a Attiny board. Here’s a great simple board to try.
  2. Get the code from that link to blink the LED on pin 0.
  3. Most important part==>In arduino, change the chip to the attiny412!!! If you don’t do this, you’ll accidently reprogram the samd which you don’t want to do. If that happens, go back and put the serial UPDI code above back on the samd.
  4. Change the “programmer” to “SerialUPDI – SLOQ: 57600 baud, any platform…”
  5. Wire up the samd board as shown below. The white wire is the jumper described above to put the board into UPDI mode. The other wires connect to a target board.

 

To program other samd chips with this board:

If you want to use this to program other SAMD boards, you’ll need to download this Free-DAP firmware and flash it to this board using the edbg program as explained above. This now becomes a programmer for other boards (called target boards). Connect up the target board to this one correctly (follow pink pin names as shown in the explanation below) and then you can program the target SAMD board with some firmware using edbg as well.

Note that the pinout for the programmer for a target samd board.

 

FUTURE WORK:

I’d like to take a page from Adafruit’s book and make the Free-Dap project into an Arduino project. Though I I’m pretty sure you can’t flash a bootloader to a SAMD using avrdude (hence the use of edbg). Adafruit’s solution is to have you load the bootloader to an SD card connected to the target board, then the arduino project just dumps the data from the card into the target board’s FLASH. Instead, I think I’d rather take a note from how pyupdi.exe was added to the Arduino IDE and simply include edbg.exe with it instead.

I’d like to make this same board also program ISP chips like the attiny45 or bare Atmega328s, but it isn’t a priority. It should be possible to do this through the ArduinoISP file but…. meh.