Cycling WinCC Flexible Scripts on PC Runtime: Tag Events & Loops

David Krause13 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

1. Overview: Why "Continuous" Script Execution Is the Wrong Question

Engineers approaching WinCC Flexible Runtime on a PC panel often ask how to make a VBScript run continuously. In practice, an infinite Do...Loop inside a script called once will lock the HMI main thread, block screen updates, starve the tag acquisition queue, and effectively freeze the runtime. The correct design question is: how do I get a script to fire repeatedly at a deterministic cadence that is decoupled from any single user action?

WinCC Flexible 2005, 2007, 2008, and the SP updates up through WinCC Flexible 2008 SP5 expose three production-grade mechanisms for cyclic script execution on a PC Runtime:

  1. The Scheduler (minimum trigger interval = 1 minute)
  2. The tag change value event driven by an HMI tag
  3. An integer-tag heartbeat loop for sub-second repetition

Each method has deterministic limits, performance budgets, and network footprints. The wrong choice creates dropped samples, missed alarms, or unresponsive screens. The methods below are field-proven against S7-200, S7-300/400, and S7-1200 backplanes over MPI/PROFIBUS and PROFINET, and they map cleanly onto WinCC Unified RT in TIA Portal V21 for migration projects.

Engineering rule: Never put a true infinite loop inside a WinCC Flexible script. WinCC Flexible Runtime is single-threaded per script execution context. A blocked script blocks tag refresh, alarm logging, and screen repaints.

2. Scheduler Method — Use Only When the Cycle Is ≥ 1 Minute

The Scheduler in WinCC Flexible allows you to trigger a function list or VBScript at a fixed time of day or on a recurring interval. It is the simplest method but has hard limits:

  • Minimum selectable interval = 1 minute. There is no native UI path to set seconds in the Scheduler properties dialog.
  • Triggered scripts are queued; if a previous run is still executing, the new run is dropped (not stacked).
  • Time base is the Windows system clock, so any clock skew on the engineering station shows up as jitter.

2.1 Configure a Scheduler Entry

  1. In the WinCC Flexible project tree, open Schedulers.
  2. Right-click and choose New Scheduler. Name it (e.g., Heartbeat_1min).
  3. On the Properties > General tab, set Start time (e.g., 00:00:00) and Interval = 1 minute.
  4. On the Events tab, click Add function, select your function list or VBScript, and confirm with OK.
  5. Compile and download the project to the PC Runtime.

If your cycle is 1 minute or longer (data archival, slow trending, shift handover triggers), the Scheduler is the correct tool. For anything tighter, continue to the tag-event method.

3. Tag Change-Value Method — The Standard Sub-Minute Approach

The reliable method to run a script faster than once per minute is to attach the script to the Change Value event of an HMI tag. When the tag value changes, the runtime fires the configured function. The repetition cadence is then a function of how often the underlying tag value changes — which you control either in the PLC or inside a chained VBScript.

3.1 Configure the HMI Tag

  1. In the project tree, open Tags > HMI Tags and create a tag, for example Heartbeat_Trigger of type Bool or Int.
  2. Open the tag's Properties. On the Acquisition cycle property, select a value from the drop-down.
  3. Choose Cyclic continuous, not Cyclic on demand. The on-demand setting only refreshes the tag when an active screen references it, which means a hidden popup will not refresh the value and the Change Value event will not fire.
Sampling theorem applied to HMI: Set the acquisition cycle to at least 2× faster (half the time) than the PLC's expected change interval. If the PLC toggles a bit every 500 ms, set the HMI cycle to 250 ms. Otherwise a single acquisition window can capture two PLC transitions (e.g. 1 → 0 → 1), and the HMI will see no change, so the event will not fire and the script will silently skip a beat.

3.2 Wire the Script to the Change Value Event

  1. Select the HMI tag in the editor.
  2. Open Properties > Events.
  3. Click in the white box next to Change Value; the function list dialog opens.
  4. Choose Edit VBScript and enter the body that should fire on every change.
  5. Compile and download.

3.3 Example VBScript Body

