
Энкодеры – это датчики обратной связи, которые преобразуют механическое вращение в цифровые сигналы. Для Arduino чаще всего используют инкрементальные энкодеры с двумя выходными каналами (A и B) и, иногда, третьим каналом (Z) для индексации. Типичные модели: KY-040, EC11 или AS5600 (магнитный). Выбор зависит от задачи: KY-040 подходит для простых проектов с разрешением 20 импульсов на оборот, AS5600 – для точного позиционирования с разрешением до 12 бит.
Подключение требует учета электрических характеристик. Стандартные энкодеры работают на 5 В, но некоторые модели (например, AS5600) совместимы с 3.3 В. Для надежной работы используйте подтягивающие резисторы на 10 кОм между выходами A/B и питанием, если энкодер не имеет встроенных. Без них сигналы могут «плавать», вызывая ложные срабатывания. Для энкодеров с высокой скоростью вращения (>1000 об/мин) рекомендуется добавить конденсаторы 0.1 мкФ между выходами и землей для фильтрации шумов.
Программная обработка сигналов энкодера реализуется через прерывания или опрос в цикле. Прерывания (attachInterrupt()) предпочтительны для высокоскоростных задач, так как минимизируют задержки. Для Arduino Uno доступны только два внешних прерывания (пины 2 и 3), поэтому подключайте каналы A и B именно к ним. Пример кода для обработки прерываний:
volatile int counter = 0;
void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), handleA, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), handleB, CHANGE);
}
void handleA() {
counter += (digitalRead(2) == digitalRead(3)) ? 1 : -1;
}
Для точной калибровки учитывайте квадратурное декодирование. Энкодеры генерируют сигналы со сдвигом фаз на 90°, что позволяет определять направление вращения. Ошибки в подключении (например, перепутанные каналы A и B) приведут к некорректному счету. Проверяйте фазу с помощью осциллографа или логического анализатора. Если инструментов нет, используйте простой тест: вращайте вал в одну сторону и следите за счетчиком – он должен только увеличиваться или уменьшаться.
Подключение энкодера к Arduino: пошаговая инструкция

