搜索
bottom↓
回复: 46

python做串口通信,对于高速数据流,感觉丢包很严重?[已解决]

[复制链接]

出0入0汤圆

发表于 2023-4-2 20:58:34 | 显示全部楼层 |阅读模式
本帖最后由 sy8501 于 2023-4-3 15:27 编辑

还没做深度优化,先来问问

用单片机50ms发送一次数据流,数据流10个字节。pyserial 基本上不丢。

间隔改为25ms,就有点吃力了。

再快就感觉更不好了。

====

2023 04 03 15:27 编辑:已解决

出200入2554汤圆

发表于 2023-4-2 21:44:46 来自手机 | 显示全部楼层
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包

当然也说明ch340够稳定

出0入71汤圆

发表于 2023-4-2 21:47:39 | 显示全部楼层
t3486784401 发表于 2023-4-2 21:44
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包

当然也说明ch340够稳定 ...
(引用自2楼)

确实CH340牛皮,疫情前测过,频率误差5%也可以做到115200bps 不丢包!

出1310入193汤圆

发表于 2023-4-2 21:58:04 来自手机 | 显示全部楼层
不提波特率和硬件数据抓取工具
猜一猜吗?

出0入0汤圆

 楼主| 发表于 2023-4-2 21:58:29 | 显示全部楼层
dellric 发表于 2023-4-2 21:47
确实CH340牛皮,疫情前测过,频率误差5%也可以做到115200bps 不丢包!
(引用自3楼)

CH340的名声,是被淘宝那些牛屎反相冒充232给搞臭的。

前2个月,我弄了一个CH340G 跑蓝牙串口, 跑1M也很稳定。

出0入0汤圆

 楼主| 发表于 2023-4-2 22:00:52 | 显示全部楼层
t3486784401 发表于 2023-4-2 21:44
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包

当然也说明ch340够稳定 ...
(引用自2楼)


C# 的
using System.IO.Ports 下的串口

也很稳定,我用了好多年,一个字节都没丢过。

出200入2554汤圆

发表于 2023-4-2 22:03:45 | 显示全部楼层
sy8501 发表于 2023-4-2 21:58
CH340的名声,是被淘宝那些牛屎反相冒充232给搞臭的。

前2个月,我弄了一个CH340G 跑蓝牙串口, 跑1M也 ...
(引用自5楼)


回到这个问题,目测 bug 是这样产生的:

PC 端为了效率,不能一直查询/访问接收缓冲区,因而有个“超时”的说法。
即在超时时间内,接收数据不再更新,才主动截断数据包进行处理。

python 底层也是 C 写的,目测会有类似的超时截断机制,然后这个超时时间若恰好位于 25ms-50ms 范围内,就可能出现 1L 所言故障。
50ms 间隔的数据包可以正确截断+处理,而 25ms 数据包没法准确截断,到头来不停拼接直至缓冲区溢出。

出0入0汤圆

 楼主| 发表于 2023-4-2 22:09:12 | 显示全部楼层
lb0857 发表于 2023-4-2 21:58
不提波特率和硬件数据抓取工具
猜一猜吗?
(引用自4楼)

115200 配 FT232 ,都是老司机了,这种低级错误不会犯的。

115200,常规配置下,10字节发送耗时0.955ms,没超过1ms。

====

即使是这年头没什么人用的9600,同样10个字节,9600发完需要11.5ms,25ms周期理论上也不应该丢。

出0入0汤圆

 楼主| 发表于 2023-4-2 22:11:31 | 显示全部楼层
t3486784401 发表于 2023-4-2 22:03
回到这个问题,目测 bug 是这样产生的:

PC 端为了效率,不能一直查询/访问接收缓冲区,因而有个“超时 ...
(引用自7楼)

貌似2011年时候,也用Delphi写过串口,丢包也是丢的一塌糊涂,用的第三方的串口库。

最后还是微软官方的最稳定。

