Python:使用PySerial发送状态位和时间戳的最佳方式是什么

0 投票
2 回答
2081 浏览
提问于 2025-04-16 07:53

我搜索和阅读了很多内容,但还没有找到一个明确的答案。我正在制作一个Python应用程序,它会通过串口与另一个应用程序进行通信。我使用了PySerial来实现这个功能。我想发送的数据包类型包括状态信息和数据读数。

我打算将我的数据包格式设计成这样:

[ Start Byte ][ Length ][ Message ][ End Byte ][ Checksum ]

不过我觉得我不需要结束字节,因为里面已经有长度信息了。我这样想对吗?

我考虑将数据包中的“消息”部分设计成状态信息,像这样:

[ MsgTypeID ][ PacketID ][ Status Bits ][ Timestamp ]

这里的消息ID只是用来区分这是一个状态包,而不是数据包。状态信息本身由16位组成,表示发送应用程序中多个子系统的状态。对于某些子系统,一个位就能提供足够的信息('0'表示子系统关闭/低/假,'1'表示开启/高/真)。其他的子系统可能需要2或3个位来表示状态等。为了原型测试,我只是简单地将这些位拼接成一个字符串,比如'1001110101101100',然后通过串口发送出去,校验和是状态位的模256。

我对Python和串口通信还很陌生,但我知道这样可能会浪费带宽。我知道PySerial需要发送字符串,但像这样将每个位表示为'0'或'1',实际上是为每个位都使用了完整的字符串表示。我在想,有什么更好的方法可以发送这些位,以减少带宽的使用呢?

比如,我是否可以将每8个位转换成十六进制,然后发送拼接的十六进制字节,像这样:

'10011101' + '01101100'

表示为

'\x9d' + '\x6c'

或者我应该将它们作为ASCII发送?我还看到有人提到Struct模块。我是否应该走这条路呢?

我还在想如何表示消息中的时间戳部分。

如果你能给我一些帮助或建议,我将非常感激。

非常感谢 :)

2 个回答

0

你打算多频繁地发送这些更新呢?如果你发送更新的频率乘以消息的长度,远远小于串口连接的数据传输速度,那就没必要太担心数据编码的效率了。其实你甚至可以考虑把内容弄得更容易让人看懂,特别是在你刚开始的时候。

0

显然,每发送一个字符需要一个字节,所以如果你能把数据编码成ASCII字符串(在Python 2中是str,在Python 3中是bytes),那就是最有效的方式。

struct模块绝对是个好主意:它可以把Python的数据打包成字符串(然后在另一端解包)。这对于你的时间戳是有效的;你可以把它们打包成合适的整数类型(可以查看链接的文档了解你的选择)。

不过,struct模块不处理单独的位,所以你得自己来做。我之前做过一个字典,用来把字符转换成八个True/False值的组合:

要解码的话:

pot = [2**x for x in range(8)]  # Powers of 2 (bytes with one 1 and seven 0s)
bitvalues = {}
for x in range(256):
    bitvalues[chr(x)] = [(x & y) != 0 for y in pot]

如果你想要创建一个编码用的字典,可以把最后一行替换成:

bitvalues[tuple((x & y) != 0 for y in pot)] = chr(x)

如果你想从1和0的字符串进行编码/解码,可以把生成列表/元组的位替换成:

"".join("1" if (x&y) else "0" for y in pot)

撰写回答