An encoder is a sensor or peripheral that converts mechanical position or motion (rotary or linear) into an electrical signal, typically as a sequence of pulses or a coded digital word that a microcontroller can interpret to determine angle, distance, or speed. In embedded systems, "encoder" most often refers to an incremental quadrature encoder, which produces two out-of-phase pulse trains (channels A and B) whose relative phase indicates direction of travel.
In practice
Incremental quadrature encoders are common on brushed and brushless DC motors, rotary knobs (including mechanical panel controls and scroll wheels), and linear positioning stages. The two output channels are shifted 90 degrees apart; by observing which edge leads, firmware or dedicated hardware can determine both displacement and direction. Some rotary encoders also include a third index channel (Z or I) that produces one reference pulse per revolution, which is useful for homing sequences, though this channel is not present on all encoders.
Many MCUs include dedicated timer peripherals with a quadrature encoder interface mode. On STM32 devices, for example, certain general-purpose and advanced-control timers (such as TIM1, TIM2, TIM3, TIM4, TIM5, and TIM8, depending on the specific STM32 family) can be configured directly in encoder mode, where the hardware counts A/B edges and updates a counter register automatically -- no CPU involvement is needed per edge. Similar hardware is available on NXP LPC and Kinetis parts, Microchip dsPIC (QEI module), and Renesas RX/RA series timers. On MCUs without dedicated encoder hardware, quadrature decoding must be done in software using GPIO interrupts, which increases CPU load and limits the maximum trackable pulse rate.
A key practical challenge is velocity estimation. Simply dividing the pulse count by a fixed time window (frequency method) works well at high speeds but produces poor resolution at low speeds. Measuring the period between edges (period method) gives better low-speed resolution but degrades at high speed. Combining both approaches or using a more sophisticated observer is often necessary in motor control applications. The blog post "How to Estimate Encoder Velocity Without Making Stupid Mistakes: Part I" covers the tradeoffs in detail.
Signal integrity problems are a frequent source of bugs. Long cable runs, improperly terminated lines, and electrical noise near motor drivers can cause false counts or missed edges. Differential line drivers (RS-422) on the encoder output significantly reduce noise susceptibility compared to single-ended TTL/open-collector outputs. Contact bounce is a concern with mechanical (contact-type) rotary encoders used as user-interface knobs; this is typically addressed through software debouncing, hardware RC filtering, or tolerant state-machine decoding. Optical and magnetic encoder outputs generally do not exhibit contact bounce. The blog post "Signal Processing Contest in Python (PREVIEW): The Worst Encoder in the World" illustrates how badly degraded encoder signals can be in practice, and how to cope with them.
Frequently asked
What is the difference between an incremental encoder and an absolute encoder?
An incremental encoder outputs pulses relative to motion from a starting point; the
microcontroller must count pulses from a known reference (or home) position to know current position, and the count is lost on power-off. An absolute encoder encodes the current position in a multi-bit code (
Gray code is common) that is valid immediately on power-up without homing. Absolute encoders are more expensive and interface differently -- often via SSI,
SPI, or BiSS-C rather than simple pulse counting.
How does quadrature encoding convey direction?
The A and B channels are driven 90 degrees out of phase. When the encoder moves in one direction, A leads B (A rises before B). In the opposite direction, B leads A. By sampling both channels on each edge, firmware or hardware can determine direction from the sequence of states. A full four-state cycle (00 -> 10 -> 11 -> 01 -> 00, for example) corresponds to a defined fraction of a revolution depending on the encoder resolution; whether this aligns with a mechanical detent depends on the specific encoder design.
What is X1, X2, and X4 decoding?
These refer to how many edges per electrical cycle are counted. X1 decoding counts only one edge type on one channel (e.g., rising edge of A only), giving the lowest resolution but simplest logic. X2 decoding counts both edges of one channel. X4 decoding counts both edges of both channels, quadrupling the effective resolution -- a 500 PPR (pulses per revolution) encoder yields 2000 counts per revolution with X4 decoding. Most hardware encoder timer peripherals support X4 decoding, though the available modes and defaults vary by vendor and device family.
Can I decode a quadrature encoder in software without hardware support?
Yes, but with limitations. The typical approach attaches
GPIO interrupts to both A and B channels and reads the state of both signals in the ISR to update a signed counter. This works adequately at low pulse rates, but on fast-moving systems the interrupt rate can saturate the CPU. Maximum decodable velocity is bounded by ISR
latency and CPU throughput. For high-resolution or high-speed applications, hardware decoder support (as found in STM32 timers or dsPIC QEI) is strongly preferable. The blog post 'C++ on microcontrollers 4 - input pins, and decoding a rotary switch' covers a software decoding approach for panel knobs.
How do I handle noise and false counts from an encoder?
For electronic (optical or magnetic) encoders, use differential RS-422 outputs where possible, keep encoder cables away from motor power wiring, use shielded cable with the shield grounded at one end, and add small filter
capacitors (typically 10-100 nF) on the input lines close to the
MCU. For mechanical contact encoders, implement software debouncing or an RC filter on the inputs. Some encoder timer peripherals include a configurable input filter (e.g., STM32 TIM input filter, settable to 2-16 clock cycles) that can reject narrow glitches in hardware.
Differentiators vs similar concepts
Encoder vs. resolver: a resolver is an analog rotary transformer that outputs sine/cosine signals representing absolute shaft angle; it requires an R/D (resolver-to-digital) converter IC and is more robust in high-vibration or high-temperature environments, but more complex to interface. Encoder vs. Hall-effect sensor array: three discrete Hall sensors arranged around a BLDC stator give 6 commutation states per electrical revolution (very coarse position) and are used for sensorless-style commutation, not precision positioning. Encoder vs. potentiometer: a potentiometer gives an absolute analog voltage proportional to angle but wears mechanically, has limited rotation range on most types, and requires an
ADC; an incremental encoder has no wear, unlimited rotation, but no absolute position without homing.