WinCC Flexible Discrete Alarm Number to PLC: Complete Integration Guide
When a Siemens Comfort Panel, Multi Panel, or Mobile Panel running WinCC Flexible (2008 SP5 and later) raises a discrete alarm, the alarm is identified by a unique internal number assigned in the alarm configuration. Operators see this number (or a derived text) in the alarm view, but the PLC has no native visibility into that number unless the integration is designed in. This reference shows four production-ready methods to expose the active alarm number from the HMI to the PLC, the engineering trade-offs of each, and the path forward to WinCC Unified discrete alarms when the project is migrated.
1. Problem Definition and Engineering Constraints
A discrete alarm in WinCC Flexible is bound to a single boolean tag. The HMI runtime evaluates the trigger tag on every acquisition cycle; when the bit transitions, the alarm is raised and the HMI logs it with:
- An internal alarm number (1…65,536) defined in the alarm editor.
- A configurable acknowledgement state and state machine (raised, cleared, acknowledged, locked).
- Optional events that fire on activation, deactivation, acknowledgement, or lock/unlock.
The PLC only knows the bit that was the source of the alarm. It does not natively receive the HMI-side alarm number, timestamp, priority, or text. If a downstream system (SCADA, MES, third-party dashboard) needs the WinCC Flexible alarm number, the HMI must publish it. Three core constraints drive the design:
| Constraint | Engineering impact |
|---|---|
| HMI acquisition cycle is decoupled from the PLC OB1 cycle | Alarm events arrive asynchronously; the PLC must tolerate gaps of 100–2000 ms between updates. |
| Multiple alarms can transition in the same HMI cycle | Sending a single register only exposes the last alarm written; the application must define a queue or use a different mechanism. |
| WinCC Flexible scripts run on the panel CPU | Heavy VBScript on a 177-series panel or KTP can starve the runtime; prefer PLC-side logic whenever possible. |
| Alarm numbers are project-local | A change in the HMI alarm list breaks the mapping to the external system unless the source of truth is documented and version-controlled. |
2. Architecture Overview
The integration pattern is one-directional from HMI to PLC for status and a small back-channel from HMI to PLC for the alarm number. The PLC remains the source of truth for process state; the HMI is the source of truth for the alarm number and operator-facing metadata.
The two data flows between PLC and HMI are:
- Trigger bits (PLC → HMI): one boolean tag per alarm. The PLC sets/clears these as the source of truth.
- Alarm number (HMI → PLC): a 16-bit word (or 32-bit dword) plus a hand-shake bit/strobe carrying the most recent alarm number and optional metadata.
3. Method A — Mirror the Alarm List in the PLC (Recommended)
This is the production-preferred method. The PLC maintains a data block that mirrors the WinCC Flexible alarm table one-for-one. The PLC, not the HMI, is the source of the alarm number, so the back-channel disappears entirely.
3.1 PLC data block layout (S7-300/400 example, STEP 7 V5.x)
Create a shared DB (default DB100) of sufficient size for the project alarm count. For 256 alarms, allocate 32 bytes of bits plus 256 words of metadata:
| Address | Symbol | Type | Description |
|---|---|---|---|
| DB100.DBX0.0 … DBX31.7 | HMI_Alarm_Trigger[1..256] | BOOL | One bit per discrete alarm. Bound 1:1 to WinCC Flexible alarm trigger tag. |
| DB100.DBW32 | Active_Alarm_Count | INT | Number of currently raised alarms (computed in PLC). |
| DB100.DBW34 | Latest_Alarm_Number | INT | Highest-numbered alarm currently raised; used by external SCADA. |
| DB100.DBW36 | Latest_Alarm_Time | INT | Seconds since top of hour; combined with date in DW38. |
| DB100.DBD38 | Latest_Alarm_Timestamp | DATE_AND_TIME | Full timestamp of last transition. |
| DB100.DBW44 | Latest_Alarm_Priority | INT | Priority field mirrored from HMI project. |
3.2 STEP 7 STL snippet to compute the latest alarm number
Scan from the highest alarm number down; the first raised bit wins. This is O(N) but executes in microseconds for N≤512 on an S7-300/400:
// FC 200 "Compute latest alarm"
// Input: none (uses DB100)
// Output: DB100.DBW34 = latest alarm number, 0 if none
L 256 // highest alarm number
T #i
NEXT: L DB100.DBX [#i - 1] // bit addressed by index
A DB100.DBX0.0 + (#i - 1) // alternative absolute
JC FOUND
L #i
LOOP NEXT
L 0 // no alarm raised
JU WRITE
FOUND:L #i
WRITE:T DB100.DBW34
Bool tagged HMI_Alarm_Trigger[1..256] declared in a global DB. The pattern is identical; the address arithmetic is replaced by the array index.3.3 WinCC Flexible alarm editor binding
- Open Alarm Logging and create a new discrete alarm, e.g. number
1. - In the Trigger tag field, browse to the PLC and select
DB100.DBX0.0(Alarm 1),DB100.DBX0.1(Alarm 2), and so on. - Set the alarm number in the Number column to match the bit offset: bit 0.0 → 1, bit 0.1 → 2, …, bit 31.7 → 256.
- Disable any PLC-side logic that would also re-write the same bit; the PLC owns the bit, the HMI only reads.
3.4 Why this wins
- No back-channel: the alarm number is computed where the data already exists.
- Deterministic timing: the PLC cycle is the source of timestamps.
- Survives HMI restart: re-connection automatically re-synchronises the bits.
- Script-free: no VBScript load on the panel.
4. Method B — HMI Action on Alarm Event (Back-Channel)
When the alarm list cannot be mirrored in the PLC (e.g. alarms are generated inside the HMI because they are local operator prompts, audit prompts, or conditions the PLC cannot see), use the WinCC Flexible event-driven action system.
4.1 Configure the alarm event
- In the alarm editor, select the alarm and open Properties → Events.
- Click On appearance (or On raising in some builds).
- Add a Set tag function that writes the alarm number to a 16-bit PLC tag, e.g.
HMI_Last_Alarm_Number. - Optionally, set a second bit
HMI_Last_Alarm_Strobefor the PLC to detect the update.
4.2 Hand-shake protocol with the PLC
| Step | HMI (WinCC Flexible) | PLC |
|---|---|---|
| 1 | Alarm n raises | Idle, waiting on Busy flag |
| 2 | Action: HMI_Last_Alarm_Number := n; HMI_Last_Alarm_Strobe := 1
|
Detects Strobe rising edge |
| 3 | Monitors HMI_Ack_Busy
|
Copies number to PLC_Last_Alarm, sets HMI_Ack_Busy := 1
|
| 4 | Sees Busy = 1, clears Strobe := 0
|
Sees Strobe = 0, clears Busy := 0
|
| 5 | Idle | Idle |
4.3 Limitations of the action method
- If two alarms raise in the same acquisition cycle, the action fires twice in undefined order; only the last write is visible to the PLC.
- The panel must be configured with the VBScript runtime option enabled (default on Comfort Panels).
- On a 177-series panel with 800 tags, VBScript execution can be 200–800 ms; budget accordingly.
5. Method C — Global VBScript on Runtime Cycle
For projects that need to publish the current alarm number (not the last one to raise), a global VBScript running on the runtime cycle can poll the alarm state and write it to a tag. The relevant API is the HMIRuntime.Alarm object.
5.1 VBScript example (WinCC Flexible 2008 SP5 and later)
' Stored in the project under "Scripts\Global\Project"
Function OnCycle( ByVal lparCycSeconds )
Dim oAlarm, oResult
Set oAlarm = HMIRuntime.Alarm
' Filter to discrete alarms with priority > 0
oAlarm.Filter.AlarmClass = 1 ' 1 = discrete in most projects
oAlarm.Filter.State = 1 ' 1 = active (raised)
Set oResult = oAlarm.GetCurrent
If oResult.Count > 0 Then
SmartTags("HMI_Active_Alarm_Count") = oResult.Count
SmartTags("HMI_Latest_Alarm_Number") = _
oResult.Item(oResult.Count).Number
SmartTags("HMI_Latest_Alarm_Time") = _
oResult.Item(oResult.Count).RaiseTime
Else
SmartTags("HMI_Active_Alarm_Count") = 0
SmartTags("HMI_Latest_Alarm_Number") = 0
End If
Set oResult = Nothing
Set oAlarm = Nothing
End Function
HMIRuntime.Alarm vs HmiRuntime.Screens with .Alarms collection) depend on the WinCC Flexible SP level. Always confirm the API against the project Help → Programming Reference → VBScript Reference → Alarm object.5.2 When to use this method
- You need a continuous current state (count, latest number) without writing custom logic for every alarm.
- The HMI is a PC Runtime (not a 177-series panel) and CPU load is not a concern.
- The PLC supports the
SmartTagsnamespace, which is created automatically in WinCC Flexible/Comfort.
6. Method D — Structured Tag (Array) for Bulk Transfer
When 256+ alarms must be visible to the PLC simultaneously (rare; usually only for synchronous cross-coupling between two PLCs), the HMI can publish the whole array of BOOL states plus a WORD status code per alarm. The PLC then computes the highest active bit locally, exactly as in Method A. This method is functionally identical to Method A from the PLC's perspective; the difference is that the HMI may add metadata (priority, group, suppression state) in a second array.
| WinCC Flexible tag | Type | Direction | PLC counterpart |
|---|---|---|---|
HMI_Alarm_Trigger[1..256] |
BOOL array | PLC → HMI | DB100.DBX0.0..DBX31.7 |
HMI_Alarm_Priority[1..256] |
INT array | HMI → PLC (constant) | DB110.DBW0..DBW510 |
HMI_Alarm_TextID[1..256] |
INT array | HMI → PLC (constant) | DB110.DBW512..DBW1022 |
HMI_Latest_Alarm_Number |
INT | HMI → PLC | DB100.DBW34 (read-only) |
7. Commissioning and Verification
Once the chosen method is implemented, verify with the following checklist before going live. Use a SIMATIC Panel or HMI simulator and STEP 7 / TIA Portal online watch.
7.1 Static checks (offline)
- In WinCC Flexible, open Project → Compiler → Consistency check and resolve every warning related to alarm trigger tags.
- In the PLC, compile the project (Build → Rebuild all). Confirm no implicit type conversions on the alarm number word.
- Open the WinCC Flexible Tag simulation and force every alarm trigger bit high in turn; confirm the alarm appears with the correct number in the alarm view.
7.2 Dynamic checks (online with simulator)
- Start WinCC Flexible Runtime on the engineering PC with the S7-PLCSIM coupled.
- In PLCSIM, set DB100.DBX0.10 (alarm 11) to TRUE. Confirm the alarm appears in the runtime within one HMI acquisition cycle.
- Watch DB100.DBW34 in PLCSIM and confirm it reads
11. - Set DB100.DBX0.10 to FALSE and DB100.DBX0.50 (alarm 51) to TRUE. Confirm DB100.DBW34 updates to
51. - Toggle 3 alarms in the same PLC cycle; verify the HMI logs all three and the PLC word shows the highest number.
7.3 Acceptance criteria
| Criterion | Target | How to verify |
|---|---|---|
| Latency from PLC bit set to PLC word update | ≤ 2 HMI acquisition cycles | Cross-trigger an oscilloscope on the bit and the word via HMI trace |
| Alarm-number correctness for 100 random triggers | 100% match | Auto-test with a watch table forcing sequential bits |
| PLC CPU load after enabling the FC | ≤ +2 ms on a 315-2 PN/DP | Compare OB1 execution time before/after |
| HMI script CPU on a 177B 6" | ≤ 30% | Use System Diagnostics → CPU load |
8. Edge Cases and Field-Proven Caveats
- Alarm number vs. alarm ID. WinCC Flexible exposes a project-local number (1…65,536) and a runtime-assigned ID (a GUID-like handle). The external system must use the number, not the ID, because IDs are not stable across project rebuilds.
- Alarm number reuse. If you delete alarm 200 and re-create it as a different condition, the number 200 now refers to new semantics. Maintain a separate change-log CSV in source control.
- Multilingual projects. The number does not change with language switching, but the text does. If the external system needs the localized text, the HMI must also publish a text-ID word that the SCADA can map to its own string table.
- Acknowledgement state. WinCC Flexible tracks four states: raised, cleared, acknowledged, locked. A bit-only transfer cannot distinguish these. If the external system needs the state, add a second word per alarm (16 bits) or use the structured-array method.
- Acquisition cycle vs. update cycle. Setting the trigger tag acquisition to 1 s on a 50-ms PLC OB1 is a common cause of "missed" alarms. Use 100 ms or 200 ms for fast processes; use 1–2 s for slow ones.
- Panel restart. After a panel reboot, the HMI re-reads the trigger bits. If the PLC does not re-assert them, the alarms clear on the panel. The PLC must keep the trigger bits latched until the condition is genuinely gone, not just until the operator acknowledges the alarm.
- Tag length limits. WinCC Flexible on a 177-series panel limits a single tag to 200 bytes. An array of 256 INTs is 512 bytes, exceeding the limit; split into two tags of 128 INTs each, or use Method A (bit-only). The Comfort Panel (TIA Portal) raised the limit to 4096 bytes per tag.
9. Migration to WinCC Unified
WinCC Flexible is end-of-life and has been superseded by WinCC Unified discrete alarms in TIA Portal. The migration is non-trivial because:
- The trigger tag model changed: Unified uses alarm conditions in the PLC or HMI, evaluated by a separate alarm engine.
- The VBScript API is replaced by JavaScript with the
HMIRuntime.Alarmingnamespace. - Alarm numbers are now 32-bit (DWORD) and include a configurable source ID.
For projects that already use Method A, the migration is straightforward: the PLC-side DB remains, the alarm list in the Unified project points to the same trigger tags, and the optional metadata is published via the new alarm-state tag interface. For projects that rely on the VBScript global cycle, the equivalent code in Unified is:
// TIA Portal V18+, JavaScript in a global module
import { Tag } from "HMIRuntime";
export function OnAlarmCycle() {
let active = HMIRuntime.Alarming.GetActiveAlarms("DiscreteAlarms");
if (active.length > 0) {
Tag("HMI_Active_Alarm_Count").Write(active.length);
Tag("HMI_Latest_Alarm_Number").Write(active[active.length - 1].Number);
Tag("HMI_Latest_Alarm_Time").Write(active[active.length - 1].RaiseTime);
} else {
Tag("HMI_Active_Alarm_Count").Write(0);
Tag("HMI_Latest_Alarm_Number").Write(0);
}
}
10. Comparison of Methods
| Criterion | A. PLC mirror | B. Action event | C. Global VBScript | D. Bulk array |
|---|---|---|---|---|
| PLC load | +0.1–0.5 ms | 0 | 0 | +0.5–1.0 ms |
| HMI load | 0 | low | medium–high | low |
| Survives HMI restart | yes | yes (re-fires events on re-eval) | yes | yes |
| Multi-alarm same cycle | handled by PLC | only last visible | handled by VBS | handled by PLC |
| Configuration effort | medium | high (per alarm) | low (one script) | medium |
| Best fit | any project ≤1024 alarms | small projects, few events | PC Runtime | cross-PLC coupling |
11. Frequently Asked Questions
What is the maximum number of discrete alarms in WinCC Flexible?
Up to 4,000 discrete alarms are supported on a Comfort Panel, 2,000 on a 177-series, and 8,000 on a WinCC Flexible PC Runtime. The limit is defined in the project settings; increasing it requires recompilation of the runtime.
Can the PLC read the alarm text, not just the number?
Not directly. WinCC Flexible stores the text in the panel's string table, indexed by the alarm number. The PLC must reference a parallel text table it maintains itself, or the SCADA must read the HMI text via OPC UA on a Unified panel. The pattern shown in Method A uses a Word tag and a documented CSV in source control.
Why does the alarm appear in the HMI but DB100.DBW34 still reads 0?
Three common causes: (1) the FC that computes the latest number is not called in OB1; (2) the alarm trigger tag is the wrong DB byte offset, so the bit does not actually exist; (3) the HMI acquisition cycle is still loading the tag after a project download. Force a tag refresh on the panel (System → Tag simulation → Update) and check the HMI diagnostics buffer.
What happens if the HMI goes offline while an alarm is raised?
The PLC keeps the trigger bit latched. When the HMI reconnects, it re-evaluates all trigger tags and the alarm reappears in the alarm view with a fresh timestamp. The PLC Latest_Alarm_Number word does not change because the source state did not change; if the external system needs to know the alarm re-appeared, use the alarm's Appearance event (Method B) or have the SCADA poll the HMI status OPC tag.
Can the alarm number be exposed via OPC DA/UA to a non-Siemens SCADA?
Yes. Expose the PLC tag holding the number (e.g. DB100.DBW34) as an OPC item on the S7-1500 OPC UA server, or use a WinCC Comfort OPC DA server. The tag is read-only on the HMI side, so security policies can be set to deny write access. The SCADA then receives the number in real time without needing a direct PLC driver.