pyserial - How to read the last line sent from a serial device

前端 未结 10 1781
再見小時候
再見小時候 2020-12-02 07:12

I have an Arduino connected to my computer running a loop, sending a value over the serial port back to the computer every 100 ms.

I want to make a Python scr

相关标签:
10条回答
  • 2020-12-02 08:02

    Using .inWaiting() inside an infinite loop may be problematic. It may hog up the entire CPU depending on the implementation. Instead, I would recommend using a specific size of data to be read. So in this case the following should be done for example:

    ser.read(1024)
    
    0 讨论(0)
  • 2020-12-02 08:04

    Too much complications

    What is the reason to split the bytes object by newline or by other array manipulations? I write the simplest method, which will solve your problem:

    import serial
    s = serial.Serial(31)
    s.write(bytes("ATI\r\n", "utf-8"));
    while True:
        last = ''
        for byte in s.read(s.inWaiting()): last += chr(byte)
        if len(last) > 0:
            # Do whatever you want with last
            print (bytes(last, "utf-8"))
            last = ''
    
    0 讨论(0)
  • 2020-12-02 08:06

    Perhaps I'm misunderstanding your question, but as it's a serial line, you'll have to read everything sent from the Arduino sequentially - it'll be buffered up in the Arduino until you read it.

    If you want to have a status display which shows the latest thing sent - use a thread which incorporates the code in your question (minus the sleep), and keep the last complete line read as the latest line from the Arduino.

    Update: mtasic's example code is quite good, but if the Arduino has sent a partial line when inWaiting() is called, you'll get a truncated line. Instead, what you want to do is to put the last complete line into last_received, and keep the partial line in buffer so that it can be appended to the next time round the loop. Something like this:

    def receiving(ser):
        global last_received
    
        buffer_string = ''
        while True:
            buffer_string = buffer_string + ser.read(ser.inWaiting())
            if '\n' in buffer_string:
                lines = buffer_string.split('\n') # Guaranteed to have at least 2 entries
                last_received = lines[-2]
                #If the Arduino sends lots of empty lines, you'll lose the
                #last filled line, so you could make the above statement conditional
                #like so: if lines[-2]: last_received = lines[-2]
                buffer_string = lines[-1]
    

    Regarding use of readline(): Here's what the Pyserial documentation has to say (slightly edited for clarity and with a mention to readlines()):

    Be careful when using "readline". Do specify a timeout when opening the serial port, otherwise it could block forever if no newline character is received. Also note that "readlines()" only works with a timeout. It depends on having a timeout and interprets that as EOF (end of file).

    which seems quite reasonable to me!

    0 讨论(0)
  • 2020-12-02 08:09

    This method allows you to separately control the timeout for gathering all the data for each line, and a different timeout for waiting on additional lines.

    # get the last line from serial port
    lines = serial_com()
    lines[-1]              
    
    def serial_com():
        '''Serial communications: get a response'''
    
        # open serial port
        try:
            serial_port = serial.Serial(com_port, baudrate=115200, timeout=1)
        except serial.SerialException as e:
            print("could not open serial port '{}': {}".format(com_port, e))
    
        # read response from serial port
        lines = []
        while True:
            line = serial_port.readline()
            lines.append(line.decode('utf-8').rstrip())
    
            # wait for new data after each line
            timeout = time.time() + 0.1
            while not serial_port.inWaiting() and timeout > time.time():
                pass
            if not serial_port.inWaiting():
                break 
    
        #close the serial port
        serial_port.close()   
        return lines
    
    0 讨论(0)
提交回复
热议问题