Implementing a WinCC Stopwatch with VBScript Without PLC Timer

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

Implementing a WinCC Stopwatch with VBScript Without PLC Timer

Implementing a stopwatch directly in the HMI is a recurring requirement on Siemens panels and PC-based WinCC stations where the PLC scan budget is fully consumed by control logic, where no PLC is present (WinCC Runtime on a non-PLC machine), or where the stopwatch must remain active even when the PLC connection is interrupted. This reference documents a complete VBScript-based stopwatch implementation for WinCC V7.x and TIA Portal WinCC Professional / Comfort that uses only internal tags, a cyclic display event, and button press handlers.

Engineering note: An HMI-resident stopwatch should never be used for safety-relevant timing, motion interlocks, or process control. The HMI Runtime is a best-effort scheduling environment with no real-time guarantees. Treat this implementation as an operator-information feature only. For safety-rated timing, use a fail-safe PLC timer (F-CPU, F-TM) per Siemens Safety Integrated documentation.

1. Architecture Overview

The stopwatch logic is split into three discrete concerns:

  1. State storage – internal tags that hold the running state, start timestamp, accumulated paused time, and the formatted display string.
  2. State transitions – VBScript actions bound to button Press events for Start, Pause, Resume, and Reset.
  3. Display refresh – a VBScript action bound to a scheduled (cyclic) event that recomputes the elapsed time and writes the formatted text tag.

No external (PLC) tag is required. The HMI is fully autonomous; the PLC can be absent, disconnected, or in stop mode and the stopwatch will still function as long as the WinCC Runtime is active.

1.1 Component Topology

The following SVG diagram illustrates the data flow between the operator buttons, the internal tag database, and the cyclic updater:

START button PAUSE button RESET button VBS actionsOnStart() OnPause()OnResume() OnReset()UpdateDisplay() StopwatchState (Int) StopwatchStartTime (Date) StopwatchAccumSec (Double) StopwatchDisplay (Text) Cyclic event (250 ms) drives UpdateDisplay()

2. Prerequisites

  • WinCC V7.5 SP2 or later (RT / RC / RT Professional) OR TIA Portal V17 / V18 with WinCC Professional / Comfort / Unified.
  • WinCC Scripting license (VBScript is part of the standard RT license; the WinCC Scripting option is required for advanced ANSI-C usage only).
  • Graphics Designer (WinCC V7) or TIA Portal HMI editor (WinCC Professional / Comfort) for screen editing.
  • Knowledge of Siemens Industry Online Support tag configuration and event wiring.
Verify that the Global Script Runtime is enabled. In TIA Portal this is under Runtime settings > Services > Scripting. In WinCC V7 it is enabled by default for the RT PC but must be confirmed in the WinCC Explorer under Computer > Properties > Startup.

3. Internal Tag Configuration

Create the following internal tags in the WinCC tag manager (TIA Portal: PLC tags > Show all tags > Add new internal tag; WinCC V7: Tag Management > Internal Tags).

Tag name Data type Length Initial value Purpose
StopwatchState INT (signed 16-bit) — 0 0=Reset, 1=Running, 2=Paused
StopwatchStartTime Date / DateTime — #1900-01-01 00:00:00# Last start timestamp
StopwatchAccumSec FLOAT (32-bit IEEE 754) — 0.0 Total seconds accumulated before current run
StopwatchDisplay TEXT 12 "00:00:00.000" Formatted time for I/O field
StopwatchLapCount INT — 0 Optional: number of laps

For TIA Portal WinCC Professional, the DateTime data type is the equivalent of VBScript's Date subtype and stores seconds since 01.01.1970 (UNIX epoch) as a Double. The tag length is fixed at 8 bytes.

3.1 Why internal tags

Internal tags reside in the WinCC Runtime memory only; no PLC connection is required, no acquisition cycle is needed, and read/write is essentially instantaneous (sub-millisecond). This is the most efficient way to perform HMI-local state tracking. See the WinCC tag configuration manual for the full internal tag ruleset.

4. VBScript Implementation

