在Arduino上通过串行发送float
,double
和int16
的最佳方式是什么?
Serial.print()
仅发送ASCII编码的值。但我想将值作为字节发送。 Serial.write()
接受字节和字节数组,但是将值转换为字节的最佳方法是什么?
我试图将int16
投射到byte*
,但没有运气。我也使用了memcpy,但它使用了很多CPU周期。 Arduino使用普通的C / C ++。它是一个ATmega328微控制器。
答案 0 :(得分:10)
HM。怎么样:
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));
}
答案 1 :(得分:9)
是的,要发送这些号码,您必须先将它们转换为ASCII字符串。如果你正在使用C,那么IMO是sprintf()
进行此转换的最便捷方式:
[后来添加: AAAGHH!我忘记了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;
}
类似于花车和双打。执行转换的代码已事先知道。必须告诉它 - 它正在转换的实体是什么类型,因此您可能最终得到函数char *float2str( float float_num)
和char *dbl2str( double dblnum)
。
你将从转换中获得一个NUL终止的左调整(没有前导空格或零)字符串。
你可以随时随地进行转换;这些功能只是插图。
答案 2 :(得分:3)
使用Firmata协议。引用:
Firmata是与微控制器通信的通用协议 来自主机上的软件。它适用于任何主机 电脑软件包。现在有一个匹配的对象 语言数量。可以很容易地为其他软件添加对象 使用此协议。基本上,该固件为其建立协议 从主机软件与Arduino交谈。目的是允许 人们从主机上的软件完全控制Arduino 计算机。
答案 3 :(得分:2)
您需要查找的行话词是“序列化”。
这是串行连接的一个有趣问题,可能会限制哪些字符可以端到端,也可能无法为每个字符传递8位。
对某些字符代码的限制相当普遍。这是袖口上的几个:
如果正在使用软件流控制,那么传统上控制字符DC1和DC3(Ctrl-Q和Ctrl-S,有时也称为XON和XOFF)不能作为数据传输,因为它们被发送到启动和将发送者停在电缆的另一端。
在某些设备上,NUL和/或DEL字符(0x00和0x7F)可能会从接收器的FIFO中消失。
如果接收器是Unix tty,并且termio模式设置不正确,那么字符Ctrl-D(EOT或0x04)可能会导致tty驱动程序向进程发出文件结束信号那是开放的。
串行连接通常可配置为字节宽度,并且可能包含奇偶校验位。某些连接将要求使用带有奇偶校验的7位字节,而不是8位字节。连接到(严重旧的)传统硬件甚至可以为5位和6位字节配置许多串行端口。如果每个字节可用的小于8位,则需要更复杂的协议来处理二进制数据。
ASCII85是一种用于解决7位数据和控制字符限制的流行技术。这是一种仅使用85个精心选择的ASCII字符代码重写二进制数据的惯例。
此外,您当然要担心发送方和接收方之间的字节顺序。您可能还需要担心浮点格式,因为并非每个系统都使用IEEE-754浮点。
最重要的是,选择纯ASCII协议通常是更好的答案。它具有可以被人理解的优点,并且对串行连接的问题更具抵抗力。除非您发送大量浮点数据,否则表示的低效率可能会因为易于实现而被抵消。
只要对自己所接受的内容持开放态度,对你所发出的内容保守。
答案 4 :(得分:0)
尺寸重要吗?如果是,您可以使用ASCII85将每个32位组编码为5个ASCII字符,请参阅http://en.wikipedia.org/wiki/Ascii85。
答案 5 :(得分:0)
也许这是将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;
}
问候。 `
答案 6 :(得分:0)
结构和工会解决了这个问题。使用具有与结构匹配的字节大小的联合的压缩结构。重叠指向结构和联合的指针(或在结构中添加联合)。使用Serial.write发送流。在接收端有一个匹配的结构/联合。只要字节顺序匹配没有问题,否则您可以使用“C”hto(s..l)函数解压缩。添加“标题”信息以解码不同的结构/联合。
答案 7 :(得分:0)
这很简单。使用 Serial.println()函数
void setup() {
Serial.begin(9600);
}
void loop() {
float x = 23.45585888;
Serial.println(x, 10);
delay(1000);
}
这是输出:
答案 8 :(得分:0)
对于Arduino IDE:
float buildUp(int index, unsigned char outbox[])
{
unsigned long d;
d = (long(outbox[index +3]) << 24) | \
(long(outbox[index +2]) << 16) | \
(long(outbox[index +1]) << 8) | \
(long(outbox[index]));
float member = *(float *)&d;
return member;
}
否则不起作用。