===== Эксперимент 34. Подключение энкодера ===== В этом эксперименте мы научимся подключать инкрементальный энкодер и получать с него данные. В комплект конструктора входит модуль энкодера — небольшая печатная плата с энкодером и разъемом для удобного подключения к макетной плате. Модуль также включает встроенные подтягивающие резисторы на выводах A и B и кнопку, которая срабатывает при нажатии на вал. Подписи выводов модуля: * GND — общий контакт * + — Питание * SW — выход кнопки * DT — Сигнал А * CLK — Сигнал B Соберем устройство, которое отображает на экране число, увеличивающееся при вращении энкодера по часовой стрелке и уменьшающееся при вращении против часовой стрелки. ==== Схема эксперимента ==== {{ :products:esp-iot:exp14_sch.png?nolink |}} //Рисунок 1. Электрическая принципиальная схема эксперимента// Обрати внимание, что резисторы R1 и R2 уже припаяны на плате модуля энкодера и нам не нужно устанавливать на макетной плате. Зачем же нужны резисторы R3, R4 и конденсаторы C1, C2? Дело в том, что контакты энкодера, как и любые механические контакты, подвержены неприятному эффекту — //дребезгу контактов//. На самом деле при нажатии на кнопку и отпускании кнопки замыкание и размыкание контактов не происходит мгновенно. После замыкания происходят многократные неконтролируемые замыкания и размыкания контактов за счет упругости материалов и деталей контактной системы — некоторое время контакты отскакивают друг от друга при соударениях, размыкая и замыкая электрическую цепь. Это и называется дребезгом контактов. Этому явлению подвержены и контакты энкодера. С дребезгом нужно бороться программным или электрическим способом. В нашей схеме резистор с конденсатором являются фильтром для коротких импульсов, возникающих при дребезге контактов. Благодаря этому фильтру данный эффект можно в значительной мере устранить. {{ :products:esp-iot:exp14_mon.png?direct&600 |}} //Рисунок 2. Монтажная схема эксперимента// ==== Программный код эксперимента ==== #include #define ENC_A 13 #define ENC_B 12 #define DEFAULT_I2C_ADDR 0x3F // Или 0x27 в зависимости от твоей платы IoT LCDI2C_Generic lcd(DEFAULT_I2C_ADDR, 16, 2); bool value_a = 0; bool value_a_old = 0; bool value_b = 0; int count = 0; void printLcd(int number) { lcd.clear(); lcd.print(number); } void setup() { Serial.begin(9600); lcd.init(); lcd.setBacklight(0); pinMode(ENC_A, INPUT); pinMode(ENC_B, INPUT); printLcd(count); } void loop() { value_a = digitalRead(ENC_A); value_b = digitalRead(ENC_B); if (value_a != value_a_old) { if ((value_a and value_b) or (not value_a and not value_b)) { count++; Serial.println("+"); printLcd(count); } else if ((not value_a and value_b) or (value_a and not value_b)) { count--; Serial.println("-"); printLcd(count); } } value_a_old = value_a; } Настраиваем выводы для работы с энкодером: pinMode(ENC_A, INPUT); pinMode(ENC_B, INPUT); Переменная ''old_value_a'' будет хранить предыдущее состояния сигнала A, в переменной ''count'' будем считать количество сигналов от энкодера. Чтобы лучше понять алгоритм работы программы еще раз посмотрим на график сигналов энкодера: {{ :encoder.png?nolink&600 |}} В основном цикле программы получаем текущие состояния линий А и B. Если состояние линии А изменилось, то проверяем условие вращения против часовой стрелки: if ((value_a and value_b) or (not value_a and not value_b)) Если уровни сигналов А и B оба стали высокими (состояние 2) или оба стали низкими (состояние 0), то увеличиваем значение ''count'' на 1, печатаем в терминал символ ''+'' и обновляем информацию на дисплее. Если условие выше не подтвердилось, то проверяем второй вариант: вращение по часовой стрелке: else if ((not value_a and value_b) or (value_a and not value_b)): Если уровень сигнала А стал низким, а сигнала B высоким (состояние 3) или уровень сигнала А стал высоким, а B низким (состояние 1), то уменьшаем значение ''count'' на 1, печатаем символ ''-'' в терминал и обновляем информацию на дисплее. Если ни одно из этих условий не выполнено, то игнорируем сигналы. Перед завершением итерации записываем текущее состояние линии А как старое, для использования в следующей итерации. value_a_old = value_a; ==== Дополнительное задание ==== * Попробуй убрать конденсаторы из схемы и покрутить энкодер. Программа будет работать не так, как хотелось бы. Необходимость конденсаторов станет очевидной.