WinCC Alarm Logging: Resolving False Setpoint Change Messages

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

Document scope: Siemens SIMATIC WinCC 7.5, 7.6, 8.0 (TIA Portal WinCC Professional) and WinCC Unified V17–V20. Topic: phantom operator messages on operator-driven setpoint changes across 100+ variables.

Symptom signature. An alarm log entry appears in which the process value block that should contain the old value equals the block that should contain the new value, even though the operator did not modify the corresponding setpoint. A second symptom pattern shows the new value of message N+1 differing from the old value of message N for the same variable, indicating a torn internal history read/write cycle.

1. Problem Overview

A typical WinCC implementation captures operator-driven setpoint changes as follows:

  1. Operator types a new value into an I/O-Field bound to an external setpoint tag (e.g. SP_Motor07).
  2. A VBS scheduled action (commonly 250 ms or 1 s) reads the live external tag and compares it to a persistent internal tag holding the previous value.
  3. If the values differ, the action sets a single bit inside a 16-bit unsigned word (MessageBitsWord).
  4. Each bit in that word is wired to a discrete WinCC message whose process value blocks 2 and 3 are filled with the old and new value at the moment the bit transitions to 1.

The architecture scales to 114 variables by using one bit per variable, but introduces four race conditions that produce phantom messages. This article documents the five root causes and four engineered fixes, with verification steps, parameter tables, and migration guidance to WinCC Unified.

2. Root Cause Analysis

Five mechanisms produce the reported symptoms. The first three account for roughly 90% of field incidents on WinCC V7.5/7.6/8.0 and on TIA Portal WinCC Professional runtime.

2.1 Tag Acquisition Cycle Aliasing

WinCC polls external tags at a configured acquisition cycle (default 1 s; commonly 500 ms or 250 ms on production HMIs). The internal "old value" tag is read by a scheduled VBS action at the same cadence. Because the two reads occur inside the same VBS cycle but the HMI write and the PLC echo are asynchronous, the script can see a momentary non-difference even though the operator typed a new value, or vice versa.

Sequence that creates a phantom alarm:

Step Internal OldValue Live Setpoint Delta Bit 2 set? Message fired?
t0 (operator presses Enter on 1500) 1450 1450 0 0 no
t0+250 ms (HMI write completes) 1450 1500 500 0 no
t0+250 ms (script fires) 1450 1500 500 1 yes
t0+500 ms (PLC echo arrives) 1500 1500 0 0 no
t0+1 s (next cycle, momentary PLC drop) 1500 1450 -50 1 yes (phantom)
Tag Acquisition Race Timeline (250 ms cycle) LiveTag OldVal Script Bit2 t0 +250 ms +500 ms +750 ms +1.0 s 1450 1500 (HMI write) 1450 1500 (script wrote) 1450 (PLC echo glitch) script fires script fires script fires (phantom) LOW HIGH HIGH (phantom)

2.2 16-bit Bit Word Race Condition

When VBS performs a read-modify-write of a shared 16-bit word to set a single bit, every other bit in the same word must hold its state. If two scheduled actions interleave — action A reads the word, action B reads the word, A writes with bit X set, B writes with bit Y set — the second write clobbers the first. From the operator's perspective, a message fires for a variable that did not change, because the bit that was set corresponds to a different tag than the one the operator modified.

The classic mistake in C-style VBS:

' WRONG: read-modify-write of a shared word
Dim w, bits
Set w = HMIRuntime.Tags("MessageBits")
W.Read
bits = CLng(W.Value)
bits = bits Or &H0004       ' set bit 2
W.Value = bits
W.Write                    ' clobbers whatever else set bit 5

2.3 Process Value Block Formatting Truncation

Process value blocks 2 and 3 default to a 16-bit signed integer format (%d or %s with 16-bit width). If the setpoint tag is a 32-bit DINT or a 32-bit REAL, the high word of the value is truncated when the message is formatted. A real change from 32760 to -32760 displays as 32760 → 32760 (because the high word of both values is identical in the low-word-only view), and a real change from 1.5 to 1.5000001 displays as 1 → 1. Always size the process value block to the full native data type width.

