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 the in 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.

  1. last_command

    serBuffer = ""
    last_command = None
    
  2. Copy the ready read_buffer to last_command, empty only read_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
    
  3. 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 no 0x1 in last_command as i use PORT = '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)