' Heartbeat_Trigger has just changed value
' This body runs once per change, NOT infinitely
If SmartTags("Tag_5") = 1 Then  ' Tag_5 wired to PLC bit M0.0
    SetBit SmartTags("Tag_1")
    SetBit SmartTags("Tag_2")
    SetBit SmartTags("Tag_3")
    SetBit SmartTags("Tag_4")
Else
    ResetBit SmartTags("Tag_1")
    ResetBit SmartTags("Tag_2")
    ResetBit SmartTags("Tag_3")
    ResetBit SmartTags("Tag_4")
End If

The block above is the canonical pattern for "press a button automatically when M0.0 goes high". Because the animation on the button is bound to the same tag M0.0, the visual state and the script fire in lockstep — there is no need to script the button press itself.

4. Button Animation Tied to a PLC Bit (No Script Required for the Press)

To make a WinCC Flexible button appear pressed or released based on a tag, do not simulate the click — animate the appearance directly. This is faster, deterministic, and immune to script load.

  1. Insert a Button object on the screen.
  2. Open its Properties > Animation.
  3. Select Enable animation and click Add.
  4. Set AppearanceObject state = Disabled.
  5. Bind the Variable field to your PLC bit (M0.0).

When the bit is 1, the button renders as disabled (greyed); when 0, it renders as enabled. If you need the opposite visual, add a second appearance state and bind the same bit. Combined with the script from §3.3, you have a fully automatic acknowledge / cycle-end handler with zero user interaction.

5. Integer-Heartbeat Loop for Sub-Second Script Cycles

WinCC Flexible enforces a minimum acquisition cycle of 1 second in the standard drop-down for most tag types on PC Runtime. If you need to fire a script faster than 1 Hz — for instance to poll a status, sample a counter, or drive a watchdog — the production pattern is an integer heartbeat.

5.1 PLC-Side Counter

Create an integer tag (e.g., DB10.DBW0, type INT) and increment it by 1 every PLC cycle, wrapping from 32767 back to 0 via a comparison:

// S7-300/400 STL (OB1 cycle)
L DB10.DBW0
L 1
+I
T DB10.DBW0
L 32767
>I
JC RESET
BEU
RESET: L 0
T DB10.DBW0

If the PLC cycle is 10 ms, the integer increments 100 times per second, yielding 100 changes per second on the wire. The HMI sees a fresh value at every acquisition tick (1 s on standard PC Runtime, or 100 ms on a SIMATIC Panel with a faster cycle, or 100 ms on WinCC Unified V21).

5.2 HMI-Side Self-Loop Counter

If the PLC is busy or you do not want to add a counter there, the heartbeat can live entirely on the HMI:

  1. Create an internal HMI tag Tick, type Int, acquisition cycle = 1 s, Cyclic continuous.
  2. Attach a VBScript to the Change Value event of Tick.
  3. Inside the script, do the work, then increment Tick by 1 and reset to 0 on overflow:
Dim v
v = SmartTags("Tick")
v = v + 1
If v > 32767 Then v = 0
SmartTags("Tick") = v

' --- body of cyclic work below ---
If SmartTags("TankLevel") > SmartTags("HighLimit") Then
    SmartTags("AlarmBit") = 1
End If

The first execution needs a one-time bootstrap. Add a second event trigger on the Loaded event of the start screen that sets Tick = 0; the subsequent value change kicks the loop off.

6. Acquisition Cycle Reference (PC Runtime, WinCC Flexible 2008 SP5)

Tag type Drop-down minimum Custom 100 ms supported? Recommended use
Bool (PLC) 1 s No on PC RT (Yes on Unified V21) Status, enable bits, animation
Int / Word (PLC) 1 s No on PC RT (Yes on Unified V21) Heartbeat counters, error codes
Real (PLC) 1 s No on PC RT (Yes on Unified V21) Process values, trends
Internal HMI tag 100 ms Yes Local HMI logic, debouncing
Pointer tag 1 s No Indirect addressing

7. PROFINET Load Budget for 100 Tags at 100 ms

