Введение
Энкодер — датчик углового положения, преобразующий поворот вала в последовательности электрических сигналов. Его применяют в интерфейсах пользователя (регуляторы в меню, громкость), приводах, ЧПУ, робототехнике и измерительных системах. Правильный выбор типа энкодера, схемы подключения и алгоритма обработки напрямую влияет на надёжность и
«ощущение» от работы поворотной ручки.
В статье собраны практические рекомендации из нескольких источников и полевой опыт: от выбора и согласования уровней до подавления дребезга, чтения в опросе/прерываниях/«encoder mode», а также типичных ошибок и приёмов отладки.
1. Типы энкодеров и принцип работы
Инкрементальные формируют импульсы на каналах A и B, смещённых по фазе на 90° (квадратура). Направление вращения определяется порядком смены состояний A/B; абсолютного положения без опорной метки нет. Часто присутствует канал Z (индекс) — один импульс на оборот.
Абсолютные выдают код позиции (одно- или многовитовые). После пропадания питания положение не теряется. Интерфейсы: параллельные коды, SSI/SPI/I²C, иногда CAN/RS-485 в промышленных датчиках.
По физике сигналов:
▪ Механические (контактные) — дешёвые, небольшой ресурс, выраженный дребезг.
▪ Оптические/магнитные — «чистые» фронты, высокий ресурс и разрешение, дороже.
2. Электрические уровни и интерфейсы
▪ Контактные выходы: замыкание на землю/питание. Требуются подтяжки (внешние или внутренние) 10…47 кОм.
▪ Push-pull (TTL/HTL): активные выходы; при длинных линиях — терминаторы,
экранирование.
▪ Открытый коллектор/сток: гибкая совместимость уровней, подтяжка к локальному питанию на стороне МК.
▪ Дифференциальные RS-422 (A/!A, B/!B, Z/!Z): лучшая помехоустойчивость на длинах кабеля >1–2 м.
Согласование уровней 5 В → 3,3 В: делители/транзисторы/трансиверы. Для длинных линий — экранированный кабель, витая пара, правильная точка заземления экрана.
3. Схемы подключения к микроконтроллеру
Базовая: каналы A/B — на входы МК, каждый с подтяжкой к VCC (типично 10…47 кОм); общий вывод энкодера — к GND.
Дребезг механики обязателен к учёту:
▪ RC-фильтр (например, 10 кОм + 100 нФ → f_c≈159 Гц) на каждом канале;
▪ входы со Шмитт-триггером;
▪ «цифровой» антидребезг (см. раздел 9).
Кнопка на валу — отдельная подтяжка и антидребезг.
4. Подходы к чтению: опрос, прерывания, «encoder mode»
Опрос (polling) таймером с фиксированной частотой: простая логика, устойчив к дребезгу, минимальная нагрузка на МК. Частота 500…4000 Гц обычно достаточна для ручек, быстрее — для валов.
Прерывания по фронтам A/B: точнее улавливает «тики», но легко превысить пропускную способность при дребезге/быстрых вращениях. Нужны фильтры/«мёртвое время».
Аппаратная поддержка (Encoder Interface): таймеры некоторых МК (STM32 TIMx Encoder, ESP32 PCNT, ряд PIC) аппаратно считают квадраты и направление, разгружая CPU. Рекомендовано для высокой скорости/точности.
5. Алгоритмы декодирования: код Грея и таблицы переходов
Каналы A и B образуют состояния: 00, 01, 11, 10. Направление вращения — по «правильности» последовательности переходов.
Практичный метод — 4-битный код перехода:
code = (prev << 2) | curr, где prev и curr — по 2 бита (A,B).
▪ Набор «правых» кодов для CW (по часовой): {2, 4, 11, 13}
▪ Набор «левых» кодов для CCW: {1, 7, 8, 14}
Это позволяет компактно обработать переход без больших автоматов, а
«неправильные»/шумовые коды — игнорировать.
По этим значениям всегда можно однозначно определить направление вращения энкодера. Так, при вращении по часовой стрелке, получается следующий ряд значений:
А при вращении против часовой стрелки:
6. Пример компактного обработчика (опрос таймером, AVR/Arduino-like)
Инициализация: два пина как входы с подтяжкой; таймер на период 1–2 мс.
Идея: читаем A/B, формируем код перехода, сверяем с наборами CW/CCW.
Псевдокод (С-style):
static uint8_t prev; // хранит прошлые 2 бита (A1 B1)
volatile int32_t cnt;
ISR(TIMERx_COMPA) {
uint8_t val = PINx & 0x03; // бит0=B, бит1=A
if (val != prev) {
uint8_t code = (prev << 2) | val; // 4-бит «пред+тек»
prev = val;
if (code==2 || code==4 || code==11 || code==13) cnt++; // CW
else if (code==1 || code==7 || code==8 || code==14) cnt--; // CCW
// остальное игнорируем как дребезг/некорректные переходы
}
}
Преимущество — устойчивость к дребезгу при частоте опроса и малый «вес» кода.
7. Прерывания по фронтам: «смотрим A, читаем B»
Чтобы уменьшить нагрузку, можно ловить прерывание только на одном канале (например, A по спаду) и в ISR читать уровень второго (B): B=1 → CW, B=0 → CCW (или наоборот — зависит от фазы и проводки).
Компромисс: теряем половину квантов (счёт на одном фронте), но ISR вызывается реже. Для полной точности — прерывания на обоих каналах с фильтрацией.
8. Аппаратная поддержка: «encoder mode» и измерение скорости на разных МК
STM32 TIMx Encoder: таймер считает импульсы в режимах X1/X2/X4 (по одному/двум/четырём фронтам) и сам определяет направление.
ESP32 PCNT: счётчик импульсов с фильтрацией.
PIC/другие: специализированные счётчики/кванторы.
Скорость удобно вычислять либо как Δcount за окно времени, либо по периоду между фронтами (таймер захвата/сравнения). Для плавного UI — экспоненциальное сглаживание.
9. Борьба с дребезгом: аппаратная и программная
Аппаратно: RC-фильтр (10 кОм + 100 нФ типично), входы со Шмиттом (или внешние буферы), ферритовые бусины при длинных трассах.
Программно:
▪ опрос с пороговой частотой,
▪ игнор «запрещённых» кодов перехода,
▪ «мёртвое время» (debounce window),
▪ адаптивная фильтрация по скорости (меньше фильтра — при быстром вращении).
10. Пользовательский интерфейс: кнопка, ускорение, шаги
Часто вал энкодера — с кнопкой. Антидребезг кнопки делается отдельно (аппаратно или программно с таймером).
Ускорение: при быстрой прокрутке увеличивать шаг (1 → 5 → 10 и т. п.).
Декады: короткое нажатие — единицы, удержание — десятки/сотни.
Эти приёмы сильно улучшают UX.
11. Абсолютные энкодеры: SPI/SSI/I²C, точность и калибровка
Магнитные абсолютные датчики (семейства вроде AS5048/5600 и аналоги) дают код угла, а также диагностические биты/модуль магнитного поля.
Смотреть на: разрядность (бит), повторяемость, температуру, нелинейность, допуски на размещение магнита.
Протоколы:
▪ SSI/SPI — надёжные и быстрые, нужна синхронизация и правильные тайминги.
▪ I²C — проще в разводке, но аккуратнее с помехами/тайм-аутами.
12. EMC/ESD и длинные кабели
▪ Кабель — витая пара, экран, равная длина A/B, точка заземления экрана в одном месте.
▪ Терминаторы/серийные резисторы для фронтов.
▪ TVS-диоды/RC на входах при внешнем энкодере.
▪ Опторазвязка/дифференциальные приёмники на промышленных линиях.
13. Частые ошибки и отладка
▪ Нет внешних подтяжек → хаос на входах.
▪ Опрос слишком редкий → пропуски «тиков».
▪ Прерывания на обоих фронтах без фильтров → лавина ISR и «дребезг-шторм».
▪ Долгие операции в ISR → потеря фронтов.
▪ Несогласованные уровни 5 В ↔ 3,3 В → сквозные токи и сбои.
▪ Отсутствует индекс Z, а нужен абсолют на обороте.
Отладка: логический анализатор, осциллограф, счётчики «ошибочных» кодов, лог меток времени. Введите «диагностический» режим UI — вывод числа тиков/скорости/направления на экран или в UART.
Заключение
Энкодер — простой, но очень гибкий датчик. Стабильная «ручка» получается при грамотном стеке: правильная электрическая обвязка (подтяжки, фильтры, согласование уровней), подходящий алгоритм (опрос/прерывания/encoder-mode) и аккуратный антидребезг. Для длинных линий — дифференциальные интерфейсы, для тяжёлых помех — экраны, TVS и согласование. Следуя этим практикам, ты избежишь 90% типичных проблем и получишь отзывчивый, предсказуемый интерфейс.