使用结构将浮点数从 Arduino 发送到 Python

Sending floats from Arduino to Python using a struct

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

我有一个加速度计代码的工作版本,唯一的区别是发送的信息是 4 个整数(加速度计:x、y、z、id),而温度传感器是 2 个浮点数(温度,浮点数)。我已经检查了传感器通过串行监视器发送的值,它们是正确的。当浮点数在 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 之间的浮点数表示方式有关,但我尝试将值更改为双精度/无符号长整数,但它要么崩溃,要么有类似的问题。

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

具体要注意:

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

要解决您的问题,您可以设计自己的方案(例如,将编译器配置为紧密打包内存中的结构 - 请参阅 gcc 的 packed attribute), and always encode floats as big-endian. Better yet, you can use a framework such as Google's protocol buffers,它是跨语言、跨平台、跨-无论为您处理序列化。

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