How to Fix the Codesys Modbus Byte Swap Issue (U16 to S32)
Integrating third-party energy meters or inverters into a PLC – you’ll face the Codesys Modbus byte swap is an unavoidable rite of passage. You do the communication perfectly . Now , instead of seeing ` 230.5V ‘ you see astronomical garbage values like ` 32456000 ‘ or ` 1.5e-41 ‘ in your monitoring variable .
Variable: Type: Value:
Raw_Reg_1 WORD 16#4366
Raw_Reg_2 WORD 16#8000
Combined_Value REAL 2.45e-41 (Expected: 230.5)This is not a wiring issue; it is an Endianness mismatch. The Modbus protocol inherently only defines 16-bit registers (WORDs / U16). It completely lacks a standardization for how 32-bit data (DWORDS, Reals, or S32) should be sequenced. When the field device transmits a 32-bit value split across two registers, Codesys reconstructs it based on its native architecture (usually Little-Endian). If the field device is Big-Endian, the High Word and Low Word get reversed.
Step 1: Identify the Byte Order
Before writing code, you must determine what the field device is sending. There are four possible combinations for a 32-bit float (ABCD, CDAB, BADC, DCBA).
90% of industrial power meters (like Eastron) and solar inverters transmit data in Big-Endian Word Swap format (CDAB). This means the bytes inside the WORD are correct, but the two WORDs themselves are reversed. You only need to swap Register 1 with Register 2.
Step 2: The Structured Text (ST) Solution
In Codesys , you can safely reconstruct the 32 bit value using bitwise operations (SHL and OR). Read the Modbus data into an array of WORD structures and combine into aDWORD.
// Variables Declaration VAR ModbusData : ARRAY[0..1] OF WORD; // Data pulled from Modbus Swapped32Bit : DWORD; // The corrected 32-bit variable FinalFloat : REAL; // Final human-readable value END_VAR // ST Code: Word Swap (Low Word first, High Word second) // Convert WORD to DWORD, shift the High Word 16 bits left, and merge. Swapped32Bit := (WORD_TO_DWORD(ModbusData[1]) SHL 16) OR WORD_TO_DWORD(ModbusData[0]); // Optional: Copy memory mapping to a REAL (Float) if required // Note: Do not use REAL_TO_DWORD, use ADR/POINTER mapping for raw bits. SysMem.SysMemCpy(ADR(FinalFloat), ADR(Swapped32Bit), SIZEOF(FinalFloat));
Executing this ST block will reconstruct the raw hexadecimal segments into the correct 32-bit format, instantly fixing your garbage numbers.
The Reality of Large-Scale Integrations
If you are reading two or three parameters then the ST code above is the perfect zero cost solution. But if you are integrating a commercial solar farm or multi-tenant metering panel you could be polling over 500 registers.
Writing, mapping, and testing bit-shift algorithms for hundreds of tags consumes valuable PLC scan cycle time and weeks of engineering hours. In modern OT architectures, engineers decouple this data-munging layer by using an edge protocol gateway. The gateway natively handles the CDAB byte-swapping at the hardware level, allowing Codesys to read pre-formatted, perfectly mapped S32 or Float variables directly over Modbus TCP without a single line of ST code.
Wasting hours writing byte-swap logic?
Stop writing data parsing scripts in your PLC. Valtoris Edge Gateways natively process Modbus S16, U32, and IEEE 754 Floats at the edge, delivering clean, unified data directly to your SCADA or Codesys environment.
