Как использовать энкодер (Rotary Encoder) с Raspberry Pi
В этом простом руководстве мы покажем вам, как подключить ваш энкодер (rotary encoder) и как использовать код на Python для взаимодействия с ним.
Давайте начнём с краткого объяснения того, что такое энкодер и как он работает!
Энкодер (rotary encoder) — это устройство, которое определяет вращение и направление вращения прикреплённой ручки. Он работает за счёт двух внутренних контактов, которые замыкают и размыкают цепь при повороте ручки. Когда вы поворачиваете ручку, вы можете ощутить характерный «щелчок», указывающий на поворот на одну позицию. Если внутренние контакты изначально были в состоянии HIGH (замыкали цепь), после одного щелчка они оба перейдут в состояние LOW (разомкнут цепь). С помощью простой логики можно определить направление вращения (подробно объясняется ниже, обязательно сначала ознакомьтесь с кодом!).
Вот так выглядят внутренности энкодера:
Вот так выглядит поворот энкодера на 1 щелчок против часовой стрелки:
Схема подключения
Давайте начнём со схемы подключения:
Как видно из схемы, вам нужно подключить энкодер следующим образом:
CLK — GPIO17 (pin11)
DT — GPIO18 (pin12)
+ — 3v3 (pin1)
GND — GND (pin6)
Вот и всё, что касается подключения. Вам не нужно беспокоиться о каких-либо резисторах или других компонентах, так как в энкодер встроены резисторы на 10 кОм, которые поддерживают ток на абсолютном минимуме!
Код на Python
Далее перейдём к коду на Python. Вы можете скачать наш пример кода с нашего GitHub — https://github.com/modmypi/Rotary-Encoder/
Или скачать его напрямую на ваш Pi, используя эту команду в окне терминала:
git clone https://github.com/modmypi/Rotary-Encoder/
Этот пример кода представляет собой простой счётчик. Когда вы поворачиваете энкодер по часовой стрелке, число увеличивается на 1 при каждом «щелчке», а когда вы поворачиваете его против часовой стрелки, число уменьшается на 1 при каждом «щелчке».
Давайте погрузимся в код и посмотрим, как он работает…
cd Rotary-Encoder
nano rotary_encoder.py
Строка 4 — Определяем GPIO-пин для пина CLK нашего энкодера
Строка 5 — Определяем GPIO-пин для пина DT нашего энкодера
Строки 8-9 — Устанавливаем наши GPIO-пины как входы с подтягивающим резистором к земле (pull down resistor)
Строка 11 — Определяем переменную нашего счётчика, начиная с 0
Строка 12 — Получаем начальное состояние нашего пина CLK
Строки 16-26 — Это бесконечный цикл, в котором мы проверяем состояния наших пинов CLK и DT, чтобы сначала определить, вращается ли энкодер, а затем определить, вращается ли он по часовой стрелке или против часовой стрелки
Строки 17-18 — Итак, сначала мы получаем текущее состояние наших пинов CLK и DT
Строка 19 — Затем мы сравниваем текущее состояние пина CLK с его предыдущим состоянием. Если оно отличается, энкодер вращается, и тогда мы можем определить направление вращения
Строки 20-21 — Если состояние нашего пина DT отличается от состояния нашего пина CLK, значит мы вращаем по часовой стрелке и, следовательно, нам нужно увеличить значение нашего счётчика на 1
Строки 22-23 — Если состояние нашего пина DT совпадает с состоянием нашего пина CLK, значит мы вращаем против часовой стрелки и, следовательно, нам нужно уменьшить значение нашего счётчика на 1
Строка 24 — Просто выводит значение нашей переменной счётчика
Строка 25 — Обновляем нашу переменную clkLastState, чтобы она соответствовала нашему clkState
Строка 26 — Приостанавливаем скрипт на 0.01 секунды
Логика определения направления вращения
Логика определения направления вращения очень проста для написания в коде, но не так легко понять, почему она работает.
Вот небольшой пример того, как это работает:
Для вращения по часовой стрелке
CLK и DT оба в состоянии HIGH
CLK переходит в LOW, DT остаётся HIGH — clkLastState был HIGH, clkState стал LOW (clkState != clkLastState), поэтому теперь мы можем определить направление — dtState равен HIGH, clkState равен LOW, dtState != clkState, +1
DT переходит в LOW, CLK остаётся LOW — clkLastState был LOW, clkState равен LOW — Ничего не происходит
Для вращения против часовой стрелки
CLK и DT оба в состоянии HIGH
DT переходит в LOW, CLK остаётся HIGH — clkLastState был HIGH, clkState равен HIGH — Ничего не происходит
CLK переходит в LOW, DT остаётся LOW — clkLastState был HIGH, clkState стал LOW (clkState != clkLastState), поэтому теперь мы можем определить направление — dtState равен LOW, clkState равен LOW, dtState == clkState, -1