Configuring RESET_TIMER in TIA Portal SCL for S7-1200/S7-1500

David Krause14 min read
SiemensTIA PortalTroubleshooting
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

Configuring RESET_TIMER in TIA Portal SCL for S7-1200/S7-1500

The Siemens RESET_TIMER SCL instruction is documented as a single-line call that clears an IEC timer (TP, TON, TOF, TONR) to zero along with all of its structure components. In practice, the example pasted directly from the in-software help in TIA Portal V13.1.4 on an S7-1200 CPU with firmware 4.1 does not behave as advertised when simulated in PLCSIM. The timer never advances, the Q output stays low, and a casual engineer concludes that the documentation is broken.

The documentation is not the problem. The example works under three specific constraints that the help text does not make explicit: the timer must be a multi-instance of the enclosing Function Block (not a global DB instance), the RESET_TIMER call must sit inside an IF structure, and the IEC timer must be driven on the same scan (typically by referencing timer.ET) so that the runtime actually evaluates it. This reference walks through each of those constraints, shows a corrected SCL implementation, and provides a verification procedure that closes the loop with a PLCSIM watch table.

All code samples target SCL on S7-1200 CPUs. The same RESET_TIMER rules apply to S7-1500 controllers and the S7-1200/1500 firmware line documented in the current Siemens help. References to V13.1.4 reflect the originally reported environment; later TIA Portal releases do not change the level-triggered semantics described here.

1. Problem Summary

A function block is created in TIA Portal V13.1.4 with the following (paraphrased) structure taken from the in-software help for RESET_TIMER:

FUNCTION_BLOCK "FB_TimerReset"
VAR
    TON_TIME : TON;       // IEC timer as static multi-instance
    start    : BOOL;
    tmp      : BOOL;
END_VAR

