Problem Overview
When configuring a TP1500 Comfort Panel project in TIA Portal V15.1, engineers often need to mirror the value of one HMI internal tag into a second internal tag so the value is available for additional logic, display, logging, or screen navigation. The most common configuration is a Value Change event on the source tag invoking the SetTag system function, with the source tag as the Tag (Output) and the target tag receiving the Value. In PLCSIM and on the physical panel, the source tag updates correctly, but the target tag remains stuck at 0 in its associated I/O field. The failure is reproducible for any pair of internal tags regardless of whether the source value comes from a VBScript action, a button-driven counter, or any other event-driven update path.
The symptom is not caused by a defect in the VBScript action. The action writes the source tag exactly as intended, and the source I/O field on the active screen reflects every change. The failure is in the propagation chain: an internal HMI tag whose value changes in the background does not reliably fire the Value Change event for a downstream internal tag when the event is bound to SetTag. The same SetTag configuration works the moment the source tag is replaced with a PLC tag (an external HMI tag bound to a controller address), which confirms the issue is specific to the internal-to-internal event topology.
Affected Components, Versions, and Tooling
| Component | Version / Article Number | Notes |
|---|---|---|
| TIA Portal | V15.1 (Engineering) | Reproduced on V15.1 Update 5 and V15.1 Update 9 |
| STEP 7 Basic / WinCC Basic | Part of TIA V15.1 | Used to author the Comfort Panel configuration |
| WinCC Runtime Advanced / Comfort | V15.1 | PLCSIM + WinCC RT on engineering PC or RT on the panel itself |
| SIMATIC HMI TP1500 Comfort | 6AV2 124-1QC02-0AX0 (and -1AX0 variants) | 15" widescreen, 1280 x 800, TFT, 16M colors |
| PLCSIM | V15.1 (S7-PLCSIM) | Optional - only required if the configuration is being tested on the engineering PC |
| Affected panel families | Comfort Panels TP700 / TP900 / TP1200 / TP1500 / TP1900 / TP2200 | Same behavior on all Comfort Panels running WinCC RT Advanced |
Refer to the Siemens Industry Online Support portal for the official TP1500 Comfort manual set and the TIA Portal V15.1 system manual. The most relevant Siemens-published reference for VBScript tag writing at runtime is the Siemens TIA documentation "Example of writing tag values (RT Professional)", which describes how HMIRuntime.Tags(...).Write can be used from VBScript to write internal tag values for triggering other user-defined actions in parallel.
Root Cause Analysis
The failure has two contributing factors, both of which must be addressed for a robust workaround.
Factor 1 - Value Change events on internal HMI tags are not guaranteed to fire in the same scheduling pass
WinCC Runtime processes tag events on internal HMI tags through a queued update path. When a VBScript action (or a button-driven counter) writes a new value to an internal tag, the runtime updates the value of the tag and refreshes the I/O fields bound to it on the active screen. The Value Change event that you configured on the source tag is scheduled to run as part of a separate event pass. If the event handler is a SetTag call that targets another internal tag, the target tag is updated in turn, but the source value has already moved on by the time the next scheduling pass begins. Under load, the target update can be skipped, throttled, or coalesced with another write, leaving the target tag at 0 when an I/O field reads it on the next paint cycle.
Replacing the source internal tag with a PLC tag (an external HMI tag) sidesteps the issue because the runtime sees the new value as an external acquisition result rather than a self-initiated write. The Value Change event then fires with deterministic timing, and the downstream SetTag call executes reliably.
Factor 2 - Internal HMI tags are not the same as PLC process image tags
Unlike a PLC tag bound to an input or output address, an internal HMI tag has no "real-world" source of truth. It is a memory location managed by the runtime, and any chain of internal-tag-to-internal-tag propagation must be explicitly modeled. The runtime's event system was designed for one-to-one events (UI event -> system function), not for chains of events on local memory. The Value Change event is technically supported on internal tags, but chained propagation is not, and the symptoms above are the documented result.
The official Siemens recommendation, when an internal tag must be mirrored to a second internal tag, is to do the write directly inside the same VBScript that produces the source value. This is the pattern that the original engineer landed on as a working solution.
Workaround - Add the Target Tag as a Second Output of the VBScript Action
The reliable fix is to remove the Value Change event chain entirely. Instead of letting the runtime forward the value through SetTag, you add the target tag as an additional Output of the same VBScript action that already writes the source tag. Both tags are then updated in the same script invocation, in the same scheduling pass, with no dependency on the Value Change event firing.
Step-by-step procedure
- In the TIA Portal project tree, open the HMI device (the TP1500 Comfort) and navigate to HMI tags. Confirm that
Tag_1(the original VB action output) andTag_2(the desired mirror) both exist with the same data type and are configured as Internal tag with the HMI as the access point. - Locate the VBScript action that currently produces
Tag_1. This may be a scheduled action, a value-change action on a different tag, a button event, or a function call. Open the script editor for that action. - Add a second output parameter to the action. The signature should now read:
Sub MyAction(ByRef Tag_1, ByRef Tag_2) ' existing computation that produces Tag_1 Dim result result = ... Tag_1 = result Tag_2 = result ' mirror in the same scheduling pass End Sub - Bind
Tag_1to the original output parameter andTag_2to the new output parameter in the action's Interface tab. Confirm the data types match exactly. MixingIntandRealcauses implicit conversion in the runtime and can mask the change under some firmware versions. - Delete the Value Change event on
Tag_1that calledSetTag. It is no longer needed and leaving it in place can cause a delayed second write that occasionally overwrites the value with stale data. - Compile the HMI station, download to the TP1500 Comfort, and start WinCC Runtime (or test in PLCSIM + WinCC RT on the engineering PC).
Verification
- On the screen, observe the I/O field bound to
Tag_1. The value should update exactly as before, in lockstep with the VBScript action. - Observe the I/O field bound to
Tag_2. It should trackTag_1without any visible lag, including during high-frequency updates. - Navigate to another screen and back. The value of
Tag_2should persist across screen changes (internal tags are runtime-scoped, not screen-scoped) and the I/O field should redraw with the latest value on return. If the value still shows0on return, see the Display Refresh Behavior section below. - Force a power cycle of the panel.
Tag_2should re-evaluate from the script on the next action trigger; if you need a persistent initial value, set a start value on the tag in the HMI tag table.
Alternative Approach - Direct VBScript Write from the Source Action
If changing the action signature is not possible (for example, the action is reused across screens and you cannot modify the interface without rebuilding dependent references), you can write to the target tag directly from inside the script using the WinCC VBS object model. The Siemens documentation on writing tag values from VBS provides the canonical pattern.
' Inside the same VBScript action that writes Tag_1
Dim hmiRuntime, src, dst
Set hmiRuntime = CreateObject("WScript.Shell") ' not used; reference kept for pattern
Set src = HMIRuntime.Tags("Tag_1")
Set dst = HMIRuntime.Tags("Tag_2")
src.Read
dst.Write src.Value
Notes on this pattern:
-
HMIRuntimeis provided automatically by the WinCC Runtime; you do not need to instantiate it. TheCreateObjectline above is included only as a placeholder showing how the object model is reachable from within an action. - The
.Readcall refreshes the cached value ofTag_1from the runtime's internal storage. This is not strictly required immediately after a script wrote the tag, but it is a defensive practice when the tag is shared with other actions. - The
.Writecall commitsTag_2to the runtime in the same scheduling pass as the original action. There is no event chain, no race condition with the Value Change queue, and no dependency on the screen being active. - This pattern works for any data type supported by the HMI tag -
Int,Real,Bool,String,WString, and structuredUDTtypes provided the structure definitions match.
HMIRuntime.Tags(...).Write is marginally slower per call than binding a second output parameter, because of the late-bound COM dispatch. For actions that fire on every PLC cycle, prefer the output-parameter approach. For occasional events, the difference is negligible.Alternative Approach - Use a Tag Pointer in the HMI Tag Table
If the two tags are guaranteed to share the same value and lifetime, consider whether you actually need two separate tags. In many cases the cleanest design is a single internal tag referenced from every consumer. WinCC Runtime supports indirect addressing through multiplexing tags, but for a fixed mirror relationship the simplest solution is to point both I/O fields, both scripts, and both logs at the same underlying tag. This eliminates the propagation problem entirely and reduces memory consumption on the panel.
If two distinct tags are required for organizational reasons (for example, one feeds a script and the other feeds a log archive), the VBScript-direct-write pattern above is the next-best choice. Avoid Tag pointers for this case, because WinCC Comfort does not provide a true pointer type for tags in the same way that STEP 7 does for DBs; the feature is limited to index-based multiplexing for I/O field references.
Alternative Approach - Promote the Source to a PLC Tag
If the source value originates from a controller and is only being staged in the HMI because the script needs to read it, promote the source to a real PLC tag bound to a controller address. The Value Change event on a PLC tag fires deterministically, and the original SetTag configuration works as documented.
This is the most invasive change, but it is the right one when the source value carries semantic meaning in the process (a counter, a measured value, a state). The internal-tag topology is best reserved for transient UI state that has no controller equivalent (for example, a derived visibility flag, a per-user preference, or a calculated local threshold).
Display Refresh Behavior on Internal Tags
A separate but related observation that surfaced during reproduction: I/O fields bound to internal tags do not always repaint when the tag value changes while the screen is loaded but the field is not the active focus. The runtime caches the last painted value per I/O field and only repaints on a screen-level refresh trigger (a value change of the tag bound to a property that triggers a repaint, a navigation event, or a periodic refresh tick).
Symptoms:
- An I/O field shows the new value correctly while the screen is actively interacted with, but goes stale after a few seconds of inactivity.
- Navigating away from the screen and back updates the I/O field to the latest value, confirming the underlying tag is correct but the field has not repainted.
- A periodic task that updates the source tag every 1 s will display the first value, then appear frozen even though
Tag_1andTag_2are both being written.
Mitigations:
- Configure the I/O field's Update property to On every change or to a fixed cycle (for example 500 ms) in the properties of the I/O field under Animation -> Appearance or General.
- Bind an unused tag property (such as the field's Visible property) to a rapidly changing counter and force a repaint through that binding.
- Use a Schedule task that fires
RefreshScreenor that writes a dummy value to the I/O field's tag in addition to the script path. This is a brute-force fix and should be a last resort.
The display refresh issue is independent of the SetTag propagation issue. Even after the VBScript-direct-write workaround is applied, the I/O field may need the update property tuned to repaint promptly.
Parameter Reference - SetTag and SetTagByProperty
| Parameter | Type | Required | Description |
|---|---|---|---|
Tag (Output) |
HMI tag reference | Yes | The tag that will receive the value. Accepts internal and external tags. |
Value |
Literal, tag, or expression | Yes | The value to assign. Coerced to the target tag's data type; truncation or rounding may occur. |
Triggering tag (Input) |
HMI tag reference | Optional | The tag whose value change triggers the call. If both this and the event-bound tag differ, the call is made when either changes. |
Mode |
Enum (Direct, Implicit) | Optional | Default Direct. Use Implicit when the call is part of a chain to avoid reentrancy. |
For a chain of internal-to-internal propagation, the Mode = Implicit setting does not fix the underlying problem - it only suppresses the reentrancy warning. The reliable fix is the VBScript-direct-write pattern described above.
Best Practices for Internal Tag Propagation
- Single source of truth. If two internal tags always carry the same value, ask whether you actually need two. Combine consumers onto one tag and remove the mirror.
- Compute in the script. When mirroring is required, perform the write inside the same script that produces the source value. This puts the propagation under the same scheduling pass and removes the dependency on event timing.
- Avoid chains of events. A -> B -> C event chains across internal tags are fragile in WinCC Runtime. The longer the chain, the more likely you are to see dropped updates, especially under heavy tag traffic or in the presence of a slow controller connection.
-
Validate in the script. Add a read-back after the write to confirm the value was committed. This is cheap and provides an early warning if a tag is being throttled:
HMIRuntime.Tags("Tag_2").Write value HMIRuntime.Tags("Tag_2").Read If HMIRuntime.Tags("Tag_2").Value <> value Then HMIRuntime.Trace "Tag_2 mirror failed: expected " & value & " got " & HMIRuntime.Tags("Tag_2").Value End If -
Type strictness. Match data types exactly. A
Realsource andInttarget will silently truncate. AStringsource andWStringtarget may fail to fire events in some firmware builds. - Update property on I/O fields. Set the Update property to On every change for any I/O field bound to a tag that is updated in the background, to avoid stale displays.
Related Configuration Errors and Edge Cases
| Symptom | Likely Cause | Resolution |
|---|---|---|
| Target tag stays at 0 in I/O field, source updates correctly | Value Change event on internal tag not firing reliably | Apply VBScript-direct-write or output-parameter workaround |
| Target tag updates briefly, then returns to 0 | Conflicting write from another event or periodic task | Audit all event bindings on the target; remove the redundant chain |
| Target tag updates in PLCSIM but not on physical panel | Firmware revision difference; older panels throttle internal events more aggressively | Update panel image to V15.1-compatible or later; apply workaround |
| Target tag shows correct value after navigating away and back, but not while on screen | I/O field not configured to repaint on tag change | Set the I/O field Update property to "On every change" or to a 500 ms cycle |
| Target tag updates correctly only when a button is pressed | Periodic task running on a different cycle is overwriting the value | Inspect the HMI scheduler; ensure no other writer touches Tag_2 |
| Tag_2 has correct value in online watch table but wrong on screen | I/O field bound to wrong tag or to a stale cached value | Rebind the I/O field; clear the runtime cache by reloading the screen |
Migration Notes - Forward Compatibility to V16, V17, V18, V19, V20
The internal-to-internal event propagation issue has been observed in every WinCC Comfort / Advanced release from V14 through V20 when configured with the Value Change + SetTag pattern. The VBScript-direct-write pattern documented above is forward-compatible with all of them. The newer Unified Comfort Panels (SIMATIC HMI Unified) introduced a different runtime (WinCC Unified) with a redesigned tag model; the same VBScript patterns apply, but the object model is HMIRuntime.UI and tag writes use a different syntax. If you migrate the project forward, the VBScript direct write remains the most reliable approach; the legacy SetTag system function is deprecated in Unified and should be replaced.
Why does SetTag from a Value Change event fail between two internal HMI tags in TIA Portal V15.1?
The Value Change event on an internal HMI tag is scheduled in a separate pass from the script that wrote the tag, and chained event-driven writes to other internal tags are not guaranteed to execute under load. Replace the event chain with a direct HMIRuntime.Tags("Tag_2").Write call from inside the VBScript action that writes Tag_1, or add Tag_2 as a second output parameter of the same action.
How do I mirror one internal HMI tag to another internal tag in WinCC Comfort?
Open the VBScript action that produces the source value, add a second ByRef output parameter, bind it to the target tag, and assign the same computed value to both outputs inside the action. Then delete any Value Change event on the source that called SetTag on the target. This keeps both writes in the same scheduling pass.
Why does my TP1500 Comfort I/O field show 0 for an internal tag that the script is writing?
Two common causes: (1) the I/O field is bound to the wrong tag, or (2) the I/O field Update property is set to "On focus" or "On demand" instead of "On every change". Set the Update property to "On every change" or to a 500 ms cycle, confirm the binding in the Properties pane, and reload the screen.
Does converting the source tag to a PLC tag fix the SetTag failure?
Yes. A Value Change event on an external HMI tag (one bound to a PLC address) fires deterministically and the downstream SetTag call executes reliably. The fix is to move the source value into a real PLC tag, or to write the target tag directly from the VBScript action that produces the source value.
Is the SetTag system function deprecated in TIA Portal V20 and Unified Comfort Panels?
SetTag is still present in WinCC Comfort / Advanced V20, but in WinCC Unified (used by Unified Comfort Panels) it is replaced by HMIRuntime.Tags(tag).Write in VBScript or by tag.SetValue in the Unified object model. The VBScript direct-write pattern documented here is forward-compatible to both Classic and Unified runtime.