Problem Description
A TON (Timer On-Delay) instance on a Siemens SIMATIC S7-300, S7-400, S7-1200, or S7-1500 CPU fails to accumulate time. The instance is correctly declared in the program editor, the block compiles without errors, the CPU is in RUN with no diagnostic buffer entries, and the logical condition upstream of the timer block reads TRUE when observed through a VAT (Variable Table) or watch table. Despite this, the timer's elapsed-time tag ET remains at 0 ms, the output Q never asserts, and the timer appears "frozen" in the active program window. The same program may compile and download successfully, but the timer does not function as expected at runtime.
This symptom pattern is one of the most frequently reported timer problems on Siemens S7 controllers, and it has several distinct root causes that all present with the same external symptom: a TON that never starts. The good news is that every variant is deterministic, and the diagnostic path is short once the cause is identified.
Root Cause Matrix
| Observed Symptom | Likely Cause | First Check | Field Fix |
|---|---|---|---|
| ET stays at 0, IN confirmed TRUE | Instance DB start values corrupted (IN initial = TRUE, ET non-zero, or PT non-zero) | TIA Portal / STEP 7 → DB editor → "Start values" view | Reset start values: IN=FALSE, ET=T#0ms, PT=required preset, Q=FALSE |
| ET stays at 0, IN confirmed FALSE | Upstream logic is not actually TRUE; floating contact, inverted contact, or wrong tag reference | Force IN=TRUE in the VAT; if timer then runs, fix the upstream rung | Repair upstream logic; verify tag addresses and contact types (NO vs NC) |
| ET increments briefly then resets every cycle | Same timer instance called in two networks, or M-flag feedback loop | Cross-reference (Ctrl+Shift+F in TIA) on the instance DB / IEC timer | Declare a unique instance DB or multi-instance for each TON |
| ET counts correctly but Q never asserts | Output Q is overwritten downstream, or M-flag used for both IN and Q | Watch Q directly; cross-check the destination of Q | Use a distinct memory bit for the Q destination |
| Timer appears to "miss" the first scan | Input read with :P immediate access; I/O sampled inconsistently with scan | Search for the :P suffix on the input operand | Remove :P; use process-image access for the timer input |
| Timer runs once after download, then stops on next STOP→RUN | Instance DB initialized from a snapshot with IN=TRUE start value | DB editor → "Start value" column for IN | Reset start values; re-download block with "Initialize instance DB" |
TON Timing Reference and the IEC Timer Family
The IEC 61131-3 TON (Timer On-Delay) accumulates time while its IN input is TRUE. When the accumulated elapsed time ET reaches the preset time PT, output Q is set to TRUE. If IN drops to FALSE before ET reaches PT, the timer resets: ET returns to 0 and Q returns to FALSE on the same cycle. The timer does not latch; the next TRUE pulse on IN starts a fresh cycle.
The S7-1200/1500 IEC timer family in TIA Portal (folder: Timers → IEC Timers) exposes four blocks with identical interface layout (IN, PT, Q, ET):
- TP — Pulse timer. Q is set on the rising edge of IN for a duration of PT, regardless of IN duration.
- TON — On-delay timer. Q asserts PT time after IN goes TRUE. Resets immediately on IN falling edge.
- TOF — Off-delay timer. Q asserts on IN rising edge, holds for PT after IN falling edge.
- TONR — Retentive on-delay timer. Accumulates across IN=FALSE; reset by an explicit R (reset) input.
The legacy S5-style timers (S_PULSE, S_PEXT, S_ODT, S_ODTS, S_OFFDT) on S7-300/400 use a different interface: S (start), TV (time value), R (reset), Q (output), BI/BCD (current time). Mixing the two interfaces — for example, driving an S_ODT with an IN-only contact — silently produces a non-starting timer. Always confirm the timer variant in the project before debugging.
Why the Scan Cycle Is Not the Cause
A common misconception is that the PLC scan cycle "resets" the timer every cycle. This is incorrect. A TON instruction is implemented as a multi-instance block whose state is persisted in the instance data block. The state tags — IN, ET, PT, Q, and internal start/stop flags — are updated at the end of every cycle. As long as IN is TRUE, the timer's internal tick counter accumulates the elapsed scan time, and ET increments across cycles at the real-time clock rate.
If ET does not increment, the cause is upstream of the timer (IN is not actually TRUE), in the instance data (start values are wrong), or in the timer's access path (:P modifier or feedback loop). It is never the scan architecture. A quick proof: force a memory bit TRUE in the VAT and wire it to the TON IN. If the timer counts correctly, the original IN signal is the problem, not the timer block. This is the single fastest way to localize the fault.
Root Causes in Detail
1. Timer Instance Used Twice
Each IEC TON must be backed by a single, unique instance data block or by a unique multi-instance variable inside a parent FB. Calling the same instance in two networks — for example, "MyTimer".TON_1 in Network 1 and again in Network 5 — produces undefined behavior. The first network writes ET and Q based on the current IN; the second network reads the same tags in the same scan and may overwrite them with a different IN state. The visible effect is that ET appears to count, then snap back, or never accumulate at all.
Detection: open the cross-reference (Ctrl+Shift+F in TIA Portal, or Options → Reference Data → Display in STEP 7 V5.x) on the timer instance and check the number of usage locations. Anything other than a single network is a violation.
Fix: declare a fresh instance DB or add a new multi-instance variable for each independent timer. In S7-1200/1500, prefer multi-instance FBs:
FUNCTION_BLOCK "FB_Conveyor"
VAR
StartDelay : TON_TIME; // multi-instance 1
PulseTimer : TP_TIME; // multi-instance 2
END_VAR
BEGIN
StartDelay(IN := "M_StartCmd", PT := T#3s);
PulseTimer(IN := StartDelay.Q, PT := T#500ms);
"M_RunCmd" := StartDelay.Q;
"M_Blink" := PulseTimer.Q;
END_FUNCTION_BLOCK
2. Instance DB Start Values Corrupted
The instance DB stores the timer state across scans. The Start value column in the DB editor defines what each tag contains immediately after a STOP→RUN transition or a cold restart, before the first execution of the timer block. For a correctly initialized TON, the start values must be:
- IN = FALSE (0)
- ET = T#0ms
- PT = the required preset (e.g., T#5s)
- Q = FALSE (0)
- Internal flags (Running, ST, RT): 0
If a snapshot was loaded, if the DB was edited online and the modified values were committed, or if the DB was generated from a wrong source, these start values may be wrong. The most damaging case is IN=TRUE as a start value. With IN=TRUE on the first scan, the timer never sees a FALSE→TRUE edge. On S7-1200/1500, the timer counts immediately (no edge required at start-up); on S7-300/400 with the legacy S_ODT, behavior is platform-dependent and the timer may appear dead. In both cases, the corrupted start value is the root cause, not the user's logic.
Repair (TIA Portal):
- Open the project tree → PLC → Program blocks → [Your DB].
- Switch the DB editor to the Start values column (the small icon to the right of the data view toggle).
- Set IN = FALSE, ET = T#0ms, Q = FALSE. PT is the required preset; leave as designed.
- Right-click the DB → Compile → Software (rebuild all).
- Download to the CPU with Download to device → Download with options → tick Initialize instance data blocks, or use Reset to factory settings on the instance DB only.
Repair (STEP 7 V5.x): in SIMATIC Manager, open the instance DB, switch to Data View, reset the Initial Value column for the timer tags, save, compile, and re-download with Initialize enabled. Refer to the Siemens Industry Online Support portal for the IEC timer entry under SIMATIC S7-300/400 documentation.
3. IN Input Never Transitions FALSE→TRUE
The IEC TON begins a new timing cycle when IN transitions from FALSE to TRUE. If IN is already TRUE at first scan, the behavior depends on the platform and on the timer variant used:
- S7-1200/1500 (TIA Portal): the TON starts counting immediately on the first scan if IN=TRUE. Q asserts after PT, without requiring a falling edge first. This is a level-triggered start-up.
- S7-300/400 with legacy S_ODT: the timer needs a positive edge on the S (start) input. If the input is TRUE on the first scan, the timer may not start.
- S7-300/400 with IEC TON (FB "IEC_Timer_0_32"): behaves like S7-1200/1500 — counts immediately if IN=TRUE at first scan.
If the application requires an edge-triggered start regardless of the initial IN state, condition the input with a rising-edge detector (RE_TRIG, or a manual edge: "M_Edge" := "Input" AND NOT "Input_Old").
4. Immediate I/O Access (:P)
Accessing physical I/O with the :P suffix reads the module register directly, bypassing the process image. This is useful in OB40 interrupt contexts or for diagnostic reads, but it is a frequent cause of timer problems when used carelessly in OB1. Two issues appear in practice:
- If the input that triggers the timer is read with
:Pinside a network that the timer block also reads, the input value seen by the timer may differ from the value held in the process image. If a different network writes the same input with normal access, the two reads can disagree within one cycle. - If the timer's output Q is wired to a physical output with
:P, the output writes directly to the module, and depending on the wiring, the next cycle's input read sees the same module state, breaking the timer's edge detection.
For normal cyclic OB1 logic, always use process-image I/O access. Reserve :P for OB40 interrupt OBs or for diagnostic reads where the current hardware state, not the cycle-latched image, is required.
5. M-Tag Feedback Loop
Wiring the same memory bit (for example, %M10.0) as the IN input to the timer and as the destination of the timer's Q output creates a feedback loop. Within a single cycle, the timer reads IN as the current value of M10.0 (still FALSE at the moment the timer block is evaluated), then Q is set or cleared, and the M10.0 assignment overwrites the value the timer just read. From the timer's perspective, IN never goes TRUE within the same scan, and the timer does not start.
Detection: scan the program for the timer's IN tag and the timer's Q destination. If they are the same operand, split them into two distinct memory bits. The same hazard exists for any case where the timer's Q is wired to a tag that the timer's IN upstream logic also reads.
6. Snapshot-Loaded Instance DB
A common workflow mistake is downloading a project, then loading a "snapshot" or "project backup" of the instance DB on top of the live one. The snapshot preserves the runtime values at the time it was taken, not the initial values. If the snapshot was captured while the timer was running, ET may be non-zero, Q may be TRUE, and IN may be TRUE. When the project is downloaded to a fresh CPU or after a memory reset, the start values are taken from the snapshot, and the timer starts in a mid-cycle state. The next STOP→RUN cycle does not reset these start values, and the timer appears to be stuck.
Fix: never download instance DBs from a snapshot to initialize a fresh CPU. Always download the project from the engineering station, and let the PLC perform its own DB initialization on STOP→RUN. If a snapshot download is required for any reason, follow it with a manual reset of the start values in the DB editor.
Diagnostic Procedure
Use the following ordered checklist to localize the fault in under five minutes. The steps are platform-agnostic and work on STEP 7 V5.x, TIA Portal V16+, and the Web server of recent S7-1200/1500 CPUs.
- Confirm the input is actually TRUE. Open a watch table containing the IN operand, the upstream tag, and the ET and Q tags of the timer. Force a memory bit TRUE and wire it to IN; if the timer then runs, the upstream logic is the fault.
- Confirm the instance DB exists and is unique. In the project tree, the instance DB associated with the timer must be present and not shared with another timer. Cross-reference the instance to confirm a single usage location.
- Check the start values of the instance DB. In the DB editor, switch to the Start values view. IN must be FALSE, ET must be T#0ms, PT must match the design intent, Q must be FALSE. Reset and re-download.
-
Check the timer variant. Confirm the block is
IEC_Timer_0_32,TON_TIME,TP_TIME,TOF_TIME, orTONR_TIMEas appropriate. The legacy S5 timers (S_ODT, S_PULSE, S_ODTS, S_OFFDT) are not edge-equivalent to the IEC TON; they use S (start) and R (reset) inputs, not IN. -
Check the access method on the input. Search the network for the
:Psuffix on the IN operand. If present and the timer is in OB1, remove it. - Check for M-tag feedback. Verify the destination of Q is a different tag from the IN operand.
- Reinitialize the instance DB. In TIA Portal, right-click the DB → Compile → Software (rebuild all) → download with Initialize instance data blocks. In STEP 7 V5.x, use PLC → Download User Program to Memory Card with the Initialize option.
Repairing the Instance DB to Factory Defaults
For a TIA Portal project with a corrupted instance DB, the cleanest fix is to delete the DB, re-compile the project, and re-download. The compiler regenerates the DB with the FB's default start values. This is preferred over manual editing, because manual editing can leave an inconsistent snapshot of the FB interface.
- Select the instance DB in the project tree.
- Right-click → Delete (do not delete the FB itself).
- Right-click the calling block (OB1 or the parent FB) → Compile → Software (rebuild all). The compiler will warn "Instance DB missing" and will regenerate it on download.
- Download to the CPU with Download to device → Software (only changes).
- Perform a STOP→RUN transition. The new instance DB will initialize with IN=FALSE, ET=T#0ms, and the design PT.
For STEP 7 V5.x with a corrupted DB, the equivalent procedure is to open SIMATIC Manager → PLC → Download User Program to Memory Card with the Initialize option selected. This forces a full DB re-initialization on the next STOP→RUN.
For background on the IEC timer block family and start-value semantics, see the S7-1200 system manual (Siemens support entry ID 91696622) and the S7-1500 system manual (entry ID 111007806), both available on the Siemens Industry Online Support portal.
Verification
After applying any of the fixes, perform the following sequence to confirm the timer is functional:
- Place the CPU in RUN.
- Open a watch table with the IN operand, ET, PT, and Q.
- Force IN=TRUE (or trigger the upstream condition that drives IN).
- Confirm that ET begins to increment in real time. On the watch table, ET should count up at the same rate as the system clock. After PT is reached, Q should transition to TRUE.
- Force IN=FALSE. ET should reset to T#0ms immediately; Q should transition to FALSE on the same cycle.
- Force IN=TRUE again. ET should start at 0 and count up to PT, with Q asserting on the cycle in which ET crosses PT.
Record the measured ET and Q transition times against the expected PT. A deviation greater than one OB1 cycle (typically 1–10 ms on S7-1200/1500, 10–100 ms on S7-300/400) indicates a scan time or interrupt contention issue unrelated to the timer itself. Verify the OB1 cycle time in PLC → Properties → Cycle and the OB35 (or other cyclic interrupt) configuration if the timer is driven from a time-of-day interrupt.
Platform Differences: S7-300/400 vs S7-1200/1500
Although the IEC TON behavior is standardized, the deployment and edge handling differ between the legacy and current platforms.
| Aspect | S7-300/400 (STEP 7 V5.x) | S7-1200/1500 (TIA Portal) |
|---|---|---|
| Default timer block | S5-style: S_PULSE, S_PEXT, S_ODT, S_ODTS, S_OFFDT. IEC TON is IEC_Timer_0_32 in the standard library. |
IEC-native: TP, TON, TOF, TONR in the Timers folder. S5-style timers are available as legacy blocks. |
| Edge requirement at first scan | S_ODT requires an edge on S; IEC TON counts immediately if IN=TRUE at first scan. | IEC TON counts immediately if IN=TRUE at first scan. |
| Multi-instance support | Available in FBs; timer declared as static of type IEC_Timer_0_32. |
Available; multi-instance is the recommended pattern. |
| Instance DB naming | Must be unique; DB100, DB101, etc. |
Can be a single-instance DB with optimized access or a multi-instance inside an FB. |
| Online modification of start values | Supported via Monitor/Modify; can corrupt the running timer state. | Supported via Monitor & Force; can corrupt the running state. |
| Reset of start values after edit | Requires explicit re-download with Initialize. | Tracked automatically; the project shows the mismatch in the Compare offline/online view. |
Reference product documentation: SIMATIC S7-1200 and SIMATIC S7-1500 product pages, with full system manuals and programming guides on the Siemens Industry Online Support portal.
Engineering Best Practices
- One instance per logical timer. Never share a timer instance between two networks. Use a multi-instance inside a parent FB for organization and to keep the project tree shallow.
-
Use memory flags for testing. Forcing
%Mbits is safer than forcing physical inputs, and the test is portable across projects. Add a watchdog M-bit that auto-toggles every 5 s in a test rung, and wire it to the timer input during commissioning. -
Avoid
:Paccess in OB1. Process-image access is the default; only depart from it inside OB40 or OB82 where the immediate hardware state is required. - Never use the same M-flag for IN and the Q destination. This is a feedback loop and prevents the timer from ever starting. Apply the rule consistently: IN upstream, Q downstream, two distinct tags.
- Verify start values after every project download that includes DBs. The TIA Portal Compare view (offline/online) will highlight a mismatch between the start values in the project and the values in the live CPU.
- Use the IEC TON, not the legacy S5 timer, for new code. The IEC variant is portable, multi-instance-friendly, and behaves identically across S7-300/400/1200/1500.
- Document the timer in the FB interface. If the timer is part of a function block, declare the multi-instance variable with a meaningful name and a comment that documents the preset time, the trigger condition, and the expected Q action.
- Run the diagnostic VAT before the fix. Capture the current ET, Q, and upstream tag values; apply the fix; re-run the VAT. The diff confirms the fix took effect and documents the change for the maintenance log.
Frequently Asked Questions
Why does my TON start counting on the first cycle after download but not on the next STOP→RUN?
The instance DB start values were probably written with IN=TRUE from a snapshot. Reset the start values of the instance DB (IN=FALSE, ET=T#0ms, Q=FALSE) and re-download. On S7-1200/1500, a TON with IN=TRUE at first scan counts immediately, so the symptom of "starts once" is almost always a start-value issue, not a logic issue.
Can I use the same IEC timer instance in two different networks?
No. Each IEC TON must be backed by a unique instance DB or a unique multi-instance variable. Reusing the same instance causes one network to overwrite the state written by the other, producing non-deterministic ET and Q behavior. Declare a separate instance per logical timer.
Does the scan cycle reset my TON every cycle?
No. The TON state is persisted in the instance DB across cycles, and ET increments by the cycle elapsed time as long as IN=TRUE. If ET never increments, the cause is upstream of the timer (IN is not actually TRUE) or the instance DB start values are wrong, not the scan architecture.
Should I use :P on the input that triggers the timer?
No, not in OB1. Use process-image access. The :P suffix reads the module register directly and can desynchronize the input from the cycle that the timer block uses. Reserve :P for OB40 interrupt logic or for diagnostic reads of the current hardware state.
How do I reinitialize a corrupted instance DB without re-downloading the whole project?
In TIA Portal, right-click the instance DB → Compile → Software (rebuild all) → download with Initialize instance data blocks. In STEP 7 V5.x, use PLC → Download User Program to Memory Card with Initialize enabled. Both force the DB start values to be reloaded on the next STOP→RUN transition.
What is the difference between the legacy S5 timer and the IEC TON?
The legacy S5 timers (S_PULSE, S_PEXT, S_ODT, S_ODTS, S_OFFDT) use S (start), TV (time value), and R (reset) inputs; S_ODT requires an edge on S to begin timing. The IEC TON/TOF/TP/TONR family uses a single IN input and a PT preset, with internal state stored in an instance DB. The IEC variant is portable across S7-300/400/1200/1500 and supports multi-instance use inside FBs.