Используйте библиотеку Encoder.h от Paul Stoffregen для обработки сигналов. Установите её через менеджер библиотек Arduino IDE: Sketch → Include Library → Manage Libraries → введите «Encoder». Библиотека поддерживает аппаратные прерывания, что критично для точного считывания положения вала. Подключите энкодер к пинам, поддерживающим прерывания (для Uno – D2 и D3).
Пример кода для базовой работы с энкодером:
#include <Encoder.h>
Encoder myEnc(2, 3); // CLK на D2, DT на D3
void setup() {
Serial.begin(9600);
}
void loop() {
long position = myEnc.read();
Serial.println(position);
delay(50);
}
При работе с высокоскоростными энкодерами (>100 импульсов на оборот) используйте аппаратные прерывания на всех поддерживаемых пинах. Для Arduino Mega это пины 2, 3, 18, 19, 20, 21. Избегайте программных задержек (delay()) в коде – они блокируют обработку прерываний. Вместо этого используйте millis() для неблокирующих таймеров.
Для фильтрации дребезга контактов кнопки энкодера (SW) примените программную задержку в 50 мс после срабатывания. Пример:
if (digitalRead(4) == LOW) {
delay(50);
if (digitalRead(4) == LOW) {
// Действие при нажатии
}
}
Оптимизируйте энергопотребление, отключая питание энкодера через транзистор (например, 2N2222) в режиме сна. Управляйте базой транзистора с цифрового пина Arduino. Это критично для батарейных проектов: KY-040 потребляет до 10 мА в активном режиме. Для точной калибровки энкодера используйте эталонный датчик положения и сравнивайте показания в нескольких точках оборота.
Выбор подходящего энкодера для проекта
Энкодеры делятся на два основных типа: инкрементальные и абсолютные. Инкрементальные генерируют импульсы при вращении, подсчитываемые Arduino для определения угла поворота. Абсолютные выдают уникальный код для каждой позиции, сохраняя данные даже после отключения питания. Для проектов с непрерывным вращением (например, регулировка громкости) подойдут инкрементальные модели с разрешением от 20 до 600 импульсов на оборот (P/R). Абсолютные требуются там, где критична точная позиция после перезагрузки – например, в робототехнике или системах наведения.
Ключевые параметры при выборе: разрешение, тип выходного сигнала и напряжение питания. Разрешение в 20–100 P/R достаточно для простых интерфейсов, 300–600 P/R – для точных измерений. Выходной сигнал может быть квадратурным (два канала A и B с фазовым сдвигом 90°) или одноканальным (один импульс на шаг). Квадратурные энкодеры позволяют определять направление вращения, что необходимо для большинства проектов. Напряжение питания должно соответствовать логическому уровню Arduino: 5 В для Uno/Nano, 3,3 В для ESP32 или Due.
- EC11 – бюджетный вариант с разрешением 20–30 P/R, подходит для ручек управления меню. Имеет встроенную кнопку, но низкую точность.
- KY-040 – популярный модуль с 20 P/R, квадратурным выходом и кнопкой. Совместим с 5 В, но требует подтягивающих резисторов.
- AS5600 – магнитный абсолютный энкодер с разрешением 12 бит (4096 позиций). Работает через I2C, идеален для точных механизмов.
- HEDS-5540 – оптический энкодер с 500 P/R, используется в промышленных приложениях. Требует внешнего питания 5 В и дополнительной обвязки.
Для проектов с ограниченным пространством выбирайте компактные модели: PEC11R (диаметр 11 мм) или EN11-HSM1BF20 (монолитный корпус). Если энкодер будет работать в условиях вибрации или пыли, отдайте предпочтение магнитным (AS5600) или герметичным оптическим (например, OMRON E6B2-CWZ6C). Избегайте энкодеров с открытыми контактами в средах с высокой влажностью – они быстро выходят из строя.
При подключении к Arduino учитывайте нагрузку на пины. Квадратурные энкодеры с высоким разрешением (>300 P/R) могут генерировать до 10 кГц сигнала, что требует использования аппаратных прерываний (пины 2 и 3 на Uno) или специализированных библиотек (Encoder.h). Для абсолютных энкодеров с интерфейсом I2C или SPI проверьте совместимость с тактовой частотой шины. Если проект предполагает быстрое вращение, выбирайте модели с низким моментом сопротивления – например, Bourns PEC11 вместо механически жёстких промышленных аналогов.
Необходимые компоненты и инструменты для сборки
Для подключения энкодера к Arduino потребуется базовый набор компонентов. Основной элемент – инкрементальный энкодер с разрешением не менее 20 импульсов на оборот, например, KY-040 или EC11. Эти модели оснащены встроенной кнопкой, что расширяет функционал. При выборе обратите внимание на напряжение питания: большинство энкодеров работают от 5 В, что совместимо с Arduino Uno, Nano или Mega.
Помимо энкодера, понадобятся соединительные провода типа «папа-мама» или «папа-папа» длиной 10–20 см. Для надежного соединения используйте провода с силиконовой изоляцией сечением 0,14–0,25 мм² – они гибкие и устойчивы к перегибам. Избегайте тонких проводов из наборов для макетирования: они часто ломаются при многократном подключении.
Макетная плата (breadboard) с шагом 2,54 мм упростит сборку прототипа. Выбирайте плату с металлическими контактными пружинами – они обеспечивают лучший контакт, чем пластиковые. Для стабилизации схемы добавьте конденсаторы: керамический на 0,1 мкФ между питанием и землей энкодера и электролитический на 10–100 мкФ на входе питания Arduino.
Инструменты минимальны, но критичны. Мультиметр с режимом прозвонки поможет проверить целостность проводов и контактов энкодера. Паяльник с тонким жалом (25–30 Вт) и припой диаметром 0,5–0,8 мм пригодятся, если потребуется удлинить провода или зафиксировать соединения. Для зачистки проводов используйте стриппер с регулировкой глубины резания – это предотвратит повреждение жил.
Дополнительно пригодится отвертка с крестообразным шлицем PH0 для фиксации энкодера на корпусе, если планируется монтаж в проект. Для защиты от помех рекомендуется экранированный кабель типа FTP, особенно если энкодер удален от Arduino более чем на 30 см. В случае использования беспаечной макетной платы проверьте ее на отсутствие окисленных контактов – они могут вызывать ложные срабатывания.
Программная часть потребует Arduino IDE версии 1.8.19 или новее. Установите библиотеку Encoder от Paul Stoffregen (доступна через менеджер библиотек) – она оптимизирована для работы с прерываниями и снижает нагрузку на процессор. Для тестирования схемы загрузите пример «Basic» из библиотеки, чтобы убедиться в корректности подключения до написания собственного кода.
Схема подключения энкодера к плате Arduino

