Problem Overview
When configuring discrete alarms in Siemens WinCC flexible 2008 (or WinCC Comfort/Advanced in the TIA Portal) against an S7-300, S7-400, S7-1200, or S7-1500 controller, engineers frequently encounter a symptom in which the alarm text for "Trigger Bit 0" appears when the PLC sets bit 1, "Trigger Bit 1" appears when the PLC sets bit 2, and so on. The pattern is consistent: every discrete alarm fires one bit position to the right (or, in some cases, the wrong byte entirely) of the marker the PLC program actually wrote to.
A representative field report:
Discrete alarm "Valve Water Open" is configured with trigger bit 0. Discrete alarm "Valve Water Close" is configured with trigger bit 1. Eight valves are mapped to trigger bits 0 through 7. When the PLC sets M1.0, no alarm appears. When the PLC sets M1.1, the HMI displays the "Valve Water Open" alarm (the one assigned to bit 0). When the PLC sets M1.2, the HMI again displays the "Valve Water Open" alarm. The mapping is broken across the entire byte.
The root cause is rarely a WinCC flexible bug. It is almost always a mismatch between the trigger tag datatype and the bit-numbering convention used by the SIMATIC memory model.
Root Cause Analysis
Two independent mistakes combine to produce the observed behavior:
- Wrong tag type: the alarm trigger is bound to a 16-bit Word (or 32-bit DWord) tag instead of an 8-bit Byte or 1-bit Bool tag.
- Byte swap in the S7 memory model: the bit numbered "0" in a Word does not correspond to bit 0 of the lowest-addressed byte; it corresponds to bit 0 of the high byte. WinCC flexible counts bits from the low byte of the Word; the PLC program typically sets bits from the low byte of the marker byte.
If both mistakes are made, the HMI samples a Word that contains two marker bytes in swapped order, and the discrete alarm evaluator walks the bit positions in little-endian (low byte first) order. The result is the "off-by-eight" or "off-by-one" symptom described above.
Technical Background: S7 Memory Layout and Endianness
The SIMATIC S7 stores multi-byte variables in a "big-endian on the wire, little-endian in the bit numbering" arrangement. The naming convention is:
| Symbol | Width | Address Range | Bit numbering |
|---|---|---|---|
| MB10 | 8 bits (Byte) | 10 | M10.0 (LSB) to M10.7 (MSB) |
| MW10 | 16 bits (Word) | 10-11 | 0 = M11.0, 7 = M11.7, 8 = M10.0, 15 = M10.7 |
| MD10 | 32 bits (DWord) | 10-13 | 0 = M13.0, 7 = M13.7, 8 = M12.0, 15 = M12.7, 16 = M11.0, 23 = M11.7, 24 = M10.0, 31 = M10.7 |
For an MW10 reference, byte 10 is the high byte and byte 11 is the low byte. Therefore the WinCC flexible trigger-bit index n resolves to:
- Bit
n= 0..7 -> byte 11, bitn - Bit
n= 8..15 -> byte 10, bitn - 8
If the PLC sets M10.0 (high byte, bit 0), the Word-level bit that flips is bit 8, not bit 0. An HMI alarm assigned to trigger bit 0 will never fire when M10.0 is set; the alarm that fires is the one assigned to trigger bit 8. This is the asymmetry that catches most first-time users.
Memory map diagram (SVG)
Diagnosis Procedure
- Open the WinCC flexible project. Navigate to HMIs > [your panel] > Screens > (or directly) Alarms > Discrete Alarms.
- For each affected alarm, note the Trigger Tag and the Trigger Bit field.
- In the project's tag editor, confirm the data type of the trigger tag:
-
Bool- acceptable, Trigger Bit must be 0. -
Byte- acceptable, Trigger Bit may be 0..7. -
WordorInt- acceptable, Trigger Bit 0..15, but watch the byte-swap above. -
DWordorDInt- acceptable, Trigger Bit 0..31, but watch two byte-swaps.
-
- Open STEP 7 / TIA Portal online and watch the same address with a VAT (Variable Table) or watch table. Force each marker bit individually (M1.0, M1.1, ...) and observe which alarm fires on the HMI.
- Build a mapping matrix (PLC bit set -> HMI alarm fired). If the column "HMI alarm fired" is shifted by one row from the column "PLC bit forced", you are looking at the byte-swap symptom. If multiple PLC bits fire the same HMI alarm, the trigger tag is a Word and the alarm trigger bit is duplicated across both bytes of the word.
Solution 1: Use Individual Bool Tags (Recommended)
The cleanest fix is to abandon the multiplexed-word pattern and assign one Bool tag per discrete alarm. This eliminates the byte-swap and the trigger-bit arithmetic entirely.
PLC program (SCL, for an S7-1500 in TIA Portal):
// Eight valve position bits packed into marker byte MB1
// Bit 0 = valve water open, Bit 1 = valve water close, ...
// Individual bits are then mapped to Bool tags for WinCC discrete alarms.
"ValveWaterOpen_DB".CmdOpen := ValveWaterOpen_Input;
"ValveWaterClose_DB".CmdClose := ValveWaterClose_Input;
// Map coil feedback to marker byte
M1.0 := "ValveWaterOpen_DB".PosOpen_FB;
M1.1 := "ValveWaterClose_DB".PosClosed_FB;
M1.2 := "ValveSteamOpen_DB".PosOpen_FB;
M1.3 := "ValveSteamClose_DB".PosClosed_FB;
M1.4 := "ValveAirOpen_DB".PosOpen_FB;
M1.5 := "ValveAirClose_DB".PosClosed_FB;
M1.6 := "ValveCoolOpen_DB".PosOpen_FB;
M1.7 := "ValveCoolClose_DB".PosClosed_FB;
WinCC flexible / TIA configuration:
| Alarm Text | Trigger Tag | Trigger Bit |
|---|---|---|
| Valve Water Open | ValveWaterOpen_Alarm (Bool, addr M1.0) | 0 |
| Valve Water Close | ValveWaterClose_Alarm (Bool, addr M1.1) | 0 |
| Valve Steam Open | ValveSteamOpen_Alarm (Bool, addr M1.2) | 0 |
| Valve Steam Close | ValveSteamClose_Alarm (Bool, addr M1.3) | 0 |
| Valve Air Open | ValveAirOpen_Alarm (Bool, addr M1.4) | 0 |
| Valve Air Close | ValveAirClose_Alarm (Bool, addr M1.5) | 0 |
| Valve Cool Open | ValveCoolOpen_Alarm (Bool, addr M1.6) | 0 |
| Valve Cool Close | ValveCoolClose_Alarm (Bool, addr M1.7) | 0 |
Each row creates an independent discrete alarm. Trigger Bit must be 0 because the tag is a Bool. The HMI polls each Bool on its configured acquisition cycle and raises the alarm the moment the bit goes high.
Solution 2: Keep a Word Tag, Recompute Trigger Bits
If the PLC side cannot be changed (legacy code, third-party controller, or a customer mandate to keep the multiplexed-word pattern), the trigger-bit field in WinCC flexible must be set to the Word-level bit number, which is offset by 8 from the M-address bit number whenever the source marker is in the high byte.
| PLC marker bit set | Word-level bit position | WinCC Trigger Bit to configure |
|---|---|---|
| M11.0 (low byte) | 0 | 0 |
| M11.1 (low byte) | 1 | 1 |
| M11.7 (low byte) | 7 | 7 |
| M10.0 (high byte) | 8 | 8 |
| M10.7 (high byte) | 15 | 15 |
This is fragile: any change to the marker-byte assignment in the PLC breaks the mapping. Document the convention in the HMI tag comment and add a cross-reference in the PLC data block header.
Solution 3: Use a Byte Tag with Trigger Bit 0-7
When the eight alarms map to a single marker byte, define the trigger tag as Byte and set Trigger Bit to 0..7. There is no byte-swap in a Byte datatype, so the bit numbers map 1:1 to the M-address bits.
// Trigger tag: "ValveStatus" type Byte, address MB1
// Trigger Bit 0 = M1.0 = Valve Water Open
// Trigger Bit 1 = M1.1 = Valve Water Close
// Trigger Bit 7 = M1.7 = Valve Cool Close
This is the lowest-risk pattern and the one recommended by the WinCC flexible engineering manual. It is also the only pattern that survives a migration to TIA Portal with the same data type semantics, since WinCC Comfort/Advanced in TIA Portal treats the discrete alarm trigger bit field identically to WinCC flexible.
Importing and Exporting Discrete Alarms in Bulk
For projects with more than a handful of valves, configure the alarms in a spreadsheet and import them. The official Siemens TIA Portal V20 documentation defines the XLSX schema for discrete alarm import. The columns relevant to this discussion are:
| Column | Meaning |
|---|---|
| ID | Numeric alarm identifier (unique project-wide) |
| Name | Alarm name used in the alarm log |
| Trigger tag | PLC tag name; must exist in the HMI tag table |
| Trigger bit | 0..7 for Byte, 0..15 for Word, 0..31 for DWord |
| Alarm text | Multilingual text list reference |
| Class | Errors, Warnings, Information, etc. |
Validate the file before re-import by opening it in Excel and confirming that the Trigger Bit column never exceeds (datatype width - 1). WinCC flexible ignores overflow silently and writes the alarm with Trigger Bit 0, which is the third common cause of "all my alarms show the same message" complaints.
Verification Procedure
- In STEP 7 / TIA Portal, open a watch table and force each marker bit in turn. Document the value written.
- On the HMI, open the alarm view (in WinCC flexible: Tools > Alarm Logging or the runtime alarm screen).
- For each forced bit, confirm that exactly one alarm appears, and that the alarm text matches the intended message.
- Clear the force and confirm the alarm enters the "Cleared" state. With WinCC flexible, the default acknowledgement is "Incoming, going" - the alarm disappears as soon as the trigger bit returns to 0. If the alarm remains latched, check that the alarm class is not configured for "Incoming, acknowledged, going" with a pending acknowledge.
- Repeat the test with the HMI tag acquisition cycle set to its fastest value (100 ms by default in WinCC flexible). If alarms are missed at the slower cycle, set the polling to 1 s and confirm reliability; production networks should not poll faster than 250 ms for hundreds of alarms.
Migration to TIA Portal / WinCC Comfort
WinCC flexible 2008 reached end of life when SIMATIC WinCC Comfort/Advanced V15 introduced the TIA Portal-only workflow. A discrete-alarm configuration migrates cleanly when:
- The trigger tag is a Bool or Byte. Word/DWord triggers are still supported but the byte-swap caveat described above still applies.
- The PLC connection is re-bound to a TIA Portal project and the symbolic tag name is preserved.
- The alarm class IDs are remapped to the new Alarm classes node (Errors, Warnings, Information, etc.) in the TIA Portal alarm configuration editor.
If migrating to an S7-1200/S7-1500, prefer symbolic tag access (e.g. "Valve_DB".PosOpen) over absolute marker addresses. Symbolic Bool tags with consistent naming also enable bulk operations such as the TIA Portal Alarm Generation from PLC tags wizard, which can create dozens of discrete alarms from a single UDT instance.
OPC UA Discrete Alarm Cross-Reference
For plants that have migrated the SCADA layer to OPC UA, the same alarm semantics are described by the OPC UA Part 9 - Alarms and Conditions, Section 5.8.24 DiscreteAlarmType. The standard notes:
The DiscreteAlarmType is used to classify Types into Alarm Conditions where the input for the Alarm may take on only a certain number of possible values. The DiscreteAlarm inherits the same fields as other alarm types and adds the property DiscreteAlarmState describing the discrete input value that triggered the alarm.
The key difference from WinCC flexible is that the OPC UA server pushes alarm events; the WinCC flexible HMI polls trigger bits. The trigger bit field in WinCC flexible is functionally a polled subscription filter, not an event subscription. When porting a WinCC flexible discrete alarm to an OPC UA server, map each trigger bit to a separate AlarmCondition node rather than try to express "bit 0 of word 1" as a single OPC UA condition.
Cross-Platform Notes: AVEVA InTouch and Other HMI
Engineers porting WinCC flexible discrete alarm projects to AVEVA InTouch HMI should note the inverted convention: InTouch discrete alarms are configured directly on a discrete tag, with no separate "trigger bit" field. The tag itself is the alarm source, and the alarmed state can be set to "On", "Off", or "Any change". The mapping to a WinCC flexible project is straightforward: one WinCC flexible discrete alarm per Bool tag equals one InTouch discrete alarm per discrete tag.
Troubleshooting Matrix
| Symptom | Likely Cause | Fix |
|---|---|---|
| Alarm 1 fires when bit 1 is set, not bit 0 | Byte-swap in a Word tag (high vs. low byte) | Use Bool tags or shift Trigger Bit by 8 |
| All alarms show the same text | Trigger Bit column over 7 in an XLSX import silently reset to 0 | Re-export, fix Trigger Bit, re-import |
| No alarm appears at all | HMI tag acquisition cycle too long, or tag is filtered by area / authorization | Reduce cycle to 1 s, check tag properties |
| Alarm appears but never clears | Alarm class set to "Incoming, acknowledged, going" and not yet acknowledged | Change class to "Incoming, going" or send an ACK |
| Alarm text is the wrong language | Text list not switched with the project language | Configure multilingual text list with all required languages |
| Alarm fires on TIA Portal but not on panel | Connection partner set to the wrong PLC | Recompile HMI with correct connection |
| Alarm fires intermittently | Tag acquisition cycle conflicts with PLC scan time | Move alarm to a polled area with 100 ms cycle or use coordination bits |
Frequently Asked Questions
Why does my WinCC flexible discrete alarm fire on the wrong bit when the trigger tag is a Word?
Siemens S7 stores the high byte of a Word at the lower address (MW10 = MB10 high + MB11 low). WinCC flexible counts the trigger bit starting from the low byte, so a PLC program that sets M10.0 actually flips Word bit 8, not bit 0. Either change the PLC to set M11.0-M11.7, or set the HMI Trigger Bit to 8-15 for those alarms.
Can one Word tag drive eight discrete alarms in WinCC flexible?
Technically yes - set the trigger tag to a Word, and create eight alarms with Trigger Bit 0..7. Practically, this is fragile because of the byte-swap and because the XLSX importer can silently clamp out-of-range bits to 0. Use eight separate Bool tags or a single Byte tag for production projects.
What is the difference between a discrete alarm and an analog alarm in WinCC flexible?
A discrete alarm fires on a Boolean state change (one bit going high or low) and is mapped to a fixed text. An analog alarm fires when a numeric tag crosses a configurable limit (LL, L, H, HH) and reports the actual value. Discrete alarms are for on/off conditions like valve position; analog alarms are for process variables like temperature or pressure.
How do I migrate WinCC flexible discrete alarms to TIA Portal?
Open the WinCC flexible project in TIA Portal via Migration > Project migration. Discrete alarms in the Alarms node are converted to the new alarm editor automatically. Re-bind symbolic tags to the new S7-1200/1500 DB symbols and verify byte/word trigger mappings against the byte-swap rules above before commissioning.
What is the recommended tag type for valve status discrete alarms?
Use one Bool tag per valve position (M1.0 = ValveWaterOpen, M1.1 = ValveWaterClose, ...). Create one discrete alarm per Bool with Trigger Bit = 0. This pattern is endianness-safe, survives migration to TIA Portal, and matches the OPC UA DiscreteAlarmType semantics of one alarm per condition.