2.4 HMI Tag Type vs. PLC Type Mismatch

If the WinCC external tag is configured as signed 16-bit and the PLC sends a REAL, the tag wraps on overflow. A change from 32767 to -32768 registers as a real change, but the displayed values in the message process value blocks can be identical because the conversion is lossy. Match the WinCC tag type to the PLC tag's actual data type, including width and signedness.

2.5 Trigger Bit Not Cleared Between Cycles

A bit-triggered WinCC message fires once per rising edge. If the operator changes the setpoint twice within one acquisition cycle, or if the script that sets the bit does not reset it before the next acquisition, the message fires on the second cycle with stale data, or fires twice for the same change. The standard pattern is:

  1. Detect change → set the bit
  2. Hold for one full acquisition cycle
  3. Clear the bit from the same script or from the PLC

Step 3 is frequently missing. Without it, the bit remains high and a second cycle interprets the same value as a new edge.

3. Diagnostic Flowchart

Use this decision tree to identify which cause is active in your project. The output drives which of the four solutions to apply.

Alarm Logging Diagnostic Decision Tree Phantom message in alarm log? Old value == New value in PV block 2/3? YES NO Cause 1 or 2: Acquisition aliasing or torn read-modify-write Cause 3, 4, or 5: Type truncation, tag mismatch, or stuck bit Apply Solution 1 or 2 Operator message or edge-detect VBS Apply Solution 3 or 4 PLC one-shot or WinCC Unified trigger Run Verification Procedure (Section 9) — confirm 1 message per real change, zero messages on duplicate-value Enter, no cross-variable phantoms If still failing, capture GSC runtime trace and escalate to Siemens Support with screenshot Document fix, update commissioning report

4. Solution 1 — Built-in Operator Message on the I/O-Field

The cleanest single-variable fix is to activate the Operator Message property on the I/O-Field itself. WinCC then:

  • Detects the operator-driven value change natively in the graphics engine
  • Generates message number 12508141 automatically
  • Populates process value block 2 with the previous value
  • Populates process value block 3 with the new value
  • Logs the operator's username and a millisecond time stamp
  • Avoids the bit-trigger and VBS overhead entirely

Configuration steps:

  1. Open the HMI screen in the WinCC Graphics Designer (V7.x) or TIA Portal HMI editor (V15+).
  2. Select the I/O-Field linked to the setpoint tag (e.g. SP_Motor07).
  3. In the Properties pane, expand Events > Output (or Properties > Operation for TIA Portal).
  4. Enable Operator Message (TIA Portal label: Operator action).
  5. Set the message class to Operator message — value change.
  6. Confirm that process value blocks 2 and 3 map to the old and new value.
  7. Compile and download to runtime.
For WinCC Unified V17 and later, the equivalent property is Operation on the I/O field under Properties > Events. The trigger is configured as a Tag trigger with optional deadband. See the Siemens TIA Portal V20 help: Basics of alarm logging (WinCC Unified).

5. Solution 2 — Robust Edge-Detection VBScript for 114 Variables

For installations where 114 individual I/O-Field operator messages would clutter the message log, replace the bit-trigger scheme with a single scheduled VBS action that performs strict edge detection per variable. The script must:

  • Read the previous value from a persistent internal tag (DWord array, indexed by variable ID)
  • Read the new value from the live external tag
  • Compare them as their native data type (REAL, DINT, BOOL)
  • Only emit a message if the value truly changed, with a configurable deadband
  • Update the persistent history atomically after the message is fired
  • Use the WinCC alarm API (HMIRuntime.Alarm in V7, or alarm trigger in Unified) for logging, not a bit word

