Home

Interface and Application Programming

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.

Download and Install Python:


Photo Credits

When you open python you will face a struggle which's whether to download python 2.x or 3.x, even the documentation refrences some of them is written for python 2.x the others for 3.x

So I read about the differences and the most convincing one for me was “The main advantage of 3.x is that it is on the cutting edge, so all the new features will be implemented in there rather than being added to 2.x. The other thing you may want to consider is that it is the common python of the future, so looking a couple of years down the line, this will be the mature branch that people go to.” which I found in this link in a comparison between 2.x and 3.x

Also, in wiki python there's this comparison again with reference to history of each one and which to use, so I setteled on using python 3.

Coding:

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.

  1. Reference 1
  2. Reference 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:

  1. You have to unzip the file (pyserial-3.2.1).
  2. You have to reach using the CMD the setup file to write that last command I wrote in the video.
  3. To view items in the directory you're in use command (ls) as shown in the video or memorize the folders which's harder.



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.

The Final 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()

Testing Results:

Please watch in full screen

Download Files:

(Website) I used to turn python codes into HTML for documentation.

Pyserial-3.2.1(.zip)

Interface Python Code