42

我正在使用 Python 中的脚本通过串行端口以 2Mbps 的速度从 PIC 微控制器收集数据。

PIC 在 2Mbps 下以完美的时序工作,FTDI USB 串行端口在 2Mbps 下也能很好地工作(均通过示波器验证)

我每秒发送消息(大约 15 个字符的大小)大约 100-150 次,并且那里的数字会增加(检查我是否有消息丢失等等)

在我的笔记本电脑上,我将 Xubuntu 作为虚拟机运行,我可以通过 Putty 和我的脚本(python 2.7 和 pySerial)读取串行端口

问题:

  • 通过 Putty 打开串行端口时,我看到所有消息(消息中的计数器以 1 递增 1)。完美的!
  • 通过 pySerial 打开串行端口时,我看到所有消息,但不是每秒接收 100-150 倍,而是每秒大约 5 次接收它们(消息仍然以 1 递增 1),但它们可能存储在某个缓冲区中,就像我关闭电源时一样PIC,我可以去厨房回来,我仍然收到消息。

这是代码(我省略了大部分代码,但循环是相同的):

ser = serial.Serial('/dev/ttyUSB0', 2000000, timeout=2, xonxoff=False, rtscts=False, dsrdtr=False) #Tried with and without the last 3 parameters, and also at 1Mbps, same happens.
ser.flushInput()
ser.flushOutput()
While True:
  data_raw = ser.readline()
  print(data_raw)

任何人都知道为什么 pySerial 从串口读取到行尾需要这么长时间?有什么帮助吗?

我想实时拥有这个。

谢谢

4

4 回答 4

40

您可以使用它inWaiting()来获取输入队列中可用的字节数。

然后你可以read()用来读取字节,像这样:

While True:
    bytesToRead = ser.inWaiting()
    ser.read(bytesToRead)

为什么不使用Docsreadline() 的这种情况

Read a line which is terminated with end-of-line (eol) character (\n by default) or until timeout.

您正在等待每次读数的超时,因为它等待 eol。串行输入 Q 保持不变,只是需要很长时间才能到达缓冲区的“末端”,为了更好地理解它:您正在像赛车一样写入输入 Q,并且像旧车一样读取 :)

于 2013-11-11T14:56:36.680 回答
5

打开串口时需要将超时设置为“无”:

ser = serial.Serial(**bco_port**, timeout=None, baudrate=115000, xonxoff=False, rtscts=False, dsrdtr=False) 

这是一个阻塞命令,因此您一直在等待,直到收到末尾带有换行符(\n 或 \r\n)的数据:line = ser.readline()

获得数据后,它将尽快返回。

于 2014-11-21T10:41:09.103 回答
3

手册

参数 timeout 的可能值: ... x将 timeout 设置为x

readlines(sizehint=None, eol='\n')读取行列表,直到超时。sizehint 被忽略,仅存在于与内置 File 对象的 API 兼容性。

请注意,此函数仅在超时时返回。

因此,您readlines最多每 2 秒返回一次。read()按照蒂姆的建议使用。

于 2013-11-11T14:57:56.903 回答
3

可以在这里找到一个非常好的解决方案:

这是一个用作 pyserial 对象的包装器的类。它允许您在没有 100% CPU 的情况下读取行。它不包含任何超时逻辑。如果发生超时,self.s.read(i)则返回一个空字符串,您可能希望引发异常以指示超时。

根据作者的说法,它也应该很快:

下面的代码给了我 790 kB/sec,而用 pyserial 的 readline 方法替换代码给我只有 170kB/sec。

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())
于 2019-06-17T13:55:35.347 回答