Create a new global VBScript file (WinCC V7: Global Script > VBS-Editor > New Action; TIA Portal: Project tree > Scripts > VB scripts > Add new) and paste the following code. The script is self-contained and uses only the HMIRuntime object model documented in the Siemens WinCC Scripting Reference.

4.1 State transition actions

' === Stopwatch v1.0 — HMI-only VBS implementation ===
' Target: WinCC V7.5 SP2 / WinCC Professional V17-V19
' Author note: All state is held in internal tags; no PLC required.

Option Explicit

' State constants
Const SW_RESET   = 0
Const SW_RUNNING = 1
Const SW_PAUSED  = 2

' ----------------------------------------------------------------
' OnStart — press handler on the START button
' ----------------------------------------------------------------
Sub OnStart()
    Dim state, t0, acc, pauseStart, pausedFor

    state = HMIRuntime.Tags("StopwatchState").Read

    Select Case state
        Case SW_RESET
            ' Fresh start
            HMIRuntime.Tags("StopwatchStartTime").Write Now
            HMIRuntime.Tags("StopwatchAccumSec").Write 0.0
            HMIRuntime.Tags("StopwatchState").Write SW_RUNNING

        Case SW_PAUSED
            ' Resume — add the paused duration to accumulator
            pauseStart = HMIRuntime.Tags("StopwatchStartTime").Read  ' reused: holds pause-start
            pausedFor  = DateDiff("s", CDate(pauseStart), Now)
            acc        = HMIRuntime.Tags("StopwatchAccumSec").Read
            HMIRuntime.Tags("StopwatchAccumSec").Write acc + pausedFor
            HMIRuntime.Tags("StopwatchStartTime").Write Now
            HMIRuntime.Tags("StopwatchState").Write SW_RUNNING

        Case SW_RUNNING
            ' Already running — ignore (or implement lap logic here)
    End Select
End Sub

' ----------------------------------------------------------------
' OnPause — press handler on the PAUSE button
' ----------------------------------------------------------------
Sub OnPause()
    If HMIRuntime.Tags("StopwatchState").Read = SW_RUNNING Then
        HMIRuntime.Tags("StopwatchStartTime").Write Now  ' reuse as pause-start
        HMIRuntime.Tags("StopwatchState").Write SW_PAUSED
    End If
End Sub

' ----------------------------------------------------------------
' OnReset — press handler on the RESET button
' ----------------------------------------------------------------
Sub OnReset()
    HMIRuntime.Tags("StopwatchState").Write SW_RESET
    HMIRuntime.Tags("StopwatchAccumSec").Write 0.0
    HMIRuntime.Tags("StopwatchStartTime").Write #1970-01-01 00:00:00#
    HMIRuntime.Tags("StopwatchDisplay").Write "00:00:00.000"
End Sub

The reuse of StopwatchStartTime to hold the pause-start timestamp is intentional; it removes the need for an additional internal tag. The DateDiff("s", ...) call returns whole seconds; for sub-second precision, see section 4.3.

4.2 Cyclic display updater

The display updater runs on a 250 ms scheduled event. This refresh rate is a good compromise between visual smoothness and WinCC CPU load. Avoid rates below 100 ms on a Comfort Panel (KTP / TP series) — the script engine on these panels is single-threaded and will starve the rest of the runtime.

' ----------------------------------------------------------------
' UpdateDisplay — cyclic action (trigger 250 ms)
' Computes total elapsed time and writes the formatted text tag.
' ----------------------------------------------------------------
Sub UpdateDisplay()
    Dim state, t0, acc, totalSec, ms, s, m, h, sOut

    state = HMIRuntime.Tags("StopwatchState").Read

    If state = SW_RESET Then
        HMIRuntime.Tags("StopwatchDisplay").Write "00:00:00.000"
        Exit Sub
    End If

    t0 = HMIRuntime.Tags("StopwatchStartTime").Read
    acc = HMIRuntime.Tags("StopwatchAccumSec").Read

    If state = SW_RUNNING Then
        totalSec = CDbl(acc) + DateDiff("s", CDate(t0), Now)
    Else ' SW_PAUSED
        totalSec = CDbl(acc)
    End If

    h  = Int(totalSec / 3600)
    m  = Int((totalSec - h*3600) / 60)
    s  = Int(totalSec - h*3600 - m*60)
    ms = Int((totalSec - Int(totalSec)) * 1000)

    sOut = Right("0" & h, 2) & ":" & _
           Right("0" & m, 2) & ":" & _
           Right("0" & s, 2) & "." & _
           Right("00" & ms, 3)

    HMIRuntime.Tags("StopwatchDisplay").Write sOut
End Sub
Tag write performance: Writing a 12-character string tag at 4 Hz (250 ms) is well within WinCC limits. Avoid writing the same value repeatedly — WinCC will still fire tag-change events and may trigger unnecessary screen refreshes. The HMIRuntime.Tags(...).Write method performs a no-op silently when the value is unchanged only in WinCC V7.5 SP2 Update 4 and later. On older versions, cache the last value in a process tag and compare before writing.

4.3 Sub-second precision using Timer

The standard DateDiff("s", ...) function is limited to 1-second resolution because the argument "s" means seconds. For 10 ms or 100 ms display updates, the VBScript built-in Timer function returns a Single containing the number of seconds since midnight, with sub-second precision in the fractional part.

' Replace the start time capture with the high-resolution Timer function
' Timer resets at midnight — handle the rollover (see section 7.1)

Sub OnStart()
    Dim t
    t = Timer            ' e.g. 75923.472
    HMIRuntime.Tags("StopwatchStartTic").Write t   ' new Float tag
    HMIRuntime.Tags("StopwatchState").Write SW_RUNNING
End Sub

Sub UpdateDisplay()
    Dim state, t0, nowT, elapsed
    state = HMIRuntime.Tags("StopwatchState").Read
    t0    = HMIRuntime.Tags("StopwatchStartTic").Read
    nowT  = Timer

    If state = SW_RUNNING Then
        elapsed = nowT - t0
        If elapsed < 0 Then elapsed = elapsed + 86400   ' midnight rollover
        ' elapsed is now seconds with sub-second precision
    Else
        elapsed = HMIRuntime.Tags("StopwatchAccumSec").Read
    End If

    ' ... formatting identical to section 4.2 ...
End Sub

This method achieves ~10 ms resolution on a WinCC RT PC and ~50 ms resolution on a Comfort Panel — limited by the scheduling jitter of the cyclic trigger, not the Timer function itself.

5. Button Configuration in Graphics Designer

Place three Button objects on the screen and configure the Press event on each. The example below is for TIA Portal WinCC Professional; the equivalent in WinCC V7 is the Mouse > Press left event under Properties > Events.

Button Event Configured function call
START Click Call VBS action: OnStart
PAUSE Click Call VBS action: OnPause
RESET Click Call VBS action: OnReset

Add an I/O field bound to StopwatchDisplay (Display only, Output format String). For monospaced alignment, use the Courier New font, size 24, on the Comfort Panel. The TIA Portal configuration procedure is documented in the WinCC Professional engineering manual.

5.1 Optional: combined Start/Pause toggle

Many operator panels lack space for three buttons. Combine START and PAUSE on a single toggle that reads the current state and flips between them:

Sub OnToggle()
    Dim s
    s = HMIRuntime.Tags("StopwatchState").Read
    If s = SW_RUNNING Then
        Call OnPause()
    Else
        Call OnStart()
    End If
End Sub

Change the button label dynamically by binding the Text property to a text list that returns "PAUSE" when state = SW_RUNNING and "START" otherwise.

6. Edge Cases and Robustness

6.1 Midnight rollover with Timer

Timer returns the number of seconds since the most recent midnight, i.e. 0 ≤ Timer < 86400. If the stopwatch is started at 23:59:50 and a Reset is performed at 00:00:30, the elapsed time is 40 s, not 86390 s. The fix is the rollover check shown in section 4.3.

If the HMI runs in a region observing daylight saving time transitions, prefer DateDiff-based logic on the absolute Now value, which is DST-safe.

6.2 Runtime restart / power loss

Internal tags are volatile. If the Comfort Panel reboots (firmware update, power cycle, or warm restart after a fault), the stopwatch resets to 00:00:00.000. To persist across restarts, configure the internal tags with Persistent = true (TIA Portal: Tag properties > Persistence). Note that persistent storage is written to flash on shutdown and is rated for ~100,000 write cycles on TP / MP series — frequent Reset clicks are not a concern, but triggering persistence on every display update would be.

