I have been having an issue with converting a floating point value I read over Modbus that is sent in 4 bytes. I have confirmed via logging that the correct 4 bytes are being read, but I can’t seem to get the conversion right. I have tried various permutations and combinations but of course since floats are a special encoding and not just raw bits, things like fiddling with shifts or reading the single bytes have not been very helpful.
I have previously implemented a working version of this on a different device in Python. This is the very simple code that does the conversion as intended on my ARM7(ARMV7A) 32 Bit Linux System:
res = self.get_input_register(address, 2)
if res is not None and len(res) > 1: floatp1 = res floatp2 = res float_val = unpack('f', pack('<HH', floatp2, floatp1)) if self.debug_mode: print "FLOAT:" + str(float_val)
This code flips the first 2 bytes with the last 2, so the 2 bytes received 2nd are the MSBs. Then the format string tells the system that this is a Float encoded as 2 variables of type ‘Little Endian unsigned short’ (this system is Big Endian so a conversion is needed).
It is my understanding that the NRF52840 (ARMCortexM4) is Little Endian as well. Therefore, I was hoping something this simple would work:
if (result == modbus.ku8MBSuccess)
data = modbus.getResponseBuffer(0);
data = modbus.getResponseBuffer(1);
int32_t tmpVal = ((uint32_t)(data)); tmpVal = tmpVal << 16;// shift left 2 bytes tmpVal = tmpVal | ((uint32_t)data); // OR in LSB float outVal = static_cast<float>(tmpVal); Serial.printf("FLOAT: %f", outVal);
However, this prints seemingly random/nonsensical garbage data. I have played around with various permutations and combinations of fixes I could think of, but nothing seemed to help. Does anything jump out as an obvious oversight or mistake I’m making?