Switching WinCC I/O Field Tag Links Conditionally with SetLink()

David Krause11 min read
HMI ProgrammingSiemensTutorial / How-to
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

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.
Constraint: A WinCC Classic I/O field is a single graphic object. Only one process tag can be bound to its Output Value and one to its Input Value properties at any moment. Switching tags dynamically therefore requires either a C-script rewriting the link, or a layered set of I/O fields with the visibility property driving which one is interactable.

2. Prerequisites

  1. 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.
  2. 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).
  3. 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.
  4. Reference: WinCC V7.5 Scripting: C-Script Reference (Entry ID 109773213). Locate SetLink(), GetLink(), and SetVisible() 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.

Performance: 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

  1. In the WinCC Graphics Designer, drag two I/O field controls from the toolbox onto the picture. Rename them IOField_Tag1 and IOField_Tag2.
  2. Configure IOField_Tag1: select Tag1_INT for Output Value. Configure IOField_Tag2: select Tag2_INT.
  3. Align them pixel-perfectly. Use Arrange → Align → Left/Top to stack them.
  4. Open Properties → Display → Visible on IOField_Tag1. Right-click → Dynamic Dialog. Create an expression of type Selector_Bool == 1, result type Boolean, true = visible.
  5. On IOField_Tag2 create the inverse: Selector_Bool == 0 → visible.
  6. 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.

  1. Place an IO field on the Unified screen.
  2. Open Properties → General → Process tag. Bind it to a script that returns the active tag name: Tags("Tag1_INT"); or Tags("Tag2_INT"); depending on Selector_Bool.
  3. Add a Change event on Selector_Bool calling a JavaScript function that writes the new tag into the IO field's tag property using UI.FindElement("IOField_1").Tags = Tags("Tag1_INT");.
  4. Set the DataFormat to %d for 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

  1. 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.
  2. Start WinCC Runtime in simulation mode (Start WinCC Runtime → Start in Simulation). The Diagnostics window will surface SetLink() return values.
  3. Force Selector_Bool = 1 via the internal tag simulator. The I/O field should display Tag1_INT within one screen refresh.
  4. Force Selector_Bool = 0. Confirm display switches to Tag2_INT.
  5. 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.
  6. 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.
  7. 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.

Safety note: Tag switching should never be the primary safety interlock. The selector and the value source must be validated at the controller level (e.g., S7-1500 F-CPU) using validated selection logic. The HMI is an operator convenience, not a safety function.

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.

Back to blog