Задача не так проста как может показаться. Речь пойдет про механические энкодеры с кнопкой EC11. Все, что будет описано в данной статье касается плат на базе микроконтроллере ATMega328P (платы Nano, UNO).
Принцип работы и общий алгоритм работы с этими устройствами был разобран в статье Подключение энкодера EC11 к ESP32 (программное решение), но воспользоваться тем примером при работе с Arduino не получится - так как прерывания из среды Arduino IDE поддерживаются только на выводах 2,3 а для двух энкодеров потребуется 4 ноги с прерываниями. С ESP32 было все проще - там прерывания поддерживаются всеми выводами, и весь код уместился в 60 строк.
Когда диванные дзен-эксперты дают советы в стиле, зачем там мощный контроллер хватило бы и какого-нибудь "на старом PIC16F84" имейте ввиду, что кодить под него придется гораздо дольше, и проще заплатить лишние 100 рублей за современную железку, чем угрохать несколько лишних вечеров на разработку ПО для какой-нибудь идеально подходящей старой железки.
Ссылка на статью "подключение энкодера к ESP32" будет в конце этой статьи, можете наглядно оценить трудозатраты при разработке ПО для подключения к современной ESP32 и уже в принципе морально устаревшей Arduino.
Вообще на гитхабе есть и готовая библиотека для подключения энкодеров,
но применять её можно только с дополнительными электронными компонентами устраняющими дребезг контактов. Мне лишние детали паять лень - попробуем обойтись без них.
Энкодеры подключены к аналоговым выводам, которые будет использоваться в качестве цифровых. (для Arduino NANO любые выводы кроме A6, A7).
Для решения задачи воспользуемся прерываниями при изменении состояния вывода (Pin Change Interrupts, PCINT)
- D8 .. D13 - генерируют запрос прерывания PCINT0
- A0 .. A5 - генерируют запрос прерывания PCINT1
- D0 .. D7 - генерируют запрос прерывания PCINT2
Входы-источники прерываний объединены в группы, каждой группе соответствует свой вектор и обработчик. Если мы, например, разрешим прерывания на всех выводах первой группы (PCINT0), то для всех поступающих от них запросов на прерывания будет вызываться один и тот же обработчик. Специальных средств для определения конкретного вывода, от которого поступил запрос прерывания, в микроконтроллере нет. И именно созданием этих средств и придется заняться, а вот саму логику работы с энкодерами утащу из своей прошлой статьи.
Для работы с PCINT предусмотрены регистры PCICR, PCIFR и три регистра PCMSKx.
Назначение битов регистра PCICR (Pin Change Interrupt Control Register):
- PCIE0 - значение "1" в этом бите разрешает обработку прерываний группы PCINT0.
- PCIE1 - значение "1" в этом бите разрешает обработку прерываний группы PCINT1.
- PCIE2 - значение "1" в этом бите разрешает обработку прерываний группы PCINT2.
Назначение битов регистра PCIFR (Pin Change Interrupt Flag Register):
- PCIF0 - значение "1" в этом бите сигнализирует об обнаружении запроса прерывания PCINT0.
- PCIF1 - значение "1" в этом бите сигнализирует об обнаружении запроса прерывания PCINT1.
- PCIF2 - значение "1" в этом бите сигнализирует об обнаружении запроса прерывания PCINT2.
Три регистра PCMSK0, PCMSK1 и PCMSK2 (Pin Change Mask Register) используются для указания входов, которым разрешено генерировать сигнал запроса прерывания. Соответствие битов регистров PCMSKx выводам микроконтроллера ATmega328/P (для 28-выводного DIP корпуса) и их обозначениям в IDE Arduino приведено в следующей таблице:
Более подробно читайте в источнике:
https://tsibrov.blogspot.com/2019/06/arduino-interrupts-part2.html
Собираем прототип
(там есть лишние провода - но это будет продолжение проекта)
Для проверки железа и аппаратной части пишем незамысловатый скетч
(жуткая смесь чистого С и Arduino-Wiring)
Все элементарно и никаких библиотек.....
Открываем монитор порта и слегка шатаем ручки энкодеров. Получаем числа от 14....17 в зависимости от того какую ручку и куда шатаем.
Осталось прикрутить процедуры антидребезга контактов, и вызывать их c использованием прерываний.
Все происходит в процедуре обработке прерываний, в loop мы только отображаем повороты ручек.
Осталось разобраться с кнопками. На контактах A4 A5 находится интерфейс I2C. Занимать его нежелательно, может пригодится если потребуется повесить туда какой-нибудь дисплей или датчик. Кнопки подключим к выводам 2 и 3. Прерывания использовать не будем.
Нажатие на кнопку правого энкодера увеличивает счетчик, нажатие на кнопку левого уменьшает.
Получилось полностью программное решение. Ни каких дополнительных электронных компонентов для устранения дребезга контактов не используется. Все примеры скетчей доступны по этой ссылке, можете скачивать и встраивать в свои проекты.
Если не до конца понятно что здесь происходит, читайте статью где были описаны общие принципы работы энкодера:
Подключение энкодера EC11 к ESP32 (Arduino) (программное решение)
Полный список всех статей канала доступен по этой ссылке:
Всем удачи!