PLC counters explained: CTU, CTD and CTUD pin by pin, plus the edge-detection trap that makes one button press count 400 times — and how R_TRIG fixes it.
PLC counters do the plant's bookkeeping: parts into a box, bottles down a line, starts on a motor, cycles on a valve. IEC 61131-3 gives you three standard counter function blocks — CTU (count up), CTD (count down) and CTUD (both) — and they are simpler than timers in every way but one. That one is edge detection, and it is responsible for the single most common beginner bug in PLC programming: the counter that registers 400 counts from one button press. This post explains the counters pin by pin, then the trap, then the fix.
PLC Counters Explained: CTU Pin by Pin
CTU is the workhorse. Its pins:
| Pin | Direction | Type | Meaning |
|---|---|---|---|
CU |
input | BOOL | Count input — increments CV on a rising edge |
RESET |
input | BOOL | While TRUE, forces CV to 0 |
PV |
input | INT | Preset value — the target |
Q |
output | BOOL | TRUE when CV ≥ PV |
CV |
output | INT | Current value — the running count |
Like timers, counters are function blocks with memory: each gets an instance name, each instance is one counter, and each is called once per scan. A parts counter that flags a full box of 24:
Batch(CU := PartSensor, RESET := BoxRemoved, PV := 24);
BoxFull := Batch.Q;
CountForHMI := Batch.CV;
CTD is the mirror: CD decrements from a value loaded via LD/PV, and Q goes TRUE at zero — natural for "slots remaining" logic. CTUD combines both with QU and QD outputs, for tracking a quantity that moves both ways, like cars in a car park (entry sensor on CU, exit sensor on CD).
The Trap: Why One Press Counts 400 Times
Here is the bug every PLC programmer writes exactly once. You wire a pushbutton to CU, press it briefly, and the count jumps by hundreds.
The cause is the scan cycle. A PLC scanning every 5 ms evaluates your counter 200 times per second. A "brief" two-second press is therefore 400 consecutive scans with the input TRUE. If the counting logic responds to the input's level rather than its change, it counts on every one of those scans: 400 counts, one press.
The IEC standard says CU triggers on a rising edge, and most vendor CTU implementations do edge-detect internally — which is why the trap more often bites in the surrounding logic: a homemade counter (Count := Count + 1; inside an IF Button THEN), a totalizer, a shift register, anything you built yourself that touches a physical input. The moment logic that should happen once per event is driven by a signal that stays TRUE for many scans, you have this bug.
The Fix: R_TRIG, the One-Scan Pulse
R_TRIG (rising trigger) is a tiny standard function block with one input, CLK, and one output, Q — and Q is TRUE for exactly one scan when CLK goes from FALSE to TRUE. Its sibling F_TRIG fires on the falling edge. Internally it's just one line of memory: was the input FALSE last scan and TRUE now?
The corrected homemade counter:
Edge(CLK := Button); (* Edge : R_TRIG *)
IF Edge.Q THEN
Count := Count + 1; (* now: one press, one count *)
END_IF;
In ladder, the same idea appears as the |P| (one-shot rising) contact — Rockwell calls the instruction ONS — and in FBD as an R_TRIG block wired between sensor and counter. Whatever the notation, the discipline is identical: physical inputs are levels; events need edges. Make the conversion explicit and visible, even when the counter would forgive you internally — the next person reading the program shouldn't have to know your vendor's CTU internals to trust the count. You can watch the difference live in the PLC-Ladder simulator: build one counter fed straight from a switch and one through R_TRIG, hold the switch on, and compare the two CV values climbing.
Counting Things That Aren't Buttons
The edge rule generalizes further than pushbuttons:
- Photo-eyes and prox switches are levels too — a slow part crawling past the eye is thousands of TRUE scans. Edge-detect them.
- Motor-start totalizers: R_TRIG on the run contact counts starts; the level would count runtime scans.
- Counting Q of a timer: a TON's
Qis a level once elapsed; edge it before totalizing cycles. (Timers and counters share the same instance-and-single-call discipline — see PLC Timers Explained.) - Bounce: a chattering mechanical sensor produces real rising edges, and R_TRIG will faithfully count every one. Edge detection is not debouncing — put a short TON filter before the R_TRIG when the sensor is noisy.
Resets, Presets and the Details That Bite Later
Three smaller behaviors worth knowing before they surprise you: RESET is a level, not an edge — while it's held TRUE the counter ignores counts entirely; Q is a comparison (CV >= PV), so raising PV on the fly can un-trip a done counter; and CV is an INT on many platforms, which overflows at 32,767 — use a DINT counter or roll your own for lifetime totalizers.
Where This Fits
Counters complete the stateful-block trio you'll use daily — latches, timers, counters — and the edge-detection idea you've just learned is load-bearing across all of PLC programming, from one-shot alarms to sequencer steps. To see CTU and R_TRIG working inside a full circuit (with the box-full logic and reset wired up), Example 5 of FBD Programming Examples: 8 Real Circuits builds exactly the batch counter from this post. And if the rung-side notation is your home ground, the |P| contact and its six-rung homemade ancestor get their own treatment in Edge Detection in Ladder Logic. Build the two-counter comparison first — thirty seconds of watching the wrong one race upward teaches the lesson permanently. Visit PLC-Ladder Website