sy8501 发表于 2023-4-2 20:58:34

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

本帖最后由 sy8501 于 2023-4-3 15:27 编辑

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

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

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

再快就感觉更不好了。

====

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

t3486784401 发表于 2023-4-2 21:44:46

用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包

当然也说明ch340够稳定

dellric 发表于 2023-4-2 21:47:39

t3486784401 发表于 2023-4-2 21:44
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包

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

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

lb0857 发表于 2023-4-2 21:58:04

不提波特率和硬件数据抓取工具
猜一猜吗?

sy8501 发表于 2023-4-2 21:58:29

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

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

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

sy8501 发表于 2023-4-2 22:00:52

t3486784401 发表于 2023-4-2 21:44
用 win32 api 做过,单片机115.2kbps连续发包不间断,可以送出去MB不丢包

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

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

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

t3486784401 发表于 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 数据包没法准确截断,到头来不停拼接直至缓冲区溢出。

sy8501 发表于 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周期理论上也不应该丢。

sy8501 发表于 2023-4-2 22:11:31

t3486784401 发表于 2023-4-2 22:03
回到这个问题,目测 bug 是这样产生的:

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

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

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

sy8501 发表于 2023-4-2 22:13:40

t3486784401 发表于 2023-4-2 22:03
回到这个问题,目测 bug 是这样产生的:

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

pyserial 也是第三方的库

需要pip install 下载

t3486784401 发表于 2023-4-2 22:23:18

sy8501 发表于 2023-4-2 22:13
pyserial 也是第三方的库

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

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

sy8501 发表于 2023-4-2 22:25:12

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

timeout 有的调节。

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

XIVN1987 发表于 2023-4-2 22:51:27


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

sy8501 发表于 2023-4-2 23:48:47

XIVN1987 发表于 2023-4-2 22:51
试试 https://github.com/XIVN1987/SERCOM 看会不会丢数据。。
(引用自13楼)

兄弟你用的是什么编辑器

pycharm水土不服,一堆警告。

sy8501 发表于 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

这两句 报错了

dellric 发表于 2023-4-3 09:19:41

sy8501 发表于 2023-4-2 22:00
C# 的
using System.IO.Ports 下的串口

(引用自6楼)

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

XIVN1987 发表于 2023-4-3 09:29:07

sy8501 发表于 2023-4-2 23:48
兄弟你用的是什么编辑器

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


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

XIVN1987 发表于 2023-4-3 09:31:34

sy8501 发表于 2023-4-3 00:02
我现在用的是
python3.10
pyserial 3.5
(引用自15楼)


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

zjykwym 发表于 2023-4-3 09:46:49

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

你搞512000试试{:sad:}

sy8501 发表于 2023-4-3 09:51:48

dellric 发表于 2023-4-3 09:19
都用C#了,怎么还用PYTHON?
(引用自16楼)

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

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

sy8501 发表于 2023-4-3 09:53:33

zjykwym 发表于 2023-4-3 09:46
你搞512000试试
(引用自19楼)

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

不接晶振的悬。

duxingkei 发表于 2023-4-3 11:23:45

我用 pyQT的串口库,跑4800,没出现什么异常,但是如果持续将大量数据从串口刷新到UI会有点吃力,尤其是数据累积大的时候,文本框就反应差了

sy8501 发表于 2023-4-3 11:31:10

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

4800的波特率是太低了。

发送1个字节需要 2.3ms

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

doubleforever1 发表于 2023-4-3 11:44:52

sy8501 发表于 2023-4-3 11:31
4800的波特率是太低了。

发送1个字节需要 2.3ms

(引用自23楼)

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

sy8501 发表于 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还是不适合干这种活,毕竟效率摆在那。

t3486784401 发表于 2023-4-3 14:08:12

sy8501 发表于 2023-4-3 13:53
大概搞明白了。

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

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

智涅 发表于 2023-4-3 14:14:21

python注意多线程和多进程不一样!
另外,最简单测试方法可以用别人现有的python串口工具来测试对比一下,这样子比较容易判断是否自己代码不够好

sy8501 发表于 2023-4-3 14:23:13

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

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

t3486784401 发表于 2023-4-3 14:37:57

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

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

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

rube 发表于 2023-4-3 14:56:05

sy8501 发表于 2023-4-3 11:31
4800的波特率是太低了。

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

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

sy8501 发表于 2023-4-3 15:19:30

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

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

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

一共11bit

sy8501 发表于 2023-4-3 15:23:04

t3486784401 发表于 2023-4-3 14:37
估计有临界区代码,不过这也太没谱了。

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

找到问题了。

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

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

现在串口没丢数据了。

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

===

结帖。

sy8501 发表于 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个字节的无丢包接收

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

sy8501 发表于 2023-4-3 16:29:40

现在策略是,先把所有串口数据保存下来。

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

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

sy8501 发表于 2023-4-3 16:37:28

收工

dukelec 发表于 2023-4-3 18:14:12

python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包

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

要读 bytes 格式裸数据

我的代码:
https://github.com/dukelec/pycdnet/blob/master/cdnet/dev/cdbus_serial.py

dellric 发表于 2023-4-3 19:43:10

zjykwym 发表于 2023-4-3 09:46
你搞512000试试
(引用自19楼)

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

chenchaoting 发表于 2023-4-3 20:29:31

dukelec 发表于 2023-4-3 18:14
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包


(引用自36楼)

matlab
呢,用来画图总有点卡

sy8501 发表于 2023-4-3 23:46:10

dukelec 发表于 2023-4-3 18:14
python 没这么弱
我用 10Mbps 的 485,实时传摄象头画面都不会丢包

(引用自36楼)

感谢提醒。

现在改用read(10)

比readline好用。

sy8501 发表于 2023-4-4 00:32:26

经36L提醒,改用read(10)之后,
现在接收线程里面有这些东西,
还可以做到 每间隔3ms 发送10字节 不丢包,
把print干掉的话,应该能更快。

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



sy8501 发表于 2023-4-4 00:44:14

去掉print 没啥用,依旧只能3ms一次,做不到2ms一次。

sy8501 发表于 2023-4-4 00:53:37

如果不需要处理,纯数据接收的话

还是readall()效率最高

轻轻松松1ms



zjykwym 发表于 2023-4-4 08:59:45

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

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

duxingkei 发表于 2023-4-4 11:04:10

sy8501 发表于 2023-4-3 15:19
串口里面一个字节是实际是 11bit,不是8bit

起始位1
(引用自31楼)

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

duxingkei 发表于 2023-4-4 11:05:51

sy8501 发表于 2023-4-3 15:23
找到问题了。

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

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

sy8501 发表于 2023-4-4 13:00:06

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

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

所以是11bit

acmilannast 发表于 2023-5-25 20:07:26

本帖最后由 acmilannast 于 2023-5-25 20:10 编辑

pyserial串口 1Mbps完全可以跑满波特率 收发。 serialwin32.py文件进去看看 就知道 肯定没问题,直接调用的是 win32.ReadFile、win32.WriteFile 。用c语言不知道怎么写串口 就按照serialwin32.py 里的代码{:titter:}{:titter:}{:titter:},同样c代码也可以跑满波特率。(硬件:ftdi ft232rl 交叉外接)
页: [1]
查看完整版本: python做串口通信,对于高速数据流,感觉丢包很严重?[已解决]