出0入0汤圆

 楼主| 发表于 2023-4-2 22:13:40 | 显示全部楼层
t3486784401 发表于 2023-4-2 22:03
回到这个问题,目测 bug 是这样产生的:

PC 端为了效率,不能一直查询/访问接收缓冲区,因而有个“超时 ...
(引用自7楼)

pyserial 也是第三方的库

需要pip install 下载

出200入2554汤圆

发表于 2023-4-2 22:23:18 | 显示全部楼层
sy8501 发表于 2023-4-2 22:13
pyserial 也是第三方的库

需要pip install 下载
(引用自10楼)

那就看有没能调节的参数,类似超时的东西按理说应该设计成可调节。

出0入0汤圆

 楼主| 发表于 2023-4-2 22:25:12 | 显示全部楼层
t3486784401 发表于 2023-4-2 22:23
那就看有没能调节的参数,类似超时的东西按理说应该设计成可调节。
(引用自11楼)

timeout 有的调节。

后面我再精细的研究一下,做一下计数看看。

出0入25汤圆

发表于 2023-4-2 22:51:27 | 显示全部楼层

试试 https://github.com/XIVN1987/SERCOM 看会不会丢数据。。

出0入0汤圆

 楼主| 发表于 2023-4-2 23:48:47 | 显示全部楼层
XIVN1987 发表于 2023-4-2 22:51
试试 https://github.com/XIVN1987/SERCOM 看会不会丢数据。。
(引用自13楼)

兄弟你用的是什么编辑器

pycharm水土不服,一堆警告。

出0入0汤圆

 楼主| 发表于 2023-4-3 00:02:27 | 显示全部楼层
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

这两句 报错了

出0入71汤圆

发表于 2023-4-3 09:19:41 | 显示全部楼层
sy8501 发表于 2023-4-2 22:00
C# 的
using System.IO.Ports 下的串口

(引用自6楼)

都用C#了,怎么还用PYTHON?

出0入25汤圆

发表于 2023-4-3 09:29:07 | 显示全部楼层
sy8501 发表于 2023-4-2 23:48
兄弟你用的是什么编辑器

pycharm水土不服,一堆警告。
(引用自14楼)


我没用IDE,,就用了个编辑器,,sublime。。

出0入25汤圆

发表于 2023-4-3 09:31:34 | 显示全部楼层
sy8501 发表于 2023-4-3 00:02
我现在用的是
python3.10
pyserial 3.5
(引用自15楼)


是不是你的pyserial安装到了virtualenv里面,,像这种比较简单的包,,可以安装在主环境下。。

出0入17汤圆

发表于 2023-4-3 09:46:49 | 显示全部楼层
dellric 发表于 2023-4-2 21:47
确实CH340牛皮,疫情前测过,频率误差5%也可以做到115200bps 不丢包!
(引用自3楼)

你搞512000试试

出0入0汤圆

 楼主| 发表于 2023-4-3 09:51:48 | 显示全部楼层
dellric 发表于 2023-4-3 09:19
都用C#了,怎么还用PYTHON?
(引用自16楼)

如果自己做个上位机我是瞧不上Python的。

这个就是给客户做个例程。然后发现Python干这个性能不行。

出0入0汤圆

 楼主| 发表于 2023-4-3 09:53:33 | 显示全部楼层
zjykwym 发表于 2023-4-3 09:46
你搞512000试试
(引用自19楼)

接外部晶振的CH340G
1M一点问题都有。

不接晶振的悬。

出0入0汤圆

发表于 2023-4-3 11:23:45 | 显示全部楼层
我用 pyQT的串口库,跑4800,没出现什么异常,但是如果持续将大量数据从串口刷新到UI会有点吃力,尤其是数据累积大的时候,文本框就反应差了

出0入0汤圆

 楼主| 发表于 2023-4-3 11:31:10 | 显示全部楼层
