WinCC Flexible 2008 VB Script: Read/Write S7-200 V Bytes on MP277

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

WinCC Flexible 2008 VB Script: Read and Write S7-200 V Bytes on MP277

1. Overview

WinCC Flexible 2008 (Standard) ships with a VBScript runtime on the MP 277 10" Touch and other Windows CE-based panels. That runtime exposes the SmartTags object, which lets a script read any tag declared in the project's tag table and write the value back. Combined with the fact that S7-200 V memory is byte-addressable, you can perform tag-to-tag copies (for example, VB100 -> VB200) entirely from an HMI script, without adding a single instruction to the PLC program.

This approach is most useful when the S7-200 CPU has run out of user program memory. A CPU 226, for instance, only has 24 KB of program space (8 KB of which is reserved for the project and a further portion is consumed by the run-time library). Once that budget is exhausted, supplementary logic can be moved into the HMI, executed on tag-change events, scheduled timers, or screen-cycle triggers.

The CPU 226 retains 10 KB of V memory for data, which is independent of the 24 KB program limit. Moving logic out of the CPU does not free V memory — it frees code space (subroutine/FB ladder storage). Plan the split carefully.

2. Prerequisites

Item Specification / Notes
Engineering tool WinCC Flexible 2008 Standard (SP2 or later recommended), with ES installed on Windows XP SP3 / Windows 7
HMI panel SIMATIC MP 277 10" Touch (6AV6 643-0CD01-1AX1 or later); firmware ≥ V11.0.0.0 recommended for VBScript stability
PLC SIMATIC S7-200 CPU 226 (6ES7 216-2BD23-0XB0 or comparable), STEP 7 Micro/WIN V4.0 SP9 for project transfer
Connection PPI / MPI multi-master cable (6ES7 901-3DB30-0XA0) or Ethernet via CP 243-1 IT; configured in WinCC Flexible as a "SIMATIC S7-200" channel
VBScript runtime Enabled by default on MP 277. Verify under Device Settings → Device Properties → Runtime → Script.
Tag count budget MP 277 supports 4 096 tags. Each declared byte/word tag counts separately.

Reference: WinCC Flexible 2008 System Manual (Siemens Support entry 18796084) and the S7-200 Programmable Controller System Manual (entry 1109657).

3. Tag Configuration in WinCC Flexible

For a script to access a V-memory location, the tag must already exist in the connection's tag table. Three configuration choices are critical:

  1. PLC address — Point to a V-byte address. For example, the S7-200 tag "Tag_VB100" with PLC address VB100 (data type Byte).
  2. Acquisition mode — Set to Cyclic continuous if the script is going to read or write this tag on a timer or screen event and you want the panel to refresh it independently. Use Cyclic on use if you want to reduce bus load and only poll when the script touches the tag.
  3. Data type — Match the type used in the script's right-hand side. A SmartTags("Tag_VB100") = SmartTags("Tag_VW50") assignment requires either an explicit conversion or that the destination tag's type accepts the value.
S7-200 area WinCC Flexible syntax Typical data type
VB100 (single byte) VB100 Byte / USInt
VW100 (16-bit word) VW100 Word / Int
VD100 (32-bit double word) VD100 DWord / DInt / Real
V100.0 – V100.7 (bit access) V100.0 through V100.7 Bool
VB100 and VB101 together Declare two tags: VB100, VB101 Pair to form VW100
WinCC Flexible does not expose raw bit/byte arithmetic on a script-local buffer. To split a word into bytes or combine bytes into a word, you must declare overlapping or adjacent tags in the tag table — there is no SmartTags("VW100").LowByte accessor.

4. Direct Tag-to-Tag Copy: VB100 -> VB200

The simplest, most robust pattern is to declare both endpoints as tags and let VBScript perform the assignment. This works on the MP 277 runtime without any third-party add-on.

