[Solved] IEEE 754 Floating point conversion

I have set up an Edge device to read Modbus. I am successfully connected and sending information using 16 Bit Modicon. I am sending a single register with the value of 1. The hex value for the number 1 in 16 bit Modicon is 0000 3F80 The problem is that this data is begin converted into a integer in the Losant platform it is converting each hexadecimal block individually so 3F80 in a programmer calculator is 16256 it is an improper conversion this should be converted using a floating point converter or left in a raw state so a script could be used for the conversion.

Is there any plan to bring the hex data back in raw format? It would also be nice if Losant supported several Modbus protocols such as 16 bit Modicon, 16 Bit Word Swapped so there would be less scripting involved. These protocols are widely used in the industrial world.

Here is a screen shot of the packet log in my slave device.
image

No options to bring raw hex data back to Losant.
image

Thank you
Jimmy

We’ve got some plans to allow other conversion types, however you can work around this issue using a Function Node, which provides access to the Buffer Object to perform all sorts of conversions.

Even though the result is cast as an integer, it’s still the same bytes underneath. We can load up a Buffer with those bytes and then read them out in different forms. The function would look something like this:

var buf = new Buffer(4);
buf.writeUInt32BE(payload.data.myRegister); // unsigned int 16256
payload.data.myRegisterFloat = buf.readFloatBE() // 2.2779507836064226e-41

The Buffer object provides a lot of power to convert bytes to different types (including Big/Little endianness). Definitely check it out and see if it solves your issue.

You can also get the raw hex back by running:

buf.toString('hex'); // 00003f80

Hi,
After spending a bit of time working out how to turn two holding register int16’s back into a float32 I thought it would be helpful to post for others.

As above but with a few tweeks:
var buf = new Buffer(4);
buf.writeUInt16BE(payload.results.modbus1.HoldingRegistersInt[6],0); // signed int 15846
buf.writeUInt16BE(payload.results.modbus1.HoldingRegistersInt[5],2); // signed int 26240
payload.results.modbus1.A1 = buf.readFloatBE() // float32 0.11250019073486328

Notes:

  • Make sure the ints are signed in the Modbus read, the buf.writeUInt16BE doesn’t seem to like unsigned.
  • Make sure the Endianness is the same eg. Big (in Modbus read) -BE
3 Likes

Wow! Thanks for your input @F_C :slight_smile:

F_C

This is exactly the solution to the issue. I had given up on trying to solve the issue as I am no programmer. Thank you for the effort and sharing.

Jimmy

2 Likes