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.
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:
- 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.
- The
RESET_TIMERcall sits unconditionally at the top of the FB, so it re-arms the timer to zero every scan beforeTON_TIMEcan 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.
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:
- Level-triggered: every evaluation of the instruction line clears the timer.
-
No return value: unlike
TP/TONFBs, the call does not produce a Boolean result. - 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:
- Local declarations of the enclosing FB.
- Static (multi-instance) declarations of the enclosing FB.
- 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:
- Line (1) clears
ETto zero and clears the internal accumulator. The instruction is unconditional. - Line (2) reads
Q. BecauseQwas just cleared, it readsFALSEfor this scan. - Line (3) starts the timer with
IN := TRUEand 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.
elapsedanddoneare read inside the sameIFblock that setsIN, guaranteeing one tick per scan. -
Conditional reset.
RESET_TIMERonly runs whileresetis high, removing the per-scan clearing that froze the timer in the original example. -
Explicit
IN := FALSEbefore the reset call, so that any pulse-drivenresetinput 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.
-
Audit timer declarations. Open the FB in the project tree. Confirm that every IEC timer is declared as a
TP/TON/TOF/TONRstatic variable. Delete any global DB that shadows the same name. -
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. -
Wrap the reset. Move every
RESET_TIMER(...)call inside anIFstructure that evaluatesFALSEunder normal operation. Use a one-shot if you need edge behavior. -
Force the time-base read. Inside the same
IFthat drivesIN, assigntimer.ETandtimer.Qto local variables. This forces a runtime tick. - Rebuild and download. Right-click the device and select Compile > Software (rebuild all blocks). Then download to PLCSIM or the target CPU.
- 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.
-
Create the FB and OB1. Add
FB_TimerResetto OB1 as a single-instance call:inst_TimerReset(start := I0.0, reset := I0.1);. -
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 inputsI0.0,I0.1. -
Run PLCSIM. Start the simulation, click RUN, and confirm the CPU is in
RUN. -
Set
I0.0 = TRUE.ETshould advance in 10 ms increments on a 100 ms OB1. After 2 s,Qshould latchTRUE. -
Pulse
I0.1. WithI0.0still TRUE, toggleI0.1for one scan.ETmust drop toT#0msandQmust return toFALSE. On the next scan the timer should start counting again. -
Hold
I0.1 = TRUEwithI0.0 = TRUE.ETmust remainT#0msfor as long asresetis high, proving the level-triggered behavior. ReleasingI0.1must restore counting within two seconds. - Document the result. Capture the watch table screenshot as part of the SAT/FAT package.
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 inIFor call it from a one-shot to avoid per-scan clearing. -
Prefer multi-instance timers. Declare IEC timers as static
VARin FBs. Avoid global timer DBs unless there is a documented reason (for example, exchange with HMI tags). -
Read
ETonce per scan. A single assignment to a localTIMEvariable forces the runtime tick for the entire block. -
Use a watchdog. For long-duration timers (greater than
T#24d), migrate toIEC_LTIMER/LTimetypes 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
resetinput source (operator button, fault routine, mode switch) as a comment above theRESET_TIMERcall to support SAT traceability. -
Combine with
R_TRIGfor 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_TIMERas 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.