Embedded / IoT
Advanced
ESP-IDF / Arduino
하드웨어 펄스 카운터(PCNT)를 활용한 지터 없는 로터리 엔코더 읽기
인터럽트 채터링 및 CPU 부하 없이 ESP32 내장 PCNT 하드웨어 모듈이 엔코더의 A/B 위상 구형파를 직접 카운팅하는 초정밀 입력 드라이버.
#Embedded #ESP32 #Hardware #Encoder #Interrupt
핵심 개념로터리 엔코더를 GPIO 외부 인터럽트(
attachInterrupt)로 읽으면 빠른 회전 시 인터럽트 누락이나 기계적 스위치 채터링(바운싱)으로 인해 카운트가 튀는 현상이 생깁니다. ESP32 전용 하드웨어 펄스 카운터(PCNT)를 쓰면 CPU 개입 0%로 정확한 펄스를 적산할 수 있습니다.1. PCNT 하드웨어 엔코더 설정 C 코드
#include "driver/pcnt.h"
#define PCNT_UNIT PCNT_UNIT_0
#define ENCODER_PIN_A 18
#define ENCODER_PIN_B 19
void init_encoder()
{
pcnt_config_t pcnt_config = {
.pulse_gpio_num = ENCODER_PIN_A,
.ctrl_gpio_num = ENCODER_PIN_B,
.channel = PCNT_CHANNEL_0,
.unit = PCNT_UNIT,
.pos_mode = PCNT_COUNT_INC, // 상승 에지 카운트 증가
.neg_mode = PCNT_COUNT_DEC, // 하강 에지 카운트 감소
.lctrl_mode = PCNT_MODE_REVERSE,
.hctrl_mode = PCNT_MODE_KEEP,
.counter_h_lim = 30000,
.counter_l_lim = -30000,
};
pcnt_unit_config(&pcnt_config);
// 하드웨어 디바운스 필터 적용 (80MHz 클럭 기준 글리치 제거)
pcnt_set_filter_value(PCNT_UNIT, 1023);
pcnt_filter_enable(PCNT_UNIT);
pcnt_counter_pause(PCNT_UNIT);
pcnt_counter_clear(PCNT_UNIT);
pcnt_counter_resume(PCNT_UNIT);
}
int16_t get_encoder_count()
{
int16_t count = 0;
pcnt_get_counter_value(PCNT_UNIT, &count);
return count;
}