Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
products:laboratory_iot:exp34 [2020/05/21 19:37] labuser29products:laboratory_iot:exp34 [2024/11/15 20:41] (текущий) – [Программный код эксперимента] labuser30
Строка 10: Строка 10:
   * CLK — Сигнал B   * 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. Монтажная схема эксперимента//
 +
 +==== Программный код эксперимента ====
 +
 +<file python Exp34.py[enable_line_numbers="2", start_line_numbers_at="1"]>
 +from time import sleep_ms, ticks_ms
 +from machine import I2C, Pin
 +from esp8266_i2c_lcd import I2cLcd
 +_init()
 +
 +DEFAULT_I2C_ADDR = 0x3F # Или 0x27 в зависимости от модели микросхемы на плате
 +
 +encA = Pin(13, Pin.IN)
 +encB = Pin(12, Pin.IN)
 +
 +old_value_a = 1
 +
 +count = 0
 +
 +
 +def print_lcd(data):
 +    lcd.clear()
 +    lcd.putstr(str(data))
 +
 +
 +i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
 +lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, 2, 16)
 +lcd.backlight_on()
 +
 +
 +while True:
 +    value_a = encA.value()
 +    value_b = encB.value()
 +
 +    if value_a != old_value_a:
 +        if (value_a and value_b) or (not value_a and not value_b):
 +            print('+')
 +            count += 1 
 +            print_lcd(count)
 +        elif (not value_a and value_b) or (value_a and not value_b):
 +            print('-')
 +            count -= 1
 +            print_lcd(count)
 +    old_value_a = value_a
 +</file>
 +
 +Настраиваем выводы для работы с энкодером:
 +<code python[enable_line_numbers="2", start_line_numbers_at="8"]>
 +encA = Pin(13, Pin.IN)
 +encB = Pin(12, Pin.IN)
 +</code>
 +
 +Объявляем переменную ''old_value_a'' для хранения предыдущего состояния сигнала A и переменную ''count'' в которой подсчитываем количество сигналов от энкодера.
 +
 +Чтобы лучше понять алгоритм работы программы еще раз посмотрим на график сигналов энкодера:
 +{{ :encoder.png?nolink&600 |}}
 +
 +В основном цикле программы получаем текущие состояния линий А и B.  
 +Если состояние линии А изменилось, то проверяем условие вращения против часовой стрелки:
 +<code python[enable_line_numbers="2", start_line_numbers_at="31"]>
 +        if (value_a and value_b) or (not value_a and not value_b):
 +</code>
 +Если уровни сигналов А и B оба стали высокими (состояние 2) или оба стали низкими (состояние 0), то увеличиваем значение ''count'' на 1, печатаем в терминал символ ''+'' и обновляем информацию на дисплее.
 +
 +Если условие выше не подтвердилось, то проверяем второй вариант: вращение по часовой стрелке:
 +<code python[enable_line_numbers="2", start_line_numbers_at="35"]>
 +        elif (not value_a and value_b) or (value_a and not value_b):
 +</code>
 +Если уровень сигнала А стал низким, а сигнала B высоким (состояние 3) или уровень сигнала А стал высоким, а B низким (состояние 1), то уменьшаем значение ''count'' на 1, печатаем символ ''-'' в терминал и обновляем информацию на дисплее.
 +
 +Если ни одно из этих условий не выполнено, то игнорируем сигналы. Перед завершением итерации записываем текущее состояние линии А как старое, для использования в следующей итерации.
 +<code python[enable_line_numbers="2", start_line_numbers_at="39"]>
 +    old_value_a = value_a
 +</code>
 +==== Дополнительное задание ====
 +<WRAP center round tip 60%>
 +  * Попробуй убрать конденсаторы из схемы и покрутить энкодер. Программа будет работать не так, как хотелось бы. Необходимость конденсаторов станет очевидной.
 +</WRAP>