WinCC Flexible Modbus: Reading 32-bit Float Input Registers

David Krause16 min read
HMI / SCADASiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Definition

When integrating a third-party Modbus TCP energy analyzer with SIMATIC WinCC Flexible Runtime, attempting to bind a 32-bit IEEE 754 floating-point value to a Modbus input register (function code 04, address range 3xxxx) fails at the tag editor: the %IW address field is disabled whenever the tag data type is set to Real (REAL, 32-bit). The same editor allows %MW addressing for floating-point tags. Reading the same register as a 16-bit INT or WORD at consecutive %IW addresses returns only the high or low 16-bit half of the 32-bit value, producing incorrect scaled or zero data. Inserting an OPC server (for example KEPwareEX) between the energy analyzer and WinCC Flexible resolves the data type issue but introduces 200-500 ms update latency per polling cycle, which is unacceptable for real-time energy monitoring.

Reported field configuration:

  • HMI software: SIMATIC WinCC Flexible Runtime (PC or panel-based)
  • Driver: Modicon Modbus TCP/IP (WinCC Flexible built-in protocol)
  • Target PLCs: Schneider Electric Modicon Premium (TSX P57 series) and Modicon Micro (TSX 37 series)
  • Source device: third-party energy analyzer publishing 32-bit float in input register 30218 (function code 04, 3xxxx address space)
  • Network: 10/100 Mbps Ethernet, Modbus TCP/IP port 502

Observed Tag Editor Behavior

Tag Data Type %IW Field %MW Field Driver Read Behavior
BOOL, INT, UINT, WORD Enabled Enabled Single 16-bit register read
REAL, DINT, DWORD Disabled (greyed out) Enabled Two consecutive 16-bit registers, reassembled to 32 bits
Field-validated symptom: the %IW field greys out the moment the data type is changed from INT or WORD to REAL. The tag editor will not accept a 32-bit binding at any %IW-prefixed address, regardless of the input register number.

Root Cause Analysis

The Modicon Modbus TCP/IP driver inside WinCC Flexible enforces a hard-coded separation between 16-bit and 32-bit bindings on the Modicon memory model:

  1. 16-bit data types (INT, UINT, WORD, BOOL): the tag editor allows binding to either %IW (Input Word) or %MW (Memory Word). The driver issues a single Modbus function code 04 (Read Input Registers) or 03 (Read Holding Registers) and presents the 16-bit payload as the tag value.
  2. 32-bit data types (REAL, DINT, DWORD): the tag editor permits binding only to %MW. The driver reads two consecutive 16-bit registers and reassembles the bytes into a 32-bit value in the correct IEEE 754 or signed/unsigned integer layout. The %IW area is intentionally excluded because the Modicon convention reserves %IW for physical input modules, which are intrinsically 16-bit.
  3. Source area mismatch: when the data originates in the 3xxxx (input register) Modbus space, no direct 32-bit binding path exists in the tag editor. The driver does not provide a "float at %IW" option.

This behavior is a design constraint of the driver and tag editor, not a bug. It cannot be removed by project configuration. Three independent constraints produce it: the tag editor's data-type-to-address-area binding table, the driver's atomic 32-bit read implementation, and the Modicon hardware convention that ties %IW to discrete 16-bit module inputs.

Modbus Memory Model and Modicon Addressing

Per the Modbus Application Protocol specification, the protocol defines four primary address spaces:

Prefix Name Function Code Access Bit Width
0xxxx Coils 01, 05, 15 Read/Write 1 bit
1xxxx Discrete Inputs 02 Read-only 1 bit
3xxxx Input Registers 04 Read-only 16 bits
4xxxx Holding Registers 03, 06, 16 Read/Write 16 bits

A 32-bit IEEE 754 single-precision float occupies two consecutive 16-bit registers. The high word is transmitted first on the wire (Modbus is big-endian by default). For input register 30218 containing a float, the full payload is 30218 (high word) and 30219 (low word).

Modicon Symbol Syntax

In Modicon / Schneider Electric PLCs, the %-prefixed symbol notation distinguishes memory areas:

Symbol Meaning Modbus Source
%MW Memory Word (internal RAM) Holding registers (4xxxx)
%IW Input Word Input registers (3xxxx)
%QW Output Word Output coils/registers (0xxxx, 4xxxx write)
%M Bit (internal memory) Internal coils
%I Bit (input) Discrete inputs (1xxxx)

