[英]How to convert a float into uint8_t?
我正在嘗試使用 LMIC lora 庫從 arduino 發送多個float
值。 LMIC 函數僅采用uint8_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);
但是當我得到我想要發送的其他值時,生成的十六進制太長了。
那么我如何將一個float
轉換成一個uint8_t
值,為什么我原來的給定轉換不能像我期望的那樣工作?
如果您知道發送者和接收者都使用相同的 fp 二進制表示並且都使用相同的字節序,那么您可以只使用 memcpy:
float a = 23.24;
uint8_t buffer[sizeof(float)];
::memcpy(buffer, &a, sizeof(float));
聽起來您正試圖為這些數字找出一個最小尺寸的表示,您可以以一些非常小的數據包格式傳輸。 如果范圍受到適當限制,通常最好通過使用適當的定點表示來完成。
例如,如果您的溫度始終在 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 個數量級范圍),但你可以 go 更小,特別是如果你不需要負值。 U4.4 浮點格式為您提供 1 位數的精度和 8 位的 5 個數量級范圍(僅正數)
在 Arduino 中,可以將浮點數轉換為字符串
float ds_temp=sensors.getTempCByIndex(0); // DS18b20 Temp sensor
然后將 String 轉換為 char 數組:
String ds_str = String(ds_temp);
char* ds_char[ds_str.length()];
ds_str.toCharArray(ds_char ,ds_str.length()-1);
uint8_t* data =(uint8_t*)ds_char;
uint_8 值存儲在大小為sizeof(data)
data
數據中
uint8_t
的變量只能攜帶 256 個值。 如果你真的想把溫度壓縮成單個字節,你必須使用定點方法或最低有效位值方法
float
常量(可以使用靈活的 LSB 值),您可以將其除以原始float
值 X: R = (X-T0)/LSB
。 您可以將結果四舍五入,它適合字節。X = R*LSB + T0
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.