supremus_58
supremus_58

Reputation: 57

Getting constant updates from serial to output to TexCtrl

I have a gui that I've written in wxPython, this is working as a software controller going to a PID type thermal controller. I need to get constant readings from the thermal controller to consistently output the current temperature of the device.

Let's say I have this function in another file:

    def temp_read():
        #this function will query a controller, then read the value

I import that function, and set it to the value of a TextCtrl widget:

    out_current = wx.TextCtrl(self, pos=(250,8), size=(110,23), style=TE_READONLY)
    out_temp = temp_read()#get value from function
    out_current.SetValue(out_temp)#set value to widget

How do I set this up so that it constantly outputs, while leaving the gui functional to allow for the rest of control parameters(setting temperature and other items) to be set by the user?

Upvotes: 1

Views: 298

Answers (2)

nepix32
nepix32

Reputation: 3177

You do not specify how you get the serial data. I suppose however you will use pyserial. The principal problem in reading the serial is that reading it will block until the next character arrives. And because it will immediately try to read the next byte (and block again) the GUI will never become idle.

So essentially you have to spin off the serial reading in a separate thread and communicate the result back thread-safely.

For the purpose of reading out an Arduino I have created a small running example (which also explains in more detail why threading is required). When deleting the line for DRS/DTR, it will apply to any serial device.

EDIT: And if you further look in the pyserial library and look at the wxPython example, it is using threading.

Upvotes: 2

Rolf of Saxony
Rolf of Saxony

Reputation: 22448

With regard to my comment:
This is from the pyserial manual:

>>> ser = serial.Serial('/dev/ttyS1', 19200, timeout=1)   
>>> x = ser.read()          # read one byte   
>>> s = ser.read(10)        # read up to ten bytes (timeout)   
>>> line = ser.readline()   # read a '\n' terminated line   
>>> ser.close()   


>>> ser = serial.Serial(1, 38400, timeout=0,   
...                     parity=serial.PARITY_EVEN, rtscts=1)   
>>> s = ser.read(100)       # read up to one hundred bytes   
...                         # or as much is in the buffer   

If you find that you have to take the Thread route see the accepted answer written by Fredrik Haard here PySerial non-blocking read loop

His quick example is as follows:

import threading

connected = False
port = 'COM4'
baud = 9600

serial_port = serial.Serial(port, baud, timeout=0)

def handle_data(data):
    print(data)

def read_from_port(ser):
    while not connected:
        #serin = ser.read()
        connected = True

        while True:
           print("test")
           reading = ser.readline().decode()
           handle_data(reading)

thread = threading.Thread(target=read_from_port, args=(serial_port,))
thread.start()

Upvotes: 1

Related Questions