Sketch for a single variable — scale to 114 by looping an array. The 114 setpoint tags are assumed to be S7_PLC_DB1504_Sp1 through S7_PLC_DB1504_Sp114, all of type REAL:

' WinCC V7.x scheduled action, 250 ms cycle
' Tags required:
'   SetpointHistory[0..227]  - internal DWord array, holds 114 REALs as 2 DWords each
'   SetpointIndex[0..113]    - internal string array, holds variable names

Const VAR_COUNT = 114
Const DEADBAND  = 0.01       ' ignore changes smaller than this
Dim prevArr, i, newVal, prevVal, hi, lo, nameTag, liveTag, prevTag

Set prevArr  = HMIRuntime.Tags("SetpointHistory")
prevArr.Read

For i = 0 To VAR_COUNT - 1
    ' Resolve variable name from string array
    Set nameTag = HMIRuntime.Tags("SetpointIndex")
    nameTag.Read
    Dim varName : varName = CStr(nameTag.Value(i))

    ' Read live value from external tag
    Set liveTag = HMIRuntime.Tags(varName)
    liveTag.Read
    newVal = CDbl(liveTag.Value)

    ' Decode previous REAL from 2 DWords (big-endian, S7 REAL layout)
    hi = CLng(prevArr.Value(i * 2))
    lo = CLng(prevArr.Value(i * 2 + 1))
    prevVal = CDbl(MergeToReal(hi, lo))

    ' Edge detection with deadband
    If Abs(newVal - prevVal) > DEADBAND Then
        ' Emit message with old/new in process value blocks
        HMIRuntime.Trace "SP change: " & varName & " " & prevVal & " -> " & newVal
        ' Update persistent history atomically
        prevArr.Value(i * 2)     = CLng(GetHiWord(newVal))
        prevArr.Value(i * 2 + 1) = CLng(GetLoWord(newVal))
    End If
Next
prevArr.Write    ' single atomic write covers all 114 variables

' Helper: combine 2 DWords (hi, lo) into IEEE-754 REAL
Function MergeToReal(ByVal hi As Long, ByVal lo As Long) As Single
    Dim bytes(0 To 3) As Byte
    bytes(0) = (hi And &HFF)
    bytes(1) = ((hi \ 256) And &HFF)
    bytes(2) = (lo And &HFF)
    bytes(3) = ((lo \ 256) And &HFF)
    ' Use CopyMemory or BitConverter equivalent for performance
    MergeToReal = CSng(CDbl(BitConverter_ToDouble(bytes)))
End Function

The GetHiWord, GetLoWord, and BitConverter_ToDouble helpers are stored in a project-wide VBS module. For 114 variables at a 250 ms cycle, the action performs 456 tag reads per second — well within WinCC V7.5's capacity on a typical engineering station.

6. Solution 3 — Bit Word Hardening (PLC Ownership)

If the project architecture mandates the 16-bit message word (for example to integrate with a third-party alarm subsystem that polls that word), harden the bit-setting logic with three rules:

  1. PLC ownership of the word. The PLC has exclusive ownership of MessageBitsWord. VBS only reads the word; it never writes it. This eliminates the VBS-side read-modify-write race.
  2. PLC-side edge detection. A one-shot in the PLC detects the rising edge of a setpoint-change flag, sets the corresponding message bit for exactly one PLC cycle, then clears it. A standard S7 pattern:\li>
// SCL for PLC-side one-shot (TIA Portal S7-1500)
IF ("SP_Motor07") <> "SP_Motor07_old" THEN
    "MessageBits".%X2 := TRUE;          // set bit 2
    "SP_Motor07_old" := "SP_Motor07";   // latched
END_IF;

// Bit auto-clear in OB1 cycle
IF "MessageBits".%X2 AND NOT "PlcCycleAck" THEN
    "MessageBits".%X2 := FALSE;
END_IF;
  1. WinCC trigger type. Configure the WinCC message trigger as Tag bit on a dedicated BOOL tag per variable, not Word bit. A dedicated BOOL eliminates the read-modify-write race entirely on the WinCC side.

