3.10. GPIO-вхід

Читання перемикача (або будь-якого цифрового сигналу) з GPIO-виводу знову виконується через machine.Pin, цього разу налаштованого як вхід. Інтерфейс симетричний виходу: налаштувати режим, а потім або опитувати значення виводу в головному циклі, або зареєструвати обробник переривань, що спрацьовує при зміні значення.

3.10.1. Налаштування входу

Передайте Pin.IN конструктору та, за бажанням, підтягуючий резистор:

from machine import Pin

button = Pin("P0", Pin.IN, Pin.PULL_UP)

Це налаштовує P0 як вхід із увімкненим внутрішнім підтягуючим резистором мікроконтролера. Якщо до виводу нічого не підключено, підтяжка утримує його на HIGH; замикання перемикача від виводу до землі тягне його на LOW.

3.10.2. Читання значення

value() без аргументів повертає поточний стан – 0 для LOW, 1 для HIGH:

if button.value() == 0:
    print("button pressed")
else:
    print("button released")

У патерні з головним циклом опитування виглядає так:

while True:
    if button.value() == 0:
        do_action()
    time.sleep_ms(50)

Затримка в 50 мс не дає циклу виконуватися на повній швидкості CPU.

3.10.3. Вхід на основі переривань

Опитування працює, але кожна ітерація головного циклу витрачає час CPU. Для входів, що змінюються рідко, – натискання кнопки раз на хвилину, сигнал тривоги – irq() реєструє обробник, який виконується лише при зміні виводу.

Обробник виконується в контексті переривання, що обмежує те, що він може робити:

  • Без виділення пам’яті. Створення нових об’єктів – списків, рядків, винятків, відформатованих рядків – може завершитися невдачею всередині ISR, оскільки купа заблокована. Заздалегідь виділіть будь-які буфери, що потрібні обробнику, на рівні модуля.

  • Без тривалих операцій. Обробник повинен передати роботу й повернутися. Витрачання реального часу всередині ISR затримує все інше (інші переривання, головний цикл, USB-трафік).

  • Без виведення в щільному ISR. print() виділяє пам’ять, блокує на UART і є одним із найвитратніших дій обробника.

Стандартний патерн полягає в тому, щоб ISR планував реальну роботу через micropython.schedule(), який ставить функцію в чергу для виконання назад у головному контексті в наступній безпечній точці:

import micropython

def handle_press(pin):
    print("button pressed")

def on_press(pin):
    micropython.schedule(handle_press, pin)

button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)

ISR складається з одного рядка: поставити зворотний виклик у чергу й повернутися. handle_press потім виконується у звичайному контексті, де виділення пам’яті, print() і повільний ввід-вивід знову безпечні.

Аргумент trigger вибирає, який фронт спрацьовує: