pyserial 2.7,python 3.3,发送回车符
我一直在尝试让树莓派通过UART接口与一个嵌入式电路进行通信。树莓派上的UART接口工作正常,我可以接收到来自电路的消息,但在向电路发送消息时遇到了问题。
我使用的是Python 3.3和Pyserial 2.7。虽然有示例代码,但它使用的是Pyserial 2.6。在旧版本的Python(小于2.6)中,ser.write()
可以接受字符串,但现在它只能接受字节数组。
我遇到的问题是发送回车符……旧代码据说只需要这样就能工作:
ser.write("L1\r")
但现在我使用的是:
ser.write(bytearray("L1\r", "ascii"))
电路对这个命令没有反应。我觉得发送的消息把\r
当成了两个独立的字符,而不是一个回车符。我该如何确保我的代码输出的命令后面带有回车符呢?
备注:我可以合理地认为电路工作正常,树莓派的UART接口也能正常使用。这个电路是Atlas Scientific的溶解氧电路。电路的文档要求命令的格式为l1<cr>
或L1<CR>
。
相关链接:
旧示例代码(https://www.atlas-scientific.com/_files/code/pi_sample_code.pdf)
描述写入方法的文档(http://pyserial.sourceforge.net/pyserial_api.html#classes)
提前感谢!
编辑:Netch提到一个很重要的点:ser.write(b'L1\r')
可以正常工作,而且更简洁。不过这两种方法都能发送正确的'\r'序列。问题是电路仍然不把L1\r
视为有效命令。此时,我觉得我的问题可能与我的串口设置有关。
我的端口声明如下:
ser = serial.Serial(
port = '/dev/ttyAMA0',
baudrate = 38400,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
timeout = 1
)
这个端口声明是根据电路的数据手册进行的(不幸的是我只能发两个链接 :( 谷歌很容易找到)。
2 个回答
我找到了解决办法!!不过,我没法解释它是怎么工作的。也许在看这个的人可以详细讲讲,给个好解释!
这个电路的说明书要求命令的格式是 CMD<CR>
。确实,厂家提供的示例代码通过pyserial发送 L1
命令是这样写的:ser.write("L1\r")
。
不过,现在 ser.write()
需要的是字节格式,我发现 ser.write(b'L1\r')
不管用……命令虽然被接收了,但电路似乎不知道这个命令。
经过一番尝试,我发现 ser.write(b'\rL1\r')
可以正常工作!调试灯闪了一下红灯,然后就处理了这个命令。看起来我只需要发送一个“虚假命令”来引起电路的注意!
我不确定这是pyserial的问题,电路的问题,还是我自己的无知。如果有人能帮我解释一下,那就太好了!:D
我在这里附上了电路的说明书,感兴趣的可以看看。 https://www.atlas-scientific.com/_files/_datasheets/_circuit/DO_Circuit_5.0.pdf
[编辑] 为了让未来的观众知道,我想指出,对于新版本的EZO电路,命令是“L,1”或者实际上是“L,1\r”
这是一个已知的问题,电路在通电后第一次读取会失败。与其在每次读取前加一个\r,不如发送一个包含\r的无效命令,然后重置输入缓冲区。
ser.write('bogus\r'.encode()) # EDIT: had to add .encode() to get it to work. see https://stackoverflow.com/questions/22275079/pyserial-write-wont-take-my-string
ser.flushInput() # or for pyserial 3+ ser.reset_input_buffer()
#now do your thing
编辑:需要加上.encode()才能正常工作。请查看 pySerial write() 不接受我的字符串
在EZO™类电路通电后,如果它处于UART模式,第一次发送的命令会返回错误。这是因为UART缓冲区在通电时会显示它已经接收到一个字符。只需在电路通电后发送一个空字符,这样就可以清除缓冲区。