Invert a Bit in a WinCC Flexible Array Tag Using Scripts

David Krause12 min read
HMI / SCADASiemensTutorial / 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

Invert a Bit in a WinCC Flexible Array Tag Using Scripts

When configuring a Button event in Siemens WinCC Flexible (the predecessor engineering tool to TIA Portal's WinCC Comfort/Advanced/Unified), the Click -> InvertBit system function will not list an array element. The tag-selection dialog only exposes scalar BOOL tags and the base name of an array, never an indexed element such as Tag_1[3]. This is a hard limitation of the event configuration GUI, not of the runtime. The standard workarounds are (1) declaring a dedicated scalar BOOL tag for every array element you want to toggle, or (2) writing a short VBScript that resolves the array index at click time. This article documents the script approach, the runtime implications of both methods, and the modern equivalent in WinCC Unified's InvertBitInTag system function.

1. Overview of the Problem

WinCC Flexible 2008 SP5 and WinCC (TIA Portal) Comfort/Advanced expose the following built-in system functions on a button's Click event:

  • SetBit
  • ResetBit
  • InvertBit
  • SetTag / SetTagBit

Each of these dialogs walks the configured HMI tag list and filters by data type and bit-availability. A BOOL[55] PLC tag (e.g. Tag_1 ARRAY[0..54] OF BOOL in the connected S7-300/400 DB or a STEP 7 / TIA data block) shows up in the dialog as a single multi-element entry. The Bit number field can be set, but the target address is always the start of the array. There is no Element index input, and there is no checkbox to expose a specific element. Result: clicking OK either silently drops the selection or forces you to pick a scalar BOOL tag.

Why it behaves this way: the InvertBit system function is compiled to a fixed MC7 / C-script instruction in the generated runtime project. The address operand is resolved at compile time. Since the GUI cannot express a runtime-variable index, it refuses the binding.

2. Prerequisites

  • WinCC Flexible 2008 SP5 (or WinCC Comfort/Advanced V13 SP1 and later) installed on the engineering station.
  • An HMI device with VBScript support. Supported panels: all WinCC (TIA) Comfort Panels, WinCC (TIA) RT Advanced, and PC-based WinCC Flexible RT. The basic OP 77B, TP 177B 4" and the OP 73 / TP 177A lines do not support VBScript and require the scalar-tag workaround.
  • A connected PLC (S7-300, S7-400, S7-1200, S7-1500, or a third-party controller over OPC) exposing the BOOL array.
  • The HMI tag bound to the array must be configured with Length = 55 (or matching the PLC array size) and Data type = Bool array in the tag properties.
  • The Global Script runtime option is enabled (default in Comfort Panels and PC RT).

3. Understanding the Tag Configuration

Suppose the S7-1500 contains a data block "MyDB" with a tag of type ARRAY[0..54] OF BOOL named MyFlags. The corresponding HMI tag in WinCC Flexible looks like:

Property Value
Name (HMI) dbTest_BooleanArray
PLC tag MyDB.MyFlags
Connection S7-1500 / S7-1200 (or appropriate for controller)
Data type Bool array
Length 55
Acquisition cycle 100 ms (typical for flags)
Update on change Yes

The Length field must equal the array dimension in the PLC. WinCC Flexible indexes elements from 0 to Length-1. Internally each BOOL occupies one bit in a packed byte image, but the script layer exposes them as a logical boolean array via the SmartTags() collection.

4. Solution A — VBScript with an Index Parameter (Recommended)

4.1 Create the script

Open the project's Scripts editor (Project tree -> Scripts -> VB Scripts) and add a new function:

Function InvertArrayBit(ByVal idx)
    Dim arr
    Set arr = SmartTags("dbTest_BooleanArray")

    If IsArray(arr) Then
        ' Read current value, toggle, write back
        If arr(idx) = True Then
            arr(idx) = False
        Else
            arr(idx) = True
        End If
    Else
        ' Single element fallback (HMI tag of length 1)
        If SmartTags("dbTest_BooleanArray") = True Then
            SmartTags("dbTest_BooleanArray") = False
        Else
            SmartTags("dbTest_BooleanArray") = True
        End If
    End If
End Function

Equivalently, using a one-line boolean NOT:

SmartTags("dbTest_BooleanArray")(idx) = Not SmartTags("dbTest_BooleanArray")(idx)
Note: the unary Not in VBScript performs a bitwise NOT on the 16-bit integer representation. For a BOOL (0 or -1) the result is consistent: Not 0 = -1 (True) and Not -1 = 0 (False). WinCC Flexible's runtime converts these back to the canonical True / False before writing to the tag.

4.2 Pass the index

The index can be supplied three different ways. The choice depends on how the button is generated.

Source Use case Code
Hard-coded constant One button per array element InvertArrayBit(3)
Internal HMI tag Index driven by PLC or another screen InvertArrayBit(SmartTags("iIndex"))
Dynamic dialog (event property) Different index per visible button instance Use the Tag prefix + Index tag pattern (see Section 6)

4.3 Wire the script to the button

  1. Open the screen containing the button.
  2. Select the button, open Properties -> Events -> Click.
  3. In the function list choose VB script (not System function).
  4. Click the ... button to open the script editor; the new function appears in the left tree.
  5. From the function list, drag InvertArrayBit into the right-hand pane. WinCC Flexible automatically generates a call stub.
  6. Replace the placeholder parameter with the desired index expression, for example 3 or SmartTags("iIndex").
  7. Compile the project (Project -> Compiler -> All) and transfer to the panel.

5. Solution B — Scalar Tag per Array Element

For panels that do not run VBScript, the only option is to expose every individual bit as its own HMI tag:

  • Add 55 HMI tags of type Bool bound to MyDB.MyFlags[0] ... MyDB.MyFlags[54].
  • Use the normal Click -> InvertBit event on each button.

5.1 Cost analysis

Every additional HMI tag consumes a slot in the area pointer image and a polling slot in the configured acquisition cycle. Typical numbers for a Comfort Panel with a 100 ms acquisition cycle:

Quantity Effect
1–32 tags Negligible (< 1 % CPU on a TP900 Comfort).
64–128 tags Noticeable update lag in tag-status displays if any cycle is missed.
256+ tags Runtime becomes sluggish; consider increasing the cycle time or splitting screens.
500+ tags Exceeds the recommended comfort limit; switch to scripts or move the toggling logic into the PLC.

For 55 elements the scalar approach is feasible on a Comfort Panel, but the project is harder to maintain: a PLC-side array resize requires 55 HMI-side renames. The script approach scales to arrays of any size without configuration churn.

6. Solution C — One Button, Many Indices (Index Tag Pattern)

A common requirement is a single button graphic reused at runtime, with the index changing per screen context. The pattern uses an internal HMI tag iBtnIndex of type Int (-32768 to 32767) that the screen sets before calling the script:

' Pre-event on a focus-change or mouse-hover:
SmartTags("iBtnIndex") = 7   ' element to toggle when the button is clicked

' Click event:
Call InvertArrayBit(SmartTags("iBtnIndex"))

For a dynamic alternative, use the Tag prefix feature: bind a button to a tag whose name itself is constructed from another tag, e.g. "dbTest_BooleanArray_" & SmartTags("iBtnIndex"). This is only available on SetTag / GetTag when the index tag is Static in the project's HMI Tags table; it does not extend the InvertBit system function itself.

7. Modern Alternative: WinCC Unified InvertBitInTag

WinCC Unified (TIA Portal V17 and later, with full coverage of the system function from V20) ships a dedicated runtime function that does accept an element index. The signature is:

InvertBitInTag(Tag, BitNumber)
Parameter Type Description
Tag HMI tag The HMI tag whose bit is to be inverted. May be of integer or bit-array type.
BitNumber Int Zero-based bit number within the tag value.

Behaviour: if the bit is currently 1 (True) it is set to 0 (False), and vice versa. The function returns Void. A complete reference is at the Siemens TIA Portal Help: InvertBitInTag (RT Unified, V20) page.

7.1 Example: Unified button configuration

  1. Open the screen, select the button.
  2. Open Properties -> Events -> Click.
  3. Add a new system function: InvertBitInTag.
  4. Tag: select the integer or bool-array HMI tag.
  5. BitNumber: either a literal (e.g. 3) or a tag reference (e.g. HMI_Tag_1).
  6. Compile and download. No VBScript is required.

This is the recommended path for new projects on Unified Comfort Panels (MTP700/1000/1200/1500/1900) and Unified PC RT. Existing WinCC Flexible projects that cannot be migrated to TIA Portal should continue to use the VBScript workaround from Section 4.

8. Performance and Runtime Considerations

8.1 Script execution latency

On a TP900 Comfort, a VBScript that performs one read + one write of a single array element completes in 1–3 ms. For 55 buttons on a single screen the combined script overhead is therefore in the order of 60–150 ms, well under one acquisition cycle. The bottleneck is normally the PLC read phase, not the script itself.

8.2 Are the writes acknowledged?

WinCC Flexible returns immediately after issuing the write request. The actual write to the PLC may complete on a later cycle (typically within 50–200 ms for an S7-1500 over PROFINET). If the script is part of a click animation, do not assume the value is visible in a neighbouring IO field on the same frame.

8.3 Polling vs. event-driven updates

When the script writes the array element, the panel triggers a write job for the entire BOOL array. The PLC does not need to be polled for that array to be up to date. If you also read the same element from the same screen, configure the array tag with Update on change = Yes to minimize cycle time.

8.4 Mixing scripts and system functions

You may freely mix the InvertBit system function on scalar BOOL tags with a VBScript on array elements inside the same project. They share the same global SmartTags collection and the same area pointers.

9. Step-by-Step Verification

After the project has been compiled and downloaded, perform the following checks before declaring the screen production-ready.

  1. Static check: In the engineering environment, select the button and verify that Properties -> Events -> Click shows a script call to InvertArrayBit with a valid integer argument. Recompile if the field is empty.
  2. Tag list audit: In Project -> HMI Tags, confirm that the array tag has Length = 55 and Data type = Bool array. A mismatch silently truncates the index and may produce out-of-bound writes to neighbouring PLC memory.
  3. Live read: In the runtime, place an IO field bound to dbTest_BooleanArray[5] next to the button. Click the button and confirm the IO field flips state within one acquisition cycle (default 100 ms).
  4. PLC cross-check: In TIA Portal, open the PLC online view, navigate to MyDB.MyFlags[5], and confirm the bit toggles in lockstep with the HMI display. Any delay greater than ~500 ms points to a saturated PROFINET line or an oversized acquisition cycle.
  5. Boundary test: Click the button bound to index 0 and the button bound to index 54. Confirm both write. A common bug is a copy-paste that leaves the index at SmartTags("iIndex") with no initialization, in which case iIndex reads 0 by default and only the first element ever toggles.

10. Troubleshooting Matrix

  • Check Connections -> Area Pointers. Verify MyDB is not configured as know-how protected in STEP 7.
  • Symptom Likely cause Resolution
    Button click does nothing Script not bound to the Click event; or script runtime disabled. Re-open event configuration, re-add the function. On PC RT, ensure HmiRT.exe /script /enable is set in the startup list.
    Runtime warning Index out of range Index tag exceeds array length - 1. Clamp the index with If idx > 54 Then idx = 54 at the top of the function.
    Only element 0 toggles Index tag not initialised, or literal 0 hard-coded by mistake. Pre-event must write the index before the click. Verify with the online tag inspector.
    Write succeeds but PLC value does not change Area pointer disabled; wrong DB number; write protection on the data block.
    HMI sluggish after adding 30+ script buttons Per-click VBScript overhead plus 100 ms acquisition cycle Increase acquisition cycle to 200 ms on non-critical screens, or move toggle logic into the PLC and use a single set/reset bit on the HMI side.
    Element appears stuck in the HMI IO field but updates in the PLC Update on change = No; cycle too slow Enable Update on change on the array tag and force a manual refresh of the IO field with UpdateTag.
    Script runs on panel but errors on PC RT Case-sensitive SmartTags collection; trailing semicolons in VBScript Use exactly SmartTags("..."). VBScript is case-insensitive in identifiers but not in string literals.

    11. Migration Notes: WinCC Flexible → TIA Portal Unified

    Projects upgraded from WinCC Flexible 2008 to TIA Portal V15 and later gain two new options:

    • On a Comfort Panel running Comfort/Advanced firmware, the script approach from Section 4 continues to work without modification.
    • If the target panel is a Unified Comfort Panel (MTP series), convert the script to the InvertBitInTag system function (Section 7) for a 5–10× improvement in click-to-update latency and a smaller project binary.

    During migration, the array length is auto-detected from the PLC tag, so a previous manual Length setting is replaced by the bound DB element count. Verify the resulting Length matches the array dimension before recompiling.

    Why does the InvertBit system function refuse my BOOL array tag?

    WinCC Flexible's InvertBit dialog binds the bit address at compile time. Because the GUI cannot express a runtime index, the address resolution step rejects any array-typed tag. The runtime has no such restriction, which is why a VBScript that resolves the index at runtime works fine.

    Is there a way to avoid writing a VBScript at all?

    On panels without VBScript support (TP 177B 4", OP 77B), declare one scalar BOOL HMI tag per array element and use the normal Click -> InvertBit event. The trade-off is more tag configuration and a heavier project. On WinCC Unified panels, the new InvertBitInTag system function handles arrays directly.

    Can I use C-script instead of VBScript?

    Yes. The C-syntax equivalent is BOOL b = GetTagBit("dbTest_BooleanArray", idx); SetTagBit("dbTest_BooleanArray", idx, !b);. C-scripts run faster than VBScripts on Comfort Panels and are recommended for high-frequency toggles (more than ~5 per second).

    What happens if the index is outside the array bounds?

    The runtime raises a Tag out of range warning in the diagnostic viewer and aborts the write. On PC RT the script reports Subscript out of range. Always validate the index with a If idx < 0 Or idx > 54 Then Exit Function guard.

    Does toggling a bit from the HMI also trigger the PLC's edge evaluation?

    Yes. WinCC Flexible writes the new BOOL value to the PLC, so any rising/falling edge blocks downstream in the PLC see the transition normally. If the PLC is the master for that bit (e.g. an HMI-driven set with a PLC reset), the HMI write is treated as a regular operator input.

    Back to blog