发送“(char)0”时,来自arduino的Python pySerial读取数据中断

时间:2014-09-19 12:46:04

标签: python serial-port arduino

我使用pySerial从arduino发送一些数据。

我的数据看起来像

bytearray(DST, SRC, STATUS, TYPE, CHANNEL, DATA..., SIZEOFDATA) 

其中sizeofData是一个接收所有字节的测试。

问题是,每当一个字节为零时,我的python程序就停止在那里读取:

serial_port = serial.Serial("/dev/ttyUSB0")
while serial_port.isOpen():
  response_header_str = serial_port.readline()
  format = '>';
  format += ('B'*len(response_header_str));
  response_header = struct.unpack(format, response_header_str)
  pprint(response_header)
serial_port.close()

例如,当我发送bytearray(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)时,一切都很好。但是,当我发送bytearray(1,2,3,4,0,1,2,3,4)之类的内容时,我不会看到以零开头的所有内容。

问题是我无法避免发送零,因为我只是发送"内存转储"例如当我发送一个浮点值时,可能有零个字节。

如何告诉pyserial不要忽略零字节。

1 个答案:

答案 0 :(得分:0)

我查看了PySerial的来源,问题出在PySerial的FileLike.readlinehttp://svn.code.sf.net/p/pyserial/code/trunk/pyserial/serial/serialutil.py)的实现中。违规功能是:

def readline(self, size=None, eol=LF):
    """\
    Read a line which is terminated with end-of-line (eol) character
    ('\n' by default) or until timeout.
    """
    leneol = len(eol)
    line = bytearray()
    while True:
        c = self.read(1)
        if c:
            line += c
            if line[-leneol:] == eol:
                break
            if size is not None and len(line) >= size:
                break
        else:
            break
    return bytes(line)

明显的问题是if c:行。当c == b'\x00'计算结果为false时,例程就会超出读循环。最简单的方法是将自己重新实现为:

def readline(port, size=None, eol="\n"):
    """\
    Read a line which is terminated with end-of-line (eol) character
    ('\n' by default) or until timeout.
    """
    leneol = len(eol)
    line = bytearray()
    while True:
        line += port.read(1)
        if line[-leneol:] == eol:
            break
        if size is not None and len(line) >= size:
            break
    return bytes(line)

为了澄清你的评论,这是将消耗空字节的Serial.readline方法的替代,并将它们添加到返回的字符串,直到它到达eol字符,我们在此定义为"\n"

使用新方法的示例,其中文件对象替换套接字:

>>> # Create some example data terminated by a newline containing nulls.
>>> handle = open("test.dat", "wb")
>>> handle.write(b"hell\x00o, w\x00rld\n")
>>> handle.close()
>>>
>>> # Use our readline method to read it back in.
>>> handle = open("test.dat", "rb") 
>>> readline(handle)
'hell\x00o, w\x00rld\n'

希望这更有意义。