Switching WinCC I/O Field Tag Links Conditionally with SetLink()
Engineers frequently need a single WinCC I/O field to display or modify two different process tags depending on runtime state — for example, switching between a setpoint and an actual value, between a local and a remote variable, or between two redundant sources. WinCC V7.4 and V7.5 do not expose a direct property to swap tag bindings on a control in the Properties dialog, but the C-script API provides SetLink() to rewire the tag connection at runtime. This article documents the two production-grade approaches: (1) the SetLink() C-script method, and (2) the layered I/O field / visibility method, and contrasts them with the equivalent configuration flow in WinCC Unified (TIA Portal V20).
1. Problem Definition and Use Cases
The original requirement is a Boolean control tag acting as a selector:
| Selector Tag (BOOL) | Active I/O Field Tag | Data Type | Direction |
|---|---|---|---|
| TRUE (1) | Tag1 (e.g., ProcessValue_A) | INT (16-bit) | Input/Output |
| FALSE (0) | Tag2 (e.g., ProcessValue_B) | INT (16-bit) | Input/Output |
Typical industrial use cases for this pattern include:
- Manual/Auto mode switching: one I/O field shows operator setpoint in Manual, real measured value in Auto.
- Primary/Backup source display: a redundant tag swap driven by a health bit.
- Recipe phase selection: the same I/O field writes a parameter at different recipe stages.
- Engineering unit toggle: one field shows °C when Metric = 0, °F when Metric = 1.
2. Prerequisites
- WinCC V7.4 SP1, V7.5, or V7.5 SP1 installed on the engineering station with the C-Script option enabled (the standard install includes ANSI-C). Verify under Start → Programs → Siemens Automation → WinCC → Tools → WinCC Configuration Studio that the Global Script runtime is licensed.
- All three tags defined in the WinCC Tag Management:
Selector_Bool(BOOL),Tag1_INT(signed 16-bit),Tag2_INT(signed 16-bit). External tags must be reachable from the AS via the configured channel (S7-1200/1500 OPC UA, S7 MPI/TCP, or SIMATIC S7 Protocol Suite). - Project function access rights to the C-Editor (full administration password). Test on a local WinCC RT simulator before deploying to a Panel or PC RT.
- Reference: WinCC V7.5 Scripting: C-Script Reference (Entry ID 109773213). Locate
SetLink(),GetLink(), andSetVisible()in the API index.
3. Approach A — Dynamic Tag Switch with SetLink()
3.1 SetLink() API Reference
Per the WinCC V7.5 C-Script reference manual (Entry ID 109773213), the function prototype is:
BOOL SetLink(LPCTSTR lpszPictureName,
LPCTSTR lpszObjectName,
LPCTSTR lpszPropertyName,
LPCTSTR lpszTagName);
| Parameter | Type | Description | Example |
|---|---|---|---|
lpszPictureName |
LPCTSTR | Name of the parent picture (use NULL or GetParentPicture(lpszPictureName) for the current picture) |
"MainOverview.PDL" |
lpszObjectName |
LPCTSTR | Object name of the I/O field on the screen | "IOField_Sel" |
lpszPropertyName |
LPCTSTR | Property of the I/O field to relink. Standard is "OutputValue"
|
"OutputValue" |
lpszTagName |
LPCTSTR | Full WinCC tag name, including any structure prefix | "Tag1_INT" |
| Return | BOOL | TRUE = link set successfully; FALSE on error | — |
3.2 Implementing the C-Script
Open the picture where the I/O field is placed, right-click the I/O field → Properties → Events → Mouse Click (or the property change of the boolean selector tag), and select C-Action. Paste the following code:
// Function: Switch the IO field's tag link based on Selector_Bool
// Trigger : Click on the I/O field, or change of Selector_Bool
#include "apdefap.h"
void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y)
{
DWORD dwSelector = 0;
BOOL bOkSel = FALSE;
BOOL bOkLink = FALSE;
// 1. Read the boolean selector tag
dwSelector = GetTagDWord(lpszPictureName, "Selector_Bool", &bOkSel);
if (!bOkSel) {
printf("SwitchIOF_Tag: Selector_Bool read failed (state=0x%lX)\r\n", dwSelector);
return;
}
// 2. Choose the target tag
LPCTSTR szNewTag = (dwSelector != 0) ? (LPCTSTR)"Tag1_INT" : (LPCTSTR)"Tag2_INT";
// 3. Re-link the I/O field's OutputValue to the new tag
bOkLink = SetLink(lpszPictureName,
"IOField_Sel",
"OutputValue",
szNewTag);
if (!bOkLink) {
printf("SwitchIOF_Tag: SetLink to %s FAILED\r\n", szNewTag);
} else {
printf("SwitchIOF_Tag: linked to %s\r\n", szNewTag);
}
}
Because SetLink() swaps the tag at runtime, the I/O field immediately begins displaying the new process value. The configured Output/Input formatting (decimal places, limits, color) is preserved.
SetLink() takes a few milliseconds because it tears down the existing tag connection and registers a new subscription. Do not call it on every cycle — bind it to a discrete event (button click, property change of the selector tag, or a 1-second scheduler if the selector changes frequently).
3.3 Automatic Switch on Selector Change
To trigger the swap automatically when Selector_Bool changes, attach the same script as a C-action on the tag's standard cycle (every 500 ms is enough for a human-driven selector). The GetTagDWord cache in the WinCC internal tag manager will return the updated state without generating WinCC system traffic.
// Place this as a "Standard cycle (500 ms)" C-Action on the picture
void CyclicSwap(char* lpszPictureName)
{
static DWORD dwLast = 0xFFFFFFFF; // invalid initial state
DWORD dwNow = GetTagDWord(lpszPictureName, "Selector_Bool");
if (dwNow == dwLast) return; // no change, no work
dwLast = dwNow;
SetLink(lpszPictureName,
"IOField_Sel",
"OutputValue",
(dwNow != 0) ? "Tag1_INT" : "Tag2_INT");
}
4. Approach B — Layered I/O Fields with Visibility Animation
This is the most maintainable method for projects that avoid C-scripts. Two I/O fields are placed at the same screen coordinates, one for Tag1_INT and one for Tag2_INT. The Display property of each I/O field is animated with a C-action or direct tag-driven visibility expression based on Selector_Bool.
4.1 Configuration Steps
- In the WinCC Graphics Designer, drag two I/O field controls from the toolbox onto the picture. Rename them
IOField_Tag1andIOField_Tag2. - Configure
IOField_Tag1: selectTag1_INTfor Output Value. ConfigureIOField_Tag2: selectTag2_INT. - Align them pixel-perfectly. Use Arrange → Align → Left/Top to stack them.
- Open Properties → Display → Visible on
IOField_Tag1. Right-click → Dynamic Dialog. Create an expression of typeSelector_Bool == 1, result type Boolean, true = visible. - On
IOField_Tag2create the inverse:Selector_Bool == 0→ visible. - For touch / mouse interaction, you must also animate the Operator Control Enable property so only the visible field accepts input.
| Object | Tag | Visible When | Operable When |
|---|---|---|---|
| IOField_Tag1 | Tag1_INT | Selector_Bool = TRUE | Selector_Bool = TRUE |
| IOField_Tag2 | Tag2_INT | Selector_Bool = FALSE | Selector_Bool = FALSE |
Drawback: doubled engineering effort, and the "hidden" I/O field still occupies its control in memory. The C-action approach (Approach A) is preferred when memory or screen real estate is constrained, or when more than two tags must rotate through a single control.
5. Approach C — Equivalent Configuration in WinCC Unified (TIA Portal V20)
In WinCC Unified (TIA Portal V20) — IO Field (RT Unified), the configuration model is tag-driven by design. You create the IO field by dragging a tag from the detail view onto the screen, and the tag binding is treated as a property that can be re-assigned dynamically through the Tag property of the control.
- Place an IO field on the Unified screen.
- Open Properties → General → Process tag. Bind it to a script that returns the active tag name:
Tags("Tag1_INT");orTags("Tag2_INT");depending onSelector_Bool. - Add a Change event on
Selector_Boolcalling a JavaScript function that writes the new tag into the IO field's tag property usingUI.FindElement("IOField_1").Tags = Tags("Tag1_INT");. - Set the DataFormat to
%dfor signed 16-bit integer display. Configure Limits if operator must enforce a process range.
WinCC Unified supports this natively because the IO field's tag is exposed as a writable property; you do not need a low-level API like SetLink().
6. Parameter & Property Reference
| Property | WinCC Classic (V7.4/V7.5) | WinCC Unified (V20) |
|---|---|---|
| Tag binding | Static in I/O field config; SetLink() at runtime |
Static in tag property; Tags() script at runtime |
| Numeric format |
Output Value → Output/Input → Format e.g. 9999
|
DataFormat string e.g. {D},10,0
|
| Limits | Property "UpperLimit" / "LowerLimit" via direct tag connection | Property Limits → Max / Min |
| Color / Blink | Animated via C-action or direct tag | Animated via dynamic SVG styles |
| Operator enable | Operator Control Enable property | Enabled property |
7. Verification Procedure
- Compile the project (Build → Rebuild All in Configuration Studio). Watch for the WinCC C-Script Compiler log to confirm no syntax errors. Common build error
CS0001: undefined identifier 'SetLink'indicates a missing apdefap.h include. - Start WinCC Runtime in simulation mode (Start WinCC Runtime → Start in Simulation). The Diagnostics window will surface
SetLink()return values. - Force
Selector_Bool = 1via the internal tag simulator. The I/O field should displayTag1_INTwithin one screen refresh. - Force
Selector_Bool = 0. Confirm display switches toTag2_INT. - Click the I/O field and enter a new value. Trace the value in the Tag Management → Internal Tags to confirm the write went to the active tag only.
- Toggle the selector rapidly (10 transitions over 2 seconds) and observe the WinCC system log:
SetLink()should report TRUE each time. If FALSE appears, the tag is likely read-only or its data type does not match the I/O field format. - Export the runtime log via Tools → Output Window → Save as for FAT documentation.
8. Troubleshooting Matrix
| Symptom | Likely Cause | Fix |
|---|---|---|
| SetLink returns FALSE, value never updates | Tag name does not exist in tag management or has wrong structure prefix | Verify with GetLink(); ensure tag is enabled and not filtered by channel diagnosis |
| IO field freezes on first link and does not switch | C-action only attached as Mouse Click; user is not clicking | Attach a 500 ms cyclic C-action or trigger on property change of Selector_Bool
|
| Display value is correct, but writes go to the wrong tag | Input and Output bindings are separate; only OutputValue was re-linked |
Call SetLink() for both OutputValue and InputValue properties |
| Compiler error: 'GetTagDWord' not found | ANSI-C project option not enabled | Project → Properties → Options → activate "Global Script Runtime" and "ANSI-C" |
| IO field shows '####' after switch | Format string does not match the new tag's range | Set format to @d (decimal) or 99999 for INT values up to 32767 |
| Operator can edit the hidden IO field | Operator Control Enable not animated | Add same dynamic dialog to Operator Control Enable as used for Visible |
| Script executes but no log line appears | printf() output suppressed in RT | Use APRTLogWrite() or route to GSC Diagnostics |
9. Field-Proven Best Practices
- Always validate the return value of
SetLink()and log it. A silent failure during commissioning becomes a hunt-and-peck exercise at go-live. - Add a 1-second debounce on selector-driven swaps if the selector comes from a noisy digital input or an HMI button with no anti-bounce.
- Mirror the script logic into a Global Script C-function so it can be reused across multiple pictures; pass picture name and object name as parameters.
- Document the tag name resolution in the picture header comment: which tag is currently shown under which condition. This is mandatory for SAT (Site Acceptance Test) traceability.
- For S7-1500 panels (Comfort/MTP), confirm the panel image supports C-scripts — Comfort panels (TP, KP, MP) do not run C-scripts natively. Use the visibility method (Approach B) on those, or migrate the logic to the PLC using a function block and a single tag with a multiplexer.
- Reserve the
SetLink()approach for PC-based WinCC Runtime (WinCC RT Professional, WinCC RT Advanced on a PC) where the C-script engine is fully supported.
10. Migration Path: From WinCC Classic V7.4/V7.5 to WinCC Unified
If the project is targeted for migration to TIA Portal V20, the SetLink() pattern is replaced by a Unified JavaScript function triggered by a tag change event. The state of Selector_Bool becomes the input, and the IO field's Process tag property is updated via Tags(...) or the model API. Tag names remain identical, so the AS side does not need to be re-engineered.
For mixed fleets, keep the WinCC Classic approach documented in the project history and replicate the behavior in Unified using the IO field documentation linked above. The configuration grammar differs, but the runtime semantics — one tag active at a time, switched by a boolean control tag — are preserved.
FAQ
Can I use SetLink() on a Comfort Panel (TP700/1500) running WinCC RT Advanced?
No. Comfort Panels do not run the ANSI-C script engine. Use the layered I/O field with the visibility animation (Approach B) or push the multiplexer logic into an S7 function block and bind a single tag to the I/O field.
Why does my I/O field show ##### after a SetLink() call?
The display format string configured on the I/O field cannot represent the new tag's value range, or the new tag is in an error state. Set the format to @d for 16-bit signed integers and verify the tag quality with the internal Tag Simulator.
How do I relink both the Input and Output properties in one call?
Call SetLink() twice — once with lpszPropertyName = "OutputValue" and once with "InputValue". The two properties are independent bindings in the I/O field control.
Is there a script in WinCC Unified that does the same job as SetLink()?
Yes. Use a JavaScript function triggered on the Change event of the selector tag. The script writes the active tag to the IO field's Process tag property via Tags("Tag1_INT") or the model API. The WinCC Unified IO field reference is documented at the TIA Portal V20 documentation portal.
What is the maximum number of tag switches per second that SetLink() can handle?
On a typical WinCC RT Professional PC station, SetLink() can complete in 1–5 ms per call. Sustained switching at 100 Hz is possible but unnecessary — debounce to 200–500 ms for human-driven selectors and rely on the cyclic C-action for any automated swap.