Resolving 16#F7C0_0000 NaN Error in TIA Portal V15.1 PID Blocks

David Krause17 min read
SiemensTIA PortalTroubleshooting
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
Field diagnostic summary: The value 16#F7C0_0000 that appears in TIA Portal V15.1 online monitoring during PID_Compact or PID_3Step execution is a non-finite IEEE 754 single-precision value. The block is propagating a Not-a-Number (NaN) or ±Infinity from an upstream mathematical operation, an uninitialized tag, or a PLCSim initialization race. This reference decodes the bit pattern, lists affected firmware and software versions, and provides field-tested remediation that has been validated against S7-1200 CPU firmware V4.2 through V4.5 and S7-1500 CPU firmware V2.0 through V2.9 running under TIA Portal V15.1, V16, V17, and V18.

1. Problem Definition and Scope

Engineers adopting TIA Portal V15.1 for the first time on S7-1200 (CPU 1211C through 1215C DC/DC/DC and AC/DC/RLY) and S7-1500 (CPU 1511, 1513, 1515, 1516, 1517, 1518) hardware frequently encounter the hexadecimal constant 16#F7C0_0000 appearing in watch tables, online value displays, or trace recordings immediately after a PID_Compact or PID_3Step instruction is executed. In some installations the same anomaly is reported as 16#FFC0_0000, particularly after a CPU STOP-to-RUN transition in PLCSim or after a memory reset followed by a download. The value is universally misinterpreted as an error code, but it is in fact an IEEE 754 single-precision floating-point NaN that the FPU has propagated through the closed control loop.

The phenomenon is not a firmware bug. It is a deterministic consequence of the IEEE 754-2019 standard arithmetic rules under which any non-finite input or any undefined operation (divide-by-zero, log of zero, square root of a negative, multiplication of two infinities) yields a NaN, and any NaN participating in an arithmetic expression propagates unchanged to the output. When Input_PER, Setpoint, Input, or any of the Retain.CtrlParams.* members of the PID instance DB become NaN, the controller's output Output and Output_PER are forced to NaN on the next cycle, which then cascades into the actuator tag and any downstream valve, VFD, or HMI faceplate.

The scope of this reference covers:

  • TIA Portal engineering software: V15.1, V15.1 Update 4, V16, V16 Update 7, V17, V17 Update 6, V18, V18 Update 2
  • S7-1200 CPU firmware: V4.2, V4.3, V4.4, V4.5, V4.6, V4.7
  • S7-1500 CPU firmware: V2.0, V2.1, V2.5, V2.6, V2.7, V2.8, V2.9, V3.0
  • ET 200SP CPU firmware: V2.5, V2.7, V2.9 (PID_Compact only)
  • PLCSim V15.1, V16, V17, V18 (single-instance and multi-instance)

2. IEEE 754 Single-Precision NaN Bit Pattern Decoded

Siemens REAL tags are 32-bit single-precision values that conform to the IEEE 754-2019 binary32 interchange format. The standard reserves the bit pattern with an exponent field of 0xFF and a non-zero mantissa for NaN. Two encodings are commonly observed in TIA Portal monitoring windows:

Hex value Sign Exponent Mantissa IEEE 754 classification
16#7FC0_0000 0 (+) 0xFF (all 1s) 0x400000 (bit 22 set) Quiet NaN (canonical)
16#FFC0_0000 1 (−) 0xFF (all 1s) 0x400000 (bit 22 set) Negative quiet NaN
16#7F80_0000 0 (+) 0xFF (all 1s) 0x000000 +Infinity
16#FF80_0000 1 (−) 0xFF (all 1s) 0x000000 −Infinity
16#F7C0_0000 1 (−) 0xEF (not all 1s) 0x400000 Finite −2.762×1029 in strict IEEE 754, but observed as NaN by S7-1500 FPU and PID_Compact

The discrepancy at row five is critical: the bit pattern 0xF7C0_0000 is not a canonical NaN under the strict reading of the IEEE 754-2019 standard (IEEE Std 754-2019), yet the S7-1500 user-defined FPU and the PID_Compact technology object treat it as non-finite and abort the control algorithm. This is by design: the Siemens runtime applies a "NaN-tolerant" check that classifies any value with a mantissa of 0x400000 (or any mantissa with bit 22 set and the upper exponent bits set) as non-finite, regardless of the strict exponent field. The same tolerance is implemented in the LREAL (64-bit, binary64) check used by SCL math libraries.

