Overview
The SIMATIC S7-1200 CPU family handles positive edge detection fundamentally differently from the legacy S7-200. On the S7-200, a positive edge contact -(P)- or P_TRIG instruction was self-resetting: the output remained TRUE for exactly one OB1 scan and then cleared automatically because the edge memory bit was managed internally by the firmware. On the S7-1200, edge detection is explicit. The programmer must assign a dedicated edge memory bit (typically from the M or DB area) to hold the previous state. If no memory bit is wired correctly, the instruction either latches indefinitely, fires on PLC startup when the input is already TRUE, or never fires at all.
This article explains the internal mechanics, the correct wiring pattern in TIA Portal V15 and later, and the verification procedure to confirm one-scan positive edge behavior. It also covers the related negative edge (-(N)- / N_TRIG) and the IEC 61131-3 function blocks R_TRIG / F_TRIG.
Prerequisites
- SIMATIC S7-1200 CPU (any firmware version; behavior is consistent from FW 4.0 through FW 4.6+)
- TIA Portal V15.1 / V16 / V17 / V18 or STEP 7 Basic in the matching version
- Familiarity with the LAD (Ladder Diagram) or FBD (Function Block Diagram) editor
- A free marker byte in the
Marea, or a freeBOOLtag in a global DB - Wiring verified: input module (DI) terminal block connected, sensor powered, 24 V DC on the input channel
Why the S7-1200 Differs from the S7-200
The S7-200 firmware allocated an internal, hidden edge memory buffer (commonly cited as 256 bits per scan) for its -(P)- contacts. Each instance of the edge instruction implicitly drew one bit from this hidden pool. The programmer never saw or managed the bit; the system handled it. This is why S7-200 edge contacts behaved as a clean one-shot.
The S7-1200 abandoned the hidden pool model. Per the SIMATIC S7-1200 Programmable Controller Manual Collection, section "Positive and negative edge instructions", the CPU compares the current state of the input operand to the state stored in an explicit edge memory bit. If both were FALSE on the previous scan and the input is TRUE on the current scan, a rising edge is detected and the instruction's Q output is TRUE for exactly one program cycle of OB1.
The catch: the edge memory bit must be uniquely associated with that one edge instruction. Reusing the same bit elsewhere corrupts the detection, and using a local (Temp) variable instead of a global marker causes the bit to reset on every block call, producing the latched-ON symptom most users encounter.
P_TRIG, -(P)-, N_TRIG, or -(N)- must come from a retentive or non-retentive global area (M, DB) — never from TEMP, IN, OUT, or IN_OUT block-local memory. A TEMP variable is uninitialized at block entry and provides no stable previous-state reference.
Edge Detection Fundamentals in S7-1200
An edge is the transition of a BOOL signal between two states:
-
Positive (rising) edge: FALSE → TRUE. Instruction mnemonic
-(P)-or function blockP_TRIG/R_TRIG. -
Negative (falling) edge: TRUE → FALSE. Instruction mnemonic
-(N)-or function blockN_TRIG/F_TRIG.
Detection requires two storage slots:
- Current state — read live from the operand on every scan.
- Previous state — stored from the prior scan in the assigned edge memory bit.
The detection logic is:
IF (current = TRUE) AND (previous = FALSE) THEN
output Q := TRUE; // one scan only
previous := TRUE; // store for next comparison
ELSE
output Q := FALSE;
previous := current; // store for next comparison
END_IF;
The output Q is TRUE for a single OB1 cycle even if the input remains TRUE. This is identical in spec to the S7-200; the difference is that on the S7-1200 the previous-state bit must be assigned, and the CPU does not clear the Q for you if the wiring is wrong.
Method 1 — P_TRIG / R_TRIG Function Block (Recommended)
For a S7-1200 with firmware V4.0 and later, the IEC 61131-3 compliant P_TRIG (or its alias R_TRIG) function block is the preferred method. It encapsulates the edge memory bit inside an instance data block, eliminating the risk of a programmer assigning the same M-bit to two instructions.
Wiring procedure:
- In TIA Portal, open the OB1 (or the destination network) in the LAD/FBD editor.
- From the instruction catalog, navigate to Basic Instructions → Bit Logic Operations → Edge detection.
- Drag
P_TRIGinto the network. - Click the CLK input, type the process input, e.g.
%I0.0(the sensor input). - Click the
Qoutput, type the destination tag, e.g."EdgeSensor"(a local or global BOOL). - Right-click the
P_TRIGblock header and select Generate instance DB. Accept the default name (e.g.iEdge_P_TRIG_1). - Compile and download.
Each P_TRIG instance DB contains one internal BOOL named CLK_OLD. The firmware updates CLK_OLD automatically on every call. The block is single-instance per call site: do not call the same instance DB from two networks.
Method 2 — -(P)- Contact with M-Bit
The -(P)- contact is a shorthand that exists for source compatibility with S7-200 / S7-300 STL habits. It is functionally identical to P_TRIG but the edge memory bit is exposed as a separate operand on the contact.
Wiring procedure:
- Open the network in LAD.
- Drop a Normally open contact from the toolbar — this becomes the edge contact only if you select
Pon the contact properties. - Alternatively, type directly:
"Signal1" "M11.3" -(P)-. The first operand is the trigger input; the second is the edge memory bit. - Use a unique M-bit per
-(P)-contact. Reserve a marker byte (e.g.MB10..MB20) exclusively for edge memory.
Network 1
%I0.0 M11.3
---|-|-----(P)----------( "EdgeFlag" )---
Rules for the M-bit selection:
- Bit must be in the M area or a global DB. Local TEMP bits are forbidden.
- Bit must not be written anywhere else in the program. Touching the bit elsewhere defeats the edge memory.
- Bit must not be reused for a second edge instruction, even of different polarity.
- Retentive or non-retentive setting is irrelevant; either works. Non-retentive is safer because a power-cycle gives a known-cold state.
Resolving the Latch-ON Symptom
The most common fault report on the S7-1200 is: "The edge contact stays ON as long as my input is ON." This is not a firmware bug; it is one of three configuration errors.
| Symptom | Root cause | Correction |
|---|---|---|
| Q latches ON while input is held TRUE | M-bit is being written by a coil or comparison in another network | Audit cross-references; ensure the edge bit is write-once, read-many |
| Q never fires; M-bit is being read as the trigger instead of the input | Operands on the -(P)- contact were swapped |
Format is <trigger> <edge_mem> -(P)-; verify operand order in the LAD |
| Q fires repeatedly on a held input | Two networks share the same M-bit as edge memory | Allocate a unique M-bit per edge instruction; use instance DBs with P_TRIG |
The PLC-Startup Pitfall
A particularly confusing behavior is: "When I power up the PLC with my sensor already on, the Q output is set immediately". On the S7-200, this would not happen because the internal edge memory buffer was initialized to FALSE at startup. On the S7-1200, the edge memory bit retains its last value if it sits in a retentive M-bit area, or it can be undefined if the M-bit is in a non-retentive area that was never initialized.
Recommended fix:
- Place the edge memory bit in a non-retentive marker byte. In TIA Portal, open PLC tags → Show all tags, expand the
Marea, and confirm the Retain column is unchecked for the edge byte. - Use the startup OB (
OB100for warm restart,OB101for hot restart) to explicitly reset all edge memory bits:SET M11.0 .. M11.7 := FALSE;using anSCLsnippet or a finger-of-FBDRcoil on each bit. - For critical applications, gate the trigger with an
ENinput that becomes TRUE only after the first full OB1 cycle. This is implemented with a startup-flag bit set inOB100and cleared inOB1on its second pass.
Step-by-Step: Reproducing S7-200 Behavior in TIA Portal
Goal: detect a rising edge on %I0.0 and set "OneShot" TRUE for exactly one OB1 cycle.
- Open your project in TIA Portal V17 (or V18).
- Add a new FB or open OB1.
- Insert a
P_TRIGblock from the catalog. If you cannot find it, typeP_TRIGdirectly into an empty FBD box; the autocompleter resolves it. - Wire
%I0.0→CLK. Wire"OneShot"←Q. - Accept the auto-generated instance DB
iPTRIG_DB1. - Place a normally open contact
"OneShot"on a downstream network. Wire it to a Set coil on"OutputQ"(or any BOOL tag you wish to latch). - Compile (Project → Compile all) and download to the CPU.
- Go online, force
%I0.0TRUE for 5 seconds. Observe in the monitor:"OneShot"must flash TRUE for one scan (the column shows TRUE on a single row in the cross-reference watch table).
Verification Procedure
After commissioning, perform the following three checks using a watch table and online monitoring:
-
One-scan width test: Force the trigger input TRUE; open the watch table on the edge
Qbit. The bit must display TRUE for one observation, FALSE on the next. If it stays TRUE, the edge memory bit is contaminated (see table above). -
Re-trigger test: Force input FALSE, then TRUE, then FALSE, then TRUE in succession. Each TRUE transition must produce exactly one TRUE pulse on
Q. A double pulse indicates shared M-bit memory. -
Power-cycle test: With the input held TRUE, perform an MRES or power cycle the CPU. On restart, the
Qbit must remain FALSE until the input transitions FALSE → TRUE again. A setQon restart indicates non-retentive edge memory was not initialized in the startup OB.
Edge Bit Memory: Sizing and Limits
| Parameter | S7-1200 specification | Notes |
|---|---|---|
| Marker area size | 4096 bytes (M0.0 .. M4095.7) on most CPU models; check the specific CPU datasheet | Default in TIA Portal, configurable in PLC properties → General → System and clock memory |
| Retain range | Configurable per byte, default 0 to 15 (MB0 .. MB15) on firmware 4.x | Edge memory should sit outside the retain range to avoid the startup pitfall |
| Edge memory bits per program | No fixed limit; one unique M-bit per -(P)- / -(N)-
|
For > 50 edges, switch to P_TRIG with instance DBs |
| Local TEMP | Not allowed as edge memory | Uninitialized at block entry |
| DB BOOL tag | Allowed as edge memory | Use a non-optimized DB or optimized DB with SET in startup; both are supported |
Method Comparison
| Aspect | S7-200 -(P)- | S7-1200 -(P)- with M-bit | S7-1200 P_TRIG instance DB |
|---|---|---|---|
| Edge memory managed by | Firmware (hidden) | Programmer (explicit) | Firmware (encapsulated in DB) |
| Risk of double-assignment | None (hidden pool) | High (must audit cross-refs) | None (instance is unique per call) |
| Migration effort from S7-200 | — | Low; add an M-bit operand to each contact | Medium; replace contact with function block |
| Suitable for > 100 edges | Yes | Risky; bit management scales poorly | Yes; each instance DB is a small overhead |
| Code readability | High | Medium (operand-pair syntax unfamiliar to newcomers) | High (block name is self-documenting) |
Common Fault Patterns and Diagnostics
Use the TIA Portal online Monitor & Force and Cross-reference views to triage. The following matrix maps observable symptoms to underlying cause:
| Observed | Likely cause | Diagnostic command | Fix |
|---|---|---|---|
| Edge never fires | Edge bit also assigned to a S / R coil upstream |
Right-click edge bit → Cross-reference shows multiple writers | Remove the secondary write |
| Edge fires every scan | Edge bit is in a TEMP variable | Compile log: "LAD/FBD: edge memory must be in M or DB" | Move the bit to a marker or global DB tag |
| Edge fires on PLC startup with input already TRUE | Edge bit is in a retentive area, holds TRUE from prior run | PLC tags table: Retain column = TRUE for the edge byte | Clear bit in OB100 or move to non-retentive area |
| Compiler error: "Operands of -(P)- must be of BOOL type" | One of the two operands was a non-BOOL tag | Highlight the network; hover shows the type | Change the operand to a BOOL tag or use a contact that converts |
| Edge fires twice for one input transition | Two networks call the same P_TRIG instance DB | Cross-reference on the instance DB shows two call sites | Generate a second instance DB or use the -(P)- form with a unique M-bit |
Implementation Patterns
For routine use across a large project, define an edge memory convention in the project header:
// Project edge memory convention (example)
// MB100 .. MB109: Positive edge memory (80 bits available)
// MB110 .. MB119: Negative edge memory (80 bits available)
// Each -(P)- / -(N)- consumes one bit; do not reuse.
// All bits in this area are non-retentive (Retain = FALSE).
// OB100 clears MB100 .. MB119 to 0 on every restart.
For a structured SCL approach, the function block pattern is cleanest:
FUNCTION_BLOCK "fbEdgeCounter"
VAR
iTrig : R_TRIG; // rising-edge instance
iCount : INT;
END_VAR
BEGIN
iTrig(CLK := "SensorInput");
IF iTrig.Q THEN
iCount := iCount + 1;
END_IF;
"EdgeCount" := iCount;
END_FUNCTION_BLOCK
The R_TRIG instance is held in the function block's instance DB, so the edge memory bit lives with the block. Multiple calls to fbEdgeCounter each get their own instance and therefore their own edge memory.
References Within the Article
- SIMATIC S7-1200 Manual Collection — Positive and negative edge instructions
- Siemens Industry Online Support — Detect positive signal edge (S7-1200, S7-1500) entry 109747174
Why does the S7-1200 edge instruction stay latched when the S7-200 version did not?
The S7-200 firmware allocated a hidden pool of edge memory bits internally; the S7-1200 requires the programmer to assign an explicit edge memory bit from the M or DB area. If the assigned bit is also written elsewhere — or worse, is a TEMP local variable that resets on every block call — the CPU cannot store a stable previous state, so the Q output remains TRUE for as long as the input is TRUE. Assign a unique, unwritten marker or DB bit, or use the P_TRIG function block with its own instance DB.
Can I use a TEMP variable as the edge memory bit for -(P)-?
No. TEMP variables are uninitialized at every block entry, so they cannot store a previous scan state. TIA Portal will compile the program but the edge will misbehave (firing every scan, or never, depending on stack contents). Always use a global marker (M) or a tag in a global data block (DB). Optimized or non-optimized DBs are both supported, but the tag must be a static BOOL.
How do I stop Q from being set on PLC startup when my sensor is already on?
Move the edge memory bit to a non-retentive marker byte (uncheck the Retain column in the PLC tags table) and add explicit reset logic in the startup OB (OB100) to clear the edge memory byte to zero. The combination guarantees a known-cold previous state on every restart, replicating the S7-200 behavior of "do not fire on first scan if input is already TRUE".
What is the difference between P_TRIG and R_TRIG on the S7-1200?
There is no functional difference; R_TRIG is the IEC 61131-3 standard name and P_TRIG is the Siemens-preferred alias added in firmware V4.0. Both create a function block with inputs CLK and output Q, and both require an instance data block to store the previous state. Use either, but do not call the same instance DB from two networks — that creates a shared edge memory and breaks detection.
How many edge instructions can I use in one S7-1200 program?
There is no fixed firmware limit, but practical limits come from the marker area size (4096 bytes on most CPUs, i.e. 32 768 individual M-bits) and from program maintainability. For projects with more than 50 edges, prefer the P_TRIG function block with instance DBs, because each instance DB encapsulates its own edge memory and prevents accidental cross-assignment that is easy to miss in a large M-bit pool.