How can I improve PySerial read speed

筅森魡賤 提交于 2019-12-03 08:02:49

I've switched from PySerial to PyTTY, which solves my problem. Just plugging it into this code (with some small changes, like replacing serialPort.inWaiting() == 0 by serialPort.peek() == b'' for example) makes my code able to handle the datastream and not get above 50% CPU usage, which means it is at least 10x as fast. I'm still using PySerial to set the DTR lines though.

So, I guess the answer to the question is that indeed PySerial is indeed poorly optimised.

I realize that this is an old thread, but it has been viewed 3000 times as of this writing and I would hate for someone to be turned off of pySerial on just this encounter.

I believe the most likely culprit for the author's problem is the implicit parsing that is going on between reads:

incomingData = serialPort.readline().decode('ascii')

The readline() method is telling pyserial to parse to the next line. You are also doing a decode() in the middle of your receive cycle. All of this is occurring right in the middle of your stream.

A better approach might look like this:

waiting = port.in_waiting  # find num of bytes currently waiting in hardware
buffer += [chr(c) for c in port.read(waiting)] # read them, convert to ascii

# ...keep accumulating the buffer for as long as is reasonable...

processSerialData(buffer)  # whatever processing needs to happen, split your
                           # lines, log, or whatever else *after* you get
                           # your data

A very good solution to this can be found here.

The author states:

The code below gives me 790 kB/sec while replacing the code with pyserial's readline method gives me just 170kB/sec.

This solution also avoids having 100 % CPU usage.

class ReadLine:
    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)

ser = serial.Serial('COM7', 9600)
rl = ReadLine(ser)

while True:

    print(rl.readline())
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!