Общие сведения
В этом уроке мы научимся обрабатывать состояния кнопки. Для показательности во втором и третьем примере будет использоваться светодиод, с которым мы работали в прошлом уроке.
Для этого урока нам понадобится:
Для работы данных примеров в Pi Pico необходимо загрузить прошивку MicroPython и установить Thonny IDE, о том как это сделать можно прочитать в этой статье: https://lesson.iarduino.ru/page/pi-pico-python-ide
Подключение
Подключим Trema-модуль Светодиод согласно таблице
Вывод модуля | Вывод Pi Pico |
---|---|
Vcc | 3V3(OUT) |
GND | GND |
S | GP15 |
Подключим Trema-модуль Кнопку согласно таблице
Вывод модуля | Вывод Pi Pico |
---|---|
Vcc | 3V3(OUT) |
GND | GND |
S | GP2 |
Выводим состояние кнопки в оболочку
В этом примере, как и в предыдущем уроке мы создаём объект вывода
(пина) Pi Pico, но на этот раз вместо назначения его на выход
Pin.OUT
мы назначаем ему режим работы на вход:
button = Pin("GP2", mode = Pin.IN)
В этом состоянии вывод принимает высокое входное сопротивление из него практически не выходит ток, зато мы можем понять какое на нём напряжение, логической единицы (максимальное напряжение относительно GND) или логического нуля (минимальное напряжение относительно GND).
В переменную last_state
мы сохраняем текущее состояние
кнопки:
last_state = button.value()
Функция print
выводит текст в оболочку:
print("Кнопка не нажата")
В следующем примере состояние кнопки считывается в цикле и выводится в оболочку:
# Подключаем модуль для работы с выводами from machine import Pin # Подключаем функцию сна (задержки) from time import sleep # Создаём объект кнопки, передавая в конструктор номер вывода и режим работы button = Pin("GP2", Pin.IN) # Сохраняем текущее состояние кнопки last_state = button.value() # Бесконечный цикл while True: # Читаем состояние кнопки button_state = button.value() # Если состояние изменилось if button_state != last_state: # Сохраняем новое состояние last_state = button_state # Выводим состояние в оболочку if button_state: print("Кнопка нажата") else: print("Кнопка не нажата") # Ждём сто миллисекунд sleep(.1)
Переключаем светодиод
В данном примере мы переключаем состояние светодиода при помощи кнопки. Это простое исполнение кнопки как переключателя, но на самом деле в данном примере переключателем является не кнопка, а сам объект светодиода:
led.toggle()
Пример:
# Подключаем модуль для работы с выводами from machine import Pin # Подключаем функцию сна (задержки) from time import sleep # Создаём объект светодиода, передавая в конструктор номер вывода и режим работы led = Pin("GP15", Pin.OUT) # Создаём объект кнопки, передавая в конструктор номер вывода и режим работы button = Pin("GP2", Pin.IN) # Бесконечный цикл while True: # Если кнопка нажата - переключаем светодиод if button.value(): led.toggle() sleep(.1)
Если нужно, что бы кнопка переключала что-то абстрактное, можно либо
придумать класс-оболочку для кнопки, либо переключать глобальную
переменную и led.toggle()
заменить на
toggle_state = not toggle_state
(более подробно данный
алгоритм мы рассмотрим в уроке работа с
ШИМ)
toggle_state = False ... if button.value(): toggle_state = not toggle_state ... if (toggle_state): # код, если кнопка была переключена
Устранение дребезга
При нажатии или отпускании кнопка может поменять своё состояние несколько раз в течении 50-100 миллисекунд (попробуйте убрать строчку sleep(.1) из предыдущего примера и посмотрите, что произойдёт). Это называется дребезг кнопки (bounce).
Для устранение этого в предыдущем примере мы использовали функцию
sleep
. Теоретически эта функция отличается от типичного для
ардуино delay
, так как она не блокирует другие задачи,
запущенные в операционной системе, если таковая имеется, но в контексте
данных уроков sleep
всё же блокирует текущий поток
выполнения. Поэтому рассмотрим неблокирующее устранение дребезга.
Алгоритм данного примера кажется сложным, но на самом деле он очень прост:
- проверяем состояние кнопки
- если состояние кнопки изменилось - записываем время изменения
- продолжаем выполнять программу дальше
- если подошёл интервал проверки DEBOUNCE_MS и состояние кнопки до сих
пор отличается от записанного ранее, значит состояние кнопки
действительно изменилось
- записываем новое состояние
- если подошёл интервал проверки DEBOUNCE_MS и состояние кнопки до сих
пор отличается от записанного ранее, значит состояние кнопки
действительно изменилось
# Подключаем модуль для работы с выводами from machine import Pin # Подключаем функцию счётчика миллисекунд и называем её знакомым для Arduino словом `millis` from time import ticks_ms as millis # Создаём объект светодиода, передавая в конструктор номер вывода и режим работы led = Pin("GP15", Pin.OUT) # Создаём объект кнопки, передавая в конструктор номер вывода и режим работы button = Pin("GP2", Pin.IN) # Инициируем переменные, в которых будут храниться миллисекунды для кнопки и для вывода debounce_millis = print_millis = millis() # Инициируем переменные состояния кнопки last_state = button_state = button.value() # Интерваля для устранения дребезга и для вывода DEBOUNCE_MS = 100 PRINT_INTERVAL = 2000 # Бесконечный цикл while True: # Записываем текущее состояние кнопки current_state = button.value() # Если состояние изменилось, записываем время изменения if current_state != last_state: debounce_millis = millis() # Если подошёл интервал устранения дребезга if millis() - debounce_millis > DEBOUNCE_MS: # Если состояние кнопки не соответсвует записаному ранее if current_state != button_state: # Записываем новое состояние button_state = current_state # Если новое состояние - нажатая кнопка if (button_state): # Переключаем светодиод led.toggle() # Записиваем последнее состояние кнопки last_state = current_state # Выводим текст через интервал if millis() - print_millis > PRINT_INTERVAL: print_millis = millis() print("Выполняем что-то ещё, устранение дребезга кнопки не блокирует поток")
Обсуждение