Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
| products:laboratory_iot:exp35 [2020/05/22 11:41] – labuser29 | products:laboratory_iot:exp35 [2024/11/16 11:25] (текущий) – [Программный код эксперимента] labuser30 | ||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| - | ===== Эксперимент 35. Прерывания | + | ===== Эксперимент 35. Конечные автоматы ===== |
| - | В предыдущих уроках, | + | Коне́чный автома́т — абстрактный автомат, число |
| - | Их простота заключалась в линейности логики алгоритма. В главном цикле проверялось | + | |
| - | состояние светодиода. Задержка, | + | |
| - | с помощью | + | |
| - | небольшими схемами и примитивной логикой. Но если хочется | + | |
| - | чего-то большего, то старыми средствами уже не обойтись | + | |
| - | использования time.sleep() придется отказаться. | + | |
| - | Ранее, чтобы проверить состояние вывода микроконтроллера мы использовали команду вроде '' | + | {{ : |
| - | ==== Прерывания ==== | + | Видно, что |
| - | Оказывается есть отличное решение | + | |
| - | //Прерывание// — это сигнал (событие), который заставляет контроллер прекратить выполнение текущей задачи и приступить к исполнению другой, имеющей более высокий приоритет. После выполнения высокоприоритетной задачи, | + | Конечные автоматы иногда |
| + | {{ :encoder.png?nolink |}} | ||
| - | Представь, что | + | По графику |
| - | ==== Эксперимент ==== | + | Зная это мы можем отфильтровывать ложные показания |
| - | Попробуем применить прерывания для работы с энкодером. Нам потребуется сделать две вещи — настроить прерывание | + | |
| ==== Схема эксперимента ==== | ==== Схема эксперимента ==== | ||
| - | Оставим схему прошлого эксперимента | ||
| {{ : | {{ : | ||
| // | // | ||
| Строка 31: | Строка 23: | ||
| ==== Программный код эксперимента ==== | ==== Программный код эксперимента ==== | ||
| - | <file python Exp35[enable_line_numbers=" | + | <file python Exp35.py[enable_line_numbers=" |
| + | from time import sleep_ms, ticks_ms | ||
| from machine import I2C, Pin | from machine import I2C, Pin | ||
| from esp8266_i2c_lcd import I2cLcd | from esp8266_i2c_lcd import I2cLcd | ||
| _init() | _init() | ||
| - | DEFAULT_I2C_ADDR = 0x3F | + | DEFAULT_I2C_ADDR = 0x3F # Или 0x27 в зависимости от модели микросхемы на плате |
| encA = Pin(13, Pin.IN) | encA = Pin(13, Pin.IN) | ||
| encB = Pin(12, Pin.IN) | encB = Pin(12, Pin.IN) | ||
| + | |||
| + | states = ( | ||
| + | (0,0), | ||
| + | (1,0), | ||
| + | (1,1), | ||
| + | (0,1) | ||
| + | ) | ||
| + | |||
| + | old_state = 0 | ||
| count = 0 | count = 0 | ||
| Строка 47: | Строка 49: | ||
| lcd.clear() | lcd.clear() | ||
| lcd.putstr(str(data)) | lcd.putstr(str(data)) | ||
| - | |||
| - | def callback(p): | ||
| - | global count | ||
| - | global encB | ||
| - | global encA | ||
| - | | ||
| - | value_a = encA.value() | ||
| - | value_b = encB.value() | ||
| - | |||
| - | 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) | ||
| Строка 70: | Строка 55: | ||
| lcd.backlight_on() | lcd.backlight_on() | ||
| - | encA.irq(trigger=Pin.IRQ_FALLING, | ||
| + | while True: | ||
| + | value_a = encA.value() | ||
| + | value_b = encB.value() | ||
| - | while True: | + | state = states.index((value_a, |
| - | | + | |
| + | if (state - old_state == 1) or (state == 0 and old_state == 3): | ||
| + | count += 1 | ||
| + | print(' | ||
| + | print_lcd(count) | ||
| + | old_state = state | ||
| + | | ||
| + | count -= 1 | ||
| + | print(' | ||
| + | print_lcd(count) | ||
| + | old_state = state | ||
| </ | </ | ||
| - | Сначала настраиваем | + | Описываем возможные состояния конечного автомата: |
| - | <code python[enable_line_numbers=" | + | <code python[enable_line_numbers=" |
| - | encA.irq(trigger=Pin.IRQ_FALLING, handler=callback) | + | states |
| + | (0,0), | ||
| + | (1,0), | ||
| + | (1,1), | ||
| + | (0,1) | ||
| + | ) | ||
| </ | </ | ||
| + | Список из 4 элементов. В каждом элементе первая цифра это состояние сигнала A, вторая — сигнала B. | ||
| + | Номер состояния — это индекс элемента списка. Логика переключения состояний автомата простая — состояние может смениться только на соседнее: | ||
| - | Мы настроили, | + | В переменной '' |
| - | Какие могут быть | + | В основном цикле программы мы получаем данные |
| - | * Pin.IRQ_FALLING изменение с 1 на 0 | + | <code python[enable_line_numbers=" |
| - | * Pin.IRQ_RISING изменение с 0 на 1 | + | |
| - | * Pin.IRQ_LOW_LEVEL наличие логического 0 | + | |
| - | * Pin.IRQ_HIGH_LEVEL наличие логической 1 | + | |
| - | + | ||
| - | События | + | |
| - | + | ||
| - | Рассмотрим функцию- обработчик прерывания: | + | |
| - | <code python[enable_line_numbers=" | + | |
| - | def callback(p): | + | |
| - | global count | + | |
| - | global encB | + | |
| - | global encA | + | |
| - | | + | |
| value_a = encA.value() | value_a = encA.value() | ||
| value_b = encB.value() | value_b = encB.value() | ||
| + | </ | ||
| - | if (value_a and value_b) or (not value_a and not value_b): | + | И определяем номер состояния конечного автомата, |
| - | | + | <code python[enable_line_numbers=" |
| - | count += 1 | + | |
| - | print_lcd(count) | + | |
| - | | + | |
| - | print(' | + | |
| - | count -= 1 | + | |
| - | print_lcd(count) | + | |
| </ | </ | ||
| - | Она начинается с | + | Формируем список с состояниями А и B '' |
| - | <code python[enable_line_numbers=" | + | с помощью оператора '' |
| - | | + | |
| - | global encB | + | Теперь мы знаем индекс только |
| - | global encA | + | |
| + | <code python[enable_line_numbers=" | ||
| + | if (state - old_state == 1) or (state == 0 and old_state == 3): | ||
| </ | </ | ||
| - | Ключеваое слово | + | Если индекс нового состояния на 1 больше старого или, если новое состояние 0, а старое 3, то регистрируем переход в новое состояние. Переводим конечный автомат в новое состояние '' |
| + | |||
| + | Аналогично для вращения | ||
| + | |||
| + | Когда ты запустишь | ||