Как преобразовать двойной в гекс / байт
Мне нужно отправить данные в The Things Network, и данные должны быть в байтах
Для отправки данных туда и обратно через сеть вещей вам нужно использовать байты
Некоторые функции возвращают число с плавающей запятой с 2
23,56 или 4,32
У меня есть большие трудности, чтобы преобразовать мой float и сохранить его в надежных uint8_t моих данных. Я должен найти, как конвертировать мою переменную с плавающей точкой
У меня есть такой цикл:
/*
NOTE:
uinit8_t mydata[64];
byte nbMaxCapteurs = 10;
mesMesures[i][mesCapteur[i].idDuCapteur].valeur => this is a float
*/
memset(mydata, 0xFF, 64);
uint8_t * ptr = mydata;
for (byte i = 0; i < nbMaxCapteurs; i++) {
if (mesCapteur[i].actif) {
*ptr = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;
ptr += 15; // How to know the number of step to move the pointer
if (i < nbCapteurActif + 1) {
*ptr = 0x2C; // virgule
ptr += sizeof(char);
}
} else {
*ptr = 0x2C; // virgule pour les capteurs inactifs
ptr += sizeof(char);
}
}
*ptr = '00'; // Close \0
ptr += sizeof(char);
printData();
Я очень новичок в таких преобразованиях. Настоящая проблема здесь:
*ptr = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;
printData печатает это:
04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C CB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2F A8 F8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C
Но это должно напечатать по крайней мере это:
34 2E 33 32 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C CB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C A8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C
Так как 34 2e 33 32
равно 4,32.
Я не понимаю и не знаю, как я могу "объединить" и преобразовать значение с плавающей запятой. И тогда вы могли бы помочь мне переместить указатель в соответствии с размером поплавка?
Я действительно застрял в этой теме, и я был бы очень признателен за вашу помощь.
2 ответа
Если вы хотите округлить до нуля после двух десятичных знаков, вы можете использовать следующее:
double lum = ((int)(luminosity * 100))/100.0;
Если вы хотите округлить до ближайшего (округлить половину от нуля) после двух десятичных знаков, вы можете использовать следующее:
#include <math.h> double lum = round(luminosity * 100)/100.0;
Если, с другой стороны, вы хотите максимально эффективно сохранить яркость в 8 битах, вы можете использовать следующий алгоритм.
uint8_t packed_luminosity; if (luminosity >= MAX_LUMINOSITY) // Just in case packed_luminosity = 255; else if (luminosity <= MIN_LUMINOSITY) // Just in case packed_luminosity = 0; else packed_luminosity = (uint8_t)( ( luminosity - MIN_LUMINOSITY ) / ( MAX_LUMINOSITY - MIN_LUMINOSITY + 1 ) * 256 );
Вы можете выполнять сравнения и определенные операции над светимостью в этом формате.
Другой способ упаковать десятичное число в целое число - это число с фиксированной запятой. Это работает, выбирая масштабирование для всех ваших яркостей, когда вы пишете свою программу. Вот диапазоны, поддерживаемые некоторыми масштабами:
uint8_t ======= Scaling Supported range (binary) Supported range (decimal) ------- ------------------------------- ----------------------------------------- ... B8 [00000000. .. 111111110. ] [0 .. 512) No odd numbers B7 [ 0000000. .. 11111111. ] [0 .. 256) No decimals B6 [ 000000.0 .. 1111111.1 ] [0 .. 128) .0, .5 B5 [ 00000.00 .. 111111.11 ] [0 .. 64) .0, .25, .5, .75 B4 [ 0000.000 .. 11111.111] [0 .. 32) Almost one full decimal place ... int8_t ====== Scaling Supported range (binary) Supported range (decimal) ------- ------------------------------ -------------------------------------------- ... B8 [10000000. .. 011111110. ] [-256 .. 256) No odd numbers B7 [ 1000000. .. 01111111. ] [-128 .. 128) No decimals B6 [ 100000.0 .. 0111111.1 ] [ -64 .. 64) .0, .5 B5 [ 10000.00 .. 011111.11 ] [ -32 .. 32) .0, .25, .5, .75 B4 [ 1000.000 .. 01111.111] [ -16 .. 16) Almost one full decimal place ...
Как вы можете видеть, использование только 8 битов очень ограничивает, и вы не получаете такую же гибкость выбора диапазонов, как предыдущий метод. Преимущество чисел с фиксированной точкой состоит в том, что вы можете выполнять арифметические функции (сложение, вычитание, умножение и деление) на их пары.
(Я ничего не знаю об Arduino)
Минимальное изменение, которое приблизит вас к вашим целям:
double luminosity;
uint32_t lum;
lum = (uint32_t)(luminosity * 100);
Теперь lum будет содержать ваше значение, умноженное на сотню, округленное в меньшую сторону.
Вместо 23,45 вы получите 2345. Использование uint8_t ограничит вас слишком сильно, так как диапазон слишком мал (0-255). Имеются ли у вас в наличии uint16_t и uint32_t, я не знаю.
Эта техника называется арифметикой с фиксированной точкой.