So i am reading (and displaying with a tkinter textbox) data from a serial connection, but i can't process the returning data as i would like to, in order to run my tests. In more simple terms, even though the machine response = 0x1 is displayed, i can't read it from the global serBuffer.
Before displaying it to the textbox i would read from inside the  test function and then check if the response was in the string, but now that i pass the read data(strings) to a global variable and then try to read it, it doesn't seem to work, UNLESS i remove  the serBuffer = "" from readserial. That results in a new issue though. When i press the button to send the command it sends it, but only receives the response after the second time i 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. 
Picture with the desired response ( that the test function doesn't read 0x1 and always returns FAIL)

Picture with the non-desired response ( that 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 every time after).

import tkinter as tk
import serial
from serial import *
serialPort = "COM3"
baudRate = 115200
ser = Serial(serialPort, baudRate, timeout=0, writeTimeout=0) #ensure non-blocking
#make a TkInter Window
mainWindow = tk.Tk()
mainWindow.wm_title("Reading Serial")
mainWindow.geometry('1650x1000+500+100')
scrollbar = tk.Scrollbar(mainWindow)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
log = tk.Text ( mainWindow, width=60, height=60, takefocus=0)
log.pack()
log.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=log.yview)
#make our own buffer
#useful for parsing commands
#Serial.readline seems unreliable at times too
serBuffer = ""
ser.write(b'\r\n')
def readSerial():
    while True:
        c = (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
            # add the line to the TOP of the log
            log.insert('1.1', serBuffer)
            serBuffer = ""  # empty the buffer
        else:
            serBuffer += c  # add to the buffer
    mainWindow.after(100, readSerial)  # check serial again soon
def test():
    command = b" test command \r\n"
    ser.write(command)
    global serBuffer
    time.sleep(0.5)
    if "0x1" in serBuffer:
        print('PASS')
        return 'PASS'
    else:
        print('FAIL')
        return 'FAIL'
button = tk.Button(mainWindow, text="Pone Test", font=40, bg='#b1c62d', command=test)
button.place(relx=0.8, rely=0, relwidth=0.1, relheight=0.05)
# after initializing serial, an arduino may need a bit of time to reset
mainWindow.after(100, readSerial)
mainWindow.mainloop()
                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
OOPsyntax.
last_command
serBuffer = ""
last_command = None
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
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' FAILNote: I get
FAIL, because there is no0x1inlast_commandas 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)  
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With