Обычно подключение энкодера к микроконтроллеру требует антидребезговой обвязки - но мне нужен всего лишь регулятор громкости. Рукой быстро ручку вращать не получится, поэтому попробуем решить задачу используя только программное решение.
Схема подключения:
Как обычно соберем прототип на макетной плате:
Контакты S1 и S2 это обычная кнопка (нужно утопить ручку), контакты
AB и BC будут замыкаться в определенной последовательности (с задержкой относительно друг друга) в зависимости от того в какую сторону вращается ручка, что позволит определить не только на сколько шагов повернулась ручка, но и направление вращения.
Технические характеристики энкодера EC11
- Количество положений вала - 20
- Количество импульсов на оборот - 10
- Высота вала (без резьбы) - 8 мм
- Угол вращения - 360°, бесконечный
- Максимальное напряжение - 5 В
- Максимальный ток - 10 мА
Для начала набросаем простенький скетч, для проверки работоспособности с устранением дребезга контактов. Кнопку для простоты понимания задействовать не будем - её можно опросить и в основном цикле.
Открываем монитор порта и при вращении ручки энкодера на один щелчок по часовой стрелке мы видим картинку в какой последовательности замыкались контакты А и С:
Если повернуть ручку на 1 щелчок против часовой стрелки, последовательность замыкания - размыкания контактов А и С будет другая
Таким образом мы получили определенную последовательность сигналов которая однозначно указывает на поворот ручки на 1 позицию, а также направление этого поворота.
A,C 10110100 - вращение по часовой на 1 щелчок
A,C 01111000 - вращение против часовой на 1 щелчок
Последние 4 бита можно отбросить, и таким образом если при вращении ручки к нам придет последовательность сигналов:
1011 - ручку повернули вправо
0111 - ручку повернули влево
Осталось поместить данный код в процедуру прерываний, но там возникает проблема как бороться с дребезгом контактов (задержки в прерываниях, чтобы точно убедиться что контакты энкодера не тилипаются использовать не получится).
Еще раз проанализируем табличку:
Пока энкодер находится в неподвижном состоянии - контакт А и контакт С находятся в нулевом состоянии. Потом свое состояние меняет контакт А, потом контакт С, потом снова А, и потом снова С. Смена всегда идет строго друг за другом, не важно в какую сторону мы вращаем ручку. Воспользуемся этим свойством и пусть контакт А после изменения состояния будет блокировать сам себя и разблокировать контакт С. Контакт С после изменения состояния будет блокировать сам себя и разблокировать контакт А. Можно писать код:
Переменная oldencoderCount нужна, чтобы выводить в COM порт только если крутанули ручку энкодера.
В переменную encoderResult будем скидывать все изменения стояний на входах микроконтроллера, но реагировать будем только если попадется определенная последовательность сигналов.
Каждая функция блокирует сама себя после первого вызова. Весь дребезг будет игнорироваться с помощью оператора return; Разблокировка будет происходить либо из другой функции - либо когда ручка не вращается с помощью конструкции:
if (!pinA && !pinC) blockA = false; else blockA = true;
if (!pinA && !pinC) blockC = false; else blockC = true;
Если надумаете использовать данный пример с платой Arduino - для подключения энкодера необходимо будет использовать только пины 2 и 3.
В loop выводим новое значение поворота энкодера. (только если ручку крутим). Использование механизма прерываний позволяет не пропускать импульсы, и не задействует ресурсы микроконтроллера пока ручка стоит неподвижно, и ненужно ни каких библиотек :-). Код примера скачивайте по этой ссылке.
Также вы можете ознакомиться с полным списком статей на моем канале.
Всем удачи!