S7-1200 Positive Edge Detection Resetting P_TRIG with M-Bit

David Krause13 min read
S7-1200SiemensTutorial / 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

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 M area, or a free BOOL tag 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.

Critical rule: The edge memory bit used for 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 block P_TRIG / R_TRIG.
  • Negative (falling) edge: TRUE → FALSE. Instruction mnemonic -(N)- or function block N_TRIG / F_TRIG.

Detection requires two storage slots:

  1. Current state — read live from the operand on every scan.
  2. 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:

  1. In TIA Portal, open the OB1 (or the destination network) in the LAD/FBD editor.
  2. From the instruction catalog, navigate to Basic Instructions → Bit Logic Operations → Edge detection.
  3. Drag P_TRIG into the network.
  4. Click the CLK input, type the process input, e.g. %I0.0 (the sensor input).
  5. Click the Q output, type the destination tag, e.g. "EdgeSensor" (a local or global BOOL).
  6. Right-click the P_TRIG block header and select Generate instance DB. Accept the default name (e.g. iEdge_P_TRIG_1).
  7. 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:

  1. Open the network in LAD.
  2. Drop a Normally open contact from the toolbar — this becomes the edge contact only if you select P on the contact properties.
  3. Alternatively, type directly: "Signal1" "M11.3" -(P)-. The first operand is the trigger input; the second is the edge memory bit.
  4. 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:

  1. Place the edge memory bit in a non-retentive marker byte. In TIA Portal, open PLC tags → Show all tags, expand the M area, and confirm the Retain column is unchecked for the edge byte.
  2. Use the startup OB (OB100 for warm restart, OB101 for hot restart) to explicitly reset all edge memory bits: SET M11.0 .. M11.7 := FALSE; using an SCL snippet or a finger-of-FBD R coil on each bit.
  3. For critical applications, gate the trigger with an EN input that becomes TRUE only after the first full OB1 cycle. This is implemented with a startup-flag bit set in OB100 and cleared in OB1 on 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.

  1. Open your project in TIA Portal V17 (or V18).
  2. Add a new FB or open OB1.
  3. Insert a P_TRIG block from the catalog. If you cannot find it, type P_TRIG directly into an empty FBD box; the autocompleter resolves it.
  4. Wire %I0.0 → CLK. Wire "OneShot" ← Q.
  5. Accept the auto-generated instance DB iPTRIG_DB1.
  6. 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).
  7. Compile (Project → Compile all) and download to the CPU.
  8. Go online, force %I0.0 TRUE 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:

  1. One-scan width test: Force the trigger input TRUE; open the watch table on the edge Q bit. 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).
  2. 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.
  3. Power-cycle test: With the input held TRUE, perform an MRES or power cycle the CPU. On restart, the Q bit must remain FALSE until the input transitions FALSE → TRUE again. A set Q on 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

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.

Back to blog