The WinCC Flexible Modicon Modbus TCP/IP driver maps these symbols onto Modbus address ranges. The default mapping is:

  • %MW0 ↔ Modbus holding register 40001
  • %IW0 ↔ Modbus input register 30001
  • %MD0 covers %MW0 and %MW1 (32-bit atomic access)

For a 32-bit REAL at %MW100, the driver reads Modbus registers 40101 and 40102 and reassembles them as an IEEE 754 float. The same 32-bit reassembly is not offered at %IW because the %IW area is exposed as a stream of 16-bit values only.

Why 16-bit %IW Cannot Carry a 32-bit Float in This Driver

Three independent constraints converge to produce the observed behavior:

  1. Tag editor constraint: the dialog box hard-codes the address area based on data type. Selecting REAL forces %MW and disables %IW. There is no user setting to override this.
  2. Driver runtime constraint: the 32-bit read path issues two back-to-back function code 04 requests for consecutive registers and expects the result to be written into a 32-bit-coherent %MW location. The %IW area is a 16-bit stream without a guaranteed 32-bit atomicity contract.
  3. Modicon convention: %IW historically refers to physical input module words on Modicon Premium/Micro racks (TSX DEY/DIY/DIY16 modules). These are 16-bit by hardware, and the symbol set was carried into the Modbus driver to maintain naming parity with the rack I/O convention.

None of these constraints can be relaxed in the project. Workarounds must respect the binding rule: 32-bit types must land in %MW, even if the original Modbus source is in 3xxxx.

Solution Paths Overview

Four practical approaches resolve the issue. They are listed in order of increasing hardware complexity:

# Approach Modifies PLC Adds Hardware Update Latency Best For
1 Read as two 16-bit %IW tags, combine in VBScript No No 250 ms (HMI cycle) Small systems, single energy meter
2 PLC reads input register, mirrors to %MD Yes (Unity Pro) No 100-200 ms (PLC scan) Existing Premium/Micro PLC, multiple tags
3 Modbus gateway remaps 3xxxx to 4xxxx No Yes (gateway) 50-100 ms (gateway) Many 3xxxx devices, transparent mapping
4 OPC server with built-in float handling No Yes (OPC server) 200-500 ms (OPC) Large fleets, central SCADA

For most field deployments where an OPC server is too slow, Solution 1 (VBScript combination) is the fastest to deploy, and Solution 2 (PLC-side mirroring) is the most robust for long-term operation.

Solution 1: Two %IW Tags Combined in VBScript

This approach reads the energy analyzer's 3xxxx input register as two separate 16-bit INT tags at consecutive %IW addresses, then combines them in a WinCC Flexible VBScript into a single REAL tag. No PLC changes are required and no OPC server is introduced.

Prerequisites

  • SIMATIC WinCC Flexible 2008 SP2 or later (Runtime or Engineering)
  • Configured Modicon Modbus TCP/IP connection to the energy analyzer
  • Energy analyzer exposing 32-bit IEEE 754 float at input register 30218 (0-based offset 217)
  • VBScript license activated in the HMI project

Step-by-Step Procedure

Step 1: Add the High-Word INT Tag

  1. Open the WinCC Flexible project in the engineering software.
  2. Navigate to Communication → Tags and add a new tag named Energy_HiWord.
  3. Select the Modicon Modbus TCP/IP connection as the source.
  4. Set the data type to Int (16-bit signed).
  5. Set the address to %IW217 (input register 30218, 0-based offset).
  6. Set acquisition mode to Cyclic continuous, 250 ms update cycle.
  7. Save the tag and download the project to the HMI.

Step 2: Add the Low-Word INT Tag

  1. Add a second tag named Energy_LoWord.
  2. Set the data type to Int or Word.
  3. Set the address to %IW218 (input register 30219, 0-based offset).
  4. Match the acquisition cycle of the high-word tag.
  5. Save and download.

Step 3: Add the Combined REAL Tag

  1. Add a new tag named Energy_kW with data type Real.
  2. Bind it to the Internal area (no driver connection). The value will be written by VBScript.
  3. Set acquisition mode to Cyclic continuous, 250 ms update cycle.

Step 4: Write the VBScript Combination Function

Create a new VBScript function CombineWordsToFloat in the project's script library. The implementation handles Modbus standard big-endian word order:

Function CombineWordsToFloat(hiWord, loWord)
    ' Combine two 16-bit Modbus words into a 32-bit IEEE 754 float.
    ' Word order: Modbus big-endian (high word first, low word second)
    Dim longValue, signBit, exponent, mantissa, result
    
    ' Reassemble 32-bit unsigned integer from two 16-bit words
    longValue = (CLng(hiWord) And &HFFFF&) * 65536
    longValue = longValue + (CLng(loWord) And &HFFFF&)
    
    ' Extract IEEE 754 single-precision fields
    signBit  = (longValue And &H80000000) / &H80000000
    exponent = (longValue And &H7F800000) / &H800000
    mantissa = (longValue And &H007FFFFF) / &H800000
    
    ' Decode
    If exponent = 0 Then
        result = 0
    ElseIf exponent = 255 Then
        result = 0   ' Inf/NaN: substitute 0 to avoid script abort
    Else
        result = (2 ^ (exponent - 127)) * (1 + mantissa)
        If signBit = 1 Then result = -result
    End If
    
    CombineWordsToFloat = result
End Function

If the energy analyzer publishes the float in little-endian word order (low word first), swap the operands at the call site. The IEEE 754 fields above assume Modbus-standard big-endian word ordering per the Modbus Application Protocol Specification V1.1b3.

Step 5: Schedule the Combination

  1. In WinCC Flexible, open Schedules.
  2. Add a new schedule named UpdateEnergy with a 250 ms cycle.
  3. Link the schedule to a VBScript action that calls CombineWordsToFloat(SmartTags("Energy_HiWord").Value, SmartTags("Energy_LoWord").Value) and writes the result to SmartTags("Energy_kW").Value.

Step 6: Bind the Result to the HMI Screen

  1. Open the energy display screen.
  2. Add an Output field bound to the Energy_kW tag.
  3. Format the field with one decimal place (e.g., 999.9).

Solution 2: PLC-Side Mirroring in Modicon Premium / Micro

For installations with a Modicon Premium or Micro PLC already present, the PLC can act as a Modbus TCP master to the energy analyzer and write the reassembled float into its own %MW / %MD area. The HMI then reads the float directly from a 32-bit %MW location, eliminating the script-based workaround.

Step 1: Configure the PLC Ethernet Port

  1. Open the project in Unity Pro (now branded EcoStruxure Control Expert) for Modicon Premium/Micro.
  2. Add the Ethernet communication module (TSX ETY 110/120/4103 for Premium, TSX ETZ 410/510 for Micro).
  3. Configure IP address, subnet mask, and gateway to match the plant network.
  4. Enable the Modbus TCP server on port 502.

Step 2: Add a Modbus TCP Master Read Block

In Unity Pro, drop a READ_VAR function block into the MAST task. Configure it as follows:

Parameter Value
Slave IP Energy analyzer IP address
Slave Unit ID 255 (typical for Modbus TCP)
Function Code 4 (Read Input Registers)
Starting Register 217 (0-based offset for 30218)
Number of Registers 2 (one 32-bit float)
Destination %MW100:2 (two consecutive words)
Management Parameter Word at %MW200 for status

Step 3: Reassemble the Float at the PLC

The %MW area is byte-addressable in Modicon PLCs. To combine the two 16-bit words into a 32-bit float:

  1. Use the REAL_CONV or equivalent floating-point conversion function block to read the 32-bit value from %MW100:%MW101 as a single %MD100 location.
  2. Alternatively, write the reassembled float back into a separate %MD (e.g., %MD110) using a MOVE block in Structured Text or Ladder.
  3. For Modicon Micro (TSX 37) using PL7 Junior/Pro, the equivalent operation uses the floating-point arithmetic block, which consumes two consecutive %MW words and produces a %MF (Memory Float) result.

Step 4: Configure the WinCC Flexible Tag for Direct Float Read

  1. Add a new tag named Energy_kW in WinCC Flexible.
  2. Set the data type to Real.
  3. Set the address to %MD110 (or %MW110, depending on driver interpretation; verify with the driver help).
  4. The driver reads the 32-bit float directly from the Modicon PLC's %MD area via a single function code 03 holding register read.

Step 5: Verify End-to-End

  1. Force a value on the energy analyzer (e.g., 100.0 kW).
  2. Watch %MD110 in Unity Pro's animation table. Expect 100.0.
  3. Watch the Energy_kW tag in WinCC Flexible. Expect 100.0.

