Timers and elapsed time in Structured Text
The Core Idea
A timer instance remembers elapsed time as the program calls it across scans. Timer types use that time differently, so a delay before turning on and a delay before turning off are distinct behaviors.
What you will learn
Call an on-delay timer (
TON) and an off-delay timer (TOF), and readQandET.Call every timer instance on every scan, so it sees its input turn off as well as on.
Choose between an on-delay and an off-delay for a requirement.
Why it matters
Counting scans is not the same as measuring elapsed time. A correctly called timer lets you express the required delay in time units.
The problem
A compressed-air header has a low-pressure switch. Short dips are normal when a large tool starts, so the alarm waits: it turns on only when the pressure has been low for 2 s. A dip lamp stays on for 3 s after any dip, so operators notice even a short one.
| Signal | Type | Meaning |
PRESSURE_LOW | BOOL | TRUE while the switch reads low pressure. |
LOW_ALARM | BOOL | The low-pressure alarm. |
DIP_LAMP | BOOL | On during a dip and for 3 s after it. |
The program declares two timer instances:
LowDelay, aTON. While its inputINis TRUE, its elapsed timeETcounts up, andQturns on whenETreaches the presetPT. WhenINgoes FALSE,ETreturns to 0 andQturns off.DipStretch, aTOF.Qturns on withIN, and stays on forPTafterINgoes FALSE.
PT is in milliseconds in this simulator. Both instances appear at the bottom of the Tags list with IN, PT, Q, and ET. The simulator scans every 100 ms.
After you lock in your prediction, switch PRESSURE LOW on for about 1.5 s, off for a moment, then on again for about 1 s. Then leave it off.
See it go wrong
Compare DipStretch in Tags: it is called on every scan, so it follows the switch both ways.
Fix it
Change the program so the alarm needs one continuous dip of 2 s, and clears when the pressure recovers. Hidden checks also try a single short dip on the dip lamp and two long dips in a row. Editing pauses the program, so press Run to try your version.
Passing the checks records Structured Text progress on the shared on-delay timer concept.
What happened and why
A timer instance changes only when it is called, and the call's IN is the only way it learns the input. Inside IF PRESSURE_LOW, every call said IN := TRUE. The timer could not see the recovery, so it behaved like a retentive timer that nobody resets.
Called on every scan with IN := PRESSURE_LOW, the timer sees both edges. In Ladder, an on-delay instruction is on a rung that the controller scans every time, so it always sees its rung condition go FALSE. In Structured Text, an IF around the call can stop that from happening, so keep timer calls out of conditional code.
ET measures time across scans. The program text runs once per scan, and each call of a TON with IN TRUE adds the time since the last scan. Waiting for a timer means checking Q on later scans, never looping until it is done.
On-delay or off-delay
| Requirement | Timer | Q |
| Act only after a condition has lasted a time | TON | Turns on PT after IN turns on |
| Keep acting for a time after a condition ends | TOF | Turns off PT after IN turns off |
Common mistakes
Calling a timer only while its input is TRUE: the timer never resets, so short events add up and
Qnever turns off.Reading
Qbefore the call: the alarm turns on one scan late, and off one scan late.Picking the off-delay timer for a delayed alarm: a
TOFturnsQon at once, then holds it after the pressure recovers. That is the opposite of the requirement.Latching the timer's output:
IF LowDelay.Q THEN LOW_ALARM := TRUEnever clears the alarm. AssignQdirectly unless the specification asks for a latch with a reset.
Platform notes
IEC 61131-3 (the international standard for programmable controller languages) writes presets as
TIMEliterals, such asPT := T#2S. This simulator takes the preset as a number of milliseconds.Most controllers measure
ETfrom a clock, so a timer called twice in one scan does not run twice as fast. Some platforms warn when an instance is called more than once per scan; call each instance once.
Enable JavaScript to run the embedded simulator and complete the interactive exercises.