Timers

Timers

Four blocks: a delay on, a delay off, a fixed pulse, and a blinker. Between them they cover almost everything a machine needs from time.

All of them measure real milliseconds, not cycles, and all of them report progress on a second output so you can show it on a screen.


TON — on-delay

Q switches on once IN has been held continuously for PT ms.

Pin Type Meaning
IN input, bool the condition being timed
PT parameter, ms (1000) how long it must hold
Q output, bool TRUE once IN has held for PT
ET output, number elapsed time so far, ms

The word that does the work is continuously. Any drop of IN, however brief, puts ET back to zero and the wait starts again.

What it is for: ignoring things that are not real yet. A door switch that rattles, a pressure that dips for an instant, an operator leaning on a button. TON is how you say "only if it is still true half a second later".

door_open ──[TON PT=2000]── Q ──> alarm_door

The alarm fires when the door has been open two seconds, not when somebody walks through.

ET is worth showing

Bind ET to a tag and put a bar on the screen. An operator waiting for a delay with no feedback assumes the machine is broken; the same operator watching a bar fill waits patiently.


TOF — off-delay

Q stays on for another PT ms after IN drops.

Pin Type Meaning
IN input, bool the condition
PT parameter, ms (1000) how long Q holds after IN drops
Q output, bool TRUE while IN is TRUE, and PT ms longer
ET output, number how long since IN dropped, ms

Q switches on immediately with IN. Only the switching off is delayed.

What it is for: run-on. A fan that keeps going after the heater stops. A lamp that stays lit a moment after the last motion. A conveyor that finishes carrying what is already on it.

heater_on ──[TOF PT=30000]── Q ──> fan

The fan runs while the heater does, and half a minute after it — no extra logic, no timer you have to reset.


TP — pulse

A rising edge of IN fires Q for exactly PT ms.

Pin Type Meaning
IN input, bool trigger (rising edge)
PT parameter, ms (1000) pulse length
Q output, bool TRUE for PT ms after the trigger
ET output, number time into the pulse, ms

The pulse is non-retriggerable: while it is running, further rising edges of IN are ignored. It also does not care what IN does afterwards — once started, the pulse runs its full length even if IN drops immediately.

What it is for: a fixed dose of something. A puff of air, a squirt of lubricant, a horn before a start, a solenoid that must not be energised longer than it can take.

start_button ──[TP PT=500]── Q ──> horn

Half a second of horn, whether the operator taps the button or leans on it.

Non-retriggerable matters

If you want a pulse that restarts on every edge, TP is the wrong block — use a rising edge into a TON reset, or hold the trigger in an RS latch that the pulse clears.


While RUN is TRUE, Q alternates T_ON ms on and T_OFF ms off.

Pin Type Meaning
RUN input, bool while TRUE, the block blinks
T_ON parameter, ms (500) how long Q stays on
T_OFF parameter, ms (500) how long Q stays off
Q output, bool the blinking signal
REM output, number time left in the current phase, ms

The two times are separate, which is more useful than it first looks: a short on-time in a long off-time reads as a discreet heartbeat, the reverse reads as an urgent alarm, and equal times read as a plain flash.

What it is for: telling a person something without words. A flashing lamp for an unacknowledged alarm, a slow pulse to show the program is alive, a fast one for "do not touch, it is about to move".

fault_unacked ──[BLINK T_ON=200 T_OFF=200]── Q ──> beacon
running       ──[BLINK T_ON=100 T_OFF=1900]── Q ──> heartbeat_led

A heartbeat is the cheapest diagnostic you will ever build

One BLINK on a spare output, and anyone standing at the machine can see whether the program is running — before opening a laptop.

REM counts down through the current phase. It is there when you need to synchronise something with the blink rather than just watch it.


Choosing between them

You want Block
ignore a signal until it has held TON
keep something running after the reason stopped TOF
a fixed dose, regardless of how long the trigger lasts TP
something that flashes BLINK

The trap worth knowing

Never build a timer by counting cycles. n := n + 1; IF n > 100 THEN looks like it waits a second and does — until the WiFi stack gets busy, the cycle stretches, and your second becomes 1.4. Every block here uses a monotonic millisecond clock and is immune to that.

The same applies to your own ST blocks: take a timestamp, compare timestamps.

Tags