python做串口通信,对于高速数据流,感觉丢包很严重?[已解决]
本帖最后由 sy8501 于 2023-4-3 15:27 编辑还没做深度优化,先来问问
用单片机50ms发送一次数据流,数据流10个字节。pyserial 基本上不丢。
间隔改为25ms,就有点吃力了。
再快就感觉更不好了。
====
2023 04 03 15:27 编辑:已解决 用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包
当然也说明ch340够稳定 t3486784401 发表于 2023-4-2 21:44
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包
当然也说明ch340够稳定 ...
(引用自2楼)
确实CH340牛皮,疫情前测过,频率误差5%也可以做到115200bps 不丢包! 不提波特率和硬件数据抓取工具
猜一猜吗? dellric 发表于 2023-4-2 21:47
确实CH340牛皮,疫情前测过,频率误差5%也可以做到115200bps 不丢包!
(引用自3楼)
CH340的名声,是被淘宝那些牛屎反相冒充232给搞臭的。
前2个月,我弄了一个CH340G 跑蓝牙串口, 跑1M也很稳定。
t3486784401 发表于 2023-4-2 21:44
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包
当然也说明ch340够稳定 ...
(引用自2楼)
C# 的
using System.IO.Ports 下的串口
也很稳定,我用了好多年,一个字节都没丢过。
sy8501 发表于 2023-4-2 21:58
CH340的名声,是被淘宝那些牛屎反相冒充232给搞臭的。
前2个月,我弄了一个CH340G 跑蓝牙串口, 跑1M也 ...
(引用自5楼)
回到这个问题,目测 bug 是这样产生的:
PC 端为了效率,不能一直查询/访问接收缓冲区,因而有个“超时”的说法。
即在超时时间内,接收数据不再更新,才主动截断数据包进行处理。
python 底层也是 C 写的,目测会有类似的超时截断机制,然后这个超时时间若恰好位于 25ms-50ms 范围内,就可能出现 1L 所言故障。
50ms 间隔的数据包可以正确截断+处理,而 25ms 数据包没法准确截断,到头来不停拼接直至缓冲区溢出。
lb0857 发表于 2023-4-2 21:58
不提波特率和硬件数据抓取工具
猜一猜吗?
(引用自4楼)
115200 配 FT232 ,都是老司机了,这种低级错误不会犯的。
115200,常规配置下,10字节发送耗时0.955ms,没超过1ms。
====
即使是这年头没什么人用的9600,同样10个字节,9600发完需要11.5ms,25ms周期理论上也不应该丢。 t3486784401 发表于 2023-4-2 22:03
回到这个问题,目测 bug 是这样产生的:
PC 端为了效率,不能一直查询/访问接收缓冲区,因而有个“超时 ...
(引用自7楼)
貌似2011年时候,也用Delphi写过串口,丢包也是丢的一塌糊涂,用的第三方的串口库。
最后还是微软官方的最稳定。
t3486784401 发表于 2023-4-2 22:03
回到这个问题,目测 bug 是这样产生的:
PC 端为了效率,不能一直查询/访问接收缓冲区,因而有个“超时 ...
(引用自7楼)
pyserial 也是第三方的库
需要pip install 下载
sy8501 发表于 2023-4-2 22:13
pyserial 也是第三方的库
需要pip install 下载
(引用自10楼)
那就看有没能调节的参数,类似超时的东西按理说应该设计成可调节。 t3486784401 发表于 2023-4-2 22:23
那就看有没能调节的参数,类似超时的东西按理说应该设计成可调节。
(引用自11楼)
timeout 有的调节。
后面我再精细的研究一下,做一下计数看看。
试试 https://github.com/XIVN1987/SERCOM 看会不会丢数据。。 XIVN1987 发表于 2023-4-2 22:51
试试 https://github.com/XIVN1987/SERCOM 看会不会丢数据。。
(引用自13楼)
兄弟你用的是什么编辑器
pycharm水土不服,一堆警告。
XIVN1987 发表于 2023-4-2 22:51
试试 https://github.com/XIVN1987/SERCOM 看会不会丢数据。。
(引用自13楼)
我现在用的是
python3.10
pyserial 3.5
from serial import Serial
from serial.tools.list_ports import comports
这两句 报错了
sy8501 发表于 2023-4-2 22:00
C# 的
using System.IO.Ports 下的串口
(引用自6楼)
都用C#了,怎么还用PYTHON? sy8501 发表于 2023-4-2 23:48
兄弟你用的是什么编辑器
pycharm水土不服,一堆警告。
(引用自14楼)
我没用IDE,,就用了个编辑器,,sublime。。 sy8501 发表于 2023-4-3 00:02
我现在用的是
python3.10
pyserial 3.5
(引用自15楼)
是不是你的pyserial安装到了virtualenv里面,,像这种比较简单的包,,可以安装在主环境下。。 dellric 发表于 2023-4-2 21:47
确实CH340牛皮,疫情前测过,频率误差5%也可以做到115200bps 不丢包!
(引用自3楼)
你搞512000试试{:sad:} dellric 发表于 2023-4-3 09:19
都用C#了,怎么还用PYTHON?
(引用自16楼)
如果自己做个上位机我是瞧不上Python的。
这个就是给客户做个例程。然后发现Python干这个性能不行。 zjykwym 发表于 2023-4-3 09:46
你搞512000试试
(引用自19楼)
接外部晶振的CH340G
1M一点问题都有。
不接晶振的悬。
我用 pyQT的串口库,跑4800,没出现什么异常,但是如果持续将大量数据从串口刷新到UI会有点吃力,尤其是数据累积大的时候,文本框就反应差了 duxingkei 发表于 2023-4-3 11:23
我用 pyQT的串口库,跑4800,没出现什么异常,但是如果持续将大量数据从串口刷新到UI会有点吃力,尤其是数 ...
(引用自22楼)
4800的波特率是太低了。
发送1个字节需要 2.3ms
发送完10个字节的数据流,需要23ms
sy8501 发表于 2023-4-3 11:31
4800的波特率是太低了。
发送1个字节需要 2.3ms
(引用自23楼)
2011年还是python2.0时代就用pyserial做过串口程序,没怎么丢包 t3486784401 发表于 2023-4-2 22:23
那就看有没能调节的参数,类似超时的东西按理说应该设计成可调节。
(引用自11楼)
大概搞明白了。
串口那边应该没有丢包,但是因为python执行效率太低。如果在接收那边做了一些处理,添加一些函数,处理时间就会过长导致串口缓存溢出,造成丢包。
现在删的只剩下这一小段了,用来接收计数
while True:
data_rxs = COMx.readlines()
if data_rxs:
for data_rx in data_rxs:
receive_byte_cnt += len(data_rx)
同样是10字节,115200波特率,目前最快只能做到4ms单片机发送周期才能保证不丢
改成3ms的话,就丢的一塌糊涂了。
所以python还是不适合干这种活,毕竟效率摆在那。
sy8501 发表于 2023-4-3 13:53
大概搞明白了。
串口那边应该没有丢包,但是因为python执行效率太低。如果在接收那边做了一些处理,添加 ...
(引用自25楼)
这下也放心了,大体上符合对高层语言的印象。 python注意多线程和多进程不一样!
另外,最简单测试方法可以用别人现有的python串口工具来测试对比一下,这样子比较容易判断是否自己代码不够好 t3486784401 发表于 2023-4-3 14:08
这下也放心了,大体上符合对高层语言的印象。
(引用自26楼)
我估计这个len() 数字节长度的函数,都要占用个1-2ms时间 {:sweat:}
sy8501 发表于 2023-4-3 14:23
我估计这个len() 数字节长度的函数,都要占用个1-2ms时间
(引用自28楼)
估计有临界区代码,不过这也太没谱了。
我就算用 MFC,Release 版本也都是 us 这种时间量级 sy8501 发表于 2023-4-3 11:31
4800的波特率是太低了。
发送1个字节需要 2.3ms
(引用自23楼)
4800波特率,600字节每秒,不是一字节1.67ms吗?
我的算法有误? rube 发表于 2023-4-3 14:56
4800波特率,600字节每秒,不是一字节1.67ms吗?
我的算法有误?
(引用自30楼)
串口里面一个字节是实际是 11bit,不是8bit
起始位1
数据8
校验位1
停止位1
一共11bit
t3486784401 发表于 2023-4-3 14:37
估计有临界区代码,不过这也太没谱了。
我就算用 MFC,Release 版本也都是 us 这种时间量级 ...
(引用自29楼)
找到问题了。
之前在数据发送完成的时候就直接把串口关掉了。也就是有末尾的数据还在排队的时候就被程序截掉了。
现在增加了1s的延迟关闭串口,数据就完整了。
现在串口没丢数据了。
用的460800波特率,1ms送出去10个字节,完整的接收了。
===
结帖。
while True:
data_rxs = COMx.readlines()
if data_rxs:
for data_rx in data_rxs:
receive_byte += data_rx
receive_byte_cnt += len(data_rx)
现在串口接收程序里面只有这几句,已经可以做到单片机每隔1ms发送10个字节的无丢包接收
等下看看再添加一些处理代码,会不会溢出。
现在策略是,先把所有串口数据保存下来。
串口接收结束后,再进行10字节10字节的拆分,再解包。
可以做到1kHz的发送频率,并完整接收了。
收工
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包
不要用 readline,它要解释字符串 utf8 编码之类的
要读 bytes 格式裸数据
我的代码:
https://github.com/dukelec/pycdnet/blob/master/cdnet/dev/cdbus_serial.py zjykwym 发表于 2023-4-3 09:46
你搞512000试试
(引用自19楼)
没搞过那么高的,难道有坑吗?说来分享一下,谢谢! dukelec 发表于 2023-4-3 18:14
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包
(引用自36楼)
matlab
呢,用来画图总有点卡 dukelec 发表于 2023-4-3 18:14
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包
(引用自36楼)
感谢提醒。
现在改用read(10)
比readline好用。
经36L提醒,改用read(10)之后,
现在接收线程里面有这些东西,
还可以做到 每间隔3ms 发送10字节 不丢包,
把print干掉的话,应该能更快。
刚开始最大的问题可能是在接收线程里面去写csv文件,导致时间拖的比较久
去掉print 没啥用,依旧只能3ms一次,做不到2ms一次。 如果不需要处理,纯数据接收的话
还是readall()效率最高
轻轻松松1ms
dellric 发表于 2023-4-3 19:43
没搞过那么高的,难道有坑吗?说来分享一下,谢谢!
(引用自37楼)
没带外部晶振的ch340,频偏太大,高速率数据错了。 sy8501 发表于 2023-4-3 15:19
串口里面一个字节是实际是 11bit,不是8bit
起始位1
(引用自31楼)
哈哈哈,确实,大概2ms,一个起始位,一个停止位,无校验,8个位数据 ,共10bit
不敢跑太高,也没必要太高。稳定第一 sy8501 发表于 2023-4-3 15:23
找到问题了。
之前在数据发送完成的时候就直接把串口关掉了。也就是有末尾的数据还在排队的时候就被程序 ...
(引用自32楼)
我也出现这种情况,就是处理数据耗时,导致来的数据丢了,或者延长错乱。
也是删掉无用代码,尤其是涉及UI更新和print之类的打印函数后,运行稳定. duxingkei 发表于 2023-4-4 11:04
哈哈哈,确实,大概2ms,一个起始位,一个停止位,无校验,8个位数据 ,共10bit
不敢跑太高,也没必要 ...
(引用自44楼)
虽然选的无校验,但也是要占一个bit
所以是11bit
本帖最后由 acmilannast 于 2023-5-25 20:10 编辑
pyserial串口 1Mbps完全可以跑满波特率 收发。 serialwin32.py文件进去看看 就知道 肯定没问题,直接调用的是 win32.ReadFile、win32.WriteFile 。用c语言不知道怎么写串口 就按照serialwin32.py 里的代码{:titter:}{:titter:}{:titter:},同样c代码也可以跑满波特率。(硬件:ftdi ft232rl 交叉外接)
页:
[1]