首页 > 解决方案 > 使用结构将浮点数从 Arduino 发送到 Python

问题描述

我正在使用 Bluefruit Feather 通过 BLEUART 将信息从温度传感器发送到计算机上的 Python 脚本。

我有一个用于加速度计的代码的工作版本,唯一的区别是发送的信息是 4 个整数(对于加速度计:x、y、z、id),而温度传感器是 2 个浮点数(温度、浮点 id) . 我检查了传感器通过串行监视器发送的值,它们是正确的。当浮点数在 Python 中解包时会出现问题:它们是大约1.36*e-45关闭的一个因素。

在这两种情况下,我都将变量存储在一个结构中并通过 BLE 发送这个结构。羽毛代码如下所示:

void sendData(){
  int numVals = 2;
  int vals[numVals];
  vals[0] = temp; 
  vals[1] = id; //1.0
  Serial.println(temp);
  Serial.println(id);  
  int cnt = numVals * sizeof(float) ;
  uint8_t buf[cnt];
  for (int _i=0; _i<numVals; _i++)
    memcpy(&buf[_i*sizeof(float)], &vals[_i], sizeof(float));
  bleuart.write( buf, cnt );
}

在 Python 端,它看起来像:

def received(data):
    floats = struct.unpack('ff', data)
    print('Received:', floats)

这真的很神秘!我觉得这与浮点数在 C 和 Python 之间的表示方式有关,但尝试将值更改为双精度/无符号长整数,但它要么崩溃,要么有类似问题。

标签: pythoncarduinobluetooth-lowenergy

解决方案


您提出的问题实际上是一个更广泛的问题,关于对象如何在不同的操作系统、机器架构、不同的编译器等下进行序列化和反序列化。

具体应该注意:

  • 结构如何映射到物理内存 - 不能保证您的结构占用内存中可能的最小空间。事实上,编译器很可能会在字段之间引入间隙,以优化内存访问速度(参见这个 SO question)。
  • machine Endianess,这是多字节基元(例如浮点数)在内存中存储的顺序

要解决您的问题,您可以设计自己的方案(例如,将编译器配置为在内存中紧密打包结构 - 请参阅 gcc 的packed属性),并始终将浮点数编码为大端。更好的是,您可以使用跨语言、跨平台、跨任何东西的框架(例如 Google 的协议缓冲区)来为您处理序列化。

就个人而言,我会选择选项 II,即使它引入了一些开销。


推荐阅读