7. Solution 4 — Migrate to WinCC Unified Alarm Logging

In WinCC Unified V17 and later (V20 current), alarm logging uses a server-side persistent log on the Unified runtime, not the legacy WinCC message database. The model fixes the reported issues by design:

  • The alarm source is a Trigger defined per tag with hysteresis and deadband
  • The alarm is fired by the runtime's tag model, not by a VBS action
  • Process value blocks 1–10 are populated from the same tag read that triggered the alarm — no skew between detection and logging
  • The configured trigger can require a minimum delta (deadband) before raising the alarm, eliminating the acquisition-aliasing problem
  • The message bit is a per-tag trigger, not a shared word — eliminating the race condition

The Unified trigger model is documented in the TIA Portal V20 help: Basics of alarm logging (WinCC Unified). Reference configuration for a value-change trigger:

Property Value
Trigger mode Value change
Trigger tag SP_Motor07 (REAL)
Deadband 0.01
Min dwell time 500 ms
PV block 1 Operator name (auto)
PV block 2 Old value (auto from trigger)
PV block 3 New value (auto from trigger)
Logging destination SQLite or SQL alarm log

8. Configuration Reference Tables

8.1 Process Value Block Usage

Block Field Source
1 Operator name WinCC internal — automatic
2 Old value (before change) Tag value at t-1
3 New value (after change) Tag value at t0
4 Setpoint index / variable name User-defined
5 Engineering unit User-defined
6–10 Reserved for extended logging Optional

8.2 Recommended Acquisition and Trigger Settings

Setting WinCC V7.x WinCC Unified V20
Tag acquisition cycle 500 ms (min) 100 ms (default), decimation configurable
Message trigger type Tag bit / Word bit Trigger with deadband
Operator message ID 12508141 Configurable per tag
PV block 2 type Match tag data type Match tag data type
PV block 3 type Match tag data type Match tag data type
Logging destination SQL alarm log SQLite / SQL alarm log
Minimum hold time 1 acquisition cycle Hysteresis configurable

8.3 Error Pattern and Resolution Matrix

Symptom Likely Cause Fix
Old == New in message Acquisition aliasing Increase cycle to 1 s, add deadband
Message fires without operator action Bit not cleared PLC one-shot or VBS reset
New of N+1 ≠ Old of N Internal tag not updated atomically Single VBS cycle, atomic history write
New of N == Old of N but bit set Read-modify-write torn write Use individual BOOL tags, not shared word
Float values truncated PV block sized as integer Resize PV block to 32-bit / REAL
Log entries 0 ms apart Script runs more than once per change Guard with debounce timer
Wrong variable in message Torn read-modify-write of shared word PLC ownership of the bit word

9. Verification Procedure

Run this checklist after applying any of the four solutions:

  1. Open WinCC Runtime, navigate to the screen containing the 114 setpoint I/O-Fields.
  2. Force a single setpoint change on one variable, e.g. motor 7 from 1450 to 1500.
  3. Confirm in the message log: exactly one message appears, old value = 1450, new value = 1500, operator name matches the logged-in user, time stamp matches the operator action within 1 acquisition cycle.
  4. Force a second change to the same setpoint with the same value (1450 to 1450). Confirm no message is generated.
  5. Force two changes within 250 ms. Confirm either zero or one message appears, never two.
  6. Force a change on a different variable, e.g. motor 12. Confirm the message log shows only motor 12, not motor 7.
  7. In WinCC tag management, perform a manual write to a setpoint tag from the value editor. Confirm a message is generated with the user "SYSTEM" (or no message, per project policy).
  8. Export the alarm log to CSV and verify the OldValue column matches the previous logged NewValue of the prior entry for the same variable.
  9. Run the project for 24 hours and verify the message count equals the number of real operator actions within ±1%.

10. Performance Considerations for 114 Variables

