![](/img/trans.png)
[英]Using Pyserial to plot time against voltage from an Arduino Serial Port
[英]How to decode information from the serial port using arduino and pyserial
我想读取通过 Arduino 串口发送的信息。为此,我使用 pyserial,初始化端口,然后尝试读取信息。
这是 Arduino 代码
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("1");
}
这是 python 代码
import serial
ComPort = "com3"
try:
SerialComs = serial.Serial(ComPort, 9600) # Intializes the Com port
except:
pass
while True:
for i in range(1):
data = 0
value = SerialComs.readline()
print(value)
我得到的 output 是这样的:
b'1\r\n'
为了只得到我想要的数字 1,我尝试了这个:
import serial
ComPort = "com3"
try:
SerialComs = serial.Serial(ComPort, 9600) # Intializes the Com port
except:
pass
while True:
for i in range(1):
data = 0
value = int(SerialComs.readline().decode('ascii'))
print(value)
但我得到这个错误
UnicodeDecodeError:“ascii”编解码器无法解码 position 中的字节 0xb1 0:序号不在范围内(128)
我该怎么做才能只从串口获取号码?
快速的答案是将errors='ignore'
添加到您的解码行。 例如
value = SerialComs.readline().decode(encoding='ascii', errors='ignore')
由于读取行中的 ASCII 字符无效,这将阻止代码退出并出现错误。
当您转换为 integer 时,这仍然会出错,因为字符串中会有无效内容,因此您需要检查您的内容是否为数字。 例如
readline_data0 = [b"\x00\x00\xf01\r\n",
b"1\r\n",
b"1\r\n",
b"1\r\n"]
for line in readline_data0:
txt = "".join(
[x for x in line.decode(encoding="ascii", errors="ignore") if x.isdigit()]
)
value = int(txt)
print(value)
会给 output:
1
1
1
1
如果您不确定串行端口上输入的是什么,这可能很容易出错。
为缓解此问题,来自 Arduino 的更详细的消息将有助于确定哪些是预期数据。 例如,如果来自 Aruino 的消息基于逗号分隔值,它可能看起来像: Serial.println(",sensor1,1,");
如何从序列内容中轻松提取的示例:
readline_data1 = [b"\x00\x00\xf0,sensor1,1,\r\n",
b",sensor1,1,\r\n",
b",sensor1,1,\r\n",
b",sensor1,1,\r\n"]
def get_sensor_value(sensor_name, ascii_data):
fields = ascii_data.split(',')
sensor_loc = fields.index(sensor_name) + 1
return int(fields[sensor_loc])
for line in readline_data1:
txt = line.decode(encoding="ascii", errors="ignore")
value = get_sensor_value('sensor1', txt)
print(value)
其中给出了 output:
1
1
1
1
这还有一个好处,即它可以扩展为从多个传感器发送数据,因为这些值可以与特定传感器相关联。
readline_data1 = [b"\x00\x00\xf0,sensor1,1,\r\n",
b",sensor1,1,sensor3,3,\r\n",
b",sensor2,2,\r\n",
b",sensor1,1,\r\n"]
def get_sensor_value(sensor_name, ascii_data):
fields = ascii_data.split(',')
if sensor_name not in fields:
return
sensor_loc = fields.index(sensor_name) + 1
return int(fields[sensor_loc])
for line in readline_data1:
txt = line.decode(encoding="ascii", errors="ignore")
for check_sensor in ['sensor1', 'sensor2', 'sensor3']:
value = get_sensor_value(check_sensor, txt)
if value:
print(f"{check_sensor} = {value}")
其中给出了 output:
sensor1 = 1
sensor1 = 1
sensor3 = 3
sensor2 = 2
sensor1 = 1
如果所有行都是int
,那么您需要一些步骤:
value = SerialComs.readline()
value = value.decode() # convert from bytes -> str
value = value.strip() # remove line endings
value = int(value) # convert str -> in
print(value)
一站式完成:
value = int(SerialComs.readline().decode().strip())
print(value)
如果您在将非 ascii 字节输入序列号 stream 时遇到问题,则必须将它们过滤掉:
value = bytes([v for v in SerialComs.readline() if v in range(1,127)])
value = int(value.decode().strip())
print(value)
Andrés,根据您对@quamrana 回答的评论,关于字节序列: b'\x00\x00\xf01\r\n'
,在我看来, \x00\x00\xf0
是以某种方式产生的虚假字节进入串行数据 stream,可能是数据线上的噪声。
如果在 Arduino 上,您只运行了Serial.println("1");
如你所说,那么由"1\r\n"
表示的3个字节应该是通过串行数据stream发送的唯一字节。
我可能会检查是否有任何松动的电线/连接、接地问题,或者尝试使用不同的电缆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.