Triggering WinCC 7.4 Alarm Sounds from Word Tags via C-Script
WinCC 7.4 SCADA systems frequently require acoustic notification when an alarm is raised, a process value crosses a threshold, or an operator event occurs. The Horn Editor shipped with WinCC 7.4 accepts only binary tags for horn triggering, which presents a direct limitation: a 16-bit or 32-bit WORD/DWORD tag — the most common structure for alarm status words, error registers, or device fault codes coming out of a PLC — cannot be wired directly into the Horn tab. This article provides a complete procedure to detect changes or value thresholds in a WORD tag and trigger a WAV playback through a WinCC Global Script C action, including handling multi-bit alarm words, debouncing, and assigning different sounds per bit position.
1. Why the Horn Editor Rejects WORD Tags
The Horn Editor is part of the WinCC Explorer (right-click your computer → Properties → Horn) and is bound to message classes in Alarm Logging. The trigger objects available in the trigger list are restricted to:
- Binary internal tags (channel: Internal)
- Binary process tags (channel: e.g. SIMATIC S7-PLC, MODBUS TCP, OPC)
- Tag bits accessible via the
GetTagBitinterface (e.g.MyWord_0for bit 0 of the WORD tagMyWord)
Selecting a raw WORD tag is rejected because the horn evaluation is a Boolean signal path; it expects a single bit transition to start or stop playback. A 16-bit value is treated as a numeric data object that must be decomposed into individual bits before the horn can react. The same restriction applies to DWORD, INT, and REAL tags — they must be reduced to binary representations upstream of the Horn Editor.
2. Two Engineering Approaches
| Approach | Mechanism | Best Used When |
|---|---|---|
| A. Bit alias tags + Horn Editor | WinCC internal tags reference individual bits of the WORD using MyWord_x syntax. Each bit is wired as a horn trigger. |
Alarm dictionary is fixed; you want Alarm Logging to drive the horn directly. |
| B. C-Script Global Action | A scheduled C action polls the WORD tag, evaluates bits or value ranges, and calls PlaySound/mciSendString to play a WAV file. |
Custom mapping logic, multi-level alarms, or sound files that change at runtime. |
Approach A is the simplest when the WORD is purely an aggregation of single-bit alarms. Approach B is required when:
- The same WORD carries encoded alarm classes (e.g. bits 0–3 = severity, bits 4–7 = subsystem).
- You need to play different WAV files per bit position without creating 16 horn entries.
- The horn must react to value transitions (e.g. counter > 100) rather than discrete bits.
3. Prerequisites
- WinCC 7.4 SP3 or later installed (the project structure described is verified against the WinCC V7.4 SP3 release notes).
- The WORD tag (e.g.
AlarmWord) is configured in the WinCC Tag Management with the correct channel driver, data typeWORD(unsigned 16-bit), and a sensible update cycle (250–1000 ms typical for alarms). - WAV files are placed in a directory the WinCC Runtime can access. The project subfolder
<Project>\GraCS\is the conventional location; the runtime automatically searches\GraCS, the project root, and\ssm. - Sound device enabled on the operator station (Windows Audio Service running, default audio device selected).
- Editor access to Global Script C (requires the WinCC Configuration Studio and the Global Script Runtime right on the user).
PlaySound function. If a beep is required instead of a WAV, use the Windows MessageBeep API (see Section 7).4. Approach A: Bit Alias Tags (No Scripting)
This method exposes every bit of the source WORD as a virtual internal tag using WinCC's built-in tag bit addressing.
4.1. Create the Internal Bit Aliases
- Open WinCC Explorer → Tag Management.
- Select the connection (or create an Internal connection if the bit mapping should remain in WinCC).
- Right-click → New Tag and create 16 tags named
AlarmWord_0throughAlarmWord_15with data typeBinary Tag. - In the tag properties, set the Address field to reference the source WORD plus bit offset. The syntax depends on the channel driver; for an S7-1500 connection using the symbol name
"AlarmWord"the addressing would remain a single tag — the bit extraction is performed at tag-creation time using the PLC's bit-access syntax"AlarmWord".X0only for S7-PLCSIM symbolic access. For MODBUS, the equivalent is40001.0through40001.15(function code 03, address+bit).
For internal-only evaluation, the simplest reliable method is:
- Create 16 internal binary tags.
- Create a Global Script Action with a 1 s trigger that reads the source WORD, masks each bit, and writes the result into the internal binary tag:
// Global C action — scheduled every 1000 ms
#include "apdefap.h"
int gscAction(void)
{
DWORD raw = 0;
raw = GetTagWord("AlarmWord"); // returns unsigned 16-bit value
int i;
for (i = 0; i < 16; i++)
{
char tagname[32];
sprintf(tagname, "AlarmWord_%d", i);
SetTagBit(tagname, (raw >> i) & 0x0001);
}
return 0;
}
The 16 internal tags are then bound to the Horn Editor as ordinary binary triggers.
4.2. Configure the Horn
- In WinCC Explorer, right-click your computer → Properties → Horn.
- Click Add…. For each bit, pick the message class (e.g. Alarm, Warning) and select the corresponding internal tag (e.g.
AlarmWord_3) in the trigger column. - Assign the WAV file. Click the Sound cell and browse to the WAV in
\GraCS\Sound. - Configure the acknowledge behaviour: On acknowledge (sound stops only when the operator clicks Acknowledge) vs. On reset (sound stops as soon as the bit clears).
5. Approach B: C-Script Global Action for Direct WAV Playback
When the Horn Editor is too rigid (custom mapping, conditional horn, runtime sound selection), a Global Script C action drives the audio subsystem directly. The official Siemens FAQ "How do you output a sound via C script in WinCC V7?" is the canonical reference for this technique. The implementation below extends that FAQ with WORD-tag evaluation, latching, and per-bit sound selection.
5.1. Project Layout
<Project>\GraCS\Horn\Fault1.wav<Project>\GraCS\Horn\Fault2.wav<Project>\GraCS\Horn\Critical.wav- Global Script action
WordHornAction— scheduled, trigger = 500 ms.
5.2. The C Action
// Global C action — WordHornAction.prg
// Polls the WORD tag "AlarmWord" and plays a WAV when a bit rises.
// Uses mciSendString from winmm.dll to play the file.
#include "apdefap.h"
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
int gscAction(void)
{
static DWORD sLastValue = 0xFFFF; // sentinel: triggers on first call
DWORD raw = GetTagWord("AlarmWord");
if (raw == sLastValue) return 0; // no change → no horn
DWORD rising = raw & ~sLastValue; // bits that just turned ON
sLastValue = raw;
char cmd[512];
char file[256];
// Bit 0 → critical alarm (highest priority)
if (rising & 0x0001)
{
sprintf(file, "%s\\GraCS\\Horn\\Critical.wav", GetProjectPath());
sprintf(cmd, "open \"%s\" type waveaudio alias crit", file);
mciSendString(cmd, NULL, 0, NULL);
mciSendString("play crit", NULL, 0, NULL);
}
// Bit 3 → Fault1
if (rising & 0x0008)
{
sprintf(file, "%s\\GraCS\\Horn\\Fault1.wav", GetProjectPath());
sprintf(cmd, "open \"%s\" type waveaudio alias f1", file);
mciSendString(cmd, NULL, 0, NULL);
mciSendString("play f1 from 0", NULL, 0, NULL);
}
// Bit 7 → Fault2 (loops until bit clears)
if (rising & 0x0080)
{
sprintf(file, "%s\\GraCS\\Horn\\Fault2.wav", GetProjectPath());
sprintf(cmd, "open \"%s\" type waveaudio alias f2", file);
mciSendString(cmd, NULL, 0, NULL);
mciSendString("play f2 repeat", NULL, 0, NULL);
}
// Stop the looping Fault2 when bit 7 clears
if (!(raw & 0x0080))
mciSendString("stop f2", NULL, 0, NULL);
return 0;
}
5.3. Triggering the Action
- In WinCC Explorer → Global Script → C-Editor, open the file above.
- Right-click the action function
gscAction→ Information/Trigger → Add. - Configure a cyclic trigger of 500 ms (do not go below 250 ms on a large project; the action will be a load on the script engine).
- Save, then compile (File → Compile or Ctrl+F7). Errors appear in the output window — fix missing
#includepaths or typos before starting Runtime.
6. Verification Procedure
- Force the source WORD from the PLC (or simulate via an internal tag) to
0x0001→ Critical.wav must play once and stop. - Set the WORD to
0x0080→ Fault2.wav must loop continuously. - Set the WORD to
0x0000→ looping must stop within one trigger interval (≤ 500 ms). - Set the WORD to
0xFFFFon startup → all mapped WAVs play once, no double-fire, no missed bit. - Restart WinCC Runtime (simulate power-cycle) with the WORD already at
0x0001in the PLC. Because the action uses a sentinel0xFFFF, the first poll detects the rising edge and fires the horn exactly once.
7. Alternative: Beep Instead of WAV
For a one-channel operator-station buzzer you can call the Win32 API directly without a WAV file:
// inside gscAction, instead of mciSendString
if (rising & 0x0001) MessageBeep(MB_ICONHAND); // critical
if (rising & 0x0008) MessageBeep(MB_ICONEXCLAMATION);
The advantage is zero asset management; the disadvantage is the sound cannot be customized per project and is tied to the Windows sound scheme.
8. Troubleshooting Matrix
| Symptom | Probable Cause | Fix |
|---|---|---|
| No sound, no error in GSC output | WAV file not in the runtime's search path | Place the WAV in <Project>\GraCS\ or pass the absolute path with GetProjectPath()
|
| Horn fires continuously even after bit clears | Loop without stop; no falling-edge evaluation | Add the stop f2 block from §5.2 or call PlaySound(NULL,NULL,0)
|
| Horn misses bits on the first poll | Static last-value initialised to 0 | Initialise the static variable to 0xFFFF so the first read is always treated as an edge |
"mciSendString returned 263" error |
Alias name already open from a previous call | Issue close f1 / close f2 / close crit at the top of the action, or use unique aliases per call |
| Action compiles but does not run | Trigger configuration not activated | Right-click the action → Information/Trigger → verify the trigger is enabled and the project is activated |
| Sound cuts off on alarm acknowledgement | Horn set to "On acknowledge" | Switch the message-class property to "On reset" if the bit auto-clears in the PLC |
| Audio device not available after RDP session | Windows audio service not running in the RDP context | Configure the operator station as a console session, not a thin-client RDP target, or enable audio redirection |
9. Performance and Reliability Considerations
- Keep the cyclic trigger ≥ 250 ms. Each poll performs a tag read and a small amount of bitwise logic; the cost is negligible, but the MCI open/close per WAV is heavier — 50 ms or more on Windows 10/11.
- Use
GetTagWord/SetTagBitas the synchronous API only for low-frequency polling. For high-frequency updates (> 5 Hz) prefer the asynchronous variant or use Alarm Logging as the data source. - Localize the WAV file paths with
GetProjectPath(). Hard-coded paths break the moment the project is moved or activated on a different machine. - For redundant servers, copy the WAV files in both server projects, or store them on a shared drive and reference the UNC path.
- Do not put a for-loop over 16 calls to
mciSendString— instead precompute therisingmask and branch only on the bits that actually changed, as shown in §5.2.
10. Relationship to Alarm Logging
If the goal is to play a sound on every alarm message of a given class, the recommended route is to let Alarm Logging drive the horn — not the C action. The C action is the correct tool only when the alarm state is encoded in a non-binary tag, or when the WAV must be selected dynamically. To convert Alarm Logging messages to horn triggers, configure the message class's Acknowledgement and Horn properties in WinCC Explorer → Alarm Logging and select the appropriate internal binary or process bit. Detailed step-by-step procedure is in the WinCC Information System under Alarm Logging → Configuring the Horn.
FAQ
Can the Horn Editor in WinCC 7.4 trigger directly from a WORD tag?
No. The Horn Editor accepts only binary tags or single tag bits (e.g. MyWord_0). For a 16-bit WORD you must either expose 16 bit-alias tags or use a C-Script Global Action to play the WAV directly via mciSendString.
Which Siemens document covers sound output via C script in WinCC V7?
Siemens Support entry ID 748844 "How do you output a sound via C script in WinCC V7?" describes the PlaySound / mciSendString approach used in this article.
What WAV format is recommended for WinCC horn playback?
Use 16-bit PCM mono WAV at 22.05 kHz placed under <Project>\GraCS\. MP3 and other compressed formats are not supported by PlaySound or the MCI waveaudio interface.
How do I avoid double-firing the horn on WinCC Runtime startup?
Initialise the static "last value" variable in the C action to 0xFFFF (or any value impossible in normal operation). The first poll will then detect a true rising edge for every active bit and fire each horn exactly once.
Can I use a DWORD or REAL tag with the same script?
Yes. Replace GetTagWord with GetTagDWord or GetTagFloat and adjust the bit-mask constants. For a REAL tag, evaluate value thresholds instead of bit positions (e.g. if (value > 95.0) PlaySound(...);).