BEGIN
    // (Example as it appears in the TIA Portal help)
    RESET_TIMER(TON_TIME);
    tmp := TON_TIME.Q;
    IF start THEN
        TON_TIME(IN := TRUE, PT := T#2s);
    END_IF;
END_FUNCTION_BLOCK

The block is downloaded to PLCSIM V13 SP1. With start held TRUE in a watch table, the engineer's expectation is that TON_TIME will count, TON_TIME.Q will become TRUE after two seconds, and that RESET_TIMER can be called separately to clear the timer to zero. In the simulator, the timer does not advance. ET stays at T#0ms, and Q stays at FALSE indefinitely.

Two failures occur simultaneously:

  1. The IEC timer is never driven to a state where its time base increments, because the runtime only ticks a timer when at least one of its output components is read inside the active code path.
  2. The RESET_TIMER call sits unconditionally at the top of the FB, so it re-arms the timer to zero every scan before TON_TIME can accumulate.

2. Root Cause Analysis

The Siemens help for RESET_TIMER describes the instruction's effect on the timer structure but does not document the evaluation order required to make an IEC timer visible inside a single FB scan. Three root causes combine to produce the observed behavior on S7-1200 FW 4.1.

2.1 Multi-instance requirement

An IEC timer is a structured data type (DTL or system-internal IEC_TIMER / IEC_LTIMER). When the timer is declared as a TON static variable inside the FB, the compiler generates a multi-instance data block that lives inside the FB's instance DB. If the same timer name is also visible as a global DB (for example a leftover TIMER or TIMER_DB global block), the unqualified identifier resolves to the global symbol first and the FB-internal multi-instance is shadowed. The reset then operates on a different memory area than the timer that is actually being started.

2.2 Level-triggered reset

RESET_TIMER is a level-triggered statement, not an edge-triggered one. Each scan in which the instruction line is executed, the timer is forced back to T#0ms with Q = FALSE. Placing the call at the top of the FB, outside any conditional, guarantees that the timer is reset every cycle, which is the most common reason engineers observe that "the timer never runs."

2.3 Time-base evaluation

S7-1200/S7-1500 IEC timers are evaluated by the runtime only when one of their output tags (Q, ET, or the legacy running flag in the case of TP) is referenced inside the current OB scan. If the FB only writes the timer and never reads it, the runtime may short-circuit the call and the time base will not advance. Reading TON_TIME.ET (or assigning TON_TIME.Q to a local variable) inside the same conditional branch that drives IN forces the runtime to perform a full tick.

This time-base rule is the same one that produces "the timer only runs when I open the watch table" behavior on S7-1200 hardware. PLCSIM mimics the production runtime in this respect; if a timer does not advance in PLCSIM, it will not advance on a physical CPU either.

3. RESET_TIMER Instruction Semantics

The official Siemens documentation describes RESET_TIMER as follows:

You can use the "Reset timer" instruction to reset an IEC timer to "0". The structure components of the timer in the instance DB are reset.

Reference: RESET_TIMER: Reset timer (S7-1200, S7-1500) - TIA Portal Help

The instruction applies to all four IEC timer types available on S7-1200/S7-1500:

IEC Timer Behavior Reset result
TP (pulse) Sets Q for the configured pulse duration on a rising edge of IN. ET = T#0ms, Q = FALSE, internal edge flag cleared.
TON (on-delay) Sets Q after ET reaches PT while IN is high. ET = T#0ms, Q = FALSE, elapsed-time accumulator cleared.
TOF (off-delay) Sets Q on a falling edge of IN; clears Q after PT. ET = T#0ms, Q = FALSE, internal start flag cleared.
TONR (retentive on-delay) Accumulates ET while IN is high; manual reset only. ET = T#0ms, Q = FALSE. Note: the retentive accumulator is cleared because RESET_TIMER clears the timer structure.

Three semantic rules apply uniformly:

  1. Level-triggered: every evaluation of the instruction line clears the timer.
  2. No return value: unlike TP/TON FBs, the call does not produce a Boolean result.
  3. Single operand: only one timer instance is accepted per call.

4. IEC Timer Data Structures and Multi-Instance DBs

On S7-1200/S7-1500, an IEC timer call such as TON_TIME(IN := start, PT := T#2s); expands at compile time into a write to a structured data block. The structure layout (V13.1.4 / FW 4.1 representation) is conceptually:

Component Type Meaning
IN BOOL Start input. Held high to allow the time base to run.
PT TIME Preset duration. Range: T#-24d20h31m23s648ms to T#+24d20h31m23s647ms.
Q BOOL Output that reflects the timer's logical state.
ET TIME Elapsed time. Read to force runtime evaluation.
Internal state STRUCT Edge flags and the time accumulator. Cleared by RESET_TIMER.

When TON_TIME is declared as a static variable inside FB_TimerReset, the compiler allocates the structure inside the FB's instance DB. If the FB is called as a multi-instance (for example inst_fbTimerReset inside another FB), the timer lives inside inst_fbTimerReset.TON_TIME. This naming is what makes the assignment unambiguous in the SCL source.

If a separate global DB with the same timer symbol exists, the symbol resolution rule is:

  1. Local declarations of the enclosing FB.
  2. Static (multi-instance) declarations of the enclosing FB.
  3. Global DB symbols, in the order shown in the project tree.

The engineer who sees RESET_TIMER(TON_TIME) "work" for the start sequence but fail to update Q is almost always hitting case 3: RESET_TIMER and TON_TIME.Q resolve to different DBs. Renaming the local timer to a unique identifier (for example ioT_TON) and rebuilding removes the ambiguity.

5. Why the Help Example Fails in PLCSIM

Walking through the original example line by line on S7-1200 FW 4.1:

BEGIN
    RESET_TIMER(TON_TIME);          // (1) reset every scan
    tmp := TON_TIME.Q;              // (2) snapshot output
    IF start THEN
        TON_TIME(IN := TRUE, PT := T#2s);   // (3) start
    END_IF;
END_FUNCTION_BLOCK

On every OB1 pass:

  1. Line (1) clears ET to zero and clears the internal accumulator. The instruction is unconditional.
  2. Line (2) reads Q. Because Q was just cleared, it reads FALSE for this scan.
  3. Line (3) starts the timer with IN := TRUE and a preset of two seconds.

The runtime tick happens at the end of the OB1 pass, but because line (1) executed before the tick, the elapsed time accumulator is zero. On the next scan, line (1) runs again before the tick is committed, so the timer appears frozen.

The PLCSIM observation that "the timer does not run" is therefore correct and reproducible. It is not a bug in the firmware; it is the documented behavior of RESET_TIMER combined with an unconditional placement.

6. Corrected SCL Implementation

The corrected FB keeps the reset conditional and forces the runtime to evaluate the timer in the same code path that starts it.

FUNCTION_BLOCK "FB_TimerReset"
{ S7_Optimized_Access := 'TRUE' }
VAR
    ioT_TON : TON;            // IEC timer as multi-instance
    start   : BOOL;
    reset   : BOOL;
    elapsed : TIME;
    done    : BOOL;
END_VAR

BEGIN
    // 1) Drive the timer explicitly inside the same branch
    //    that controls IN. The read of ET forces the runtime
    //    to perform the time-base evaluation this scan.
    IF start THEN
        ioT_TON(IN := TRUE,
                PT := T#2s);
        elapsed := ioT_TON.ET;
        done    := ioT_TON.Q;
    ELSE
        ioT_TON(IN := FALSE);
        elapsed := ioT_TON.ET;
        done    := ioT_TON.Q;
    END_IF;

    // 2) Reset is gated. RESET_TIMER is level-triggered, so
    //    a single pulse on 'reset' would be ignored unless the
    //    line sits inside an IF and the timer is held
    //    out-of-run during the same scan.
    IF reset THEN
        ioT_TON(IN := FALSE);
        RESET_TIMER(ioT_TON);
    END_IF;
END_FUNCTION_BLOCK

Three improvements over the help example:

  • Unified drive branch. elapsed and done are read inside the same IF block that sets IN, guaranteeing one tick per scan.
  • Conditional reset. RESET_TIMER only runs while reset is high, removing the per-scan clearing that froze the timer in the original example.
  • Explicit IN := FALSE before the reset call, so that any pulse-driven reset input does not leave the timer armed.

6.1 Edge-triggered reset pattern

Most production code wants a single reset on a rising edge, not a sustained level. Combine RESET_TIMER with a standard edge flag:

VAR
    resetTrig    : BOOL;
    resetEdgeMem : BOOL;
END_VAR

BEGIN
    // Rising-edge detection
    resetTrig    := reset AND NOT resetEdgeMem;
    resetEdgeMem := reset;

    IF resetTrig THEN
        ioT_TON(IN := FALSE);
        RESET_TIMER(ioT_TON);
    END_IF;

The pattern is identical to the standard R_TRIG FB. Once the rising edge has fired, the RESET_TIMER line is dormant on subsequent scans, leaving the timer free to count.

7. Step-by-Step Migration Procedure

Use this procedure to repair an existing FB that exhibits the "timer never runs" symptom on TIA Portal V13.1.4 / S7-1200 FW 4.1.

  1. Audit timer declarations. Open the FB in the project tree. Confirm that every IEC timer is declared as a TP / TON / TOF / TONR static variable. Delete any global DB that shadows the same name.
  2. Disable optimized-access collisions. If the FB uses non-optimized access (legacy), ensure that the timer DB is not shared with a UDT or another instance. Prefer S7_Optimized_Access := 'TRUE' for new code.
  3. Wrap the reset. Move every RESET_TIMER(...) call inside an IF structure that evaluates FALSE under normal operation. Use a one-shot if you need edge behavior.
  4. Force the time-base read. Inside the same IF that drives IN, assign timer.ET and timer.Q to local variables. This forces a runtime tick.
  5. Rebuild and download. Right-click the device and select Compile > Software (rebuild all blocks). Then download to PLCSIM or the target CPU.
  6. Verify with PLCSIM. Continue with the verification procedure in section 8.

8. Verification Procedure

Use the following PLCSIM-based verification sequence to confirm that RESET_TIMER is wired correctly without needing a physical S7-1200.

  1. Create the FB and OB1. Add FB_TimerReset to OB1 as a single-instance call: inst_TimerReset(start := I0.0, reset := I0.1);.
  2. Open a watch table. Create WatchTable_1 and add the symbols inst_TimerReset.ioT_TON.IN, inst_TimerReset.ioT_TON.PT, inst_TimerReset.ioT_TON.ET, inst_TimerReset.ioT_TON.Q, inst_TimerReset.elapsed, inst_TimerReset.done, and the inputs I0.0, I0.1.
  3. Run PLCSIM. Start the simulation, click RUN, and confirm the CPU is in RUN.
  4. Set I0.0 = TRUE. ET should advance in 10 ms increments on a 100 ms OB1. After 2 s, Q should latch TRUE.
  5. Pulse I0.1. With I0.0 still TRUE, toggle I0.1 for one scan. ET must drop to T#0ms and Q must return to FALSE. On the next scan the timer should start counting again.
  6. Hold I0.1 = TRUE with I0.0 = TRUE. ET must remain T#0ms for as long as reset is high, proving the level-triggered behavior. Releasing I0.1 must restore counting within two seconds.
  7. Document the result. Capture the watch table screenshot as part of the SAT/FAT package.
If ET does not advance when I0.0 is held TRUE, the timer is being shadowed by a global DB. Rename the local variable, recompile, and repeat from step 4.

9. Firmware and Portal Version Compatibility Matrix

The level-triggered semantics described in this article have been consistent across the S7-1200/1500 firmware line. The table below captures the reported and documented behavior across the versions a service engineer is likely to encounter.

TIA Portal S7-1200 FW S7-1500 FW RESET_TIMER availability Notes
V13.1 SP1 4.0 - 4.2 1.7 - 1.8 (not on S7-1200) Yes Originally reported environment. Help example ambiguous. Multi-instance and ET read rules apply.
V14 SP1 4.2 - 4.4 2.0 - 2.1 Yes Same semantics. Long-time data type LTime added for IEC_LTIMER.
V15.1 / V16 4.4 2.6 - 2.8 Yes Help text revised. RESET_TIMER still level-triggered. ET rule unchanged.
V17 / V18 4.5 - 4.6 2.9 - 3.0 Yes Compiler stricter on global DB / multi-instance collisions.
V19 / V20 4.6 - 4.7 3.0+ Yes Help cloud version clarifies structure components. Behavior identical.

The current Siemens documentation for V20 confirms the same instruction definition: RESET_TIMER: Reset timer (S7-1200, S7-1500) - TIA Portal Help.

10. Common Failure Modes and Diagnostic Matrix

Symptom Likely cause Diagnostic action Corrective action
Timer never advances; ET = T#0ms. Unconditional RESET_TIMER at top of FB. Search the FB for RESET_TIMER outside any IF. Wrap the call in IF reset THEN ... END_IF;.
Timer never advances; reset call is inside an IF. Time base not evaluated. No read of ET/Q in the active branch. Add a temporary watch entry for timer.ET. Read ET into a local variable in the same IF.
Timer counts in PLCSIM but not on physical CPU. PLCSIM forces a tick; physical CPU does not, because ET is never read in OB1. Add the FB call to OB1 and ensure ET is referenced. Reference ET or Q in the production code path.
Compiler warning "Instance DB is already used". Global DB shadows the multi-instance name. Project tree search for the timer symbol. Rename the local timer; remove the global DB.
Reset on a momentary pushbutton has no effect. Pushbutton is sampled for less than one OB1 scan. Wire a R_TRIG instance to extend the pulse. Use the edge-triggered pattern shown in section 6.1.
Retentive TONR loses accumulated time on reset. By design: RESET_TIMER clears the entire timer structure including the retentive accumulator. Verify against the IEC 61131-3 table for TONR. Use a separate flag if you need to retain ET across resets.
Timer advances by 10 ms per OB1 on PLCSIM, but by 1 ms on the physical CPU. PLCSIM clock granularity differs from the hardware OB1 period. Check the CPU's OB1 properties. Use the actual CPU's OB1 period for tolerance calculations.

11. Field-Proven Best Practices

  • Always gate RESET_TIMER. Treat the instruction as a side effect. Wrap it in IF or call it from a one-shot to avoid per-scan clearing.
  • Prefer multi-instance timers. Declare IEC timers as static VAR in FBs. Avoid global timer DBs unless there is a documented reason (for example, exchange with HMI tags).
  • Read ET once per scan. A single assignment to a local TIME variable forces the runtime tick for the entire block.
  • Use a watchdog. For long-duration timers (greater than T#24d), migrate to IEC_LTIMER / LTime types available on S7-1500 from FW 2.0 onward.
  • Validate in PLCSIM, then in HMI. PLCSIM does not detect all time-base issues. Verify the timer values from an HMI tag list or a watch table attached to the production CPU.
  • Document the reset source. In a regulated environment, write the reset input source (operator button, fault routine, mode switch) as a comment above the RESET_TIMER call to support SAT traceability.
  • Combine with R_TRIG for hand-operated resets. Operator pushbuttons rarely produce pulses longer than the OB1 period; an edge flag guarantees the reset fires exactly once per press.
  • Cross-check against the help example. Treat any in-software help that omits the conditional placement of RESET_TIMER as illustrative rather than executable. Always test in PLCSIM before downloading to the line.

Why does my IEC timer never advance even though I call TON_TIME(IN := TRUE)?

The S7-1200/S7-1500 runtime only ticks an IEC timer when one of its output components (typically ET or Q) is read inside the active OB scan. Add an assignment such as elapsed := TON_TIME.ET; in the same branch that sets IN to force a tick. If you also call RESET_TIMER(TON_TIME) unconditionally, the timer is cleared before the tick commits.

Is RESET_TIMER edge-triggered or level-triggered?

Level-triggered. The instruction clears the timer on every scan in which the call is executed. Place the call inside an IF structure (for a held reset) or behind a rising-edge flag (for a one-shot reset).

Does RESET_TIMER work on TONR and clear the accumulated time?

Yes. RESET_TIMER clears the entire timer structure, including the retentive accumulator of TONR. If you need to keep the elapsed-time history, do not use RESET_TIMER; gate IN with the start condition instead.

Why does the help example work for one engineer and not another?

Symbol resolution. If the project also contains a global DB with the same name as the timer (for example TIMER or TIMER_DB), RESET_TIMER and TON_TIME.Q may resolve to different instances. Rename the local timer to a unique identifier and remove any shadowing global DB.

Does the TIA Portal V20 help change the recommended placement of RESET_TIMER?

No. The current Siemens documentation for V20 still describes RESET_TIMER as a level-triggered instruction that resets an IEC timer to zero along with its structure components. The placement rules and the requirement to read ET/Q on S7-1200/S7-1500 are unchanged.

Back to blog