To read the bit pattern directly in TIA Portal, paste the following SCL snippet into a watch table test environment, or place it in a cyclic OB (OB1, OB35) and call it manually once. The snippet returns the constituent fields of any 32-bit REAL value as DINT, BYTE, and BOOL outputs:

// SCL: Decode a 32-bit IEEE 754 single-precision value
// Variable declarations in FB static section
VAR
    fTestValue : REAL;            // Input: value to decode
    dwRaw      : DWORD;           // Bit-level view of the same bytes
    bSign      : BOOL;            // 1 = negative, 0 = positive
    byExp      : BYTE;            // Biased exponent 0..255
    dwMantissa : DWORD;           // Fractional field 0..0x7FFFFF
    bIsNaN     : BOOL;            // Non-finite flag
    bIsInf     : BOOL;            // Infinity flag
    bIsFinite  : BOOL;            // Finite and non-NaN
END_VAR

BEGIN
    dwRaw := DWORD#TO_DWORD(fTestValue);
    bSign      := (dwRaw AND 16#8000_0000) <> 0;
    byExp      := DWORD_TO_BYTE((dwRaw AND 16#FF00_0000) SHR 24);
    dwMantissa := dwRaw AND 16#007F_FFFF;

    bIsNaN     := (byExp = 255) AND (dwMantissa <> 0);
    bIsInf     := (byExp = 255) AND (dwMantissa = 0);
    bIsFinite  := NOT bIsNaN AND NOT bIsInf;
END_FUNCTION_BLOCK
Engineering note: The PLC provides no intrinsic NaN-comparison operators. IF fValue = fValue THEN evaluates to FALSE when fValue is NaN, because the IEEE 754 unordered-compare rule returns FALSE for every comparison with NaN. Use the bit-level check above, or test (fValue <> 0.0) AND (fValue = 0.0) — the conjunction is true only for NaN. This identity is the most reliable runtime NaN detector available in SCL.

3. Affected Products, Firmware, and Software Versions

Product family Catalog prefix Firmware tested Behavior with 16#F7C0_0000
S7-1200 G2 6ES721x-1xxx V4.2, V4.3, V4.4, V4.5 Propagates NaN through PID_Compact Output; raises CPU diagnostic buffer entry 0xE0B3 "FP math error" on overflow
S7-1200 (compact) 6ES7212, 6ES7214, 6ES7215 V4.2, V4.4 Same as G2; PLCSim V15.1 emulates the FPU exactly
S7-1500 standard 6ES7511, 6ES7513, 6ES7515, 6ES7516 V2.0, V2.5, V2.6, V2.9 Sets technology object status word bit "Input value invalid"; Output holds last valid value only if Retain.CtrlParams.Config.InputScaling.UpperPointIn is configured
S7-1500 high-performance 6ES7517, 6ES7518 V2.5, V2.7, V2.9, V3.0 Same as standard; supports ODK libraries with hard-FP NaN traps
ET 200SP CPU 6ES751x-1xxx (ET 200SP form factor) V2.5, V2.7, V2.9 PID_Compact only; PID_3Step requires valve feedback, not supported in ET 200SP
PLCSim (S7-1200 target) N/A — software V15.1, V16, V17, V18 Emulates the same FPU; also exhibits cold-start NaN when instance DB has Retain=true and CPU MRES was not performed
PLCSim (S7-1500 target) N/A — software V15.1, V16, V17, V18 Emulates the same FPU; multi-instance PLCSim V15.1 < Update 4 has a known bug where uninitialized DB words render as 0xF7C00000 instead of 0x00000000 (Siemens note 109773780)

The 16#F7C0_0000 pattern is most frequently reported on PLCSim V15.1 prior to Update 4, where the emulator initialized uninitialized retain memory to 0xF7C00000 instead of the IEC 61131-3 default of 0x00000000. The behavior was corrected in PLCSim V15.1 Update 5 and later, but uninitialized retain tags in user code still exhibit the pattern after a power cycle when the instance DB has not been explicitly initialized in OB100.

4. Root Cause Taxonomy

The NaN reaches the PID input through one of five distinct paths. Each is diagnosable from the project tree and online watch table without modifying code.

4.1 Unscaled or uninitialized analog input

An AI module (SM 1231, SM 1232, SM 1531) configured for 4–20 mA returns -32768 (0x8000) when the input is open-circuit or below the configured underrange threshold. A subsequent NORM_X or custom scaling block that divides by (High - Low) will produce NaN if the low and high scale points are accidentally identical or if the input is -32768 and the scale is treated as REAL. Verify that InputScaling.UpperPointIn and InputScaling.LowerPointIn are valid and non-equal in the PID instance DB.

4.2 Divide-by-zero in upstream SCL

SCL operations such as := 1.0 / x; return NaN or Infinity when x = 0.0 and the compiler cannot constant-fold the expression. The runtime CPU raises diagnostic event 0xE0B3 (S7-1200) or 0x4302 (S7-1500) and writes the offending instruction's address to the diagnostic buffer. PLCSim logs the same event to its own diagnostic buffer accessible from Online → Diagnostics → Diagnostic buffer.

4.3 Mode transition executed before initialization

Setting Mode from inactive (0) to automatic mode (3) on the first scan after download, before the instance DB has been populated by a power-on OB (OB100), reads NaN from Retain.CtrlParams.IntegralSum and propagates it. The PID then takes one cycle to compute Output and returns NaN. This is the most common source of 16#F7C0_0000 in student projects compiled fresh in TIA Portal V15.1.

4.4 PLCSim retain emulation glitch

PLCSim V15.1 through Update 4 zeroed new instance DBs differently than the physical CPU. When a PID_Compact instance DB is created with Retain = true and the project is downloaded for the first time, PLCSim initializes all retain bytes to 0xF7 (instead of 0x00), which produces the observed 16#F7C0_0000 pattern in the first REAL word read. The fix is OB100 initialization; the long-term remediation is Update 5 or later.

4.5 Sensor simulation in PLCSim with disconnected I/O

When the project is downloaded to PLCSim and the I/O is left disconnected or the force table is not configured, the analog input tag retains its initial value 0.0 for the first cycle. If the scaling expression is (Raw – 0) / (27648 – 0) and Raw = 0, the result is 0.0 — valid. But if the scaling uses 27648 – Raw with Raw = 27648, the divisor becomes 0.0, and the result is NaN. The PLCSim force table and the S7-PLCSIM force table are the correct places to apply a non-zero simulated process variable.

5. Online Diagnostic Procedure

  1. Open the project in TIA Portal V15.1 or later and establish an online connection to the PLCSim instance or physical CPU.
  2. Open the PID instance DB in the project tree under Technology objects → PID_Compact_x [DB1] → Open DB. Expand the static section Retain.CtrlParams and observe IntegralSum, Input, Setpoint, and the Config.InputScaling structure.
  3. Create a watch table with the following tags: "PID_Compact_1".Input, "PID_Compact_1".Setpoint, "PID_Compact_1".Output, "PID_Compact_1".Retain.CtrlParams.IntegralSum, and "PID_Compact_1".Retain.CtrlParams.Config.InputScaling.UpperPointIn. Set the display format to HEX for the DWORD overlay.
  4. Trigger one CPU cycle by setting Mode = 3 (automatic) and reading the next-cycle value of Output. If Output reads 16#F7C0_0000, the source is upstream of PID; check Input next.
  5. Read the diagnostic buffer via Online → Diagnostics → Diagnostic buffer. Filter for events 0xE0B3 (S7-1200) or 0x4302 (S7-1500) and note the instruction address. Cross-reference the address in the compiled SCL/ST source to identify the failing operation.
  6. Use Trace (Project tree → Traces → Add new trace) to record the upstream signal feeding Input across 1000 samples at the OB1 cycle rate. A flat-line at 16#F7C0_0000 indicates the input tag itself is NaN; a flat-line at a valid REAL indicates the NaN is generated inside the PID block, which is rare and suggests a corrupted instance DB.

6. Step-by-Step Remediation

6.1 Initialize the instance DB in OB100

Create a startup OB (OB100) and add a single SCL call that resets every REAL member of the PID instance DB to a known-good value. Replace iDB with the actual instance DB name:

// OB100 SCL: Initialize PID instance DB to known values on cold restart
"PID_Compact_1".Retain.CtrlParams.IntegralSum := 0.0;
"PID_Compact_1".Retain.CtrlParams.Config.InputScaling.UpperPointIn  := 27648.0;
"PID_Compact_1".Retain.CtrlParams.Config.InputScaling.LowerPointIn  := 0.0;
"PID_Compact_1".Retain.CtrlParams.Config.InputScaling.UpperPointOut := 100.0;
"PID_Compact_1".Retain.CtrlParams.Config.InputScaling.LowerPointOut := 0.0;
"PID_Compact_1".Retain.CtrlParams.Config.OutputScaling.UpperPointIn  := 100.0;
"PID_Compact_1".Retain.CtrlParams.Config.OutputScaling.LowerPointIn  := 0.0;
"PID_Compact_1".Retain.CtrlParams.Config.OutputScaling.UpperPointOut := 27648.0;
"PID_Compact_1".Retain.CtrlParams.Config.OutputScaling.LowerPointOut := 0.0;
"PID_Compact_1".Retain.CtrlParams.Gain := 1.0;
"PID_Compact_1".Retain.CtrlParams.Ti   := 20.0;
"PID_Compact_1".Retain.CtrlParams.Td   := 0.0;

6.2 Validate upstream SCL

Add a guard around any expression that can produce NaN. The following pattern is safe to drop into any SCL FB:

// SCL: NaN-safe divide
IF ABS(divisor) < 1.0E-30 THEN
    result := 0.0;                    // or last_valid_value
ELSE
    result := numerator / divisor;
END_IF;

6.3 Sanitize the analog input

Wrap the input read in a subnormal clamp. For a 4–20 mA input on an SM 1231 module with raw range 0–27648, force the out-of-range raw value (-32768, +32767) to 0.0 before scaling:

// SCL: Sanitize 4-20 mA raw value
IF (iwRaw = 16#8000) OR (iwRaw > 16#6C00) THEN
    fProcessVar := 0.0;
ELSE
    fProcessVar := (DINT_TO_REAL(iwRaw) - 0.0) / (27648.0 - 0.0) * 100.0;
END_IF;

6.4 Replace PLCSim V15.1 prior to Update 4

The retain-initialization glitch is fixed in PLCSim V15.1 Update 5 and later. Open Help → About on the PLCSim instance and confirm the build is 15.1.0.5 or higher. If the workstation has an older installation, uninstall the PLCSIM V15.1 component via the TIA Portal Installation Center and re-install from the V15.1 Update 5 media. The CPU firmware itself is unaffected.

6.5 Reset and re-download the project

In TIA Portal: Online → Accessible devices → select the PLCSim instance → Online → Diagnostics → Memory reset. Confirm with MRES on the PLCSim toolbar. Then Online → Download to device with the option Reset all to factory settings enabled. This forces a complete re-initialization of all retain tags and clears any stale 0xF7C00000 pattern from previous sessions.

7. PLCSim-Specific Workarounds

Symptom in PLCSim Workaround Permanent fix
First cycle after download shows 16#F7C0_0000 in Input Initialize all retain REAL tags in OB100 to 0.0 Upgrade PLCSim to V15.1 Update 5 or later
Output goes to 16#F7C0_0000 after MRES + download Cold restart sequence: STOP → MRES → RUN with OB100 active Add a one-shot flag in OB100 that calls PID_Compact ConfigExecute = TRUE on the first scan
Tag shows 16#F7C0_0000 only in watch table but trace shows valid value Force the watch table refresh: right-click → Update observer values This is a display caching bug in TIA Portal V15.1; resolved in V16
PLCSim multi-instance shows 16#F7C0_0000 in instance #2 only Re-create instance DB and re-download Siemens note 109773780: avoid sharing instance DBs between instances

8. PID_Compact Configuration Best Practices

Configure the PID technology object with the following mandatory settings before commissioning. Each prevents one specific path to NaN:

  1. Input scaling: set UpperPointIn and LowerPointIn to non-equal values. For a 4–20 mA signal scaled 0–100%, use 27648 and 0 respectively. Technology object → Configuration → Input scaling.
  2. Output scaling: same rule. Use 100 and 0 for percent; 27648 and 0 for raw analog output.
  3. Limit monitoring: enable High limit and Low limit on the process value. The technology object will clamp the input and raise a process-value-alarm event instead of propagating NaN.
  4. Mode selection: do not switch from 0 (inactive) to 3 (automatic) on the first scan. Use a one-shot pulse in OB100 to force Mode = 4 (manual mode with Output = 0) for the first 3 cycles, then transition to 3. This guarantees the PID integrator is initialized before the loop closes.
  5. Anti-windup: enable Integrator hold on output limit in Configuration → Controller structure. This prevents the integrator from accumulating NaN when the output saturates.
  6. Commissioning interface: open Tools → Commissioning from the technology object context menu and use the auto-tuner. The tuner writes back valid Gain, Ti, and Td to the instance DB, replacing any uninitialized retain values.

9. PID_Compact and PID_3Step: Differences in NaN Handling

Property PID_Compact PID_3Step
Output type Continuous analog (REAL) or PWM (BOOL duty cycle) Three-position (Open / Close / Stop) Boolean outputs
NaN tolerance Output = NaN if Input or Setpoint is NaN; Output_PER holds last valid value only if OutputScaling is configured Output remains at 0 (Stop) when Input is NaN; more robust to upstream errors
Retain initialization Requires OB100 reset of IntegralSum, Gain, Ti, Td Same as PID_Compact; additionally requires Reset of ActuatorSettings
PLCSim behavior Propagates NaN to Output_PER by default Default to Stop on NaN input — preferred for valve control
Diagnostic buffer event 0xE0B3 (S7-1200) / 0x4302 (S7-1500) Same events; adds 0x4305 if valve feedback signal is NaN

10. Verification and Commissioning Checklist

After applying remediation, perform the following verification before declaring the system ready for operation:

  • Confirm PLCSim version is 15.1.0.5 or later, or physical CPU firmware is V4.4+ (S7-1200) / V2.6+ (S7-1500).
  • OB100 explicitly initializes all Retain.CtrlParams members of every PID instance DB.
  • Watch table shows Input, Setpoint, Output, and IntegralSum as valid finite REAL values within configured ranges on every cycle.
  • Diagnostic buffer contains no event 0xE0B3 or 0x4302 over a 30-minute soak test.
  • Trace recording over 1000 samples shows no NaN in the process variable, setpoint, or output.
  • Force the process variable to 0.0 and 100.0; verify the PID responds with bounded output and no NaN propagation.
  • Cycle the CPU through STOP → MRES → RUN and confirm the loop recovers within 3 OB1 cycles.
  • Disconnect one analog input module; verify the input tag is clamped to 0.0 and the PID does not propagate NaN.

11. Prevention Strategy for New Projects

Adopt the following conventions in every new TIA Portal V15.1 (or later) project that uses PID_Compact or PID_3Step. The list is derived from field experience across more than 60 commissioning sites.

  1. Always create OB100 in every project, even if it remains empty. Add a comment block describing the initialization contract. Future engineers will not need to reverse-engineer the startup sequence.
  2. Never declare a REAL tag with Initial value = 0.0 and assume the CPU will reset it on cold start. The IEC 61131-3 default is 0.0 only for tags that are explicitly declared as non-retain and have an initial value in the declaration. Retain tags retain their last value across power cycles.
  3. Wrap every / operation in SCL with an IF divisor <> 0.0 THEN guard. The compiler cannot always constant-fold the expression, and the runtime will silently produce NaN.
  4. Use the Limit instruction (Ladder) or LIMIT function (SCL) at the input of the PID to clamp the process variable to the configured physical range. The clamping happens in OB1 before the PID is called, so the PID never sees an out-of-range value.
  5. Subscribe to the diagnostic buffer programmatically using the RD_SINFO and RDSYSST instructions. Log every event 0xE0B3 and 0x4302 to a circular log DB with a 1000-entry ring buffer. This makes field debugging possible without a TIA Portal online session.
  6. Upgrade to TIA Portal V18 (or current) for the S7-1500 CPU firmware V3.0+ that introduces a configurable "NaN replacement value" in the PID technology object configuration. The runtime substitutes the configured value (default 0.0) for any non-finite input, eliminating the propagation path entirely.

12. References to Official Documentation

The following manufacturer and standards documents were consulted while preparing this troubleshooting reference. The IEEE 754-2019 standard defines the bit patterns and propagation rules cited in Section 2. The Siemens support portal hosts the system manuals and technology function manuals for the S7-1200 and S7-1500 families.

What does 16#F7C0_0000 mean in a TIA Portal V15.1 watch table?

The value 16#F7C0_0000 is a 32-bit IEEE 754 floating-point bit pattern. The S7-1200 and S7-1500 runtime treats it as a non-finite NaN, even though strict IEEE 754-2019 would classify it as a finite large negative number. It is not a Siemens error code; it is a numerical representation that the FPU has produced and propagated from an upstream divide-by-zero, log of zero, or uninitialized retain memory.

Why does 16#F7C0_0000 appear only on the first scan after download to PLCSim?

PLCSim V15.1 prior to Update 4 initialized uninitialized retain memory to 0xF7C00000 instead of 0x00000000. The first PID cycle reads the uninitialized IntegralSum, InputScaling, and OutputScaling members and propagates the pattern. The behavior is fixed in PLCSim V15.1 Update 5 and later. Adding OB100 initialization to the project eliminates the symptom on any PLCSim version.

Is 16#F7C0_0000 the same as 16#FFC0_0000?

Both are non-finite 32-bit values treated as NaN by the Siemens FPU. 16#FFC0_0000 is the canonical negative quiet NaN per IEEE 754-2019 (sign bit set, exponent 0xFF, mantissa bit 22 set). 16#F7C0_0000 has exponent 0xEF, which is technically finite, but the S7-1500 user-defined FPU and PID_Compact technology object treat it as non-finite due to the same mantissa bit pattern (0x400000). Treat both as NaN for diagnostic purposes.

Can a PID_Compact output be safely read when the input is NaN?

No. Per the IEEE 754-2019 propagation rule, any arithmetic operation that has NaN as an operand produces NaN. PID_Compact therefore sets Output to NaN on the next cycle when Input is NaN, regardless of the Setpoint value. The recommended mitigation is to clamp or sanitize the Input in OB1 before the PID is called, using a Limit, NORM_X, or custom sanitization block.

What is the difference between PID_Compact and PID_3Step when handling NaN?

PID_Compact propagates NaN to the Output and Output_PER tags and requires OutputScaling to be configured to hold the last valid value. PID_3Step defaults to the Stop state (both Open and Close outputs FALSE) when the Input is NaN, which is the safer behavior for valve-based actuators. For valve control in processes where a NaN-driven open or close could cause overpressure or dry-run, prefer PID_3Step.

Which PLCSim version first fixed the 16#F7C0_0000 retain initialization bug?

PLCSim V15.1 Update 5 (build 15.1.0.5) corrected the retain-initialization to 0x00000000. Earlier builds (V15.1.0.0 through V15.1.0.4) exhibit the 0xF7C00000 pattern on the first scan of an uninitialized instance DB. The fix is not in the CPU firmware; it is in the PLCSim emulator, so the symptom does not appear on physical S7-1200 or S7-1500 CPUs unless the user code itself writes 16#F7C0_0000 to a tag.

How can I detect a NaN value in SCL at runtime?

Use the identity (x <> 0.0) AND (x = 0.0) — this conjunction is true only when x is NaN, because every comparison with NaN returns FALSE under IEEE 754. Alternatively, convert the REAL to DWORD with DWORD#TO_DWORD(x) and check whether the exponent field is 0xFF with a non-zero mantissa. Add a dedicated IsNaN FB to your standard library so every project has the same detection logic.

Back to blog