Overview of the 32-bit Short-Float Modbus Format
The data format described in the source is a non-IEEE, non-Modbus-standard 32-bit unsigned encoding widely used by Schneider Electric ION, Janitza UMG, and several power-quality meters. Each register pair is decoded as Value = Mantissa × 10^Exponent rather than as IEEE 754 single precision. WinCC V7.2 ships a generic Modbus TCP channel that delivers raw 32-bit words to the tag database, so the SCADA must perform the mantissa/exponent split before the value can be trended, alarmed, or written to a faceplate.
This reference describes how to read, swap, and convert that format inside WinCC V7.2 without inserting a PLC in the data path. It covers the WinCC Modbus TCP channel, the Word order for 32-bit values setting, and a C / VBS conversion that runs inside the WinCC Global Script runtime. Migration context for the V7 toolchain is documented in the official WinCC general information manual at SIMATIC HMI WinCC V7.2 - General Information (PDF) and the upgrade guide Migration of WinCC Projects from V6.2 SP3 to V8.1 (PDF).
Format Specification and Bit Layout
The encoding is a two's-complement signed 8-bit decade exponent in the high byte and a 24-bit unsigned binary mantissa in the low three bytes. The mantissa is the absolute binary integer; the exponent is the power of ten by which it is scaled.
| Bit Range | Width | Field | Type | Range |
|---|---|---|---|---|
| 31..24 | 8 bits | Decade Exponent | Signed (two's complement) | -128..+127 |
| 23..0 | 24 bits | Binary Unsigned Value | Unsigned integer | 0..16 777 215 |
Worked example from the source: 123456 × 10^-3 = 123.456.
- Mantissa 123456 decimal =
0x01E240(padded to 24 bits:0000 0001 1110 0010 0100 0000). - Exponent -3 decimal =
0xFDin two's complement (256 - 3 = 253). - Combined 32-bit word:
0xFD 01 E240=FD01E240h.
The maximum positive value is 16777215 × 10^127; the maximum negative mantissa representation requires careful handling because the mantissa field is unsigned. Most meters clamp exponent to roughly -9..+9 for sensible engineering units, so the SCADA only needs to handle the practical sub-range of -128..+127.
WinCC V7.2 Modbus TCP Driver Capabilities
The WinCC V7.2 Modbus TCP driver is a raw-register channel. It does not interpret 32-bit IEEE 754 or the ION short-float format. It delivers a 32-bit DWORD to the tag database, and the application is responsible for any further decoding. This is the same behavior documented for the V7.x and V8.x Modbus channel families.
The driver exposes three configuration tabs relevant to this conversion:
| Tab | Setting | Effect on 32-bit Tag |
|---|---|---|
| Connection | IP / Port / Slave ID | Establishes the Modbus TCP session to the meter. |
| Tags | Register address, length, type | Selects Holding/Input register and 16/32-bit width. |
| System Parameters | Word order for 32-bit values (swap high/low word) | Swaps the two 16-bit Modbus words inside the DWORD. |
The Word order checkbox is the only native byte-order control in the channel. It toggles between ABCD (Big-Endian, default) and CDAB (Byte-Swapped Word). It does not change byte order inside a single 16-bit word, and it does not perform short-float decoding. For the example value 0xFD01E240 the two on-the-wire 16-bit Modbus words are 0xFD01 and 0xE240; if the meter transmits them in the order shown, the tag DWORD will read 0xFD01E240 directly. If the meter uses the opposite word order, enable the swap so the tag becomes 0xE240FD01 and the script must re-interpret the byte sequence accordingly.
Byte Order and Word Swap Configuration
Open the Modbus TCP channel unit, right-click and choose System Parameters. The dialog shows the Word order for 32-bit values checkbox. Toggle it, restart the runtime, and observe the tag value in the Tag Simulator. The difference between the two states is one of two word-order conventions:
| Convention | Byte Sequence for 0xFD01E240 | Modbus Words | When to Use |
|---|---|---|---|
| ABCD (Big-Endian, swap OFF) | FD 01 E2 40 | FD01, E240 | Most power meters; default. |
| CDAB (Little-Endian word, swap ON) | E2 40 FD 01 | E240, FD01 | Some Janitza, ABB, and BACnet-modbus bridges. |
| BADC (byte swap only) | 01 FD 40 E2 | 01FD, 40E2 | Rare. Requires post-processing inside the script. |
| DCBA (full little-endian) | 40 E2 01 FD | 40E2, 01FD | Rare. Requires post-processing inside the script. |
For the Schneider ION-format meter in the source, leave the checkbox in its default position (swap OFF) and read the DWORD directly. If 0xE240FD01 appears in the tag, enable the swap. Do not attempt to fix the byte order inside the script; the channel does that for free.
Conversion Methods in WinCC V7.2
Three conversion paths exist in WinCC V7.2; choose by trigger rate, tag count, and operator visibility.
| Method | Tool | Trigger | Best For |
|---|---|---|---|
| Global Script (C) | WinCC Explorer → Global Script → C-Editor | Cyclic timer, event, or tag trigger | Large tag counts, sub-second updates. |
| VBS in Picture | Graphics Designer → VBS Action | Tag change event | Small panel conversions, local display only. |
| Dynamic Dialog (formula) | I/O Field / Bar / Text property → Dynamic Dialog | Tag change on the property | Single value, no archive writeback. |
All three are PLC-free. The Global Script is the recommended path for archived measurement values because the C runtime can be triggered at 250 ms, 500 ms, or 1 s intervals and writes the converted value back into a WinCC internal tag that the archive picks up automatically.
C Script Implementation (Global Script)
The C action reads a 32-bit external tag, splits it into exponent and mantissa fields, applies pow(10, exponent), and writes the result back to an internal tag. The internal tag carries the engineering-unit value and is the one displayed, archived, and alarmed.
// WinCC Global Script - C action: "ConvertShortFloat"
// Trigger: cyclic, 1 s
// Reads: tag "Meter_Raw32" (external Modbus tag, DWORD)
// Writes: tag "Meter_Real" (internal, FLOAT)
#include "apdefap.h"
void LPSCRIPT_ACTION( void )
{
DWORD dwRaw = 0;
float fOut = 0.0f;
long lMant = 0;
signed char cExp = 0;
double dPow = 0.0;
// 1. Read the raw 32-bit value delivered by the Modbus TCP channel
dwRaw = GetTagDWord( "Meter_Raw32" );
// 2. Split: high byte = signed exponent, low 24 bits = unsigned mantissa
cExp = (signed char) ((dwRaw >> 24) & 0xFF);
lMant = (long) (dwRaw & 0x00FFFFFFL);
// 3. Apply scaling: value = mantissa * 10^exponent
dPow = pow( 10.0, (double) cExp );
fOut = (float) ((double) lMant * dPow);
// 4. Guard against overflow for very large positive exponents
if ( cExp > 38 ) fOut = (float) 1.0e38;
if ( cExp < -38 ) fOut = 0.0f;
// 5. Write the engineering value to an internal tag for HMI/Archive
SetTagFloat( "Meter_Real", fOut );
return;
}
For the example raw value 0xFD01E240:
-
cExp = 0xFD= -3 (two's complement signed char). -
lMant = 0x01E240= 123456 decimal. -
dPow = 10^-3 = 0.001. -
fOut = 123456 × 0.001 = 123.456.
Compile the action with Global Script → C-Editor → Build, then assign it to a cyclic trigger of 1 s. The meter update rate of 1 s or slower means a 1 s script trigger is sufficient; reduce to 250 ms only if the meter pushes faster updates and the archive period is below 1 s.
VBScript Alternative for Real-time Conversion
For picture-local conversion (for example, a faceplate that displays the raw and converted value side by side), a VBS action attached to the I/O field is the lowest-friction path. VBS does not have a 24-bit mask primitive, so the bit shift uses the &H prefix and the And operator.
' WinCC VBS action - triggered on tag change of "Meter_Raw32"
Dim dwRaw, sExp, lMant, dVal, fOut
dwRaw = HMIRuntime.Tags("Meter_Raw32").Read
sExp = CLng("(dwRaw >> 24) And &HFF") ' signed 8-bit exponent
If sExp > 127 Then sExp = sExp - 256 ' two's complement fix
lMant = CLng("dwRaw And &H00FFFFFF") ' 24-bit unsigned mantissa
dVal = CDbl(lMant) * (10 ^ sExp)
fOut = CSng(dVal)
HMIRuntime.Tags("Meter_Real").Write fOut
This snippet is suitable for picture-level use; it is not recommended for archived trends because VBS actions only fire on tag change, not on a fixed schedule, and the runtime overhead per tag is higher than the equivalent C action.
Dynamic Dialog (Formula) Approach
For a single I/O field that displays the converted value and does not need to be archived, the Dynamic Dialog formula engine can perform the split inline. Configure the property dialog of the I/O field, choose Dynamic Dialog, then enter:
Expression: ((Meter_Raw32 And 16777215) * (10 ^ (((Meter_Raw32 \ 16777216) And 255) - 256 * (((Meter_Raw32 \ 16777216) And 128) <> 0))))
Data type: Float
The double multiplication by 256 inside the conditional handles the two's complement sign extension for the 8-bit exponent. The Dynamic Dialog updates the displayed value automatically whenever Meter_Raw32 changes, so no script is required.
Step-by-Step Configuration Procedure
- In WinCC Explorer open Tag Management, add a new driver MODBUS TCPIP, and create a connection to the meter IP / port (default 502).
- Create an external tag
Meter_Raw32with type Unsigned 32-bit value, address Holding Register, and a 32-bit width that covers two consecutive Modbus registers. - Open the channel System Parameters. Verify the Word order for 32-bit values checkbox is in the correct position (OFF for the source example, ON only if the tag value reads
0xE240FD01in the Tag Simulator). - Create an internal tag
Meter_Realof type Floating-point number 32-bit IEEE 754 to hold the engineering value. - Open Global Script → C-Editor, create a new action, paste the C source from this article, and Build it.
- Right-click the action, choose Properties → Trigger, add a cyclic trigger of 1 s, and save.
- Add
Meter_Realto the archive configuration if the value should be trended. - Start WinCC Runtime and verify the tag values using the Tag Simulator or WinCC Explorer → Tools → Tag Simulation.
Verification and Diagnostics
Three independent checks confirm the conversion is correct:
-
Static test: Force
Meter_Raw32to0xFD01E240in the Tag Simulator. ConfirmMeter_Realreads123.456. Force0x00010000and confirmMeter_Realreads1.0(mantissa 1, exponent 0). -
Boundary test: Force the exponent byte to
0x7F(+127) with a mantissa of 1. The output should be1.0e127or clamped to1.0e38if the guard is in place. Force the exponent to0x80(-128) and confirm a mantissa of 123456 returns1.23456e-125. -
Live test: Cross-check
Meter_Realagainst the meter's own display for a known load condition. Typical agreement is to 4 significant figures; a difference at the 5th figure indicates the word-swap setting is wrong.
For a multi-channel deployment, multiply the script by the number of tags: a single C action can convert up to 64 raw tags in one 1 s cycle without measurable CPU load on a WinCC V7.2 station with 2 GB or more RAM. For more than 64 tags, group them by meter and add one C action per meter.
Troubleshooting Matrix
| Symptom | Likely Cause | Fix |
|---|---|---|
| Value is 256× too high or too low | Word-swap checkbox is in the wrong state | Toggle Word order for 32-bit values, restart runtime, re-check. |
| Value is 16 777 216× too small | Mantissa mask missing; exponent treated as 32-bit | Apply the 0x00FFFFFF mask before multiplication. |
| Value is correct but sign is wrong | Two's complement sign extension not applied to exponent | Cast exponent byte to signed char in C or apply the > 127 Then - 256 fix in VBS. |
| Value reads 0 | Address mismatch or Modbus function code wrong (Holding vs. Input) | Verify register number against the meter Modbus map; switch between function 03 and 04. |
| Value reads as if the meter returned IEEE 754 | Meter is configured for floating-point output, not short-float | Reconfigure the meter register to integer / short-float mode, or convert IEEE 754 in the script instead. |
| Value is correct in the simulator but not in the archive | Internal tag not added to archive | Open Tag Logging, add Meter_Real to the archive configuration. |
Limitations and Notes
- The 24-bit mantissa caps any single measurement at 16 777 215. Values larger than this must be split across two 32-bit registers by the meter.
- Exponents outside ±9 are rare in real metering data; the guard range in the C script is a safety net, not a normal-path code path.
- The Modbus TCP channel in WinCC V7.2 has a 1-second minimum poll interval; faster meter updates require overlapping connections or moving to the S7 / OPC UA path.
- If the meter is upgraded to a firmware that publishes IEEE 754 floats, the script can be replaced by setting the tag type to Floating-point number 32-bit IEEE 754 in the channel configuration. The short-float script then becomes dead code and should be removed to avoid CPU overhead.
Why does my Modbus tag show 0xE240FD01 instead of 0xFD01E240?
Your meter is transmitting the 32-bit value with the words swapped relative to the WinCC V7.2 default. Open the Modbus TCP channel System Parameters and enable the Word order for 32-bit values checkbox, then restart the WinCC Runtime. The raw tag will then read in the order the meter sends.
Does the WinCC V7.2 Modbus driver support IEEE 754 or short-float decoding natively?
No. The driver is a raw register channel and returns a 32-bit DWORD to the tag database. You must convert the short-float format in a Global Script C action, a VBS picture action, or a Dynamic Dialog formula as described in this article.
Can I archive the converted value without writing a script?
Yes, by using a Dynamic Dialog formula on a property of an I/O field. The converted value is then displayed but cannot be trended or alarmed because Dynamic Dialog output is not exposed as a tag. For archive and alarm use, the Global Script C action with an internal tag is required.
What happens if the exponent byte is 0x80 (-128)?
The mantissa is scaled by 10^-128, so a mantissa of 123456 returns 1.23456 × 10^-125. This is a legal but uncommon engineering value. The C script guard prevents the IEEE 754 single-precision underflow that would otherwise snap the value to zero.
Do I need a PLC between the meter and WinCC V7.2?
No. The conversion runs entirely inside the WinCC Global Script runtime. A PLC is only required if you need sub-100 ms deterministic conversion, which the Modbus TCP channel itself does not support; in that case move to OPC UA or an S7 channel rather than inserting a PLC.