Это старая версия документа!
В этом эксперименте мы научимся подключать инкрементальный энкодер и получать с него данные. В комплект конструктора входит модуль энкодера — небольшая печатная плата с энкодером и разъемом для удобного подключения к макетной плате. Модуль также включает встроенные подтягивающие резисторы на выводах A и B и кнопку, которая срабатывает при нажатии на вал.
Подписи выводов модуля:
Соберем устройство, которое отображает на экране число, увеличивающееся при вращении энкодера по часовой стрелке и уменьшающееся при вращении против часовой стрелки.
Рисунок 1. Электрическая принципиальная схема эксперимента
Обрати внимание, что резисторы R1 и R2 уже припаяны на плате модуля энкодера и нам не нужно устанавливать на макетной плате. Зачем же нужны резисторы R3, R4 и конденсаторы C1, C2? Дело в том, что контакты энкодера, как и любые механические контакты, подвержены неприятному эффекту — дребезгу контактов. На самом деле при нажатии на кнопку и отпускании кнопки замыкание и размыкание контактов не происходит мгновенно. После замыкания происходят многократные неконтролируемые замыкания и размыкания контактов за счет упругости материалов и деталей контактной системы — некоторое время контакты отскакивают друг от друга при соударениях, размыкая и замыкая электрическую цепь. Это и называется дребезгом контактов. Этому явлению подвержены и контакты энкодера.
С дребезгом нужно бороться программным или электрическим способом. В нашей схеме резистор с конденсатором являются фильтром для коротких импульсов, возникающих при дребезге контактов. Благодаря этому фильтру данный эффект можно в значительной мере устранить.
<file arduino Exp34.ino[enable_line_numbers=«2», start_line_numbers_at=«1»]> #include <LCDI2C_Multilingual.h>
#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() {
lcd.init();
lcd.setBacklight(0);
pinMode(ENC_A, INPUT);
pinMode(ENC_B, INPUT);
}
void loop() {
value_a = digitalRead(ENC_A);
value_b = digitalRead(ENC_B);
if (value_a != value_a_old) {
if 1) {
count++;
printLcd(count);
}
else if 2) {
count–;
printLcd(count);
}
}
value_a_old = value_a;
}
Настраиваем выводы для работы с энкодером:
<code arduino[enable_line_numbers=«2», start_line_numbers_at=«22»]>
pinMode(ENC_A, INPUT);
pinMode(ENC_B, INPUT);
</code>
Переменная old_value_a
будет хранить предыдущее состояния сигнала A, в переменной count
будем считать количество сигналов от энкодера.
Чтобы лучше понять алгоритм работы программы еще раз посмотрим на график сигналов энкодера:
В основном цикле программы получаем текущие состояния линий А и B.
Если состояние линии А изменилось, то проверяем условие вращения против часовой стрелки:
<code python[enable_line_numbers=«2», start_line_numbers_at=«31»]>
if 3)
</code>
Если уровни сигналов А и B оба стали высокими (состояние 2) или оба стали низкими (состояние 0), то увеличиваем значение
count
на 1, печатаем в терминал символ +
и обновляем информацию на дисплее.
Если условие выше не подтвердилось, то проверяем второй вариант: вращение по часовой стрелке:
<code arduino[enable_line_numbers=«2», start_line_numbers_at=«35»]>
else if 4):
</code>
Если уровень сигнала А стал низким, а сигнала B высоким (состояние 3) или уровень сигнала А стал высоким, а B низким (состояние 1), то уменьшаем значение count
на 1, печатаем символ
- в терминал и обновляем информацию на дисплее.
Если ни одно из этих условий не выполнено, то игнорируем сигналы. Перед завершением итерации записываем текущее состояние линии А как старое, для использования в следующей итерации.
<code arduino[enable_line_numbers=«2», start_line_numbers_at=«39»]>
value_a_old = value_a;
</code>
==== Дополнительное задание ====