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

前端 未结 10 1780
再見小時候
再見小時候 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 07:47

    Slight modification to mtasic & Vinay Sajip's code:

    While I found this code quite helpful to me for a similar application, I needed all the lines coming back from a serial device that would send information periodically.

    I opted to pop the first element off the top, record it, and then rejoin the remaining elements as the new buffer and continue from there.

    I realize that this is not what Greg was asking for, but I thought it was worth sharing as a side note.

    def receiving(ser):
        global last_received
    
        buffer = ''
        while True:
            buffer = buffer + ser.read(ser.inWaiting())
            if '\n' in buffer:
                lines = buffer.split('\n')
                last_received = lines.pop(0)
    
                buffer = '\n'.join(lines)
    
    0 讨论(0)
  • 2020-12-02 07:53
    from serial import *
    from threading import Thread
    
    last_received = ''
    
    def receiving(ser):
        global last_received
        buffer = ''
    
        while True:
            # last_received = ser.readline()
            buffer += ser.read(ser.inWaiting())
            if '\n' in buffer:
                last_received, buffer = buffer.split('\n')[-2:]
    
    if __name__ ==  '__main__':
        ser = Serial(
            port=None,
            baudrate=9600,
            bytesize=EIGHTBITS,
            parity=PARITY_NONE,
            stopbits=STOPBITS_ONE,
            timeout=0.1,
            xonxoff=0,
            rtscts=0,
            interCharTimeout=None
        )
    
        Thread(target=receiving, args=(ser,)).start()
    
    0 讨论(0)
  • 2020-12-02 07:58

    You can use ser.flushInput() to flush out all serial data that is currently in the buffer.

    After clearing out the old data, you can user ser.readline() to get the most recent data from the serial device.

    I think its a bit simpler than the other proposed solutions on here. Worked for me, hope it's suitable for you.

    0 讨论(0)
  • 2020-12-02 07:58

    You will need a loop to read everything sent, with the last call to readline() blocking until the timeout. So:

    def readLastLine(ser):
        last_data=''
        while True:
            data=ser.readline()
            if data!='':
                last_data=data
            else:
                return last_data
    
    0 讨论(0)
  • 2020-12-02 07:58

    Here's an example using a wrapper that allows you to read the most recent line without 100% CPU

    class ReadLine:
        """
        pyserial object wrapper for reading line
        source: https://github.com/pyserial/pyserial/issues/216
        """
        def __init__(self, s):
            self.buf = bytearray()
            self.s = s
    
        def readline(self):
            i = self.buf.find(b"\n")
            if i >= 0:
                r = self.buf[:i + 1]
                self.buf = self.buf[i + 1:]
                return r
            while True:
                i = max(1, min(2048, self.s.in_waiting))
                data = self.s.read(i)
                i = data.find(b"\n")
                if i >= 0:
                    r = self.buf + data[:i + 1]
                    self.buf[0:] = data[i + 1:]
                    return r
                else:
                    self.buf.extend(data)
    
    s = serial.Serial('/dev/ttyS0')
    device = ReadLine(s)
    while True:
        print(device.readline())
    
    0 讨论(0)
  • 2020-12-02 08:02

    These solutions will hog the CPU while waiting for characters.

    You should do at least one blocking call to read(1)

    while True:
        if '\n' in buffer: 
            pass # skip if a line already in buffer
        else:
            buffer += ser.read(1)  # this will block until one more char or timeout
        buffer += ser.read(ser.inWaiting()) # get remaining buffered chars
    

    ...and do the split thing as before.

    0 讨论(0)
提交回复
热议问题