如何通过串口发送浮动

时间:2010-07-17 09:44:37

标签: c++ c serial-port bytearray arduino

在Arduino上通过串行发送floatdoubleint16的最佳方式是什么?

Serial.print()仅发送ASCII编码的值。但我想将值作为字节发送。 Serial.write()接受字节和字节数组,但是将值转换为字节的最佳方法是什么?

我试图将int16投射到byte*,但没有运气。我也使用了memcpy,但它使用了很多CPU周期。 Arduino使用普通的C / C ++。它是一个ATmega328微控制器。

9 个答案:

答案 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);
}

这是输出:

enter image description here

答案 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;
}

否则不起作用。