When a Modbus Float Reads 1.2e-41: Getting Byte and Word Order Right
Modbus has no standard endianness for 32-bit values, so two registers can decode to garbage. Proving byte and word order on site instead of guessing.
The register address is only half the answer
A Modbus register map may say that a flow value is at 40021 and uses two holding registers. That still does not tell the whole story. The SCADA driver must also know how bytes and words are ordered when those two 16-bit registers become one 32-bit value.
This problem shows up during commissioning as values that are stable but obviously wrong:
- A temperature reads
1.2e-41instead of84.7. - A totalizer jumps by huge amounts after restart.
- A signed value looks correct until it crosses zero.
- A vendor test tool works, but the HMI tag does not.
Here is the root cause. The Modbus Application Protocol Specification (V1.1b3) defines a register as 16 bits and says nothing about how to combine two of them into a 32-bit value. There is no standard endianness in the protocol. Every 32-bit float, long integer, and packed double word is a convention the vendor bolted on top. So treat byte order and word order as part of the interface spec, not a driver checkbox you sort out later.
Name the four common 32-bit layouts
For a 32-bit value split across two registers, engineers usually describe the layout by byte order inside each register and word order between registers. Unfortunately, different tools use different labels. Write the actual byte sequence in the project note.
Assume the real 32-bit bytes are A B C D.
| Field layout | Register N | Register N+1 | Common label |
|---|---|---|---|
AB CD | AB | CD | Big-endian word order |
CD AB | CD | AB | Word swapped |
BA DC | BA | DC | Byte swapped per register |
DC BA | DC | BA | Byte and word swapped |
Many PLCs and meters use AB CD for documentation examples, but gateways often expose configuration choices such as normal, swap words, swap bytes, or swap both. Do not rely on the label alone. Test with a known value.
The one that bites most, in my experience, is word swap (CD AB). Plenty of energy meters and drive gateways store the low word first while their manual prints the value big-endian. So if a float comes out wildly wrong but the sign looks plausible, try a word swap before you touch anything else — it clears more startup tickets than the other three layouts combined.
Commission with values that prove the order
A single live process value is a poor test. A temperature of 25.0 may produce several wrong-looking but not impossible values depending on scaling. Use a test value that makes byte and word errors obvious.
Good commissioning methods:
- Ask the device vendor for a register map example with raw register values and decoded engineering value.
- Force a simulator value such as IEEE-754 float
123.456and record the two raw registers. - For integer counters, use a value above
65535so the high word is not zero. - For signed integers, test one positive value and one negative value.
- For scaled integers, document both raw count and scale factor.
Example note for a flow meter:
Tag: FT101_TOTAL_M3
Modbus: holding registers 40210-40211
Type: unsigned 32-bit integer
Raw test value: 0x0001 0x86A0
Decoded value: 100000 m3
Driver setting: word order normal, byte order normal
Scale: raw x 1.0
This note is more useful than saying "32-bit unsigned" because it captures the actual layout proven in the field.
Separate scaling problems from ordering problems
Byte or word order errors often get confused with scaling errors. Diagnose them separately.
| Symptom | Likely cause | Check |
|---|---|---|
| Value is wildly tiny or huge for a float | Word or byte order | View raw hex registers and try all four layouts in a calculator |
| Value is exactly 10, 100, or 1000 times off | Scale factor or unit | Compare raw count and engineering unit in vendor manual |
| Value is correct below 32767 but wrong above it | Signed/unsigned mismatch | Check whether the device sends int16, uint16, int32, or uint32 |
| Value resets around 65535 | Only one register is being read | Confirm the driver tag length and starting address |
| Value changes but jumps in blocks | Wrong word used or stale register | Read both registers in one request if possible |
Do not fix an endian problem by adding a strange multiplier. That may make one test point look right while the whole operating range remains wrong.
Watch addressing conventions at the same time
Byte order is not the only Modbus convention that causes off-by-one mistakes. While proving a multi-register value, also record the addressing convention used by the driver.
Common sources of mismatch:
- Documentation says
40001, while the driver wants zero-based address0. - A gateway calls the first holding register
1, while a PLC driver calls it400001. - Input registers and holding registers have separate address spaces but similar numbers.
- A 32-bit value starts at an odd register and the driver assumes even alignment.
- The driver reads register
NandN+1, while the device documentation lists high word and low word in reverse order.
When possible, capture one Modbus poll in Wireshark or the driver diagnostic log. It gives you the function code, starting address, quantity, and returned bytes. That removes a lot of debate.
Packed status words need bit numbering notes
The same issue appears in packed status registers. A manual may say "bit 0 = running" and "bit 8 = fault," but HMI tools may display bits left-to-right or right-to-left. Some drivers number bits from 1 instead of 0.
For each packed register, document:
- Register address and function code.
- Whether bit numbering is 0-based or 1-based.
- Which bit is least significant bit (LSB).
- Whether alarm bits are active-high or active-low.
- Whether a bit is momentary, latched, or valid only in a specific mode.
Test packed bits by forcing one status at a time if the device allows it. If not, use a known machine state such as stopped, running, interlocked, and faulted, then compare the raw register value to the expected bit pattern.
What goes in the point list before handover
Before handing over the Modbus point list, make sure the project record includes:
- Raw register examples for at least one float, one 32-bit integer, and one packed status word.
- Driver settings for byte order and word order, written as byte sequence where possible.
- Addressing convention used by the SCADA driver.
- Signedness, scale factor, unit, and engineering range.
- Poll grouping notes for multi-register values so words are read consistently.
- Screenshots or logs from the device, driver, or packet capture used to prove the value.
It is ten minutes of paperwork against the worst Modbus failure mode there is: a value that updates, trends, and alarms like it is healthy while quietly reporting the wrong number.