Why a Modbus float reads 1.5E+35
You expect 123.456 and the screen shows 1.5184998E+35. The device is fine, and so is the wiring: the four bytes are right, they're just being read in the wrong order.
The symptom
A device sends a 32-bit float in two registers. For 123.456 the registers hold 42F6
and E979. Read in the right order, the four bytes 42 F6 E9 79 give 123.456.
Read in another order, the same bytes give something that looks like noise:
| Byte order | Bytes | Float |
|---|---|---|
| ABCD | 42 F6 E9 79 | 123.456 |
| CDAB | E9 79 42 F6 | -1.8833671E+25 |
| BADC | F6 42 79 E9 | -9.8611155E+32 |
| DCBA | 79 E9 F6 42 | 1.5184998E+35 |
The giveaway is the size of the number. Physical quantities rarely need exponents beyond ±10: a value around E+25, E+35 or E-38 is almost never a real measurement. It's a correct value with its bytes shuffled.
Why it happens
Modbus sends each 16-bit register high byte first, but it says nothing about how to split a 32-bit value across two registers. Each manufacturer chooses, and the master has to make the same choice.
The second cause is often in our own code. A PC's processor is little-endian, so the most natural line of C# reads the four bytes backwards:
// bytes = 42 F6 E9 79, in the order they arrived
float value = BitConverter.ToSingle(bytes, 0); // 1.5184998E+35 on a PC
That's exactly the number in the title, from bytes that are perfectly correct.
How to fix it
In C#, say explicitly which order you expect:
using System.Buffers.Binary;
float value = BinaryPrimitives.ReadSingleBigEndian(bytes); // 123.456
If the device uses word swap (CDAB), swap the two registers before decoding. In a SCADA or a commercial master, look for an option called byte order, word swap or swap registers: the name changes from product to product.
Finding the order in one step
When the manual doesn't say, read a value you roughly know, such as a setpoint you entered or the supply voltage, and paste the raw registers into the register decoder together with the value you expect. It shows all four orders and highlights the one that matches. Once you've found it, it usually holds for every value from that device.