# Counters Overview

Source: https://rungs.dev/docs/ladder-logic/instructions/counters

> Reference for Ladder Logic counter instructions in rungs.dev — CTU, CTD, and RES — and the COUNTER tag with preset, accumulator, and done/up/down status bits.

Counters track discrete events. A counter instruction references a `COUNTER` tag, which is a structure with a preset, an accumulator, and status bits.

## Available Counter Instructions [#available-counter-instructions]

| Instruction  | Symbol                           | Purpose                                                                                                                |
| ------------ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| [CTU](https://rungs.dev/docs/ladder-logic/instructions/ctu) |  | Increments .ACC by 1 on each rising edge of the rung. Sets .DN when .ACC reaches .PRE; keeps counting past the preset. |
| [CTD](https://rungs.dev/docs/ladder-logic/instructions/ctd) |  | Decrements .ACC by 1 on each rising edge of the rung. Typically paired with CTU on the same COUNTER tag.               |

## COUNTER Tag Members [#counter-tag-members]

| Member | Type   | Meaning                                                     |
| ------ | ------ | ----------------------------------------------------------- |
| `.PRE` | `DINT` | Preset — target count                                       |
| `.ACC` | `DINT` | Accumulated count so far                                    |
| `.CU`  | `BOOL` | Count-up enable — `1` while a `CTU` rung is true            |
| `.CD`  | `BOOL` | Count-down enable — `1` while a `CTD` rung is true          |
| `.DN`  | `BOOL` | Done — `1` when `.ACC` is greater than or equal to `.PRE`   |
| `.OV`  | `BOOL` | Overflow — `1` when `.ACC` wraps past the positive maximum  |
| `.UN`  | `BOOL` | Underflow — `1` when `.ACC` wraps past the negative minimum |

Reference members as contacts:

```ladder
XIC(PartsCount.DN)OTE(FullBin)
```

## Rising-Edge Only [#rising-edge-only]

Counters increment (or decrement) **once per rising edge** of the rung. They do **not** count every scan while the rung is true. No `ONS` needed — the counter already detects the edge internally.

A rung that is already true when the program starts does not add a count. A counter only counts a change it sees while the program is running — the rung has to go false, then true. This protects real machines: a part already sitting on a sensor at power-up must not be counted twice. It's set up by [prescan](https://rungs.dev/docs/scan-cycle/the-scan-cycle#before-the-first-scan), the preparation pass that runs before the first scan.

## Resetting a Counter [#resetting-a-counter]

A counter is retentive — `.ACC` survives rung transitions. Use a [`RES`](https://rungs.dev/docs/ladder-logic/instructions/res) instruction to clear it:

```ladder
XIC(ResetBtn)RES(PartsCount)
```

Writing `.ACC` from a running rung (`MOVE(0, PartsCount.ACC)`) also takes effect on a ladder counter, but use `RES` as shown — the Structured Text [`CTUD`](https://rungs.dev/docs/structured-text/instructions/ctud) ignores runtime `.ACC` writes, so the technique doesn't port.

## Setting the Preset [#setting-the-preset]

The preset is stored on the counter tag, not inside the instruction. There are two ways to set it:

- **From the rung:** click the `Preset` row on the `CTU` or `CTD` block and type the target count. This edits the `.PRE` default of the underlying `COUNTER` tag in place — no need to leave the ladder editor.
- **From the Tag editor:** expand the counter tag's row and edit the `Default Value` of `.PRE`.

The `Accum` row on the block is editable the same way and sets the `.ACC` default, which is mainly useful for tests that start mid-count.