Solution 3: Modbus Gateway / Protocol Converter

If neither VBScript nor PLC-side mirroring is acceptable, a standalone Modbus gateway can remap the energy analyzer's input registers into a virtual Modbus slave's holding registers. The HMI then reads floats from the holding register area using the standard float tag binding.

Supported Hardware

  • HMS Anybus X-gateway Modbus TCP
  • Moxa MGate MB3170 / MB3270 series
  • Schneider EGX300 / Link150 gateway
  • Red Lion Data Station Plus

Configuration Example (Moxa MGate MB3170)

  1. Set the MGate as a Modbus TCP server (downstream to the HMI).
  2. Configure the upstream connection to the energy analyzer as a Modbus TCP client.
  3. Define a mapping rule: input register 30218-30219 → holding register 40001-40002 on the virtual server.
  4. Point the WinCC Flexible Modicon Modbus TCP/IP driver to the MGate's IP address as the slave.
  5. Read the float at %MW0 (which now transparently carries the energy analyzer's 3xxxx float payload).

Verification Procedure

After implementing any of the three solutions, run the following checks before sign-off:

1. Static Value Test

  1. Force the energy analyzer to a known value (e.g., 1234.56 kW).
  2. Check the HMI display matches within ±0.01 kW.
  3. Cross-check the raw Energy_HiWord and Energy_LoWord values against the IEEE 754 hex encoding:
Decimal Value IEEE 754 Hex High Word (dec) Low Word (dec)
0.0 0x00000000 0 0
1.0 0x3F800000 16256 0
1234.56 0x449A51EC 17562 20972
-100.0 0xC2C80000 49824 0
1.0E+38 0x7F7FFFFF 32639 65535

2. Range Sweep

  1. Sweep the energy analyzer input from 0.0 to full scale.
  2. Check for linear response with no sign flip, no scale error, and no dead band.

3. Negative Value Test

  1. If the energy analyzer reports negative values (e.g., export power in a PV system), force -100.0.
  2. Verify the sign is preserved end-to-end through the binding, the driver, and the HMI display.

4. Endianness Check

  1. Compare the HMI value against the energy analyzer's web interface or local display.
  2. If the value reads as 0.0000, a very large number (~1.7E+38), or a very small number (~1.2E-38), the word order is reversed. Swap the high and low word arguments in the VBScript or check the gateway mapping table.

5. Polling Latency Check

  1. Trigger a step change on the energy analyzer.
  2. Measure the time from the step event to the HMI display update.
  3. Acceptable latency for energy monitoring dashboards: 1-2 seconds.

Troubleshooting Matrix

Symptom Likely Cause Resolution
%IW field greyed out for float tag Driver design (by design) Apply Solution 1, 2, or 3
Value reads as 0.0000 Word order reversed Swap high and low words in the script
Value reads as ~1.2E-38 Exponent bits misread, sign handling off Confirm function code is 04 (Read Input Registers)
Value reads as ~1.7E+38 Exponent all-ones, mantissa non-zero Verify the input register base address (off-by-one error between 0-based and 1-based)
Value oscillates between two readings Polling cycle too short, two reads not atomic Increase the poll cycle to 500 ms or use PLC-side atomic read (Solution 2)
Connection drops intermittently TCP keepalive mismatch Enable Modbus TCP keepalive on the gateway / PLC Ethernet port
Value stable but wrong by a factor of 10 Modbus register address offset wrong Verify 0-based vs 1-based addressing (30218 → 217 or 218)
%MW field accepts float but reads garbage Holding register (4xxxx) misread as 3xxxx Reconfigure the driver connection or use the correct prefix
VBScript runtime error: overflow Integer overflow when shifting by 16 Use CLng() before shifting, mask with &HFFFF
Driver returns Modbus exception code 02 (Illegal Data Address) Energy analyzer does not have the requested register Verify the energy analyzer's register map against the requested %IW address
Driver returns Modbus exception code 04 (Slave Device Failure) Energy analyzer internal error, unsupported function Check energy analyzer logs; verify function code 04 is supported

Reference Tables

Modbus Register Address Offset (0-based vs 1-based)

A common source of off-by-one errors in field deployments is the offset between Modbus protocol's 0-based register numbering and the documentation's 1-based numbering:

Documented Register 0-based Offset (Driver) 1-based Offset (Documentation)
30001 0 1
30218 217 218
40001 0 1
49999 9998 9999

WinCC Flexible's Modicon driver uses 0-based offsets. Input register 30218 in the energy analyzer's documentation corresponds to %IW217 in the driver. Verify by reading a known register (e.g., a firmware version word) before scaling out the full register map.

IEEE 754 Quick Reference

Format Sign Exponent Mantissa Bias Total Bits Modbus Registers
Single (REAL) 1 8 23 127 32 2
Double (LREAL) 1 11 52 1023 64 4
Half (REAL16) 1 5 10 15 16 1

Modbus applications use single-precision (32-bit) as the standard float format. Double-precision is rare in process instrumentation; half-precision is essentially never used in Modbus.

IEEE 754 Single-Precision Decoding Formula

For a 32-bit unsigned integer raw reconstructed from two Modbus words:

sign     = (raw AND 0x80000000) / 0x80000000   ' 0 or 1
exponent = (raw AND 0x7F800000) / 0x00800000   ' 0-255
mantissa = (raw AND 0x007FFFFF) / 0x00800000   ' 0.0 - ~0.9999

if exponent == 0:
    value = 0
elif exponent == 255:
    value = NaN or Inf
else:
    value = (-1)^sign * 2^(exponent - 127) * (1 + mantissa)

This formula is the reference for the VBScript implementation in Solution 1. See the National Instruments Modbus Protocol Reference for additional background on Modbus data encoding and endianness conventions.

Quick Reference: Solution Selection

Criterion Solution 1 (VBScript) Solution 2 (PLC Mirror) Solution 3 (Gateway)
HMI tags required 2 INT + 1 REAL 1 REAL 1 REAL
HMI tag addresses %IW217, %IW218, internal %MD110 %MW0 (via gateway)
PLC programming None READ_VAR + float block None
Additional hardware None None Modbus gateway
Update latency 250 ms (HMI cycle) 100-200 ms (PLC scan) 50-100 ms (gateway)
Engineering effort Medium High Low
Field reliability Good (script-based) Excellent (PLC-native) Excellent (transparent)
Recommended for 1-3 meters, fast deployment Existing Premium/Micro PLC, many tags Many 3xxxx devices, central HMI

FAQ

Why does the %IW address field grey out when I select a Real (float) data type in WinCC Flexible?

The Modicon Modbus TCP/IP driver in WinCC Flexible binds 32-bit data types (REAL, DINT, DWORD) to %MW only. The %IW area is reserved for 16-bit input words, reflecting the Modicon hardware convention where %IW maps to physical 16-bit input modules. This is a design constraint of the driver, not a project setting that can be changed.

Can I read a 32-bit float from a Modbus input register (3xxxx) directly into a WinCC Flexible float tag?

No, not directly through the %IW path. You must either (1) read two consecutive %IW addresses as 16-bit INT tags and combine them in a VBScript into a REAL, (2) have the Modicon PLC read the input register and mirror the reassembled float into its %MD area, or (3) deploy a Modbus gateway that remaps 3xxxx into 4xxxx holding registers.

What is the correct Modbus register offset for input register 30218 in WinCC Flexible?

WinCC Flexible's Modicon Modbus TCP/IP driver uses 0-based offsets. Register 30218 in the device documentation corresponds to %IW217 in the driver. The next consecutive word is %IW218. The high word is at the lower %IW address because Modbus transmits big-endian: high word first, low word second.

Why does the float read as 0.0000 or as a very large number (~1.7E+38)?

Almost always a word-order issue. Modbus big-endian puts the high word at the lower register address. If the VBScript receives the words in the wrong order, the IEEE 754 exponent field ends up in the wrong bit position, producing either 0 (exponent = 0) or the maximum representable value (exponent = 255 with non-zero mantissa). Swap the operands at the call site and re-test.

Is the OPC server approach (KEPwareEX, Matrikon) faster than direct Modbus TCP for this use case?

No. OPC DA introduces 200-500 ms of update latency per poll cycle, and OPC UA adds 100-300 ms even on a local network. Direct Modbus TCP from WinCC Flexible to the energy analyzer cycles in 100-250 ms. For real-time energy monitoring, the VBScript combination approach (Solution 1) or PLC-side mirroring (Solution 2) is significantly faster than OPC.

Back to blog