Procedure:

  1. In the project tree, open Communication → Tags for the S7-200 connection.
  2. Add tag Src_VB100, address VB100, data type Byte, acquisition mode Cyclic continuous.
  3. Add tag Dst_VB200, address VB200, data type Byte, acquisition mode Cyclic on use.
  4. Attach a new script to the event you want to drive the copy (e.g. a button's Press event, or a scheduler with a 100 ms cycle).

Script body:

Sub OnLButtonDown(ByVal Item)
    Dim src, dst
    src = SmartTags("Src_VB100")
    dst = src          ' implicit Byte-to-Byte copy
    SmartTags("Dst_VB200") = dst
End Sub

For a word copy (VW100 → VW200) the structure is identical, but the tags are declared as Word / Int:

SmartTags("Tag_VW200") = SmartTags("Tag_VW100")

This one-liner was confirmed working in the field on an MP 277 10" Touch running WinCC Flexible 2008 RT against a CPU 226. After the script fires once, the value at VB200 on the CPU matches VB100.

5. Bit-Level Access Within a Byte

S7-200 V memory allows bit-granular addressing (V100.0 … V100.7). WinCC Flexible tag configuration lets you expose each of those bits as a Bool tag. From inside a script you can then read or write individual bits by name:

Dim allBits As Boolean
allBits = SmartTags("Tag_V100_0") Or _
          SmartTags("Tag_V100_1") Or _
          SmartTags("Tag_V100_2") Or _
          SmartTags("Tag_V100_3")
SmartTags("Tag_AnyBit") = allBits

To set a specific bit:

SmartTags("Tag_V100_5") = True ' writes a 1 to V100.5

This gives you full read/write access to all bits, bytes, words, and double words of a declared tag, even though the script itself only sees them as discrete SmartTags(...) values. The cost is tag-count: an 8-bit byte becomes 8 Bool tags if you want to manipulate individual bits.

6. Simulating Indirect Addressing in VB Script

The S7-200 instruction set supports pointer-based indirect addressing, for example:

// S7-200 ladder (STEP 7 Micro/WIN)
MOVD  &VB200, AC1     // load pointer to VB200 into accumulator AC1
MOVW  *AC1, AC0       // copy the word pointed to by AC1 into AC0

VBScript on the MP 277 does not provide a comparable raw pointer model. The closest practical substitute is to use SmartTags with computed tag names combined with a VBScript Execute statement, but Execute is not available on the CE runtime, so a different pattern is required:

Approach A — explicit table lookup (preferred):

Dim idx As Integer
idx = SmartTags("Tag_Index")          ' read 0..7 from the PLC

Select Case idx
    Case 0: SmartTags("Tag_CopyDest") = SmartTags("Src_VB100")
    Case 1: SmartTags("Tag_CopyDest") = SmartTags("Src_VB101")
    Case 2: SmartTags("Tag_CopyDest") = SmartTags("Src_VB102")
    Case 3: SmartTags("Tag_CopyDest") = SmartTags("Src_VB103")
    Case 4: SmartTags("Tag_CopyDest") = SmartTags("Src_VB104")
    Case 5: SmartTags("Tag_CopyDest") = SmartTags("Src_VB105")
    Case 6: SmartTags("Tag_CopyDest") = SmartTags("Src_VB106")
    Case 7: SmartTags("Tag_CopyDest") = SmartTags("Src_VB107")
    Case Else: SmartTags("Tag_CopyDest") = 0
End Select

This trades tag declarations for branching code. It is the only portable way to mimic pointer-driven reads on the MP 277 runtime.

Approach B — array of tags via SmartTags array notation (WinCC Flexible 2008 SP2 and later):

Dim arr(7)
arr(0) = SmartTags("Src_VB100")
arr(1) = SmartTags("Src_VB101")
arr(2) = SmartTags("Src_VB102")
arr(3) = SmartTags("Src_VB103")
arr(4) = SmartTags("Src_VB104")
arr(5) = SmartTags("Src_VB105")
arr(6) = SmartTags("Src_VB106")
arr(7) = SmartTags("Src_VB107")

SmartTags("Tag_Index") = SmartTags("Tag_Index")   ' clamp in PLC if needed
If (SmartTags("Tag_Index") >= 0) And (SmartTags("Tag_Index") <= 7) Then
    SmartTags("Tag_CopyDest") = arr(SmartTags("Tag_Index"))
End If

This avoids the Select Case ladder while keeping the lookup deterministic and auditable. The downside is that each element still requires a declared tag.

Both approaches presuppose that the destination Tag_CopyDest is a separate, fixed V-memory location. You cannot, on the MP 277, ask the script to "write to whatever address the index points to" without pre-declaring each destination tag as well.

7. Memory Constraints on CPU 226 — Why Move Logic to the HMI?

The S7-200 CPU 226 reports 24 KB of program memory (8 KB of which is reserved for the project record; the remainder is the user-program budget). Once that budget is full the CPU refuses to download new code with SF/DIAG errors. A common field workaround is:

  1. Identify seldom-executed branches (data marshalling, alarm text composition, recipe-massaging) that do not need deterministic cycle time.
  2. Move those branches into WinCC Flexible scripts, triggered by button events, value-change events, or the scheduler.
  3. Keep anything time-critical (interlocks, fast I/O, PID) on the CPU.
Resource CPU 226 limit MP 277 10" Touch limit
User program 24 KB total Not applicable
V data 10 240 bytes (VB0 – VB10239) Indirect via tags
Tags n/a 4 096
Scripts (VBScript) n/a Limited only by project memory (~32 MB)
Number of connections 1 PPI/MPI + 1 Ethernet (CP 243-1) Up to 4 PLCs (depends on license)

Avoid moving anything that affects safety or motion control to the HMI. The MP 277 is not part of any SIL-rated loop and the VBScript cycle time is not deterministic — it depends on the panel's main loop, screen redraws, and tag-update scheduling.

8. Connection Setup and Runtime Verification

Before any script can talk to the CPU, the panel must complete a successful connection handshake. The recommended verification sequence is:

  1. In WinCC Flexible ES, open Project → Transfer → Transfer Settings and set the panel's IP (or enable PPI autodetect via the supplied cable).
  2. Compile the project. Look for "0 errors, 0 warnings" in the output window. Warning 100xxx about unresolved tag addresses usually means a PLC address typo.
  3. Download to the MP 277 using Project → Transfer → Transfer to Device. The panel will restart Runtime.
  4. On the panel, open Start → Settings → OP → Connections (or the diagnostic overview) and confirm the CPU shows a green status indicator.
  5. Trigger the script manually (tap the assigned button). Watch the diagnostic view for the SmartTag value change.

Sanity-check ladder on the CPU:

// Status word that the HMI will write
NETW  VB100, VW200          // monitor VW200 in STEP 7 Micro/WIN status chart

Add both VB100 and VB200 to a STEP 7 Micro/WIN status chart and observe them while the script runs. The values must mirror within one PPI cycle (~50–100 ms).

9. Troubleshooting Matrix

Symptom Likely cause Remedy
Script runs but destination tag stays 0 Source tag's acquisition mode is On demand and the script hasn't read it before Set both source and destination to Cyclic continuous or read the source once first
Tag value visible in ES but not at runtime Project not transferred, or transfer failed midway Re-transfer; check the OP diagnostic page for "Connection: S7-200 OK/Error"
SmartTags("...") returns Empty / Null Tag name typo, or tag exists in a different connection Verify the tag name in Communication → Tags; case-sensitive on RT
Type-mismatch runtime error on assignment Mixing Byte and Word tag types without conversion Match data types exactly or use CByte(), CInt(), CLng()
Values flicker between old and new Two scripts writing the same destination on overlapping triggers Centralise writes through a single scheduled script and disable button-level duplicates
Script fires but PPI red-light on CPU Address outside V range, or CPU in STOP Confirm CPU is RUN; check VBxxx is within VB0–VB10239
Tag shows correct value in WinCC Flexible ES but the CPU never sees it Wrong connection selected for that tag Open the tag properties and verify the assigned connection points to the CPU 226
MP 277 displays "VBScript error 0x800A000D" Type mismatch — assigning a String to a Byte tag or similar Validate the right-hand side type; coerce with CByte/CInt
Long scripts time out / abort WinCE VBScript runtime is single-threaded; heavy work blocks UI Break the script into chunks; trigger each chunk with the scheduler

10. Best Practices and Field Notes

  • Tag naming: Prefix each tag with its memory area (VB_, VW_, VBit_) so that SmartTags lookups stay self-documenting in larger projects.
  • Acquisition mode: Reserve Cyclic continuous for tags that change on the PLC side without script prompting; everything else can use Cyclic on use to minimise PPI/MPI traffic.
  • Determinism: Avoid placing critical interlocks in scripts. The MP 277 cycle is in the 100 ms range and can stall during screen changes, alarm logging, or recipe transfers.
  • Watchdog: If a script writes a tag every cycle, add a "heartbeat" tag (toggling 0/1 on alternate cycles) so the PLC can detect a stalled HMI.
  • Diagnostics: Use SmartTags("Tag_DiagWord") as a free-form error log; Hex() the last error code into a Word tag and have the PLC surface it on a status screen.
  • Re-declaration pitfall: Do not declare both VB100 and VW100 pointing to the same byte-pair on the PLC — WinCC Flexible will treat them as independent polls, doubling bus load. Decide whether the panel sees a byte or a word and stick to it.
  • Project size: A single MP 277 project can hold hundreds of scripts; just keep the per-script body under ~2 KB of source to keep the runtime compile time short.

11. Worked Example: Recipe Index Copy

Suppose you have eight recipes stored as eight bytes each in V-memory starting at VB1000, and you want the HMI to surface the active recipe in VB200 based on an index from the PLC.

  1. Declare tags Src_VB1000 through Src_VB1007, all Byte.
  2. Declare tag Dst_VB200, Byte.
  3. Declare tag Tag_RecipeIndex, Byte, address VB50 (PLC writes the active index 0–7 here).
  4. Add a scheduler that fires every 200 ms and calls the script below.
Sub OnScheduled(ByVal Item)
    Dim idx As Integer
    idx = CInt(SmartTags("Tag_RecipeIndex"))
    If idx < 0 Or idx > 7 Then
        SmartTags("Dst_VB200") = 0
        Exit Sub
    End If
    Select Case idx
        Case 0: SmartTags("Dst_VB200") = SmartTags("Src_VB1000")
        Case 1: SmartTags("Dst_VB200") = SmartTags("Src_VB1001")
        Case 2: SmartTags("Dst_VB200") = SmartTags("Src_VB1002")
        Case 3: SmartTags("Dst_VB200") = SmartTags("Src_VB1003")
        Case 4: SmartTags("Dst_VB200") = SmartTags("Src_VB1004")
        Case 5: SmartTags("Dst_VB200") = SmartTags("Src_VB1005")
        Case 6: SmartTags("Dst_VB200") = SmartTags("Src_VB1006")
        Case 7: SmartTags("Dst_VB200") = SmartTags("Src_VB1007")
    End Select
End Sub

Verify in STEP 7 Micro/WIN by adding VB200 to a status chart and watching it follow the indexed source byte as you change VB50.

12. FAQ

Can a WinCC Flexible 2008 VB Script on an MP 277 directly read VB100 and write it to VB200 on a CPU 226?

Yes. Declare two Byte tags (VB100 and VB200) with acquisition mode Cyclic continuous, then use SmartTags("Dst_VB200") = SmartTags("Src_VB100") in a button, value-change, or scheduled script. This is the simplest supported pattern.

Can I do indirect addressing such as *AC1 from a script?

No. The WinCE VBScript runtime on the MP 277 does not expose raw S7-200 pointers. Use a Select Case ladder or a fixed arr(...) lookup table over pre-declared tags instead.

Why does my script's value disappear when I leave the screen?

Tags are read at runtime only while the screen or pop-up referencing them is active. Either keep the source tag on a permanently active screen, set its acquisition mode to Cyclic continuous, or read it into an internal Dim variable inside the script before leaving the screen.

How do I split a word (VW100) into its two bytes without using more ladder code?

Declare three tags: Tag_VW100 (Word), Tag_VB100 (Byte), Tag_VB101 (Byte). WinCC Flexible polls each independently, so the script can read either byte, the word, or both.

Is it safe to move PLC logic into the HMI when the CPU 226 is full?

For non-time-critical, non-safety logic — yes, the script approach is a recognised workaround. For interlocks, motion, or anything safety-rated, keep it in the PLC. The MP 277 cycle is not deterministic and is not part of any SIL-rated loop.

Back to blog