如何通过串口发送浮点数
在 Arduino 上通过串行发送 float
、double
和 int16
的最佳方式是什么?
Serial.print()
仅发送 ASCII 编码的值。但我想以字节形式发送值。 Serial.write()
接受字节和字节数组,但是将值转换为字节的最佳方法是什么?
我尝试将 int16
转换为 byte*
,但没有成功。我还使用了 memcpy,但这会占用很多 CPU 周期。 Arduino 使用纯 C/C++。它是一个 ATmega328 微控制器。
What's the best way to send float
, double
, and int16
over serial on Arduino?
The Serial.print()
only sends values as ASCII encoded. But I want to send the values as bytes. Serial.write()
accepts byte and bytearrays, but what's the best way to convert the values to bytes?
I tried to cast an int16
to an byte*
, without luck. I also used memcpy, but that uses to many CPU cycles. Arduino uses plain C/C++. It's an ATmega328 microcontroller.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
嗯。这个怎么样:
hm. How about this:
是的,要发送这些数字,您必须首先将它们转换为 ASCII 字符串。如果您使用 C,
sprintf()
是,IMO,执行此转换的最方便的方法:[稍后添加:AAAGHH!我忘记了
ints
/longs
,函数的输入参数希望是无符号的。对于传递给 sprintf() 的格式字符串也是如此。所以我在下面更改了它。对我的严重疏忽感到抱歉,这将是一个很难发现的错误。另外,ulong
使其更加通用。]浮点数和双精度数也类似。进行转换的代码是预先已知的。必须告诉它 - 它要转换的实体类型,因此您最终可能会得到函数
char *float2str( float float_num)
和char *dbl2str( double dblnum)
。您将从转换中得到一个以 NUL 结尾的左调整(无前导空格或零)字符串。
您可以在任何地方/以您喜欢的方式进行转换;这些功能只是示例。
Yes, to send these numbers you have to first convert them to ASCII strings. If you are working with C,
sprintf()
is, IMO, the handiest way to do this conversion:[Added later: AAAGHH! I forgot that for
ints
/longs
, the function's input argument wants to be unsigned. Likewise for the format string handed tosprintf()
. So I changed it below. Sorry about my terrible oversight, which would have been a hard-to-find bug. Also,ulong
makes it a little more general.]And similar for floats and doubles. The code doing the conversion has be known in advance. It has to be told - what kind of an entity it's converting, so you might end up with functions
char *float2str( float float_num)
andchar *dbl2str( double dblnum)
.You'll get a NUL-terminated left-adjusted (no leading blanks or zeroes) character string out of the conversion.
You can do the conversion anywhere/anyhow you like; these functions are just illustrations.
使用 Firmata 协议。引用:
Use the Firmata protocol. Quote:
您需要查找的行话是“序列化”。
这是串行连接上的一个有趣问题,串行连接可能对哪些字符可以端到端进行限制,并且可能无法每个字符传递八位。
对某些字符代码的限制相当常见。以下是一些即兴的内容:
如果使用软件流控制,则通常控制字符 DC1 和 DC3(Ctrl-Q 和 Ctrl-S,有时也称为 XON 和 XOFF)不能作为数据传输,因为它们是发送以启动和停止电缆另一端的发送器。
在某些设备上,NUL 和/或 DEL 字符(0x00 和 0x7F)可能会从接收器的 FIFO 中消失。
在
如果接收方是 Unix tty,并且 termio 模式设置不正确,则字符 Ctrl-D(EOT 或 0x04)可能会导致 tty 驱动程序向具有文件结束符的进程发出文件结束信号。 tty open。
串行连接通常可配置字节宽度并可能包含奇偶校验位。某些连接需要使用带有奇偶校验的 7 位字节,而不是 8 位字节。甚至可以连接到(非常旧的)传统硬件来配置许多 5 位和 6 位字节的串行端口。如果每个字节可用的位数少于 8 位,则需要更复杂的协议来处理二进制数据。
ASCII85 是一种流行的技术,用于解决 7 位数据和控制字符的限制。这是仅使用 85 个精心挑选的 ASCII 字符代码重写二进制数据的约定。
此外,您当然还必须担心发送方和接收方之间的字节顺序。您可能还需要担心浮点格式,因为并非每个系统都使用 IEEE-754 浮点。
最重要的是,选择纯 ASCII 协议通常是更好的答案。它的优点是人类可以理解,并且更能抵抗串行连接的问题。除非您发送大量浮点数据,否则实现的简便性可能会抵消表示效率低下的问题。
只要对你接受的东西保持开放的态度,对你发出的东西保持保守即可。
The jargon word you need to look up is "serialization".
It is an interesting problem over a serial connection which might have restrictions on what characters can go end to end, and might not be able to pass eight bits per character either.
Restrictions on certain character codes are fairly common. Here's a few off the cuff:
If software flow control is in use, then conventionally the control characters DC1 and DC3 (Ctrl-Q and Ctrl-S, also sometimes called XON and XOFF) cannot be transmitted as data because they are sent to start and stop the sender at the other end of the cable.
On some devices, NUL and/or DEL characters (0x00 and 0x7F) may simply vanish from the receiver's FIFO.
If the receiver is a Unix tty, and the termio modes are not set correctly, then the character Ctrl-D (EOT or 0x04) can cause the tty driver to signal an end-of-file to the process that has the tty open.
A serial connection is usually configurable for byte width and possible inclusion of a parity bit. Some connections will require that a 7-bit byte with a parity are used, rather than an 8-bit byte. It is even possible for connection to (seriously old) legacy hardware to configure many serial ports for 5-bit and 6-bit bytes. If less than 8-bits are available per byte, then a more complicated protocol is required to handle binary data.
ASCII85 is a popular technique for working around both 7-bit data and restrictions on control characters. It is a convention for re-writing binary data using only 85 carefully chosen ASCII character codes.
In addition, you certainly have to worry about byte order between sender and receiver. You might also have to worry about floating point format, since not every system uses IEEE-754 floating point.
The bottom line is that often enough choosing a pure ASCII protocol is the better answer. It has the advantage that it can be understood by a human, and is much more resistant to issues with the serial connection. Unless you are sending gobs of floating point data, then inefficiency of representation may be outweighed by ease of implementation.
Just be liberal in what you accept, and conservative about what you emit.
尺寸重要吗?如果是这样,您可以使用 ASCII85 将每个 32 位组编码为 5 个 ASCII 字符,请参阅 http://en .wikipedia.org/wiki/Ascii85。
Does size matter? If it does, you can encode each 32 bit group into 5 ASCII characters using ASCII85, see http://en.wikipedia.org/wiki/Ascii85.
这很简单。使用 Serial.println() 函数
这是输出:
This simply works. Use Serial.println() function
And this is the output:
也许这是将浮点转换为字节和字节转换为浮点的最佳方法,-Hamid Reza。
问候。
`
Perhaps that is best Way to convert Float to Byte and Byte to Float,-Hamid Reza.
regards.
`
结构和工会解决了这个问题。使用带有与该结构匹配的字节大小联合的打包结构。重叠指向结构和联合的指针(或在结构中添加联合)。使用 Serial.write 发送流。在接收端有匹配的结构/联合。只要字节顺序匹配就没有问题,否则您可以使用“C” hto(s..l) 函数解包。添加“标头”信息以解码不同的结构/联合。
Structures and unions solve that issue. Use a packed structure with a byte sized union matching the structure. Overlap the pointers to the structure and union (or add the union in the structure). Use Serial.write to send the stream. Have a matching structure/union on receiving end. As long as byte order matches no issue otherwise you can unpack using the "C" hto(s..l) functions. Add "header" info to decode different structures/unions.
对于 Arduino IDE:
否则无法工作。
For Arduino IDE:
otherwise not working.