💖 作者简介:大家好,我是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
猜你想看:
【pyqt、mysql、爬虫】新冠疫情信息管理系统(详细图文)总结两种最常用的python打包方式Python最佳实践-构建自己的第三方库【broadcast-service】一个轻量级Python发布订阅者框架