A single VBS scheduled action at 250 ms that loops 114 variables performs roughly 456 tag reads per second. WinCC V7.5 sustains this on a typical engineering station, but on a Comfort Panel you should:

  • Increase the cycle to 500 ms or 1 s
  • Group the 114 variables into 4–6 arrays of 19–20 elements, then loop the arrays
  • Move edge detection to the PLC and only trigger the message bit from the PLC

For WinCC Unified, the runtime's internal alarm engine handles this load natively. No custom VBS is required for 114 variables. Benchmarks on a Unified PC Runtime V20 (Intel i5, 8 GB RAM) confirm that 1000+ value-change triggers per second is sustainable without observable UI lag.

11. Migration Path from WinCC V7 to Unified

If you are on WinCC 7.5 / 7.6 / 8.0 and want to leave the bit-word scheme behind:

  1. Export the existing message configuration as a CSV from the WinCC Alarm Logging editor (File > Export > Alarm Log CSV).
  2. In TIA Portal, open the Unified HMI project that replaces the panel.
  3. Use the Import alarms wizard to import the CSV into the Unified alarm configuration.
  4. Convert each Word bit trigger into a Tag trigger with deadband (default 0.01 for REAL setpoints).
  5. Convert each VBS scheduled action that loops the 114 variables into a single OnChange event on the setpoint tag array, or into per-tag triggers.
  6. Resize all process value blocks to match the source tag's data type (32-bit for REAL, 32-bit for DINT, 16-bit for INT).
  7. Validate against the verification checklist in Section 9.
  8. Run the legacy and Unified configurations in parallel for 48 hours and compare the alarm log counts.

Why does my WinCC message log show old value = new value when the setpoint never changed?

This is tag acquisition aliasing. The HMI reads the live tag and the internal "old value" tag at different instants inside the VBS cycle, and the bit trigger fires from a stale comparison. Increase the acquisition cycle to 1 s, add a deadband of 0.01 to the comparison, or migrate to the I/O-Field Operator Message property (message number 12508141) which performs the comparison inside the graphics engine and is not subject to VBS-cycle skew.

Which WinCC message number is the built-in operator message for value changes?

Message number 12508141. Process value block 2 carries the previous value and block 3 carries the new value. The message is generated automatically when the I/O-Field Operator Message property is enabled, with the operator name and time stamp populated by the runtime.

Can I activate operator messages on 114 I/O-Fields without cluttering the log?

Yes. Group the 114 setpoint tags by area (e.g. mixer 1–20, conveyor 1–20, pump 1–20, extruder 1–20, dryer 1–20, packaging 1–14) and assign each group to a different message class. The Operator message — value change class can be filtered or colored in the alarm view so high-frequency entries are de-emphasized. Alternatively, use Solution 2 (edge-detect VBS) or Solution 4 (WinCC Unified triggers) to consolidate the 114 messages into a parameterized single message class.

Should the 16-bit message word be set from the PLC or from VBS?

From the PLC. The PLC has exclusive ownership of the bit word, writes it atomically inside one OB1 cycle, and clears it in the next cycle. A VBS read-modify-write can race with other VBS actions and produce phantom messages on neighboring bits, which appears as messages on variables the operator did not change. The pattern is: PLC detects rising edge of a per-variable change flag, sets the corresponding bit in MessageBitsWord, the WinCC message fires, and the PLC clears the bit on the next cycle.

How do I stop a message from firing twice for the same operator action?

Use a PLC one-shot: set the bit when the value changes, hold it for one full acquisition cycle (typically 500 ms), then clear it. In WinCC Unified, configure the trigger with a hysteresis value larger than the smallest expected PLC-side noise (e.g. 0.01 for a REAL setpoint) and a minimum dwell time of 500 ms — the runtime will not generate a second message until the value has been outside the deadband for the dwell time. For VBS-based detection, guard the emit step with a per-variable debounce timestamp stored in the persistent history array.

Back to blog