This week objective is to make an interface to work with one of your boards.
I had previous experience using C++ language, and there was different platforms that works with C++.
However, this wasn't my goal, so I decided to work with Tkinter which's a language based on python (which I barely have knowledge about) and it's already embedded in python files.
Note: be aware whether it's python 2 or 3! Because I had tons of errors because of this issue! Because most of the internet code documentation was written for python 2.
I spent hours digging into several documenations given above for tkinter to understand the syntax of it.
My recommendation is to read this page before you proceed and type any code.
and the very first code I faced was the one below which opens just a blank window as the base interface for any GUI.
1 2 3 4 | import tkinter top = tkinter.Tk() # Code to add widgets will go here... top.mainloop() |
After learning how to open the blank GUI, I wanted to add buttons and Labels and much more by adding components to the GUI and amending new ones I learn.
After that, I got a thought that I want my GUI to be a bit interactive, so you get to choose which COM port you'll use and this feature was available using the Option menu.
Furthermore, the hard part wasn't the loops and and buttons I added with option menu or anything, the entire challenge for me was in connecting Arduino with Python.
I was adviced by one of my friends to install and use PySerial you'll find on the website how to install it on different operating systems and here's how to install it using CMD:
The reason I installed PySerial is that it helps in integrating between the serial communication and python and I found several classes that make you select the baud rate and the COM port that arduino is connected on.
Also, in this thread I found this module which helps in opening and configuring ports which saved me a lot of time and the rest of the code was just iterations (loops) and declaring a function that does a specific task in the code.
Before showing you the code I have to thank one of my dear friends who've helpt me a lot while learning about python GUI and making this code! Thank you :D Abdelrahman Abounegm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | # Imports import tkinter as tk import serial from serial.tools.list_ports import comports # Define constants used throughout the program PORT = 'COM5' BAUD_RATE = 9600 TIMEOUT = 0 # Initialize the serial communication and GUI Device = serial.Serial(baudrate=BAUD_RATE, timeout=TIMEOUT) window = tk.Tk() window.title('Serial Communication') def initDevice(com = PORT): '''This function opens the connection between Device and the PC Input: <string> COM port (optional. uses the globally defined port if not given) Output: <boolean> the success of the operation''' print("Connection to:", com) Device.port = com try: #Try and except function is similar to if condition, the differece is it does the action then waits for the reply whether it's true or false. Device.open() print("Connection with Device successfully opened") return True except (FileNotFoundError, OSError): print("ERROR: Can't connect to this port!") return False def reading(): '''Tries to read the value sent by Device and returns it Input: None Output: <int|str> the integer sent by the Device, or ‘N/A’ if it couldn’t be read ''' try: read = Device.read(3) # read 3 bytes (1 digit + 2 line terminators) string = read.decode().strip() # decode the binary string to unicode and strip all whitespace return int(string) except: return 'N\A' sel = tk.StringVar() sel.set('Refresh to see available ports') sel.trace('w', lambda *args: initDevice(sel.get())) options = tk.OptionMenu(window, sel, []) def listPorts(): ''' Refreshes the available COM ports and updates the Options Menu ''' ports = [port.device for port in comports()] # get the available ports #ports = [1,2,3] # for testing. comment later print("Ports found:", ports) menu = options['menu'] menu.delete(0, 'end') # Clear the previous items if len(ports) == 0: sel.set('No ports found. refresh again') else: for port in ports: menu.add_command(label=port, command=lambda p=port: sel.set(p)) sel.set('Choose a port:') refreshPorts = tk.Button(window, text='Refresh COM ports', command=listPorts) label = tk.Label(window) def update_label(): label.configure(text=f"Current reading: {reading()}") # Update the text with the latest reading label.after(100, update_label) # Queue the function to run again after 100 milliseconds update_label() # Call for the first time to initialize the recursive updating # pack the UI elements to the window refreshPorts.pack(side='top') options.pack() label.pack() window.config() window.mainloop() |
Please watch in full screen