Issue processing data read from serial port, when displaying it in a Tkinter textbox
Comment: but only receives the response after the second time a press it, and every time after. So as a result i get a Fail if i run the test once, but i get a pass everytime after
Raise the first, timeout from 100
to 500
ore more.
# after initializing serial, an arduino may need a bit of time to reset
mainWindow.after(100, self.readSerial)
To find out the delay for the first response, try the following:
Note: You have to do this without running
def readSerial
, to prevent concurent empty thein buffer
"
command = b" test command \r\n"
self.ser.write(command)
delay = 0.0
# wait until you get `.in_waiting` data.
while not self.ser.in_waiting:
time.sleep(0.1)
delay += 0.1
print('.', end='')
if delay >= 10:
print('BREAK after {} no in_waiting'.format(int(delay * 10)))
break
print('Delay:{}, in_waiting:{}'.format(delay, self.ser.in_waiting))
The following works for me.
Note: I use
OOP
syntax.
last_command
serBuffer = "" last_command = None
Copy the ready
read_buffer
tolast_command
, empty onlyread_buffer
def readSerial(self): while True: c = (self.ser.read().decode('utf-8', 'ignore')) # attempt to read a character from Serial # was anything read? if len(c) == 0: break # get the buffer from outside of this function global serBuffer # check if character is a delimeter if c == '\r': serBuffer += "\n" # don't want returns. chuck it if c == '\n': serBuffer += "\n" # add the newline to the buffer global last_command last_command = serBuffer # add the line to the TOP of the log # log.insert('1.1', last_command) print('readSerial.last_command:"{}"'.format(bytes(last_command, 'utf-8'))) serBuffer = "" # empty the buffer else: serBuffer += c # add to the buffer print('readSerial:"{}"'.format(bytes(serBuffer, 'utf-8'))) self.after(100, self.readSerial) # check serial again soon
Do
test()
def test(self, write=True): print('test(write={})'.format(write)) if write: command = b" test command \r\n" self.ser.write(command) self.after(500, self.test, False) elif last_command is not None: print('last_command:{}'.format(bytes(last_command, 'utf-8'))) if "0x1" in last_command: print('PASS') else: print('FAIL') else: # ATTENTION: This could lead to a infinit loop # self.after(500, self.test, False) pass
Output:
test(write=True) readSerial:"b' '" readSerial:"b' t'" readSerial:"b' te'" readSerial:"b' tes'" readSerial:"b' test'" readSerial:"b' test '" readSerial:"b' test c'" readSerial:"b' test co'" readSerial:"b' test com'" readSerial:"b' test comm'" readSerial:"b' test comma'" readSerial:"b' test comman'" readSerial:"b' test command'" readSerial:"b' test command '" readSerial:"b' test command \n\r'" readSerial.last_command:"b' test command \n\r\n'" test(write=False) last_command:b' test command \n\r\n' FAIL
Note: I get
FAIL
, because there is no0x1
inlast_command
as i usePORT = 'loop://'
which echo what is writen!
I made some changes, check this one.
def readSerial():
while True:
c = (ser.read(1).decode('utf-8', 'ignore')) from Serial
if len(c) == 0:
break
global serBuffer
if c == '\r':
serBuffer += ""
if c == '\n':
serBuffer += "\n"
log.insert(tk.END, serBuffer)
log.see(tk.END)
log.update_idletasks()
serBuffer = ""
else:
serBuffer += c
mainWindow.after(500, readSerial)