A question raised in the field: "If I have 100 tags each at a 100 ms acquisition cycle, will PROFINET keep up?" The answer is yes, with margin on a 100 Mbit PROFINET segment, but the math should be checked.

Effective per-tag poll rate at 100 ms = 10 polls/s. 100 tags = 1,000 polls/s. Each PROFINET real-time frame is ~120 bytes including the slot, and a single IRT cycle of 1 ms easily carries several hundred bytes of I/O data on an S7-1500 controller. The actual limiting factor is not bandwidth but the PLC scan time: if OB1 is 8 ms, the PLC cannot update a tag faster than every 8 ms no matter what the HMI requests. Set the HMI cycle to half the PLC cycle, not the inverse.

For a S7-1200 over PROFINET, Siemens' practical limit is roughly 150 HMI tags per second of acquisition cycle per HMI connection; above that, the OPC / S7 connection queue depth must be raised in the WinCC Flexible PC Runtime connection properties.

8. Logging and Cycle-End Acknowledgement Without User Action

A common follow-up requirement: log a value automatically at the end of a machine cycle, and arm the next log using a single bit from the PLC, with no human input on the HMI.

  1. Add a tag CycleDone mapped to a PLC bit that pulses 1 → 0 → 1 when the cycle ends.
  2. Attach a VBScript to the Change Value event of CycleDone.
  3. Inside the script, write the cycle data to a CSV via the FileSystemObject, and acknowledge back by setting an HMI bit LogAck that the PLC reads and clears.
If SmartTags("CycleDone") = 1 Then
    Dim fso, ts
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpenTextFile("C:\Logs\cycle_" & Year(Now) & "_" & _
        Right("0" & Month(Now),2) & "_" & Right("0" & Day(Now),2) & ".csv", 8, True)
    ts.WriteLine SmartTags("CycleCount") & ";" & SmartTags("LastCycleTime")
    ts.Close
    SmartTags("LogAck") = 1
End If

The PLC reads LogAck, resets CycleDone, and the system is armed for the next cycle without any operator touching the screen.

9. Step-by-Step Debugging in WinCC Unified RT (TIA Portal V21)

For projects that have migrated (or will migrate) from WinCC Flexible to WinCC Unified, the script debugging model is much richer. In TIA Portal V21 you can step into a running script inside the PC Runtime.

  1. Start the PC Runtime with the Debug option enabled in the Runtime settings.
  2. Open the script in the TIA Portal editor and set a breakpoint on the desired line (left margin, double-click).
  3. Trigger the script (e.g. by changing the bound tag in PLCSIM or on the live PLC).
  4. When the runtime hits the breakpoint, execution pauses.
  5. Click Step into next function call in the debugging area, or press F11, to step one line at a time. The script pauses on the first line of any function call it enters.
  6. Hover over variables to inspect their current values. Use the Watch window to track specific tags across iterations.

For the full procedure see the Siemens TIA Portal V21 documentation: Step-by-step execution of scripts in RT Unified.

10. Method Comparison Matrix

Method Minimum cycle Determinism CPU overhead Network footprint Best for
Scheduler 1 min Medium (Windows clock) Low Zero Archival, shift handover, slow trending
Tag Change Bool 1 s (PC RT) High Low 1 bit / s Status, enable, animation
Tag Change Int heartbeat 100 ms (Unified), 1 s (Flexible PC RT) High Medium 1 INT / cycle Sub-second cyclic logic
PLC-side INT counter PLC cycle (typ. 5–20 ms) Highest Trivial in PLC 1 INT / cycle Hard real-time heartbeats
Truly infinite VBScript loop n/a None — HMI freezes 100% n/a Never use in production

11. Troubleshooting Matrix

