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 read Q and ET.

  • 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.

SignalTypeMeaning
PRESSURE_LOWBOOLTRUE while the switch reads low pressure.
LOW_ALARMBOOLThe low-pressure alarm.
DIP_LAMPBOOLOn during a dip and for 3 s after it.

The program declares two timer instances:

  • LowDelay, a TON. While its input IN is TRUE, its elapsed time ET counts up, and Q turns on when ET reaches the preset PT. When IN goes FALSE, ET returns to 0 and Q turns off.

  • DipStretch, a TOF. Q turns on with IN, and stays on for PT after IN goes 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

RequirementTimerQ
Act only after a condition has lasted a timeTONTurns on PT after IN turns on
Keep acting for a time after a condition endsTOFTurns 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 Q never turns off.

  • Reading Q before the call: the alarm turns on one scan late, and off one scan late.

  • Picking the off-delay timer for a delayed alarm: a TOF turns Q on 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 := TRUE never clears the alarm. Assign Q directly 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 TIME literals, such as PT := T#2S. This simulator takes the preset as a number of milliseconds.

  • Most controllers measure ET from 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.