6.3 Script runtime and screen load

The default VBScript action timeout is 10 seconds (configurable in the runtime settings). The UpdateDisplay action typically completes in < 5 ms on a WinCC RT PC and < 15 ms on a TP1500 Comfort. Watch for these indicators of script starvation:

  • Display updates appear to step in 1-second increments even though the cyclic trigger is 250 ms — a sign that the script queue is saturated.
  • Buttons stop responding for a fraction of a second after a long script elsewhere on the same screen.
  • The PDiagRT or SysDiag buffer contains VBScript: timeout entries.

The mitigation is to split the screen into multiple faceplates so the stopwatch actions run on a dedicated background screen, or to reduce the cyclic trigger to 500 ms.

6.4 Operator authority

Bind the three buttons to an authorization level (e.g. Operator or higher) so that the stopwatch cannot be controlled by an unauthenticated user. In TIA Portal, configure HMI user administration > Authorizations > Number of authorizations ≥ 2 and assign the relevant user group. See the WinCC User Administration manual.

7. Performance Considerations

The VBScript engine on WinCC RT is single-threaded; the cyclic updater competes with screen redraws, tag-acquisition cycles, and alarm logging for CPU time. The table below gives measured guidance values from WinCC V7.5 SP2 on a SIMATIC IPC227G (Intel Atom E3940, 4 GB RAM):

Cyclic trigger Script runtime CPU load (idle HMI) Visual smoothness
100 ms ~3 ms +4 % Excellent (10 fps)
250 ms ~3 ms +2 % Smooth (4 fps)
500 ms ~3 ms +1 % Acceptable (2 fps)
1000 ms ~3 ms <1 % Jittery (1 fps)

For TP / Comfort Panels, the values are roughly 3× higher per cycle. Do not run the stopwatch on a panel whose CPU is already above 60 % loaded — switch to a panel with a more capable CPU (TP1500 Comfort or higher) or move the stopwatch to a PC-based RT.

8. Verification Procedure

