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:
- The Scheduler (minimum trigger interval = 1 minute)
- The tag change value event driven by an HMI tag
- 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.
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
- In the WinCC Flexible project tree, open Schedulers.
- Right-click and choose New Scheduler. Name it (e.g.,
Heartbeat_1min). - On the Properties > General tab, set Start time (e.g., 00:00:00) and Interval = 1 minute.
- On the Events tab, click Add function, select your function list or VBScript, and confirm with OK.
- 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
- In the project tree, open Tags > HMI Tags and create a tag, for example
Heartbeat_Triggerof typeBoolorInt. - Open the tag's Properties. On the Acquisition cycle property, select a value from the drop-down.
- 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.
3.2 Wire the Script to the Change Value Event
- Select the HMI tag in the editor.
- Open Properties > Events.
- Click in the white box next to Change Value; the function list dialog opens.
- Choose Edit VBScript and enter the body that should fire on every change.
- 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.
- Insert a Button object on the screen.
- Open its Properties > Animation.
- Select Enable animation and click Add.
- Set Appearance → Object state = Disabled.
- 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:
- Create an internal HMI tag
Tick, typeInt, acquisition cycle = 1 s, Cyclic continuous. - Attach a VBScript to the Change Value event of
Tick. - Inside the script, do the work, then increment
Tickby 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.
- Add a tag
CycleDonemapped to a PLC bit that pulses 1 → 0 → 1 when the cycle ends. - Attach a VBScript to the Change Value event of
CycleDone. - Inside the script, write the cycle data to a CSV via the
FileSystemObject, and acknowledge back by setting an HMI bitLogAckthat 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.
- Start the PC Runtime with the Debug option enabled in the Runtime settings.
- Open the script in the TIA Portal editor and set a breakpoint on the desired line (left margin, double-click).
- Trigger the script (e.g. by changing the bound tag in PLCSIM or on the live PLC).
- When the runtime hits the breakpoint, execution pauses.
- 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.
- 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
CreateTextFilewithTristateTrueand an explicit Unicode flag, or useADODB.Stream. -
Migration to Unified: When porting to TIA Portal V21, replace the WinCC Flexible VBScript
SmartTags()calls with the Unified JavaScript APITags('TagName').Read()/.Write(). Acquisition cycle minimum drops to 100 ms uniformly.
13. Verification Checklist
- Open the HMI project in WinCC Flexible and confirm the tag's Acquisition cycle is set to Cyclic continuous.
- Right-click the runtime icon and choose Diagnostics > Tags. Verify the heartbeat tag updates at the expected rate.
- Add a trace button on a service screen that sets the heartbeat tag manually; confirm the script fires once per change.
- For integer loops, increment the counter from PLCSIM and confirm the HMI log shows the script's
Debug.Printoutput at the expected rate. - Watch the Windows Task Manager for the CCRtPMon.exe process; CPU should stay below 25% on a typical PC Runtime project.
- 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.