Can you write me a float to uint16 converter for Arduino because HX711 library get the weight value in float?
I found one here but I don’t really understand:
The following from your earlier post is already converting a float or double to an unsigned 16 bits integer, preserving 2 decimals:
uint16_t weight = scale.get_units() * 100;
It depends on the HX711 library you’re using what the value means. Looking at a random description of the HX711, it seems you may need to calibrate the scale. The output also depends on the library you’re using. I’d first create a sketch to see the readings for the scale; like when using the bodge library, its example will print the measurements to the Arduino’s console.
Note that the above library indeed gives you a float:
// returns get_value() divided by SCALE, that is the raw value divided by
// a value obtained via calibration
// times = how many readings to do
float get_units(byte times = 1);
Also note that a 2 byte unsigned integer has a maximum value of 65535, so if your weight exceeds 655.35 then you’ll get overflows with unexpected results. If the scale returns small units (like grams instead of kilograms) then you might not want to divide by 100 when converting the float into an integer. Or you might need to use more bytes, like 24 or 32 bits:
// NOT RECOMMENDED; it's better to use a SIGNED integer; see next posts.
// NOT RECOMMENDED; the ADC is 24 bits, so using 32 bits is really not needed.
uint32_t weight = scale.get_units() * 100;
...
byte message[8];
...
// 0x12345678 >> 24 shifts the 0x345678 out of memory, leaving 0x00000012
// 0x00000012 does not fit in a single byte, so 0x12 is stored in message[4]:
message[4] = weight >> 24;
message[5] = weight >> 16;
message[6] = weight >> 8;
message[7] = weight;
To decode 4 bytes in TTN you would not need sign extension (like you would for 2 or 3 bytes, if you’d expect negative values too):
// 0x12 << 24 yields 0x12000000,
// 0x34 << 16 yields 340000, and so on:
var w = bytes[4]<<24 | bytes[5]<<16 | bytes[6]<<8 | bytes[7];
For this, it would probably suffice to multiply a reading in kilograms by 10, hence preserving 1 decimal, as the accuracy is just 100 gram or 0.1 kg anyway.
But multiplying by 10 would allow an unsigned 16 bits integer to hold a maximum of 6553.5 kg, which is way above the scale’s maximum. So, if the float reading is in kilograms, one could still preserve 2 decimals (multiply by 100, just like in the code above), yielding a maximum of 655.35 kg which is still way above the scale’s maximum. A single 8 bits byte, with a maximum of 255, would be too small to hold the maximum of 149.9 kg with one decimal though.
To detect negative weight values (probably indicating a calibration error), it’s even better to send a 16 bits signed integer (int16_t), which supports -32768 up to 32767, hence a maximum of 327.67 kg with two decimals. Like noted earlier, that needs sign extension when decoding negative values in a payload function.
The setting for the frame counter width should match the internals of your node. But it will only get you into trouble if the counter exceeds the first 16 bits (65,536), after which the digital signature of the node’s payload will be invalid if the counter’s width does not match. However, I doubt this is giving you any problems now…