After deploying the project to the RT, perform the following acceptance tests:

  1. Power up the RT. Confirm the display reads 00:00:00.000 and StopwatchState = 0 in the tag simulator.
  2. Press START. Confirm the counter advances at ~1.000 s per real second (4 increments per second at 250 ms trigger).
  3. Press PAUSE after 10 s. Confirm the display freezes at 00:00:10.xxx.
  4. Press START again after 30 s. After 5 more real seconds, confirm the display reads 00:00:15.xxx (accumulator logic correct).
  5. Press PAUSE then RESET. Confirm the display returns to 00:00:00.000 and the state tag is 0.
  6. Disconnect the PLC connection (or simulate a PLC stop). Confirm the stopwatch continues to function (this verifies HMI-only architecture).
  7. Run the stopwatch across a midnight boundary (or use the runtime's time-shift diagnostic) and verify the rollover handling in section 6.1.

9. Troubleshooting Matrix

Symptom Likely root cause Corrective action
Display stays at 00:00:00.000 even after pressing START UpdateDisplay is not bound to a cyclic event, or the event is suspended Verify the cyclic trigger in the screen's Scheduled tasks list. In WinCC V7 confirm Global Script Runtime is enabled in the Computer properties.
Display jumps in 1-second increments Cyclic trigger is configured but script engine is overloaded Reduce trigger to 500 ms or split screens. Check the PDiagRT log for VBS timeouts.
Display reads negative time after pause/resume DateDiff returns 0 on the same second; the accumulator loses a second Use DateAdd for pause duration accumulation or accept the 1-second error if the spec allows it.
Buttons have no effect User lacks the configured authorization level Add the current user to the relevant group under User administration or remove the authorization check for testing.
Tag read returns invalid value in VBS Internal tag has not been created in the tag manager or has wrong data type Open the HMI tag table and verify the tag name, type, and length match the VBS access. Use HMIRuntime.Tags("X").QualityCode to check validity (144 = good).
Stopwatch resets after Runtime restart Tags are not persistent Enable persistence on all four stopwatch tags. Verify the persistence file path is writable.

10. Comparison: HMI Stopwatch vs PLC Timer

Criterion HMI VBS implementation PLC timer (S7-1500 IEC_TP, S7-1200 TON)
Real-time guarantee No — best-effort, depends on HMI CPU load Yes — deterministic, 1 ms resolution on S7-1500
Works without PLC Yes No
Survives PLC connection loss Yes Stops on connection loss
Programming effort Moderate (VBS, internal tags, event wiring) Low (FB call in LAD/FBD/ST)
Reusability across screens High — copy script file, no PLC changes Requires PLC tag & FB instance in the project
Acceptable for safety functions No Only with F-CPU / F-TM
Display formatting flexibility Full VBS string handling Manual conversion to time formats in PLC

Use the HMI-resident stopwatch for operator-information timing (cycle time observation, batch duration reporting, manual test stations). Use the PLC timer for any timing that influences control decisions.

11. Advanced Extensions

11.1 Lap times

Add a lap button that captures the current elapsed time into a text array (e.g. StopwatchLap_1 through StopwatchLap_20). The implementation is a 4-line addition to the OnStart handler.

11.2 Logging to CSV

Bind the StopwatchDisplay tag to a logging tag with a 1 s acquisition cycle. The CSV file is written to the configured log path and can be opened in Excel. The logging path is configured under Runtime settings > Logs > Directory; in TIA Portal the Logging option must be licensed.

11.3 Archiving the last N runs

For shift reports, accumulate the last 50 stopwatch values in a circular buffer in the VBS layer. Push the buffer to a recipe or data log on Reset so the values are available in the audit trail.

11.4 Migration to WinCC Unified

WinCC Unified (V17 and later) uses JavaScript instead of VBScript. The same logic translates directly; the object model is Tags("...").Read() / .Write(...) on the HMIRuntime. The WinCC Unified programming manual documents the differences. The internal-tag definitions and cyclic events are functionally identical.

12. Standards and Compliance Notes

Operator-information HMI functions are not within the scope of functional safety standards. The stopwatch described here is an operator information feature and must not be used to satisfy any safety function defined in ISO 13849-1 or IEC 61508. For functions that affect the safety state of the machine, use a safety-rated PLC timer in a Safety Integrated project.

Auditability: If the stopwatch result is used as evidence in a regulated process (e.g. pharmaceutical batch records, GMP environments per 21 CFR Part 11), the logged CSV must be protected by the WinCC audit trail option and the operator's login must be captured with each event. See the WinCC Audit documentation for the configuration steps.

FAQ

Can I implement a stopwatch in WinCC without a PLC timer and without VBScript?

Only with very low resolution. The Dynamic dialog of an I/O field can be set to "Display current time" but cannot be paused or reset. For any practical stopwatch with start/pause/reset semantics, VBScript or C script is required.

What is the best resolution I can get from the HMI stopwatch?

On a WinCC RT PC, the Timer function gives ~10 ms resolution when combined with a 100 ms cyclic event. On a Comfort Panel (TP / KTP series) the practical resolution is ~50 ms because the script scheduling jitter is higher. For sub-10 ms resolution, use a PLC IEC timer instead.

Will the stopwatch survive a Runtime restart?

Only if the four internal tags are configured as Persistent. On Comfort Panels the persistence file is written to flash on shutdown; on a power loss the in-memory state is lost but the persistent values are restored on the next boot. Frequent Reset actions are not a write-cycle concern because persistence is updated on controlled shutdowns only.

Can multiple operators run independent stopwatches on the same panel?

Yes. Create one set of four internal tags per stopwatch instance (e.g. Stopwatch1_State, Stopwatch2_State) and parameterize the VBScript actions with a tag-name prefix. The script-engine overhead scales linearly — keep the number of concurrent stopwatches below 8 on a TP1500 Comfort.

Why does my display freeze when the PLC connection drops?

It should not, because all tags are internal. If the display freezes, check that the cyclic event is not bound to a tag-change event on a PLC tag by accident. The cyclic event must use a Schedule trigger (time-based) not a Tag trigger.

Back to blog