duxingkei 发表于 2023-4-3 11:23
我用 pyQT的串口库,跑4800,没出现什么异常,但是如果持续将大量数据从串口刷新到UI会有点吃力,尤其是数 ...
(引用自22楼)

4800的波特率是太低了。

发送1个字节需要 2.3ms

发送完10个字节的数据流,需要23ms

出0入0汤圆

发表于 2023-4-3 11:44:52 来自手机 | 显示全部楼层
sy8501 发表于 2023-4-3 11:31
4800的波特率是太低了。

发送1个字节需要 2.3ms

(引用自23楼)

2011年还是python2.0时代就用pyserial做过串口程序,没怎么丢包

出0入0汤圆

 楼主| 发表于 2023-4-3 13:53:54 | 显示全部楼层
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还是不适合干这种活,毕竟效率摆在那。

出200入2554汤圆

发表于 2023-4-3 14:08:12 | 显示全部楼层
sy8501 发表于 2023-4-3 13:53
大概搞明白了。

串口那边应该没有丢包,但是因为python执行效率太低。如果在接收那边做了一些处理,添加 ...
(引用自25楼)

这下也放心了,大体上符合对高层语言的印象。

出40入518汤圆

发表于 2023-4-3 14:14:21 | 显示全部楼层
python注意多线程和多进程不一样!
另外,最简单测试方法可以用别人现有的python串口工具来测试对比一下,这样子比较容易判断是否自己代码不够好

出0入0汤圆

 楼主| 发表于 2023-4-3 14:23:13 | 显示全部楼层
t3486784401 发表于 2023-4-3 14:08
这下也放心了,大体上符合对高层语言的印象。
(引用自26楼)

我估计这个len() 数字节长度的函数,都要占用个1-2ms时间

出200入2554汤圆

发表于 2023-4-3 14:37:57 | 显示全部楼层
sy8501 发表于 2023-4-3 14:23
我估计这个len() 数字节长度的函数,都要占用个1-2ms时间
(引用自28楼)

估计有临界区代码,不过这也太没谱了。

我就算用 MFC,Release 版本也都是 us 这种时间量级

出0入8汤圆

发表于 2023-4-3 14:56:05 | 显示全部楼层
sy8501 发表于 2023-4-3 11:31
4800的波特率是太低了。

发送1个字节需要 2.3ms
(引用自23楼)

4800波特率,600字节每秒,不是一字节1.67ms吗?
我的算法有误?

出0入0汤圆

 楼主| 发表于 2023-4-3 15:19:30 | 显示全部楼层
rube 发表于 2023-4-3 14:56
4800波特率,600字节每秒,不是一字节1.67ms吗?
我的算法有误?
(引用自30楼)

串口里面一个字节是实际是 11bit,不是8bit

起始位1
数据8
校验位1
停止位1

一共11bit

出0入0汤圆

 楼主| 发表于 2023-4-3 15:23:04 | 显示全部楼层
t3486784401 发表于 2023-4-3 14:37
估计有临界区代码,不过这也太没谱了。

我就算用 MFC,Release 版本也都是 us 这种时间量级 ...
(引用自29楼)

找到问题了。

之前在数据发送完成的时候就直接把串口关掉了。也就是有末尾的数据还在排队的时候就被程序截掉了。

现在增加了1s的延迟关闭串口,数据就完整了。

现在串口没丢数据了。

用的460800波特率,1ms送出去10个字节,完整的接收了。

===

结帖。

出0入0汤圆

 楼主| 发表于 2023-4-3 15:35:50 | 显示全部楼层
    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个字节的无丢包接收

等下看看再添加一些处理代码,会不会溢出。

出0入0汤圆

 楼主| 发表于 2023-4-3 16:29:40 | 显示全部楼层
现在策略是,先把所有串口数据保存下来。

串口接收结束后,再进行10字节10字节的拆分,再解包。

可以做到1kHz的发送频率,并完整接收了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2023-4-3 16:37:28 | 显示全部楼层
收工

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出615入1076汤圆