Настройка питания и заземления для стабильной работы
Энкодеры, особенно инкрементальные, чувствительны к помехам в цепях питания и заземления. Для Arduino Uno или Nano используйте стабилизированный источник 5 В с током не менее 500 мА. Если энкодер потребляет 20–30 мА, а остальные компоненты (датчики, дисплей) – ещё 200–300 мА, запас по току предотвратит просадки напряжения при скачках нагрузки.
Если энкодер питается от внешнего источника (например, 12 В), используйте гальваническую развязку. Оптопары PC817 или изолированные DC-DC преобразователи (например, B0505S-1W) исключат влияние помех от силовой части. При этом сигнальные линии энкодера подключайте к Arduino через резисторы 1–10 кОм для ограничения тока и защиты от статического электричества.
Проверяйте качество пайки и контактов. Холодные пайки или окисленные клеммы создают паразитные сопротивления, которые приводят к нестабильному питанию. Для энкодеров с разъёмами используйте позолоченные контакты и фиксирующие колодки. Если провода подключены через клеммники, затягивайте винты с усилием 0,5–0,8 Н·м – этого достаточно для надёжного контакта без деформации проводов.
При работе в условиях электромагнитных помех (например, рядом с частотными преобразователями) экранируйте кабели энкодера. Используйте витую пару с экраном, заземлённым только с одной стороны – на корпусе Arduino. Экран не должен быть частью сигнальной цепи. Для дополнительной защиты добавьте ферритовые кольца на кабель питания и сигнальные линии.
Тестируйте стабильность питания осциллографом. Подключите щуп между 5V и GND энкодера и прокрутите вал на максимальной скорости. Допустимые пульсации – не более 50 мВ от пикового значения. Если наблюдаются скачки более 100 мВ, увеличьте ёмкость конденсаторов или замените источник питания на более мощный. Для энкодеров с аналоговым выходом (например, потенциометрических) проверяйте линейность сигнала при разных нагрузках – нестабильное питание искажает показания.
Программирование базового кода для считывания сигналов
Базовый код начинается с подключения библиотеки и инициализации объекта энкодера. Пример минимальной настройки:
#include <Encoder.h>
Encoder myEnc(2, 3); // Пин 2 – канал A, пин 3 – канал B
long oldPosition = -999;
void setup() {
Serial.begin(9600);
}
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
}
Функция read() возвращает текущее положение энкодера в импульсах. Значение может быть как положительным (вращение по часовой стрелке), так и отрицательным (против часовой). Для энкодеров с разрешением 20 импульсов на оборот полный оборот даст ±20 импульсов. Если требуется считывать скорость вращения, добавьте таймер и вычисляйте разницу между текущим и предыдущим положением за фиксированный интервал времени.
При использовании энкодера без библиотеки потребуется ручная обработка прерываний. Подключите каналы A и B к пинам с поддержкой прерываний (например, 2 и 3 для Arduino Uno) и настройте прерывания по фронту сигнала. Пример обработчика прерывания:
volatile long encoderPos = 0;
byte lastState = 0;
void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), updateEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), updateEncoder, CHANGE);
Serial.begin(9600);
}
void updateEncoder() {
byte currentState = (digitalRead(2) << 1) | digitalRead(3);
if (currentState != lastState) {
switch ((lastState << 2) | currentState) {
case 0b0001: case 0b0111: case 0b1110: case 0b1000: encoderPos++; break;
case 0b0010: case 0b1011: case 0b1101: case 0b0100: encoderPos--; break;
}
lastState = currentState;
}
}
void loop() {
Serial.println(encoderPos);
delay(100);
}
Этот метод требует точной настройки состояний для корректного определения направления вращения. Таблица переходов состояний (Gray-код) исключает ложные срабатывания при дребезге. Для энкодеров с кнопкой добавьте отдельный пин и обрабатывайте его состояние через digitalRead().
Оптимизируйте код для конкретных задач. Если энкодер используется для управления меню, ограничьте диапазон значений с помощью constrain(). Для регулировки яркости светодиода или громкости звука преобразуйте импульсы в ШИМ-сигнал через map(). Пример:
int brightness = map(newPosition, 0, 100, 0, 255);
analogWrite(9, brightness);
Для энкодеров с высоким разрешением (>100 импульсов на оборот) увеличьте частоту опроса или используйте аппаратные таймеры. На платах с несколькими ядрами (например, ESP32) вынесите обработку энкодера в отдельное ядро, чтобы избежать задержек в основном цикле.
Обработка дребезга контактов энкодера в скетче
Дребезг контактов энкодера – физическое явление, при котором механические переключатели генерируют серию ложных импульсов в момент замыкания или размыкания. Для энкодера с разрешением 20 импульсов на оборот дребезг может вызывать до 5–10 ложных срабатываний на один реальный импульс, что приводит к некорректному подсчёту положения. Основные методы борьбы: аппаратный (RC-фильтры) и программный. Программный подход эффективнее, так как не требует дополнительных компонентов и гибок в настройке.
Минимальная задержка для подавления дребезга зависит от типа энкодера. Для механических энкодеров с тактильным откликом (например, EC11) достаточно 5–20 мс. Оптические энкодеры (AS5600) практически не подвержены дребезгу, но при использовании дешёвых моделей с пластиковыми контактами задержка может достигать 50 мс. Тестирование конкретного энкодера с помощью осциллографа или логического анализатора поможет определить оптимальное значение.
Простейший способ программной фильтрации – использование функции delay() после обнаружения изменения состояния. Пример для энкодера с двумя фазами (A и B):
- Если состояние изменилось, запускаем задержку на 10 мс.
- Повторно считываем состояние после задержки.
- Если состояние осталось прежним, регистрируем событие.
Этот метод прост, но блокирует выполнение остального кода на время задержки, что неприемлемо для систем реального времени.
Более эффективный подход – неблокирующая фильтрация с использованием таймера. В Arduino для этого подходит библиотека millis(). Алгоритм:
- При обнаружении изменения состояния сохраняем текущее время (
millis()) в переменнуюlastDebounceTime. - В каждом цикле
loop()проверяем, прошло ли с момента последнего изменения больше заданного интервала (например, 15 мс). - Если интервал истёк и состояние не изменилось, обрабатываем событие.
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 15;
bool lastButtonState = LOW;
bool buttonState;
void loop() {
bool reading = digitalRead(encoderPinA);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
// Обработка события
}
}
lastButtonState = reading;
}
Для энкодеров с квадратурным выходом (две фазы, A и B) дребезг обрабатывается отдельно для каждого канала. Однако важно учитывать взаимосвязь сигналов: ложные импульсы на одном канале могут вызывать ложное декодирование направления вращения. Решение – проверять оба канала одновременно и игнорировать изменения, если они не соответствуют ожидаемой последовательности (например, A↑B↓ для вращения по часовой стрелке).
Библиотеки для работы с энкодерами, такие как Encoder от Paul Stoffregen или RotaryEncoder, уже содержат встроенные механизмы подавления дребезга. Например, Encoder использует метод "временного окна": если импульсы поступают чаще, чем раз в 1 мс, они игнорируются. Для большинства энкодеров этого достаточно, но для дешёвых моделей может потребоваться увеличение параметра ENCODER_DO_NOT_USE_INTERRUPTS до 2–5 мс.
При использовании прерываний дребезг обрабатывается аналогично, но с учётом особенностей работы обработчиков. Прерывания срабатывают мгновенно, поэтому задержку нельзя реализовать через delay(). Вместо этого:
- В обработчике прерывания сохраняем текущее время и состояние.
- В основном цикле проверяем, прошло ли достаточно времени с момента последнего прерывания.
- Если да, обрабатываем событие; если нет – игнорируем.
Пример для прерывания по изменению состояния:
volatile unsigned long lastInterruptTime = 0;
const unsigned long interruptDebounceDelay = 10;
void encoderISR() {
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime > interruptDebounceDelay) {
// Обработка события
}
lastInterruptTime = interruptTime;
}
Для критичных приложений, где важна максимальная точность (например, станки с ЧПУ), комбинируют аппаратные и программные методы. Аппаратный RC-фильтр (10 кОм + 100 нФ) снижает количество ложных импульсов на 80–90%, а программная фильтрация устраняет оставшиеся. В таких случаях задержку можно уменьшить до 1–2 мс, что ускоряет реакцию системы без потери стабильности.
