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

发布于 2024-10-05 02:25:26 字数 1036 浏览 6 评论 0原文

我已经做了相当多的搜索和阅读,但还没有找到确切明确的答案。我正在制作 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 模块。我应该走那条路吗?

我想知道的另一件事是如何表示消息的时间戳部分。

如果您能给我任何帮助、建议,我将不胜感激。

非常感谢:)

I have done a fair bit of searching and reading around but haven't found an exact clear answer. I am making python application which will communicate with another over the serial port. I have been using PySerial to accomplish this. The types of packets I want to send are status information and data readings.
I am proposing to form of my packets as follows:

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

Although I don't think I need the end byte since have a length in there. Am I correct?

I am thinking of shaping the 'Message' part of the packet for status info like so:

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

The message ID here is just to differentiate that this is a status packet rather than a data packet. The status information itself is made up of 16 bits, representing the state of a number of subsystems in the sending application. For some of these subsystems, a single bit will provide enough info ('0' to say the subsystem is off/low/false, '1' for on/high/true). Others will require 2 or 3 bits (representing states and such). Prototyping the system up, I have been simply constructing a string concatenating the bits up to form a something like '1001110101101100' and sending this out the serial port, with the checksum being a modulo 256 of the status bits.

I am pretty new to Python and serial communication but I know this is probably a waste of bandwidth. I know that PySerial has to send strings but representing each bit as a '0' or '1' like this is using a full string representation for each bit. I was wondering what is the best way to send these bits to reduce the bandwidth?

For example, would I take each 8 bits, convert them to hex and send concatenated hex bytes, as in:

'10011101' + '01101100'

represented as

'\x9d' + '\x6c'

or should I send them as ASCII? I've also seen mentions of the Struct module. Should I be going down that route instead?

The other thing I am wondering is how to represent the timestamp parts of the message.

Any help, suggestions you can give me would be greatly appreciated.

Thanks very much :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

马蹄踏│碎落叶 2024-10-12 02:25:26

嗯,很明显,发送的每个字符需要一个字节,因此如果您可以将数据编码为 ascii 字符串(Python 2 中的 str,Python 3 中的 bytes),那就最多了高效的。

struct 模块绝对是个好主意:它将 Python 数据打包成字符串(并在另一端)。这适用于你的时间戳;将它们打包为任何似乎合适的 int 或 long 类型(有关您的选项,请参阅链接文档)。

不过,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)

If如果您想从 1 和 0 的字符串进行编码/解码,请将生成列表/元组的位替换为:

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

Well, obviously it needs one byte per character sent, so if you can encode your data as an ascii string (str in Python 2, bytes in Python 3), that's most efficient.

The struct module is definitely a good idea: it packs Python data into a string (and unpacks it at the other end). That'll work for your timestamps; pack them as whatever type of int or long seems appropriate (see the linked documentation for your options).

struct doesn't do individual bits, though, so you'll have to do that yourself. I've built a dictionary before to translate characters into groups of eight True/False values:

To decode:

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]

To make a dictionary for encoding, replace the last line with:

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

If you want to encode/decode from strings of 1s and 0s instead, replace the bit generating the list/tuple with:

"".join("1" if (x&y) else "0" for y in pot)
千仐 2024-10-12 02:25:26

您预计多久发送一次这些更新?如果 update_Frequency * length_of_message 远小于串行连接的数据速率,那么就没有理由担心数据编码的效率,您甚至可以考虑将内容扩展为更易于阅读的格式,特别是当您正在开始。

How frequently are you expecting to send these updates? If update_frequency * length_of_message is far less than the data rate of the serial connection, then there's very little reason to worry about the efficiency of the data encoding, and you might even consider expanding things out to a more human-readable format, especially when you're getting started.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文