3.10. Wejście GPIO

Odczyt przełącznika (lub dowolnego sygnału cyfrowego) z pinu GPIO znów przechodzi przez machine.Pin, tym razem skonfigurowany jako wejście. Interfejs jest symetryczny względem wyjścia: skonfiguruj tryb, a następnie albo odpytuj wartość pinu w głównej pętli, albo zarejestruj obsługę przerwania, która uruchamia się, gdy wartość się zmienia.

3.10.1. Konfigurowanie wejścia

Przekaż Pin.IN do konstruktora oraz opcjonalnie rezystor podciągający:

from machine import Pin

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

To konfiguruje P0 jako wejście z włączonym wewnętrznym rezystorem podciągającym MCU. Gdy do pinu nic nie jest podłączone, podciąganie utrzymuje go w stanie wysokim; zamknięcie przełącznika od pinu do masy ściąga go w stan niski.

3.10.2. Odczyt wartości

value() bez argumentów zwraca bieżący stan – 0 dla niskiego, 1 dla wysokiego:

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

We wzorcu z główną pętlą odpytywanie wygląda tak:

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

50 ms uśpienia zapobiega działaniu pętli z pełnym obciążeniem CPU.

3.10.3. Wejście sterowane przerwaniami

Odpytywanie działa, ale każda iteracja głównej pętli kosztuje czas CPU. W przypadku wejść, które zmieniają się rzadko – naciśnięcie przycisku raz na minutę, sygnał alarmowy – irq() rejestruje obsługę, która uruchamia się tylko wtedy, gdy pin się zmienia.

Obsługa działa w kontekście przerwania, co ogranicza to, co może robić:

  • Brak alokacji pamięci. Tworzenie nowych obiektów – list, łańcuchów znaków, wyjątków, sformatowanych łańcuchów – może się nie powieść wewnątrz ISR, ponieważ sterta jest zablokowana. Wstępnie zaalokuj wszelkie bufory potrzebne obsłudze w zakresie modułu.

  • Brak długotrwałej pracy. Obsługa powinna przekazać zadanie dalej i zakończyć działanie. Spędzanie rzeczywistego czasu wewnątrz ISR opóźnia wszystko inne (inne przerwania, główną pętlę, ruch USB).

  • Brak drukowania w napiętym ISR. print() alokuje pamięć, blokuje się na UART i jest jedną z najbardziej kosztownych rzeczy, jakie obsługa może wykonać.

Standardowym wzorcem jest, by ISR zaplanował rzeczywistą pracę za pomocą micropython.schedule(), która kolejkuje funkcję do wykonania z powrotem w głównym kontekście w najbliższym bezpiecznym punkcie:

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 to jedna linia: zakolejkuj wywołanie zwrotne i zakończ. handle_press działa następnie w normalnym kontekście, gdzie alokacja, print() i wolne operacje I/O są znów bezpieczne.

Argument trigger wybiera, które zbocze wyzwala: