C++ 如何通过串行发送浮动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3270967/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to send float over serial
提问by chriszero
What's the best way to send float
, double
, and int16
over serial on Arduino?
什么是派出最好的方式float
,double
以及int16
通过串行上的Arduino?
The Serial.print()
only sends values as ASCIIencoded. 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?
在Serial.print()
只发送值作为ASCII编码。但我想将值作为字节发送。Serial.write()
接受字节和字节数组,但是将值转换为字节的最佳方法是什么?
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 ATmega328microcontroller.
我试图将 an 转换int16
为 an byte*
,但没有运气。我也使用了 memcpy,但它使用了许多 CPU 周期。Arduino 使用普通的 C/C++。这是一个ATmega328微控制器。
回答by Nils Pipenbrinck
hm. How about this:
嗯。这个怎么样:
void send_float (float arg)
{
// get access to the float as a byte-array:
byte * data = (byte *) &arg;
// write the data to the serial
Serial.write (data, sizeof (arg));
}
回答by Pete Wilson
Yes, to send these numbers you have to first convert them to ASCIIstrings. If you are working with C, sprintf()
is, IMO, the handiest way to do this conversion:
是的,要发送这些数字,您必须先将它们转换为ASCII字符串。如果您正在使用 C,那么sprintf()
IMO 是进行此转换的最简便方法:
[Added later: AAAGHH!I forgot that for ints
/longs
, the function's input argument wants to be unsigned. Likewise for the format string handed to sprintf()
. 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.]
[后来补充:啊啊啊!我忘记了ints
/ longs
,函数的输入参数想要无符号。同样对于传递给sprintf()
. 所以我在下面改变了它。很抱歉我的疏忽,这本来是一个很难找到的错误。此外,ulong
使它更通用一点。]
char *
int2str( unsigned long num ) {
static char retnum[21]; // Enough for 20 digits plus NUL from a 64-bit uint.
sprintf( retnum, "%ul", num );
return retnum;
}
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)
and char *dbl2str( double dblnum)
.
浮动和双打也类似。进行转换的代码是预先知道的。必须告诉它 - 它正在转换什么样的实体,所以你最终可能会得到函数char *float2str( float float_num)
和char *dbl2str( double dblnum)
.
You'll get a NUL-terminated left-adjusted (no leading blanks or zeroes) character string out of the conversion.
您将在转换中得到一个以 NUL 结尾的左调整(没有前导空格或零)字符串。
You can do the conversion anywhere/anyhow you like; these functions are just illustrations.
您可以在任何地方/以您喜欢的方式进行转换;这些功能只是说明。
回答by noonv
Use the Firmataprotocol. Quote:
使用Firmata协议。引用:
Firmata is a generic protocol for communicating with microcontrollers from software on a host computer. It is intended to work with any host computer software package. Right now there is a matching object in a number of languages. It is easy to add objects for other software to use this protocol. Basically, this firmware establishes a protocol for talking to the Arduino from the host software. The aim is to allow people to completely control the Arduino from software on the host computer.
Firmata 是一种通用协议,用于通过主机上的软件与微控制器进行通信。它旨在与任何主机计算机软件包一起使用。现在有多种语言的匹配对象。很容易为其他软件添加对象以使用此协议。基本上,这个固件建立了一个协议,用于从主机软件与 Arduino 对话。目的是让人们可以通过主机上的软件完全控制 Arduino。
回答by RBerteig
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.
这是一个关于串行连接的有趣问题,它可能对哪些字符可以端到端地进行限制,并且也可能无法每个字符传递 8 位。
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.
如果使用软件流控制,则通常控制字符 DC1 和 DC3(Ctrl-Q 和 Ctrl-S,有时也称为 XON 和 XOFF)不能作为数据传输,因为它们被发送以启动和停止另一端的发送器电缆的末端。
在某些设备上,NUL 和/或 DEL 字符(0x00 和 0x7F)可能会从接收器的 FIFO 中消失。
如果接收器是 Unix tty,并且 termio 模式设置不正确,则字符 Ctrl-D(EOT 或 0x04)会导致 tty 驱动程序向打开 tty 的进程发出文件结束信号。
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.
串行连接通常可配置字节宽度和可能包含的奇偶校验位。某些连接需要使用带奇偶校验的 7 位字节,而不是 8 位字节。甚至可以连接到(非常旧的)传统硬件来为 5 位和 6 位字节配置许多串行端口。如果每字节少于 8 位可用,则需要更复杂的协议来处理二进制数据。
ASCII85is 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.
ASCII85是处理 7 位数据和控制字符限制的流行技术。这是仅使用 85 个精心挑选的 ASCII 字符代码重写二进制数据的惯例。
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.
此外,您当然必须担心发送方和接收方之间的字节顺序。您可能还需要担心浮点格式,因为并非每个系统都使用 IEEE-754 浮点。
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.
最重要的是,通常选择纯 ASCII 协议是更好的答案。它的优点是可以被人类理解,并且更能抵抗串行连接的问题。除非您正在发送大量浮点数据,否则表示的低效率可能会被实现的简易性所抵消。
Just be liberal in what you accept, and conservative about what you emit.
只是对你接受的东西保持自由,对你发出的东西保持保守。
回答by partho
回答by John Reynolds
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.
大小重要吗?如果是这样,您可以使用 ASCII85 将每个 32 位组编码为 5 个 ASCII 字符,请参阅http://en.wikipedia.org/wiki/Ascii85。
回答by Hamid Reza
Perhaps that is best Way to convert Float to Byte and Byte to Float,-Hamid Reza.
也许这是将 Float 转换为 Byte 并将 Byte 转换为 Float 的最佳方式,-Hamid Reza。
int breakDown(int index, unsigned char outbox[], float member)
{
unsigned long d = *(unsigned long *)&member;
outbox[index] = d & 0x00FF;
index++;
outbox[index] = (d & 0xFF00) >> 8;
index++;
outbox[index] = (d & 0xFF0000) >> 16;
index++;
outbox[index] = (d & 0xFF000000) >> 24;
index++;
return index;
}
float buildUp(int index, unsigned char outbox[])
{
unsigned long d;
d = (outbox[index+3] << 24) | (outbox[index+2] << 16)
| (outbox[index+1] << 8) | (outbox[index]);
float member = *(float *)&d;
return member;
}
regards. `
问候。`
回答by Tego
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.
结构和工会解决了这个问题。使用具有与结构匹配的字节大小联合的打包结构。将指向结构和联合的指针重叠(或在结构中添加联合)。使用 Serial.write 发送流。在接收端有一个匹配的结构/联合。只要字节顺序匹配没有问题,否则您可以使用“C” hto(s..l) 函数解包。添加“标题”信息以解码不同的结构/联合。