14. Interface and application programming
Goals
Individual assignment:
- [x] Week an application that interfaces a user with an input &/or output device that you made
Group assignment:
- [x] Compare as many tool options as possible
Tools Used
- Pureref - An amazing program for gathering images into a big moodboard
- Concepts - My goto sketching app on the ipad
- Thonny
- Zed
- ChatGPT
TLDR; Nice images
Group Project
For this weeks group we compared different approaches to Interface and application programming
Summary
I used Tkinter for python and further developed my final project.
Individual Project
1. Making a custom HID
For this assignment I will be sending inputs over USB serial to a desktop application. I will be implementing a lot of the code I have written in previous assignments, but now rather than using a HID library on the device I will be using a desktop application to receive the inputs and convert them into key and mouse events.
1.0 Starting Point
As a starting point I wanted to recreate my blender view toggle from week 10.
But before I got there I wanted to just send a button press over USB serial to a desktop application.
See code below:
Firmware
from machine import Pin
import time
import sys
button = Pin(0, Pin.IN, Pin.PULL_UP)
previous_state = button.value()
while True:
current_state = button.value()
if current_state is not previous_state:
if current_state ==0:
sys.stdout.write("Pressed\n") # Send message over USB serial
else:
sys.stdout.write("Released\n") # Send message over USB serial
previous_state = current_state
time.sleep(0.01)
The send the value “Pressed” or “Released” depending on the button state.
desktop
import serial
import time
try:
ser = serial.Serial("/dev/tty.usbmodem21201", 115200, timeout=1) # Use correct port
print("Serial port opened.")
except serial.SerialException as e:
print("Error opening serial port:", e)
exit(1)
while True:
try:
if ser.in_waiting:
line = ser.readline().decode("utf-8", errors="ignore").strip()
print("Received:", line)
except serial.SerialException as e:
print("Serial communication error:", e)
break
except Exception as e:
print("Unexpected error:", e)
break
time.sleep(0.01)
This opens up a serial connection on the same port as the device and listens for incoming messages. When it gets a message it prints “Recieved: ” followed by the message
1.1 Adding a GUI with Tkinter
Now that we can send data over serial lets add a GUI for the desktop app so we have a more user friendly interface.
The code is as follows;
import tkinter as tk
import serial
import threading
def read_serial():
while True:
if ser.in_waiting:
line = ser.readline().decode().strip()
if line == "Pressed":
label.config(text="Button Pressed", fg="green")
elif line == "Released":
label.config(text="Button Released", fg="black")
ser = serial.Serial("/dev/tty.usbmodem21201", 115200)
root = tk.Tk()
root.title("Macro Pad GUI")
label = tk.Label(root, text="Waiting for input...", font=("Helvetica", 16))
label.pack(pady=20)
thread = threading.Thread(target=read_serial, daemon=True)
thread.start()
root.mainloop()
1.2 Install guide
The tools to use the above are installed using pip in your local environment;
pip install tkinter
pip install serial
pip install threading
2 bonus Making a new board for the Pico
Up until now I have been using my RP2040 based Fab-Xiao for weekly projects and testing.
For my final project I will need to step up to a Raspberry Pi Pico 2 W to add more pins and Blueooth support.
So now I need a new board to develop my code on for my final project as working with the breadboards has been very frustrating and time consuming.
I downloaded a Pico V2 footprint from the link above
Downloaded the symbols and footprint for my encoders from Digikey
And imported my OLED screen and linear pot symbols from previous weeks
Pushed the design to the board design workspace
rearranged the parts until autoroute completed successfully
And tweaked the layout until I was happy with how everything looked and used export->image
to get my files ready from CAM.
The sittings I used were:
[x] monochrome images
1000 dpi
*.png file format
Area: Full
There were some elements that were included in some of my downloaded footprint’s that I could not hide with layers
in Fusion 360 so took the
Pushed the file to a 3D pcb and designed a quick housing for it.
Handled my CAM in mods, I am still finding the 60 deg vbit is working for me.
And got to cutting!
Traces part way complete
And started soldering parts. One of the more interesting things on the board is the way the through hole 4 pin header is mounted.
The pins are removed from the header, soldered in place and then the plastic header is then placed down over the top.
I then realised that I was using a double sided board… this meant that all my pins on the picos headers were shorting on the underside of the board.
So I recut the board and removed some of the copper on the underside with a dremmel.
NOTE: only do this with FR1 board and still make sure to use eye and dust protection.
And we are up and running with the code from earlier!
In Summary
This week the I kept the brief for the week pretty simple as I spent a lot of time rewriting a lot of my scrips for handling the logic.
The goal for my final project will be a mix of a desktop based GUI program that is reading serial from the device so this was a critical step towards that.
Things I would do differently next time
The reason I made a new board this week was due to frustration with bread boarding but I know that this was not a optimal use of time.
It would have been ideal if I had already had a working prototype and done more ambitious things with tkinter.
For me the ideal thing would have been to have made a test file where I manipulate a cube using the device. Spinning, zooming etc.
See below link to to files created this week: