- 💖 作者简介:大家好,我是Zeeland,全栈领域优质创作者。
- 📝 CSDN主页:Zeeland🔥
- 📣 我的博客:Zeeland
- 📚 Github主页: Undertone0809 (Zeeland) (github.com)
- 🎉 支持我:点赞👍+收藏⭐️+留言📝
- 💬介绍:The mixture of software dev+Iot+ml+anything🔥
1. 概况
Python中Serial在读取数据的时候具有几种方法,本文将简单介绍一下如何使用serial库解析串口的数据。
2. 介绍
本文需要用到的几种方法和属性,大概看看就好,主要看下面的教程如何使用。
方法 | 功能 |
---|---|
serial.read(size) | 读取size字节的数据 |
serial.readline() | 读取一行的数据 |
serial.readlines() | 读取多行的数据,将数据保存到数组里 |
serial.read_all() | 读取一个timeout周期内的全部数据(常用方法) |
serial.read_all | 读取串口所有的参数信息 |
serial_timeout(参数) | 超时属性,下面具体介绍 |
3. 快速上手
-
下面的场景我们需要用用COM4串口发送一串字符串
"hello world"
,波特率9600,如何使用python的serial
库进行解析串口发送来的数据? -
直接上代码
import serial
ser = serial.Serial("COM2", 9600, timeout=0.01)
while True:
data = ser.read_all()
if data:
rec_str = data.decode('utf-8')
print(rec_str)
- 这里我创建了两个虚拟的串口进行模拟,COM2向COM1发送了两次
hello world
,而Python端实现了COM1,监听来自COM2的消息,用read_all()
方法读取接收到的数据,接收到的数据类型是bytes
类型的,因此我们需要将bytes
数组转成字符串print出来,如下图所示。
-
而初始化的时候这里的
timeout
是指在设定的timeout
时间范围内,如果读取的字节数据是有效的(就是非空)那就直接返回,否则一直会等到这个设定的timeout时间并返回这段时间所读的全部字节数据。 -
简单来说你可以理解为每
timeout
秒读一次数据,而如果timeout
太小,数据量太大,可能一次发送不完,会数据未读完的状态。 -
也就是说,如果我的timeout设置为0.01,现在我有一个串口通信的传感器,传感器通过串口使用COM2发送一次数据,传感器如果在0.01秒内将所有数据都传输过来,就保存到缓存
buffer
中,到了0.01秒后会调用一次read_all()
就可以读取到传感器发送到buffer
中的数据了;如果传感器在0.01秒内没有将数据发送全的话,buffer
中的数据就是不完全的,就会返回不完全的数据;如果传感器在0.01秒内发送了数据的话,buffer
也会返回两组合在一起的数据。
注意:timeout的设置至关重要,如果不是特别高频的数据的话,timeout=0.01的100Hz完全够了,当然timeout最小支持多少要看你的波特率。如果我0.3秒发送了一次数据,timeout设置0.01,就可以返回一次完整的数据;如果我0.01秒发送一次数据,timeout设置0.3,那么一次就会返回30次数据,所以这就是timeout的作用。
- 前面引入了
buffer
的概念,这里你应该可以知道,你可以直接把buffer
理解为一个文件夹,读数据的方式是和file
是一样的,只是引入的timeout
的概念,使得buffer
内的数据会以1/timeout
的频率进行刷新。 - 如果你把
buffer
当做file
理解,那么readline()
就是读取buffer中的一行,如果你的数据中存在\n
这样的换行,那么用readline()
先让不合适,很容易产生漏读的问题,而且如果你在一个timeout
周期内没有用readline()
处理完所有你想要的数据的话,buffer
就刷新了,因此通过笔者的实践和项目经历读数据只推荐用read_all()
来读取。
4. 更好的解决方案——cushy-serial
cushy-serial是一个轻量级的Serial框架,初衷是希望使Serial编程变得更加简单、快捷,因此,相较于传统的pyserial,该框架可以更加快速地构建起一个serial程序,其可以兼容pyserial的所有特性,并且自定义serial消息异步回调,无需花费精力在多线程上,项目地址:https://github.com/Undertone0809/cushy-serial
主要特性
- 兼容pyserial的所有特性
- 自定义serial消息异步回调,无需花费精力在多线程上
- 提供串口定时任务
- 方便实现和管理多个serial连接
- 可自定义消息协议,兼容性强
快速上手
pip install cushy-serial --upgrade
- 下面是一个简单的serial程序,当python客户端接收到来自串口的信息时会自动回调
from cushy_serial import CushySerial
serial = CushySerial("COM1", 9600)
serial.send("I am python client")
@serial.on_message()
def handle_serial_message(msg: bytes):
str_msg = msg.decode("utf-8")
print(f"[serial] rec msg: {str_msg}")
需要说明的是,CushySerial兼容了Serial中所有的功能,因此,你可以在CushySerial中使用Serial的所有功能。
- 运行结果如下
- 如果你想要执行定时任务,
CushySerial
也提供了相关的解决方案,你可以方便的轮询发送指令,并获取来自串口的信息,示例如下:
from cushy_serial import CushySerial, enable_log
enable_log()
serial = CushySerial("COM1", 9600)
instruction = bytes([0x01, 0x06, 0x00, 0x7F, 0x00, 0x01, 0x79, 0xD2])
# msg为你要轮询发送的指令,interval为轮询的时间间隔,times为执行次数,可不填写
@serial.polling_task(msg=instruction, interval=0.5, times=5)
def handle_rec_msg(rec_msg):
print(f"[serial] rec polling message: {rec_msg}")
5. 总结
- 在平时串口通信中,最好使用
read_all()
方法,并选定合适的timeout。 - timeout的参考资料:相关链接
- 要是懒一点就直接用cushy-serial
猜你想看: