0

我正在尝试float使用 LMIC lora 库从 arduino 发送多个值。LMIC 函数仅将 auint8_t作为其传输参数类型。

temp包含我的温度值作为浮点数,我可以毫无问题地打印测量的温度:

Serial.println((String)"Temp C:         " + temp);

有一个示例显示此代码用于进行转换:

uint16_t payloadTemp = LMIC_f2sflt16(temp);
// int -> bytes
byte tempLow = lowByte(payloadTemp);
byte tempHigh = highByte(payloadTemp);
payload[0] = tempLow;
payload[1] = tempHigh;

我不确定这是否可行,似乎不行。发送的结果数据是:FF 7F

我不相信这就是我要找的。我还尝试了以下转换过程:

uint8_t *array;
array = (unit8_t*)(&f);

使用arduino,这甚至不会编译。

确实有效但产生的结果太长的东西是:

String toSend = String(temp);
toSend.toCharArray(payload, toSend.length());
payloadActualLength = toSend.length();
Serial.print("the payload is: ");
Serial.println(payload);

但是当我得到我想要发送的其他值时,生成的十六进制太长了。

那么如何将 a 转换float为一个uint8_t值,为什么我原来的给定转换不能像我期望的那样工作呢?

4

2 回答 2

0

如果您知道发送方和接收方都使用相同的 fp 二进制表示并且都使用相同的字节序,那么您可以只使用 memcpy:

float a =  23.24;
uint8_t buffer[sizeof(float)];

::memcpy(buffer, &a, sizeof(float));
于 2020-06-21T23:40:03.317 回答
0

听起来您正试图为这些数字找出一个最小尺寸的表示,您可以以一些非常小的数据包格式传输。如果范围受到适当限制,通常最好通过使用适当的定点表示来完成。

例如,如果您的温度始终在 0..63 范围内,您可以在单个字节中使用 6.2 定点格式:

if (value < 0.0 || value > 63.75) {
    // out of range for 6.2 fixed point, so do something else.
} else {
    uint8_t bval = (uint8_t)(value * 4 + 0.5);
    // output this byte value
}

当您读回字节时,只需将其乘以 0.25 即可获得(近似)浮点值。

当然,由于 8 位的精度非常有限(大约 2 位),它会被四舍五入以适应 - 你的 23.24 值将被四舍五入为 24.25。如果您需要更高的精度,则需要使用更多位。

如果您只需要一点精度但范围更广,则可以使用自定义浮点格式。IEEE 16 位浮点数 (S5.10) 非常好(为您提供 3 位精度和大约 10 个数量级的范围),但您可以做得更小,尤其是在您不需要负值的情况下。U4.4 浮点格式为您提供 1 位数的精度和 8 位的 5 个数量级范围(仅正数)

于 2020-06-22T01:30:21.297 回答