Setting up the serial object from a function (called from tkinter interaction)

660 Views Asked by At

I managed to get my tkinter aplication to display text on a text field.

I did this by hardcoding the COM port and baud rate, then set up a serial object at the beginning of my program.

baudRate = 9600
ser = serial.Serial('COM16', baudRate)

Then all my code runs afterwards.

But the problem with this is that everything is hardcoded. I want the user to be able to select the COM port from a dropdown. And when he selects one port, the serial communication should start.

So i built exactly that. Here is my relevant code.

#hardcoded baud rate
baudRate = 9600

# this is the global variable that will hold the serial object value
ser = 0 #initial  value. will change at 'on_select()'

#this function populates the dropdown on frame1, with all the serial ports of the system
def serial_ports():    
    return serial.tools.list_ports.comports()

#when the user selects one serial port from the dropdown, this function will execute
def on_select(event=None):
    global ser
    COMPort = cb.get()
    string_separator = "-"
    COMPort = COMPort.split(string_separator, 1)[0] #remove everything after '-' character
    COMPort = COMPort[:-1] #remove last character of the string (which is a space)
    ser = serial.Serial(port = COMPort, baudrate=9600)
    return ser
    readSerial() #start reading

#this function reads the incoming data and inserts them into a text frame
def readSerial():
    ser_bytes = ser.readline()
    ser_bytes = ser_bytes.decode("utf-8")
    text.insert("end", ser_bytes)
    if vsb.get()[1]==1.0:
       text.see("end")
    root.after(100, readSerial)

What happens when i select a COM port from the dropdown, is that i see transmision on the led buttons of my device.

However, nothing is displayed on the text frame. Before, when i hardcoded everything and setup the serialobject in the beginning of the program, and i statre the readSerial() function in the end of my program, everything worked.

1

There are 1 best solutions below

7
astqx On BEST ANSWER

In your on_select function, you have called return before calling the readSerial() function. The return statement terminates the execution of a function, any statements following it will not be executed. Removing it would make the program work.

Also, since on_select is a callback form the dropdown, the return statement is redundant as it does not have anywhere to return to. The global ser takes care of assigning the new value to the ser variable globally.

You do not need to call the readSerial() function every time a new option is selected (else, it will increase the number of scheduled calls every time). You can either have a button that calls it once you have initially configured it and remove the call to readSerial() form on_select or create a flag that ensures that it has been called only once.


Based on your comment, I've created the following example, you could try something like this

from tkinter import *

def on_select(event):
    global value
    value=option.get()
    if stop_:
        start_button['state']='normal'

def start():
    global stop_
    stop_=False
    readSerial()
    start_button['state']='disabled'
    stop_button['state']='normal'

def stop():
    global stop_
    stop_=True
    root.after_cancel(after_id)
    start_button['state']='normal'
    stop_button['state']='disabled'

def readSerial():
    global after_id
    text.insert(END,value)
    after_id=root.after(100,readSerial)

root=Tk()

text=Text(root)
text.pack(side='bottom')

options=['1','2']
option=StringVar()
om=OptionMenu(root,option,*options,command=on_select)
om.pack(side='left')

start_button=Button(root,text='start',command=start,state='disabled')
start_button.pack(side='left')
stop_button=Button(root,text='stop',command=stop,state='disabled')
stop_button.pack(side='left')

stop_=True

root.mainloop()