Overview
WinCC (TIA Portal WinCC and WinCC V7/V8) provides several ways to navigate between process screens: direct screen windows, picture windows, screen change buttons with the OpenPicture function, and global C-scripts that react to PLC tag values. When a physical pushbutton wired to a digital input on the PLC must select one of several PDL pictures, the cleanest pattern is to map the button (or a counter/selector in the PLC) to a single integer tag, then let a WinCC global action read that tag on a cyclic trigger and call OpenPicture for the matching screen.
Prerequisites
- WinCC V7.x runtime or WinCC Professional (TIA Portal) with the C-Editor option licensed (C-Script for WinCC V7 is part of the standard install; C-Scripting in WinCC Professional is available for runtime).
- A configured WinCC project with at least four PDL pictures (
Picture1.PDLthroughPicture4.PDL). - A PLC tag (e.g.
DB1.DBW0on an S7-1500, orMW10on an S7-300/400) of typeWORD(16-bit unsigned) that the PLC sets to 0, 1, 2, or 3 according to the desired screen. - A physical pushbutton wired to a digital input on the PLC, with PLC logic that increments or selects the picture index.
- The tag
PLCtagcreated in WinCC Tag Management with the same name and type used by the C-script.
Tag Configuration in WinCC
The WinCC tag must mirror the PLC tag exactly. Mismatch in data type, address, or update cycle is the most common reason a C-script reads a constant value and falls through to the else branch.
| Parameter | Value | Notes |
|---|---|---|
| Name | PLCtag |
Must match the string passed to GetTagWord(). |
| Data type | Unsigned 16-bit value | Equivalent to WORD in STEP 7 / UINT / INT on S7-1500. |
| PLC connection | SIMATIC S7 PROTOCOL SUITE → TCP/IP (or PROFIBUS, MPI) | Channel must be online (green check in Tag Management). |
| Address | e.g. DB1, W0
|
Use the absolute address of the WORD in the PLC. |
| Update cycle | 1 s (or match trigger cycle) | Shorter than the action trigger so the value is current. |
| Length / Quality code | 2 bytes, 100 (Good) | Check Tag Status dialog during commissioning. |
The C-Action Pattern
A WinCC C-action is a C function with a fixed signature, including the header apdefap.h which provides the prototypes for GetTagWord, SetTagWord, OpenPicture, and the rest of the WinCC C API. The two lines #include "apdefap.h" and int gscAction( void ) are inserted automatically by the editor and must not be removed.
/* WINCC:TAGNAME_SECTION_START
// next TagID : 1
#define TAG_1 "PLCtag"
// WINCC:TAGNAME_SECTION_END
*/
#include "apdefap.h"
int gscAction( void )
{
WORD wValue = 0;
/* Read the current value of the PLC tag into a local WORD */
wValue = GetTagWord( TAG_1 );
/* Map tag value to picture */
if ( wValue == 0 )
{
OpenPicture( "Picture1.PDL" ); /* Return-Type: void */
}
else if ( wValue == 1 )
{
OpenPicture( "Picture2.PDL" );
}
else if ( wValue == 2 )
{
OpenPicture( "Picture3.PDL" );
}
else if ( wValue == 3 )
{
OpenPicture( "Picture4.PDL" );
}
else
{
OpenPicture( "Picture1.PDL" );
}
return 0;
}
The same logic with a switch statement is more compact and slightly faster for large mappings:
#include "apdefap.h"
int gscAction( void )
{
WORD wValue = GetTagWord( "PLCtag" );
switch ( wValue )
{
case 0: OpenPicture( "Picture1.PDL" ); break;
case 1: OpenPicture( "Picture2.PDL" ); break;
case 2: OpenPicture( "Picture3.PDL" ); break;
case 3: OpenPicture( "Picture4.PDL" ); break;
default: OpenPicture( "Picture1.PDL" ); break;
}
return 0;
}
Trigger Configuration
The C-action must be triggered cyclically so that the value of PLCtag is re-read on a regular basis. Configure the trigger in the right-hand pane of the C-Editor:
- Open the action in Global Script → C-Editor → Actions → Global Actions.
- Right-click and select Info / Trigger.
- Add a trigger of type Timer → Cyclic.
- Set Cycle to
2 s(or 500 ms for snappier response; do not go below 250 ms as it loads the WinCC scheduler). - Keep Event: Standard cycle checked; this is the default that fires the action on the configured cycle.
OpenPicture again. OpenPicture is idempotent in this case (it re-opens the same PDL), so the visible effect is harmless, but if the navigation logic relies on edge detection (e.g. opening a pop-up only on a rising edge), use GetTagBitWait or compare against a stored previous value.Common Errors in the Original Code
The thread documents three distinct mistakes. The fixes are listed in the order they appeared during the debugging session.
| Symptom | Cause | Fix |
|---|---|---|
| Compiler warning "comparison between pointer and integer" | Comparing the string literal "PLCtag" directly to an integer constant: if ("PLCtag" == 0)
|
Read the tag value into a local variable first with GetTagWord("PLCtag") and compare the variable. |
| No picture change, the else branch always runs | The C-string "wValue" was being compared instead of the numeric value: if ("wValue" == 0) is always false except for the pointer address |
Remove the quotes: if (wValue == 0)
|
Picture name missing the .PDL extension on some calls |
OpenPicture("Picture4") and OpenPicture("Picture1") in the else branch |
Always use the full picture name with extension, including the else fallback. |
After the third correction, the script compiled, ran on the 2-second cycle, and successfully switched the runtime picture whenever the PLC wrote a new value to PLCtag.
Debugging with GSC Diagnostics and printf
The line printf("%d\r\n", wValue); in the C-action writes the variable value to the Global Script diagnostics window. To see the output in Runtime, drop a GSC Diagnostics application window into the start picture:
- Open the start picture (e.g.
Picture1.PDL) in Graphics Designer. - From the Smart Objects palette choose Application Window → Global Script → GSC Diagnostics.
- Place the object on the picture and resize it.
- Alternatively, use apDiag in the background to capture
printfoutput without embedding a window.
This technique is essential for the commissioning phase because it lets you verify the tag value the script sees, independent of the value displayed in a WinCC IO field. If the diagnostics window shows the correct value but the picture does not change, the failure is downstream of the read (i.e. in the OpenPicture call or the picture name).
Alternative Implementations
The C-action pattern is the most flexible, but two other approaches cover common requirements.
Picture Window with Dynamic Picture Name
Insert a Picture Window smart object on a base screen. Bind its Picture Name property to a WinCC tag that holds the full picture name. Configure an event on a tag change to update the property, or use a direct tag connection:
- Add a string tag, e.g.
PictureName(TEXT 8). - In the PLC, write the ASCII string
Picture1.PDLthroughPicture4.PDLto the tag area. - In the Graphics Designer, select the Picture Window, open the Properties dialog, and under Miscellaneous → Picture Name create a direct tag connection to
PictureName. - Set the update cycle to 1 s.
Tag-Based Display Property on a Button
Place a transparent full-screen button over the screen. In the Display property, bind the Yes bit to a tag that the script sets after OpenPicture returns. This is what the thread author tried and rejected because the screen also had to be reachable from in-picture navigation buttons.
Trigger Cycle vs. PLC Debounce
With a 2-second trigger cycle, holding the physical button will cause a maximum of 2 seconds of latency before the screen catches up. For faster response, drop the cycle to 500 ms, but debounce the button in the PLC first; otherwise the PLC will write a sequence of increment values to the tag in tens of milliseconds and the script will skip screens.
A recommended PLC pattern uses a one-shot with a 200 ms debounce timer and a counter that wraps at 4:
// STEP 7 STL pseudo-code (S7-1500)
A I 0.0 // physical button
FP M 0.0 // rising edge
AN M 0.1 // debounce
S M 0.2 // one-shot
A M 0.2
L 1
T DB1.DBB0 // increment
A M 0.2
JC noReset
L 0
T DB1.DBW0 // wrap to 0 after value 3
noReset: NOP 0
The PLC writes the value to DB1.DBW0, the WinCC tag PLCtag mirrors it on the configured update cycle, and the C-action re-reads it on its 2 s trigger.
Verification
- Compile the project in Graphics Designer; verify no errors in the C-Editor output window.
- Activate Runtime and confirm the GSC Diagnostics window shows the expected
PLCtagvalue as the button is pressed. - Watch the WinCC screen: it must change to
Picture1.PDLwhenPLCtag == 0,Picture2.PDLwhenPLCtag == 1, and so on. - Force
PLCtagto 4 in the WinCC Tag Simulation table; the screen must fall back toPicture1.PDL(theelsebranch). - Stop Runtime, edit the script to add
printfcalls, reactivate, and check that the diagnostics window still shows the correct value (proves the script is being invoked).
Troubleshooting Matrix
| Symptom | Likely Cause | Action |
|---|---|---|
| Screen reverts to Picture 1 every 2 s | Cyclic trigger re-firing; tag is not changing | Force the tag in the Tag Simulation table; if it works there, the PLC is not writing. |
| Screen never changes, no error | Script not triggered | Open Info / Trigger, confirm the cyclic trigger is added and the cycle is non-zero. |
| Compile error "undeclared identifier GetTagWord" | Header apdefap.h missing or removed |
Restore the auto-generated #include "apdefap.h" line at the top of the action. |
| Runtime error "Function OpenPicture failed" | Picture name typo or .PDL extension missing |
Check spelling; use Picture Tree → Test Picture in Graphics Designer to confirm the PDL exists. |
| Tag shows value in IO field but script reads 0 | Mismatch between tag name in Tag Management and string passed to GetTagWord
|
Compare the two strings case-sensitively; WinCC tag names are case-sensitive. |
| Screen flashes between two pictures | Tag oscillating (e.g. PLC logic inverts it each scan) | Check the PLC logic; add a debounce or use a flip-flop with a hold time. |
Performance Notes
A C-action that runs every 2 s and performs a single GetTagWord plus an OpenPicture adds well under 0.1% CPU load on a typical WinCC server. The 2 s cycle is conservative; for most operator-screen tasks 500 ms is the practical minimum. Below that, prefer an event-driven trigger (e.g. on tag change) rather than reducing the cycle further. WinCC does not have a built-in "on tag change" trigger for external WinCC tags; the closest is to use a small cycle (500 ms) or to write a hotkey-driven script that fires on a user action.
Security and Safety Considerations
Screen switching driven by a PLC tag is a comfort feature, not a safety function. If the screen change is used to acknowledge a fault, ensure that the PLC writes the same fault ID to a non-volatile area and that the operator still has a manual acknowledgement path. A global C-action that calls OpenPicture cannot replace a SIL-rated acknowledgement.
Migration to TIA Portal / WinCC Professional
WinCC Professional in TIA Portal moves scripting to VBScript for the engineering project, but C remains available for runtime actions. The equivalent VBScript pattern is:
' HMIRuntime global action, triggered every 2 s
Sub OnLoseFocus(ByVal Item)
Dim vValue
vValue = HMIRuntime.Tags("PLCtag").Read
Select Case CLng(vValue)
Case 0 HMIRuntime.BaseScreenName = "Picture1.PDL"
Case 1 HMIRuntime.BaseScreenName = "Picture2.PDL"
Case 2 HMIRuntime.BaseScreenName = "Picture3.PDL"
Case 3 HMIRuntime.BaseScreenName = "Picture4.PDL"
Case Else HMIRuntime.BaseScreenName = "Picture1.PDL"
End Select
End Sub
Setting HMIRuntime.BaseScreenName is preferred over the legacy OpenPicture call in TIA Portal because it works with faceplates and the new screen window navigation model.
Edge Cases and Field Tips
- If the project has a configured start picture, calling
OpenPictureon the start picture has no visible effect, but the action still consumes a runtime tick. Skip the call when the current picture is already the target. - The
PDLextension is required in WinCC V7; WinCC Professional accepts the name without the extension but adding it explicitly is portable. - If the user has multiple monitors,
OpenPictureopens the picture on the default monitor; useOpenPictureInPopupor a picture window for secondary screens. - Avoid putting the C-action in the picture itself; global actions persist across picture changes and are easier to maintain.
FAQ
Why does my C-script not compile when I write if("PLCtag" == 0)?
"PLCtag" is a string literal (a pointer to char), not an integer. WinCC's compiler warns or errors because you are comparing a pointer to an int. Read the tag value first with GetTagWord("PLCtag") into a WORD variable and compare the variable.
What is the minimum cycle for a global C-action?
Practical minimum is 250 ms for a single-action project. For navigation logic 500 ms is a good compromise between latency and CPU load. Avoid going below 250 ms on a WinCC single-user station.
Can I use a BIT tag instead of a WORD and map each bit to a picture?
Yes, with GetTagBit four times and a priority encoder, or with GetTagWord on a DWORD containing the four bits and a lookup. The integer-indexed approach in the article is simpler and more robust against PLC timing jitter.
How do I see printf output from the script in Runtime?
Drop a GSC Diagnostics application window (Smart Objects → Application Window → Global Script → GSC Diagnostics) into the start picture, or run the apDiag tool. Each printf("%d\r\n", wValue); in the action will write a line to the diagnostics window.
Will the same script work on TIA Portal WinCC Professional?
Yes, by re-implementing the body in VBScript and using HMIRuntime.BaseScreenName = "Picture1.PDL" for screen change, or by enabling the C runtime option and using the C code above unchanged. Trigger configuration in TIA Portal is under the action's Properties → Trigger tab.