# TOFR — Off-Delay Timer

Source: https://rungs.dev/docs/structured-text/instructions/tofr

> TOFR is the Structured Text off-delay timer function block in rungs.dev. It uses FBD_TIMER and mirrors the behavior of the ladder TOF instruction.

Structured Text off-delay timer function block. Uses `FBD_TIMER`; the ST equivalent of ladder [`TOF`](https://rungs.dev/docs/ladder-logic/instructions/tof).

## Operands [#operands]

| Name    | Type        |
| ------- | ----------- |
| `timer` | `FBD_TIMER` |

## `FBD_TIMER` Tag Members [#fbd_timer-tag-members]

| Member           | Type   | Meaning                                                                                      |
| ---------------- | ------ | -------------------------------------------------------------------------------------------- |
| `.EnableIn`      | `BOOL` | Forced to `1` each scan by the instruction call — setting it `0` has no effect               |
| `.TimerEnable`   | `BOOL` | `1` primes the timer (`ACC` held at `0`); `0` runs the off-delay, counting `ACC` up to `PRE` |
| `.PRE`           | `DINT` | Preset target time in milliseconds                                                           |
| `.Reset`         | `BOOL` | `1` clears `EN`, `TT`, `DN` and sets `ACC` to `PRE`                                          |
| `.EnableOut`     | `BOOL` | `1` while the instruction is executing normally                                              |
| `.ACC`           | `DINT` | Accumulated time in milliseconds                                                             |
| `.EN`            | `BOOL` | `1` while `TimerEnable` is `1` and `Reset` is `0`                                            |
| `.TT`            | `BOOL` | `1` while the timer is actively counting toward `PRE`                                        |
| `.DN`            | `BOOL` | Done status — each timer (`TONR`, `TOFR`, `RTOR`) decides when this turns on                 |
| `.Status`        | `DINT` | Packed status word — combines `InstructFault` and `PresetInv` bits                           |
| `.InstructFault` | `BOOL` | `1` when the instruction hit an execution error                                              |
| `.PresetInv`     | `BOOL` | `1` when `PRE` is outside its valid range                                                    |

## How It Works [#how-it-works]

`TOFR` is the Structured Text function-block equivalent of the ladder [`TOF`](https://rungs.dev/docs/ladder-logic/instructions/tof) instruction. It operates on an `FBD_TIMER` tag.

While `.TimerEnable` is `1`, the timer is primed — `.DN` is `1` and `.ACC` stays at `0`. When `.TimerEnable` drops to `0`, `.ACC` counts up; `.DN` stays `1` until `.ACC` reaches `.PRE`, then goes `0`. So `.DN` holds `1` for the preset duration after `TimerEnable` drops to `0`.

## Example [#example]

```iecst
ExhaustTimer.TimerEnable := MachineRunning;
ExhaustTimer.PRE := 30000;
TOFR(ExhaustTimer);

ExhaustFan := ExhaustTimer.DN;
```

> **IDEA**
>
> **Practice**
>
> Try off-delay timing in the [Off Delay exercise](https://rungs.dev/exercises/off-delay) — keep an output on for two seconds after its input drops.

## Common Mistakes [#common-mistakes]

- Trying to pause with `.EnableIn := 0`. The instruction call forces `.EnableIn` back to `1` every scan, so the assignment has no effect. `.TimerEnable` is the control: `1` holds the output on, `0` begins the off-delay before the output turns off.
- Assigning `.ACC` from logic to change it (`MyTimer.ACC := 0`). Structured Text recomputes `.ACC` every scan, so a runtime write is **ignored** (the initial `.ACC` default is still honored). Reset with `.Reset := 1`. The same write _does_ take effect on the ladder [`TOF`](https://rungs.dev/docs/ladder-logic/instructions/tof) — so don't rely on it either way; it isn't portable.

## Related [#related]

- [TOF](https://rungs.dev/docs/ladder-logic/instructions/tof) — the ladder-logic equivalent
- [TONR](https://rungs.dev/docs/structured-text/instructions/tonr), [RTOR](https://rungs.dev/docs/structured-text/instructions/rtor) — other ST timer function blocks