A quadrature rotary encoder is a slotted disc fixed to a rotating shaft, read by two optical (or magnetic) sensors — channel A and channel B — placed a quarter slot-period apart. As the disc turns, each channel toggles high/low, producing two square waves offset by 90° of electrical phase:
slot period: Δ = 2π / N (N = counts per rev, "CPR")
channel A high: (θ mod Δ) < Δ/2
channel B high: ((θ + Δ/4) mod Δ) < Δ/2 ← 90° phase lag/lead
The order in which A and B toggle — not their absolute value — tells a controller which way the shaft is turning, with no extra sensor needed. Counting every edge of both channels ("×4 decoding") multiplies the raw slot count by 4:
effective counts/rev = N × mode (mode = 1, 2 or 4)
decoded angle = (pulse count / counts-per-rev) × 360°
velocity estimate = Δ(pulse count) / Δt / counts-per-rev × 60 [RPM]
This is exactly how closed-loop robot joints, drivetrains and CNC axes get position and velocity feedback for a PID controller. A once-per-revolution index (Z) pulse lets the controller re-zero absolute position after power-up.
- Sensor noise simulates a dirty lens or weak signal: some real edges are never registered, so the decoded angle silently drifts away from the true shaft angle — the reason real drives periodically re-home against the index pulse or a limit switch.
- Lower CPR or coarser decode modes make each count worth more degrees — good for noise immunity, bad for resolution: a classic robotics trade-off.
- At very low speed and low CPR, the velocity estimate becomes visibly quantized — it can only update once a whole pulse has arrived, which is why real servo drives blend pulse-counting with a minimum sample window.
- Drag the disc with the mouse/finger to jog the shaft by hand — the motor speed is ignored while dragging, so you can single-step past a read-head and watch exactly which channel toggles first for each direction.