Skip to content

Chapter 6: Quadrature Encoder Speed Measurement (PCNT)

6.1 Key Points

  • Quadrature encoder principle and A/B phase direction detection
  • ESP-IDF PCNT new API configuration
  • Overflow callback and accumulated software count
  • Converting pulse count to wheel linear speed

6.2 Course Content

OSRCORE uses a DC motor with a gearbox and a 512 PPR quadrature encoder. PCNT counts encoder pulses, and the software converts pulse differences into wheel speed using the gear ratio and wheel diameter. This speed feedback is used by the PID controller.

6.3 Basic Learning

Quadrature Encoder Principle

A quadrature encoder outputs two square waves with a 90-degree phase shift:

  • Forward rotation: phase A leads phase B.
  • Reverse rotation: phase B leads phase A.

PCNT can count edges on phase A while using phase B as the direction control level.

Speed Conversion

text
pulses_per_rev = PPR × gear_ratio = 512 × 10.55 = 5401.6
wheel_circumference = 2π × 0.0425 = 0.2670 m
distance_per_pulse = 0.2670 / 5401.6 = 4.943×10⁻⁵ m/pulse
speed_mps = delta_pulses × distance_per_pulse / delta_time

Overflow Handling

The PCNT hardware counter has a limited range. For high-speed rotation or long sampling intervals, the counter may overflow. Registering an on_reach callback allows the software to accumulate the overflow amount into a larger signed counter.

6.4 Program Study

Create the PCNT unit and channel:

c
pcnt_unit_config_t unit_config = {
    .high_limit = 32767,
    .low_limit  = -32768,
};
pcnt_unit_handle_t unit;
pcnt_new_unit(&unit_config, &unit);

pcnt_chan_config_t chan_config = {
    .edge_gpio_num  = 3,
    .level_gpio_num = 9,
};
pcnt_channel_handle_t chan;
pcnt_new_channel(unit, &chan_config, &chan);

Configure edge and level actions:

c
pcnt_channel_set_edge_action(chan,
                             PCNT_CHANNEL_EDGE_ACTION_INCREASE,
                             PCNT_CHANNEL_EDGE_ACTION_HOLD);
pcnt_channel_set_level_action(chan,
                              PCNT_CHANNEL_LEVEL_ACTION_KEEP,
                              PCNT_CHANNEL_LEVEL_ACTION_INVERSE);

Compute speed from pulse differences:

c
int64_t now_count = encoder_get_count();
int64_t delta = now_count - last_count;
float speed = delta * DIST_PER_PULSE / dt;
last_count = now_count;

6.5 Summary

This chapter showed how to use PCNT for encoder counting and how to convert pulses into linear speed. Encoder speed feedback is the key input for the motor PID loop.


Built for OSRCORE robot development board.