使用结构将浮点数从 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,尽管它会引入一些开销。
我正在使用 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,尽管它会引入一些开销。