Timers¶
Timers are IEC function blocks that measure time across PLC cycles. They are not simple functions: they have internal memory, and that memory is updated when the timer is called.
IEC Timer Types¶
The common IEC timers are:
| Timer | Name | Typical use |
|---|---|---|
TON |
On-delay timer | Start something only after a condition has been true for a configured time. |
TOF |
Off-delay timer | Keep something active for a configured time after the input becomes false. |
TP |
Pulse timer | Generate a pulse of a configured duration from a trigger. |
In TIA Portal, these timers are usually called like function blocks. Their instance memory can be declared as a static variable inside an FB.
VAR
_tonStartDelay : TON;
_xboStartDelayDone : Bool;
END_VAR
BEGIN
_tonStartDelay(
IN := xboStartRequest,
PT := T#2s
);
_xboStartDelayDone := _tonStartDelay.Q;
END_FUNCTION_BLOCK
TON¶
TON switches Q to true only after IN has been true for PT.
_tonAlarmDelay(
IN := xboAlarmCondition,
PT := T#500ms
);
xboAlarmActive := _tonAlarmDelay.Q;
Use TON for delayed alarms, startup delays, debounce logic, and minimum stable conditions.
TOF¶
TOF keeps Q true for PT after IN becomes false.
_tofFanRunOn(
IN := xboCoolingRequired,
PT := T#30s
);
xboFanRunCommand := _tofFanRunOn.Q;
Use TOF for run-on behavior, signal hold times, and controlled shutdown delays.
TP¶
TP generates a pulse. When triggered, Q remains true for PT.
_tpHornPulse(
IN := xboNewAlarmDetected,
PT := T#1s
);
xboHornPulse := _tpHornPulse.Q;
Use TP when the output should be true for a defined time independent of the trigger length.
Call Timers Once¶
Call timers once
Avoid calling the same timer instance in several places in one block. The timer output can
change when the instance is called, so multiple calls make the logic depend on call order.
Call it once, store .Q in a named Boolean, and use that Boolean later.
Prefer this:
_tonStartDelay(
IN := xboStartRequest,
PT := T#2s
);
_xboStartDelayDone := _tonStartDelay.Q;
IF _xboStartDelayDone THEN
xboStartAllowed := TRUE;
END_IF;
Avoid spreading timer calls around the block:
_tonStartDelay(IN := xboStartRequest, PT := T#2s);
IF _tonStartDelay.Q THEN
xboStartAllowed := TRUE;
END_IF;
// Later in the same block:
_tonStartDelay(IN := xboDifferentCondition, PT := T#2s);
The second call overwrites the same timer instance state for the current cycle.
Expert note: timers need static memory
IEC timers remember elapsed time, previous input state, and output state. That memory must live somewhere stable between PLC cycles.
In an FB, declare timer instances in VAR, not VAR_TEMP. Static VAR memory belongs to the
FB instance DB and survives from one call to the next. VAR_TEMP is recreated for each call and
is not suitable for timer instance memory.
This is why a timer is different from a pure calculation function. ABS(reValue) can return a
result from its inputs alone. A TON cannot: it must know how long IN has already been true.
A practical rule: if the block must remember something across cycles, it belongs in static memory. Timers, edge detectors, counters, filters, latched alarms, and state machines all depend on this idea.
Timer Checklist¶
- Declare timer instances once in static
VAR. - Call each timer instance once per cycle.
- Store
.Qin a named Boolean if it is used in several places. - Keep the timer input condition simple and readable.
- Name the timer by its engineering purpose, not only by its type.