Symptom Likely cause Fix
Script never fires Acquisition cycle set to Cyclic on demand Change to Cyclic continuous
Script fires, but twice as often as expected PLC toggles within one acquisition window Halve the acquisition time relative to the PLC change
Script fires irregularly (jitter) Booleans toggling faster than 1 s on PC RT Switch to an integer counter heartbeat
Script runs but HMI freezes periodically Script contains a tight loop or long file I/O Move work into a function list and chain via tags
Scheduler does not run Project not re-compiled after edit Rebuild the project and transfer the HMI to runtime
Button does not animate Animation bound to a script, not to the tag directly Bind Appearance > Object state directly to the PLC tag
Connection dropouts at 100 ms cycle Too many tags on a single S7 connection Split tags across multiple S7 connections, or raise the connection queue depth
Counter rolls over unexpectedly INT overflow at 32767 Add explicit reset on > 32767 in the script

12. Field-Proven Caveats

  • Bool vs Int for fast triggers: For cycles shorter than 1 s, integer heartbeats are far more reliable than booleans because WinCC Flexible's Boolean change detection can collapse a 1→0→1 transition into a no-op if the acquisition window straddles both edges.
  • Onload bootstrap: An integer loop driven by its own change event never starts the first time, because the initial value is not a "change". Always add a one-shot trigger on the start screen's Loaded event that writes a different value to the same tag.
  • Connection queue depth: On WinCC Flexible PC Runtime, the default S7 connection holds 50 pending requests. With 100 tags at 100 ms, raise this to 200 in the connection properties, or you will see intermittent 0x8004... -class connection warnings in the diagnostics file.
  • Unicode on legacy WinCC Flexible: PC Runtime 2008 SP5 still defaults to the ANSI code page. If you write filenames with non-ASCII characters, force CreateTextFile with TristateTrue and an explicit Unicode flag, or use ADODB.Stream.
  • Migration to Unified: When porting to TIA Portal V21, replace the WinCC Flexible VBScript SmartTags() calls with the Unified JavaScript API Tags('TagName').Read() / .Write(). Acquisition cycle minimum drops to 100 ms uniformly.

13. Verification Checklist

  1. Open the HMI project in WinCC Flexible and confirm the tag's Acquisition cycle is set to Cyclic continuous.
  2. Right-click the runtime icon and choose Diagnostics > Tags. Verify the heartbeat tag updates at the expected rate.
  3. Add a trace button on a service screen that sets the heartbeat tag manually; confirm the script fires once per change.
  4. For integer loops, increment the counter from PLCSIM and confirm the HMI log shows the script's Debug.Print output at the expected rate.
  5. Watch the Windows Task Manager for the CCRtPMon.exe process; CPU should stay below 25% on a typical PC Runtime project.
  6. Power-cycle the PC and confirm the bootstrap on the start screen restarts the loop.

14. Frequently Asked Questions

What is the fastest possible cyclic script rate in WinCC Flexible PC Runtime?

With an integer-heartbeat tag you can fire a script at the HMI acquisition rate. The PC Runtime minimum acquisition cycle is 1 second for external tags and 100 ms for internal tags; for sub-second external rates you must migrate to WinCC Unified in TIA Portal V21, which supports 100 ms uniformly.

Why does the Scheduler not run my script every second?

The Scheduler in WinCC Flexible has a hard-coded minimum interval of 1 minute. There is no UI option to set a shorter interval. For faster cycles use a tag change-value event driven by an HMI or PLC integer counter.

My Change-Value script fires only on every second transition, why?

Your acquisition cycle is probably too slow relative to the PLC's toggle rate. Reduce the HMI cycle to at least half the PLC change interval, and switch from a boolean tag to an integer counter for sub-second heartbeats — boolean change detection can collapse 1→0→1 transitions into a single missed event.

Can I keep a VBScript in an infinite loop inside WinCC Flexible?

No. WinCC Flexible Runtime executes scripts on the same thread that handles tag acquisition, alarm logging, and screen repaints. An infinite loop will freeze the HMI within a second and the only recovery is killing the runtime process. Use a tag change-value event or the Scheduler to get deterministic, non-blocking cyclic execution.

How do I migrate the patterns in this article to WinCC Unified?

Replace VBScript SmartTags("X") with the Unified JavaScript Tags("X").Read() / .Write() API. Acquisition cycles drop to a uniform 100 ms, and scripts can be debugged with F11 step-into on the live PC Runtime — see the Siemens TIA Portal V21 step-by-step script debugging guide.

Back to blog