发表于 2023-4-3 18:14:12 来自手机 | 显示全部楼层
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包

不要用 readline,它要解释字符串 utf8 编码之类的

要读 bytes 格式裸数据

我的代码:
https://github.com/dukelec/pycdn ... dev/cdbus_serial.py

出0入71汤圆

发表于 2023-4-3 19:43:10 | 显示全部楼层
zjykwym 发表于 2023-4-3 09:46
你搞512000试试
(引用自19楼)

没搞过那么高的,难道有坑吗?说来分享一下,谢谢!

出20入25汤圆

发表于 2023-4-3 20:29:31 来自手机 | 显示全部楼层
dukelec 发表于 2023-4-3 18:14
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包


(引用自36楼)

matlab
呢,用来画图总有点卡

出0入0汤圆

 楼主| 发表于 2023-4-3 23:46:10 | 显示全部楼层
dukelec 发表于 2023-4-3 18:14
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包

(引用自36楼)

感谢提醒。

现在改用read(10)

比readline好用。

出0入0汤圆

 楼主| 发表于 2023-4-4 00:32:26 | 显示全部楼层
经36L提醒,改用read(10)之后,
现在接收线程里面有这些东西,
还可以做到 每间隔3ms 发送10字节 不丢包,
把print干掉的话,应该能更快。

刚开始最大的问题可能是在接收线程里面去写csv文件,导致时间拖的比较久



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2023-4-4 00:44:14 | 显示全部楼层
去掉print 没啥用,依旧只能3ms一次,做不到2ms一次。

出0入0汤圆

 楼主| 发表于 2023-4-4 00:53:37 | 显示全部楼层
如果不需要处理,纯数据接收的话

还是readall()效率最高

轻轻松松1ms



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入17汤圆

发表于 2023-4-4 08:59:45 | 显示全部楼层
dellric 发表于 2023-4-3 19:43
没搞过那么高的,难道有坑吗?说来分享一下,谢谢!
(引用自37楼)

没带外部晶振的ch340,频偏太大,高速率数据错了。

出0入0汤圆

发表于 2023-4-4 11:04:10 | 显示全部楼层
sy8501 发表于 2023-4-3 15:19
串口里面一个字节是实际是 11bit,不是8bit

起始位1
(引用自31楼)

哈哈哈,确实,大概2ms  ,一个起始位,一个停止位,无校验,8个位数据 ,共10bit
不敢跑太高,也没必要太高。稳定第一

出0入0汤圆

发表于 2023-4-4 11:05:51 | 显示全部楼层
sy8501 发表于 2023-4-3 15:23
找到问题了。

之前在数据发送完成的时候就直接把串口关掉了。也就是有末尾的数据还在排队的时候就被程序 ...
(引用自32楼)

我也出现这种情况,就是处理数据耗时,导致来的数据丢了,或者延长错乱。
也是删掉无用代码,尤其是涉及UI更新和print之类的打印函数后,运行稳定.

出0入0汤圆

 楼主| 发表于 2023-4-4 13:00:06 | 显示全部楼层
duxingkei 发表于 2023-4-4 11:04
哈哈哈,确实,大概2ms  ,一个起始位,一个停止位,无校验,8个位数据 ,共10bit
不敢跑太高,也没必要 ...
(引用自44楼)

虽然选的无校验,但也是要占一个bit

所以是11bit

出0入4汤圆

发表于 2023-5-25 20:07:26 | 显示全部楼层
本帖最后由 acmilannast 于 2023-5-25 20:10 编辑

pyserial  串口 1Mbps  完全可以跑满波特率 收发。 serialwin32.py文件进去看看 就知道 肯定没问题,直接调用的是 win32.ReadFile、win32.WriteFile 。  用c语言不知道怎么写串口 就按照serialwin32.py 里的代码,同样c代码也可以跑满波特率。(硬件:ftdi ft232rl 交叉外接)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 13:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表