3.10. GPIO-tulo

Kytkimen (tai minkä tahansa digitaalisen signaalin) lukeminen GPIO-nastasta tapahtuu jälleen machine.Pin-luokan kautta, tällä kertaa tuloksi määriteltynä. Rajapinta on symmetrinen lähdön kanssa: määritä tila ja joko kysele nastan arvoa pääsilmukassa tai rekisteröi keskeytyskäsittelijä, joka laukeaa, kun arvo muuttuu.

3.10.1. Tulon määrittäminen

Välitä Pin.IN rakentajalle ja valinnaisesti vetovastus:

from machine import Pin

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

Tämä määrittää P0:n tuloksi MCU:n sisäinen ylösvetovastus käytössä. Kun nastaan ei ole kytketty mitään, ylösveto pitää sen korkeana; kytkimen sulkeminen nastasta maahan vetää sen matalaksi.

3.10.2. Arvon lukeminen

value() ilman argumentteja palauttaa nykyisen tilan – 0 matalalle, 1 korkealle:

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

Pääsilmukkamallissa kysely näyttää tältä:

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

50 ms:n nukkuminen estää silmukkaa toimimasta täydellä CPU-teholla.

3.10.3. Keskeytyspohjainen tulo

Kysely toimii, mutta jokainen pääsilmukan iteraatio kuluttaa CPU-aikaa. Tuloille, jotka muuttuvat harvoin – painikkeen painallus kerran minuutissa, hälytyssignaali – irq() rekisteröi käsittelijän, joka suoritetaan vain, kun nasta muuttuu.

Käsittelijä suoritetaan keskeytyskontekstissa, mikä rajoittaa sitä, mitä se voi tehdä:

  • Ei muistinvarausta. Uusien objektien luominen – listat, merkkijonot, poikkeukset, muotoillut merkkijonot – voi epäonnistua ISR:n sisällä, koska keko on lukittu. Esivaraa kaikki puskurit, joita käsittelijä tarvitsee, moduulitasolla.

  • Ei pitkäkestoista työtä. Käsittelijän tulisi siirtää työ eteenpäin ja palata. Todellisen ajan käyttäminen ISR:n sisällä viivästyttää kaikkea muuta (muita keskeytyksiä, pääsilmukkaa, USB-liikennettä).

  • Ei tulostusta tiukassa ISR:ssä. print() varaa muistia, lukkiutuu UART:iin ja on yksi kalleimmista asioista, joita käsittelijä voi tehdä.

Vakiomalli on, että ISR ajoittaa todellisen työn micropython.schedule()-funktion kautta, joka asettaa funktion jonoon suoritettavaksi takaisin pääkontekstissa seuraavassa turvallisessa kohdassa:

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 on yksi rivi: aseta takaisinkutsu jonoon ja palaa. handle_press suoritetaan sitten normaalissa kontekstissa, jossa muistinvaraus, print() ja hidas I/O ovat kaikki taas turvallisia.

trigger-argumentti valitsee, mikä reuna laukaisee: