siemens s7-1200

tia portal

plc timers

S7-1200 Timers in TIA Portal: TON, TOF and TONR

‌
Flat vector diagram of S7-1200 TON TOF and TONR IEC timer function blocks connected to a PLC CPU icon

S7-1200 timers trip people up in a specific way: the hardware is familiar, but the IEC timer model is meaningfully different from the old S5 timers or even from Rockwell TON blocks. If you have come from a Logix or older SIMATIC background, the instance DB requirement alone can catch you off guard. This post walks through TON, TOF and TONR on the S7-1200, with real TIA Portal configuration details, ladder and Structured Text examples, and the mistakes that actually happen on first commissioning.

What Are S7-1200 Timers?

S7-1200 timers are IEC 61131-3 compliant function blocks built into TIA Portal. Each timer instance (TON, TOF or TONR) stores its own state in a dedicated block of memory called an instance data block. The three timer types share the same pin set: an IN boolean input, a PT time preset, a Q boolean output and an ET elapsed-time output. What changes between them is the trigger logic that drives Q.

TON, TOF and TONR: What Each One Actually Does

TimerQ goes TRUE when...Q resets when...ET resets when...
TON (on-delay)IN has been TRUE for >= PTIN goes FALSEIN goes FALSE
TOF (off-delay)IN goes TRUE (immediately)IN goes FALSE AND elapsed >= PTIN goes TRUE again
TONR (accumulating)accumulated time >= PTR input goes TRUER input goes TRUE
IEC timer behaviour summary for the S7-1200

TON is the timer you will use 80% of the time: start delay, debounce, minimum run time. TOF is the go-to for anything that needs to run on after its trigger disappears, such as a cooling fan that keeps spinning for 30 seconds after the motor stops. TONR is the accumulating timer, and it is genuinely useful when you need to track run hours or measure total cycle time across multiple short bursts. I covered the broader differences between these three in TON, TOF and TONR Timers: What Actually Differs, so check that post if you want the concept-level comparison. Here we stay focused on how to actually configure them on the S7-1200.

Instance DBs: Why Every Timer Needs Its Own Memory

This is the single concept that separates S7-1200 timers from what most people learned first. On older Siemens hardware you had T1, T2... T255 as shared timer registers. On the S7-1200, every TON, TOF or TONR is a function block instance. That means it needs its own memory structure to hold IN, Q, ET and PT between scans.

TIA Portal handles this automatically in two ways depending on where you place the timer:

  • In an OB (organisation block): TIA Portal creates a single-instance DB automatically when you compile. You assign it a name like Conveyor_StartDelay and TIA Portal generates Conveyor_StartDelay_DB in the background.
  • Inside an FB (function block): Declare the timer as a static variable in the FB interface with type TON, TOF or TONR. The timer data lives inside the calling FB's own instance DB. No separate DB is created. This is the cleaner approach for reusable code.

Understanding this also explains why you cannot just copy a rung with a timer and expect it to work independently. The copy references the same instance DB unless you explicitly assign a new one. That is a real source of bugs when engineers paste rungs and forget to rename the timer instance. If you want to understand the DB types in depth, the TIA Portal Data Blocks post and the S7-1200 Data Blocks: Global vs Instance DB guide cover exactly that.

Preset Syntax: T# Literals and HMI-Adjustable Presets

The PT input expects a value of type TIME. The most common approach is a T# literal directly on the block pin. Examples:

  • T#5s = 5 seconds
  • T#500ms = 500 milliseconds
  • T#2m30s = 2 minutes 30 seconds
  • T#1h = 1 hour

If the operator needs to adjust the preset from an HMI, declare a TIME-type tag in a global DB (for example GDB_Params.ConveyorStartDelay of type TIME) and wire that tag to the PT pin instead of a literal. Then link the same tag to an HMI numeric input. Make sure your HMI tag mapping is correct before you go live, because a TIME tag linked to the wrong address will silently write a nonsense preset. The HMI Tag Linking post has good detail on getting that mapping right.

Do not connect a DINT or INT tag to the PT pin even if the numeric value looks correct. TIA Portal may allow the connection with an implicit conversion, but the units will be wrong. TIME on the S7-1200 is milliseconds as a signed 32-bit integer. A DINT value of 5000 fed directly as TIME equals 5 seconds, which may seem fine until someone enters 30 (meaning 30 seconds) and the timer runs for 30 milliseconds instead.

TON Timer in Ladder: Conveyor Start Delay

Here is a typical TON application: a conveyor motor must not start until a guard door has been closed and confirmed for at least 2 seconds. This prevents chattering contacts from triggering a start.

S7-1200 TON: 2-Second Guard Door Confirm Before Conveyor Start. Ladder logic (4 rungs): Rung 0: examine if Guard_DoorClosed is on (XIC), then examine if Sys_Ready is on (XIC), then TON on Door_Confirm. Rung 1: examine if Door_Confirm.Q is on (XIC), then examine if Estop_Active is off (XIO), then energize output Conveyor_StartEnable (OTE). Rung 2: examine if Conveyor_StartEnable is on (XIC), then examine if HMI_StartCmd is on (XIC), then latch output Conveyor_Run (OTL). Rung 3: examine if HMI_StopCmd is on (XIC), then unlatch output Conveyor_Run (OTU). Guard_DoorClosed and Sys_Ready both must be true for 2 continuous seconds before Door_Confirm.Q energises. Any door open resets ET to zero immediately. Conveyor_StartEnable gates the HMI start button, and an OTL/OTU latch holds the run state.

S7-1200 TON: 2-Second Guard Door Confirm Before Conveyor StartLadder logic
Toggle inputs
Rung 0
Ladder logic rung: examine if Guard_DoorClosed is on (XIC), then examine if Sys_Ready is on (XIC), then TON on Door_Confirm examine if Guard_DoorClosed is on (XIC), then examine if Sys_Ready is on (XIC), then TON on Door_Confirm XIC Guard_DoorClosed Guard_DoorClosed Guard_DoorClosed XIC Sys_Ready Sys_Ready Sys_Ready TON Door_Confirm T#2s 0 TONTimerDoor_ConfirmDoor_ConfirmPresetT#2sT#2sAccum00
Rung 1
Ladder logic rung: examine if Door_Confirm.Q is on (XIC), then examine if Estop_Active is off (XIO), then energize output Conveyor_StartEnable (OTE) examine if Door_Confirm.Q is on (XIC), then examine if Estop_Active is off (XIO), then energize output Conveyor_StartEnable (OTE) XIC Door_Confirm.Q Door_Confirm.Q Door_Confirm.Q XIO Estop_Active Estop_Active Estop_Active OTE Conveyor_StartEnable Conveyor_StartEnable Conveyor_StartEnable
Rung 2
Ladder logic rung: examine if Conveyor_StartEnable is on (XIC), then examine if HMI_StartCmd is on (XIC), then latch output Conveyor_Run (OTL) examine if Conveyor_StartEnable is on (XIC), then examine if HMI_StartCmd is on (XIC), then latch output Conveyor_Run (OTL) XIC Conveyor_StartEnable Conveyor_StartEnable Conveyor_StartEnable XIC HMI_StartCmd HMI_StartCmd HMI_StartCmd OTL Conveyor_Run Conveyor_Run Conveyor_Run L
Rung 3
Ladder logic rung: examine if HMI_StopCmd is on (XIC), then unlatch output Conveyor_Run (OTU) examine if HMI_StopCmd is on (XIC), then unlatch output Conveyor_Run (OTU) XIC HMI_StopCmd HMI_StopCmd HMI_StopCmd OTU Conveyor_Run Conveyor_Run Conveyor_Run U
energizedTip: click a contact in the diagram to flip its bit.
Guard_DoorClosed and Sys_Ready both must be true for 2 continuous seconds before Door_Confirm.Q energises. Any door open resets ET to zero immediately. Conveyor_StartEnable gates the HMI start button, and an OTL/OTU latch holds the run state.

In TIA Portal ladder, the TON block appears as a box with IN, PT, Q and ET pins visible on the rung. You assign the instance name (Door_Confirm) in the block header. TIA Portal will prompt you to create the instance DB on first compile.

TOF Timer in Structured Text: Fan Purge After Motor Stop

TOF is easier to show in ST because the logic is concise. This example runs a panel extraction fan for 45 seconds after the main motor stops, a common requirement on motor control panels to clear heat.

FB_MotorCooling.st
// Static variable declared in FB interface:
// Purge_Timer : TOF;

// Network 1 - TOF fan purge
Purge_Timer(IN := Motor_Running,
            PT := T#45s);

Fan_Output := Purge_Timer.Q;

// Network 2 - Elapsed time to HMI
HMI_FanPurgeET := Purge_Timer.ET;

When Motor_Running is true, Purge_Timer.Q is immediately true and the fan runs. When Motor_Running drops false, the timer starts counting. After 45 seconds Q drops false and the fan stops. ET counts up during the purge so the HMI can show remaining purge time (you would calculate T#45s - ET for a countdown display). This is a much cleaner pattern than trying to do it with a TON and extra latching logic.

TONR: Accumulating Run Time Across Multiple Starts

TONR is the timer most engineers forget exists until they actually need it. I used it on a press application where a maintenance alarm needed to fire after the press had accumulated 8 hours of actual cycle time, not calendar time. The press ran for short bursts all day with long idle periods between them. A TON would reset every time the press stopped. TONR held the elapsed time across every stop.

FB_PressMaintenance.st
// Static variables in FB interface:
// RunAccum : TONR;
// Maint_Due : BOOL;

// Network 1 - Accumulate press cycle time
RunAccum(IN := Press_Cycling,
         R  := HMI_MaintReset,
         PT := T#8h);

// Network 2 - Latch maintenance alarm
IF RunAccum.Q AND NOT Maint_Due THEN
    Maint_Due := TRUE;
END_IF;

IF HMI_MaintReset AND NOT Press_Cycling THEN
    Maint_Due := FALSE;
END_IF;

HMI_AccumTime := RunAccum.ET;

The R input on TONR is the only way to reset ET. Setting IN false does nothing to ET. That is the defining characteristic of TONR and the part that people get wrong when they try to reset it by just dropping the IN signal.

Common Mistakes on S7-1200 Timer Commissioning

  • Duplicate instance names: Copying a rung in ladder and not renaming the timer instance. Both rungs now share one DB, so one timer controls both outputs. TIA Portal does not always warn you clearly about this.
  • Wrong time base assumption: Engineers from Rockwell backgrounds sometimes assume the preset is in seconds. On the S7-1200, T#5 without a unit suffix is not valid. You must always include the unit: T#5s, T#500ms, etc.
  • Forgetting to initialise ET on HMI: Linking ET to an HMI display without accounting for the TIME format. ET is a signed 32-bit millisecond value. If your HMI expects seconds, you need a conversion or a scaling tag.
  • TONR reset logic missing: Using TONR for accumulation but never wiring the R input, so the timer can never be reset. ET climbs to PT, Q latches true and stays there forever.
  • Timer inside an OB with a reused name: Placing a timer in OB1 with a generic name like Timer1 across multiple projects. When the project is merged or a library block is reused, name collisions cause compilation errors that take time to untangle.
Flat vector diagram illustrating correct and duplicate S7-1200 TON timer instance naming in TIA Portal OB1
Giving two TON blocks the same instance name is one of the most common S7-1200 timer bugs. Each timer needs a unique instance DB.

Reading ET on the HMI and in Online Monitoring

TIA Portal's online monitoring shows ET as a TIME value (for example T#1s_350ms). That is fine for debugging, but HMI displays usually need it as a number. The cleanest approach is to create an INT or REAL tag in the same instance DB and calculate the display value in the PLC: HMI_RemainingMs := TIME_TO_DINT(PT) - TIME_TO_DINT(ET). The PLC Troubleshooting with Online Monitoring post covers how to watch timer values live in TIA Portal, which is a fast way to verify your preset and elapsed time are behaving as expected.

For S7-1200 analog inputs feeding a process where you need to compare elapsed time against a measured value, keep the time arithmetic in the PLC and pass only display-ready integers to the HMI. It keeps the HMI screen logic simple and avoids type mismatch errors in the HMI tag configuration.

Timers in Reusable FB Libraries

If you are building a reusable FB for a machine type (say, a standard conveyor drive FB), declare your timers as static variables in the FB's own interface rather than creating global instance DBs. When the FB is called multiple times (one per conveyor axis), each call gets its own instance DB automatically. This is exactly the pattern described in S7-1200 Data Blocks: Global vs Instance DB Explained. For Structured Text in TIA Portal, the ST syntax for calling the timer inside the FB is identical to the examples above.

This approach also makes the code portable across projects. Drop the FB into a new project, call it with a new instance DB name, and every timer inside resets cleanly with no DB naming conflicts. It is a much better practice than scattering global timer DBs across a project tree.

If you are writing your first S7-1200 program and want a step-by-step starting point before tackling timers, the S7-1200 First Program in TIA Portal guide walks you through project creation, CPU configuration and your first OB1 rung, which is the right foundation before adding timer logic.

Keep Learning

Now that you have TON, TOF and TONR working on the S7-1200, the natural next step is understanding how to structure bigger programs using function blocks and data blocks. The TIA Portal Data Blocks: DB Types and When to Use Each post explains when to reach for a global DB versus an instance DB, and Structured Text in TIA Portal: A Practical Guide shows how to write the same timer logic in ST if you prefer that over ladder. If you want to practice timer logic in a full machine sequence, try working through the PLC Bottle Filling Machine project, which uses multiple timers in a realistic fill-and-count application.

Related Blogs