- Published on
How to Display Serial Arduino Data on a Scrollable Tkinter GUI
- Authors
- Name
- Tinker Assist
Step By Step
First, we need to import our dependencies.
from tkinter import *
import serial.tools.list_ports
import functools
Now, get a list of available COM ports and initialize an instance of the serial object.
ports = serial.tools.list_ports.comports()
serialObj = serial.Serial()
Next, we need to create a window for our GUI. We are going to make the background grey
root = Tk()
root.config(bg='grey')
Next, we need to create a function to initialize our serial port. The user will ultimately select from a list of ports presented on the GUI.
def initComPort(index):
currentPort = str(ports[index])
comPortVar = str(currentPort.split(' ')[0])
print(comPortVar)
serialObj.port = comPortVar
serialObj.baudrate = 9600
serialObj.open()
Now, let's create buttons that are tied to each of our available COM ports in our GUI window
for onePort in ports:
comButton = Button(root, text=onePort, font=('Calibri', '13'), height=1, width=45, command = functools.partial(initComPort, index = ports.index(onePort)))
comButton.grid(row=ports.index(onePort), column=0)
Now let's create a Tkinter Canvas where we will display data being received from our Arduino.
dataCanvas = Canvas(root, width=600, height=400, bg='white')
dataCanvas.grid(row=0, column=1, rowspan=100)
Now let's create a vertical scrollbar so if our data window extends beyond the length of our GUI window, we can scroll to the bottom to see new data.
vsb = Scrollbar(root, orient='vertical', command=dataCanvas.yview)
vsb.grid(row=0, column=2, rowspan=100, sticky='ns')
dataCanvas.config(yscrollcommand = vsb.set)
Let's now anchor our Canvas into the rest of the GUI Frame.
dataFrame = Frame(dataCanvas, bg="white")
dataCanvas.create_window((10,0),window=dataFrame,anchor='nw')
Now let's create a function that will allow us to cyclically check for new data from our Arduino
def checkSerialPort():
if serialObj.isOpen() and serialObj.in_waiting:
recentPacket = serialObj.readline()
recentPacketString = recentPacket.decode('utf').rstrip('\n')
Label(dataFrame, text=recentPacketString)
We can now create an infinite loop using 'while True' that will run our GUI window and check for new data in the background.
while True:
root.update()
checkSerialPort()
dataCanvas.config(scrollregion=dataCanvas.bbox("all"))
Full Script
from tkinter import *
import serial.tools.list_ports
import functools
ports = serial.tools.list_ports.comports()
serialObj = serial.Serial()
root = Tk()
root.config(bg='grey')
def initComPort(index):
currentPort = str(ports[index])
comPortVar = str(currentPort.split(' ')[0])
print(comPortVar)
serialObj.port = comPortVar
serialObj.baudrate = 9600
serialObj.open()
for onePort in ports:
comButton = Button(root, text=onePort, font=('Calibri', '13'), height=1, width=45, command = functools.partial(initComPort, index = ports.index(onePort)))
comButton.grid(row=ports.index(onePort), column=0)
dataCanvas = Canvas(root, width=600, height=400, bg='white')
dataCanvas.grid(row=0, column=1, rowspan=100)
vsb = Scrollbar(root, orient='vertical', command=dataCanvas.yview)
vsb.grid(row=0, column=2, rowspan=100, sticky='ns')
dataCanvas.config(yscrollcommand = vsb.set)
dataFrame = Frame(dataCanvas, bg="white")
dataCanvas.create_window((10,0),window=dataFrame,anchor='nw')
def checkSerialPort():
if serialObj.isOpen() and serialObj.in_waiting:
recentPacket = serialObj.readline()
recentPacketString = recentPacket.decode('utf').rstrip('\n')
Label(dataFrame, text=recentPacketString)
while True:
root.update()
checkSerialPort()
dataCanvas.config(scrollregion=dataCanvas.bbox("all"))