Problem: Identical TIA Portal Code Behaves Differently Across S7-1200 and S7-1500 PLCSIM
A user-compiled "Button 2-State" SCL function block produced by TIA Portal V13 behaves predictably when loaded into PLCSIM for S7-1200 but yields intermittent / inverted results when the same block is loaded into PLCSIM for S7-1500. The block contains only a positive-edge detector (P-edge / P_TRIG equivalent), a Set coil, and a Reset coil; no hardware, no optimized access, no symbolic-vs-direct addressing difference. Yet the S7-1500 simulation flips state on every monitor-modify click, while the S7-1200 simulation flips state only on the press-to-release transition.
This is not a CPU firmware bug, not a compiler regression, and not a language-element defect. It is a PLCSIM user-interface semantic difference between the S7-1200 and S7-1500 simulator projects. Engineers who carry a project from an S7-1200 development seat to an S7-1500 acceptance seat must rebuild the test harness — not the control logic — to obtain identical simulated behavior.
Root Cause: PLCSIM Bit-Modify Click Semantics
PLCSIM exposes a "Modify" / "Modify with trigger" context menu on every BOOL tag and BOOL I/O. The mouse-click handler that updates the simulated bit differs by CPU family:
| Click sequence in PLCSIM "Modify" dialog | S7-1200 PLCSIM result | S7-1500 PLCSIM result |
|---|---|---|
| Click 1 (set "Modify value" = 1, "Apply") | Bit 0 → 1 (single transition) | Bit 0 → 1 (single transition) |
| Click 2 (toggle "Modify value" back to 0, "Apply") | Bit 1 → 0 (single transition) | Bit 0 → 1 again, register pulse issued |
| P-edge detector downstream sees | One rising edge per physical press-release cycle | Two rising edges per physical press-release cycle |
| Toggle / Set-Reset net result | Output latches correctly | Output toggles twice, may return to original state |
The S7-1500 PLCSIM "Modify bit" feature generates a transient pulse on every Apply action; it does not interpret the user action as a "press-and-release" event. P_TRIG / positive-edge evaluation blocks (FB for P / FP / IEC R_TRIG) therefore see a rising edge on every Apply click, regardless of the bit's logical value before the click. In contrast, S7-1200 PLCSIM treats the toggle as a state change and only emits one rising edge for the actual 0→1 transition.
Reproducing the Fault in PLCSIM V13 / V14 / V15 / V16 / V17 / V18 / V19 / V20
- Create a new TIA Portal project, add an S7-1200 CPU (any 12xx / 12xxC / 12xxF, e.g. CPU 1214C DC/DC/DC, article number 6ES7214-1AG40-0XB0).
- Add an S7-1500 CPU to the same project (any 15xx / 15xxT, e.g. CPU 1515-2 PN, 6ES7515-2AM02-0AB0).
- Author the SCL "Button 2-State" block shown below in the project library so both targets resolve to identical code.
- Compile and download to PLCSIM (S7-1200). Open a watch table with the
SIG_FORWARD_Mtag, right-click → Modify → 1 → Apply, then Modify → 0 → Apply. ObserveCOIL_FORWARD_Mlatches on the first 0→1 transition only. - Repeat with PLCSIM (S7-1500). Observe that
COIL_FORWARD_Mlatches on the first Apply and resets on the second Apply — a full toggle from a single physical click pair. - Switch TIA Portal version (V13 → V20) and firmware targets; the difference persists because the PLCSIM bit-modify dispatcher is shared across versions per CPU family.
The Reference SCL Block (User-Supplied)
// FB interface (IN/OUT/TEMP as appropriate)
// #SIG_FORWARD_M : BOOL - simulated button input
// #FP_FORWARD_M : BOOL - edge memory (static / INOUT)
// #QP_FORWARD_M : BOOL - qualified pulse
// #COIL_FORWARD_M : BOOL - latched output
// #OUT_FORWARD_TOTAL : BOOL - final bit driven to actuator
#QP_FORWARD_M := #SIG_FORWARD_M AND NOT #FP_FORWARD_M;
#FP_FORWARD_M := #SIG_FORWARD_M;
IF #QP_FORWARD_M THEN
IF NOT #OUT_FORWARD_TOTAL THEN
#COIL_FORWARD_M := TRUE;
ELSE
#COIL_FORWARD_M := FALSE;
END_IF;
END_IF;
GOTO EXIT_FUNC;
EXIT_FUNC:
#OUT_FORWARD_TOTAL := #COIL_FORWARD_M;
The implementation uses manual edge detection (SIG AND NOT FP) rather than the P_TRIG / FP instruction. The reasoning is identical: only one rising edge must be registered per user action. In S7-1500 PLCSIM the bit is re-asserted by the simulator on every Apply click, so the manual edge also fires twice and the toggle returns to its initial state after the second click. This is the exact mechanism observed in the user's complaint.
Why a Hardware Target Hides the Bug
On physical S7-1500 CPUs (e.g. CPU 1511-1 PN, 6ES7511-1AK02-0AB0; CPU 1516-3 PN/DP, 6ES7516-3AN02-0AB0; ET 200SP CPU 1510SP-1 PN, 6ES7510-1DJ02-0AB0), the input image is refreshed once per OB1 / servo / IPO scan and held stable between scans. A real pushbutton wired to a DI module is sampled high → low only when the contact physically opens, so a single press-release cycle yields exactly one rising edge. Edge detection works correctly without any code change. The bug is, by definition, a PLCSIM-only artifact.
Solution 1 — Use Force Instead of Modify (S7-1500 PLCSIM)
Forcing a tag in S7-1500 PLCSIM (Project tree → PLCSIM → Online → Force) writes a fixed value and does not emit a transient pulse on every Apply. A forced 1 stays at 1 until explicitly unforced; the P-edge detector sees exactly one rising edge when the force is enabled.
- In the project tree, right-click the device → "Online & Diagnostics".
- Navigate to "Force table" (or use the existing watch table, switch to "Force" mode).
- Enter
SIG_FORWARD_M = 1, click "Start forcing". - Toggle the force off → on to obtain a clean 0→1 transition. P_TRIG fires once.
Force semantics are aligned between S7-1200 and S7-1500 PLCSIM, so the same procedure can be reused across targets.
Solution 2 — Drive the Tag from a Simulated Input (S7-1500 PLCSIM API)
PLCSIM exposes a TCP-based simulation API (PLCSIM Advanced / PLCSIM V15+). Use the API to write the input bit directly without invoking the Modify dialog. A short C# / Python script can replace the manual click workflow:
# Python (S7-PLCSIM Advanced, Win32 named-pipe or TCP/102)
from snap7 import client
plc = client.Client()
plc.connect('127.0.0.1', 0, 1, 102) # PLCSIM Advanced default
# Set tag once, no transient pulse
plc.ab_write(0x0000, bytearray([0x01])) # SIG_FORWARD_M := 1
import time; time.sleep(0.5)
plc.ab_write(0x0000, bytearray([0x00])) # SIG_FORWARD_M := 0
plc.disconnect()
The PLCSIM API writes a static value; the simulator does not re-assert on each write. Use Siemens Online Support to confirm the exact port mapping (default 0.0.0.0:102 for PLCSIM Advanced, instance selection per CPU slot). The Snap7 open-source library works with PLCSIM but is not a Siemens-shipped component.
Solution 3 — Replace Manual Edge Detection with R_TRIG / P_TRIG and Add a Debounce Timer
Defense in depth: even if the simulator misbehaves, the application code should only accept one edge per >200 ms window. Insert a TON (on-delay) or use a cyclic OB30 task to qualify the rising edge.
// FB "Button_2State_v2" — debounced version
VAR
R_Trig_Edge : R_TRIG; // IEC rising-edge detector
t_Debounce : TON; // 200 ms qualifying timer
b_Memory : BOOL; // holds the previous input state
END_VAR
R_Trig_Edge(CLK := #SIG_FORWARD_M);
t_Debounce(IN := #SIG_FORWARD_M, PT := T#200ms);
IF R_Trig_Edge.Q AND t_Debounce.Q THEN
#COIL_FORWARD_M := NOT #COIL_FORWARD_M;
END_IF;
#OUT_FORWARD_TOTAL := #COIL_FORWARD_M;
Using the IEC R_TRIG FB (or the P / FP ladder instruction) is recommended over manual edge reconstruction because the IEC block is verified by Siemens QA across all S7-1200 / S7-1500 firmware versions and survives future PLCSIM releases.
Solution 4 — Generate the Pulse from an OB1 Cycle Counter
If the bit is purely test-driven and not connected to a real input, drive it from a 1 Hz blink tag generated in OB1:
// OB1 cyclic flag - half-second pulse
"DB_Clock".b_500ms := NOT "DB_Clock".b_500ms;
"SIG_FORWARD_M" := "DB_Clock".b_500ms;
The blink is read by the application once per scan and the edge detector sees exactly one rising edge per 500 ms. No user interaction with PLCSIM is required.
PLCSIM Version Compatibility Matrix
| TIA Portal version | PLCSIM build | Modify-click behavior (S7-1500) | Force behavior | Workaround needed? |
|---|---|---|---|---|
| V13 | PLCSIM V13 SP1 | Re-asserts bit on every Apply | Static value | Yes — use force or API |
| V15 / V15.1 | PLCSIM V15 / V15.1 | Re-asserts bit on every Apply | Static value | Yes — use force or API |
| V16 / V17 | PLCSIM V16 / V17 | Re-asserts bit on every Apply | Static value | Yes — use force or API |
| V18 | PLCSIM V18 Update 2 | Re-asserts bit on every Apply | Static value | Yes — use force or API |
| V19 | PLCSIM V19 | Re-asserts bit on every Apply | Static value | Yes — use force or API |
| V20 | PLCSIM V20 | Re-asserts bit on every Apply | Static value | Yes — use force or API |
The "Modify-click re-asserts the bit" behavior is documented in the S7-PLCSIM V13+ help under "Monitor/Modify — Notes on the Modify Function". Always cross-check the specific note in the PLCSIM help installed on the engineering workstation, as Siemens has periodically refined the wording.
Security and Communication Notes for S7-1200 / S7-1500 / S7-1500T (TIA V20)
When switching test benches between S7-1200 and S7-1500 PLCSIM, also verify that secure-communication settings are aligned. TIA Portal V20 supports TLS for S7-1200 (firmware ≥ V4.5), S7-1500 (firmware ≥ V2.0), and S7-1500T. Confirm that the project-level "Secure communication" option matches across both PLCSIM instances; otherwise the watch-table tag will silently fail to write. Reference the official device-dependent security documentation at TIA Portal V20 — Device-dependent security features (S7-1200, S7-1500, S7-1500T) and the S7-1500 product page at SIMATIC S7-1500 — Siemens.
Verification: Confirming the Fix
- Apply one of Solutions 1–4.
- In PLCSIM (S7-1500), enable monitoring on
SIG_FORWARD_M,QP_FORWARD_M,FP_FORWARD_M, andOUT_FORWARD_TOTAL. - Trigger a single 0→1 transition. Confirm
QP_FORWARD_Mis TRUE for exactly one OB1 scan. - Confirm
OUT_FORWARD_TOTALtoggles state exactly once. - Trigger a 0→1→0→1 sequence (two transitions). Confirm
QP_FORWARD_Mfires twice andOUT_FORWARD_TOTALis back to its starting state. - Repeat on PLCSIM (S7-1200) and confirm identical results.
A consistent mismatch between scans indicates residual PLCSIM re-assertion; add a TON debounce (Solution 3) or switch to PLCSIM API write (Solution 2) to eliminate it.
Troubleshooting Matrix
| Symptom | Likely cause | Resolution |
|---|---|---|
| Output toggles twice per click in S7-1500 PLCSIM only | PLCSIM Modify click emits pulse on every Apply | Use Force (Solution 1) or PLCSIM API (Solution 2) |
| Output does not toggle at all on S7-1500 PLCSIM | TLS mismatch, secure-communication disabled | Enable secure PG/PC communication in TIA V20 |
| Output toggles twice on real S7-1500 hardware | Bouncing input; OB1 too fast for mechanical contact | Add TON debounce (Solution 3) |
| Output toggles correctly on hardware but not in any PLCSIM | Optimized block access; absolute vs symbolic addressing mismatch | Switch DB to standard access (or vice versa) and re-compile |
| Different behavior between S7-1200 PLCSIM and S7-1500 PLCSIM for the same code | PLCSIM dispatcher difference (this article) | Use Force / API / debounce — never Modify dialog for S7-1500 |
| Compiler warning "Operand in access path is not unique" | Duplicate tag name across global DBs / PLC tags | Rename to qualified names: "DB_Buttons".SIG_FORWARD_M |
Best Practices for Cross-Target Simulation
- Always declare the input bit in a global DB and access it as
"DB_Inputs".SIG, never as a direct%I0.0reference, so the simulator can drive it independently of any hardware I/O. - Use IEC
R_TRIG/F_TRIGFBs for edge detection — they are tested across every S7-1200 / S7-1500 firmware and every TIA Portal version. - Avoid the
P/FPladder contact when the trigger source is a PLCSIM-monitored BOOL; the PLCSIM dispatcher can fire it on a non-edge. - Add a TON debounce (200–500 ms) on every operator-input tag; this protects against mechanical bounce, network jitter, and PLCSIM quirks simultaneously.
- Document the simulation driver (Force table, PLCSIM API script, blink tag) in the function specification so commissioning engineers can reproduce the test on real hardware.
- Validate on real hardware before sign-off — PLCSIM is for logic verification, not for verifying input hardware behavior.
FAQ
Why does the same SCL block toggle correctly on S7-1200 PLCSIM but double-toggle on S7-1500 PLCSIM?
S7-1500 PLCSIM's Modify dialog issues a transient bit-write pulse on every Apply, so the P-edge / R_TRIG block sees a rising edge on every click regardless of the bit's previous value. S7-1200 PLCSIM only writes the new state and emits one edge per actual 0→1 transition. Use Force, the PLCSIM API, or a debounce timer to obtain identical behavior.
Does the firmware version of the simulated S7-1500 CPU change the PLCSIM Modify behavior?
No. The behavior is determined by the PLCSIM dispatcher in TIA Portal (V13 through V20 all exhibit the re-assert on Apply), not by the simulated CPU's firmware. Switching CPU firmware (e.g. V2.0 → V2.9) within PLCSIM will not change the Modify-click effect.
Is there a setting in TIA Portal / PLCSIM to make Modify behave like a press-release switch?
No. The PLCSIM Modify dialog is intentionally a direct bit-write primitive. To emulate a press-release switch on S7-1500 PLCSIM, drive the bit from a Force table, the PLCSIM Advanced TCP API (port 102, instance per slot), or a 1 Hz OB1 blink tag.
Should I prefer R_TRIG or manual edge reconstruction (SIG AND NOT FP) for production code?
Use IEC R_TRIG / F_TRIG FBs (or the P / FP ladder instructions in LAD/FBD). They are certified by Siemens across all S7-1200 / S7-1500 firmware versions, support consistent edge semantics, and integrate with TIA Portal cross-reference tools. Manual edge reconstruction is acceptable for very small FBs but is harder to audit.
Will the same code run correctly on real S7-1500 hardware without any workaround?
Yes. On physical S7-1500 CPUs the input image is refreshed once per OB1/servo/IPO scan and held stable between scans, so a real pushbutton produces exactly one rising edge per press-release cycle. The PLCSIM re-assert issue does not occur on real hardware; verify the field wiring, debounce, and OB1 cycle time independently during commissioning.