3.1. Mikrovezérlők

Az OpenMV Cam egy mikrovezérlőn (MCU) fut: ez egyetlen chip, amely egyesíti a CPU-t, a munkamemóriát (RAM), a programtárolót (flash memória) és egy sor perifériát – a külvilággal való kommunikációért felelős hardveres blokkokat.

A perifériák jelentik az érdekes részt. Mindegyik egy-egy szilíciumdarab, amelyet egyetlen feladatra szántak: egy láb magasra vagy alacsonyra hajtása, egy analóg feszültség mérése, bájtok kiléptetése egy soros buszon. A CPU minden perifériát regisztereken keresztül konfigurál és olvas – ezek rögzített memóriacímek, amelyeket a hardver figyel és frissít.

A MicroPython ezeket a regisztereket osztályokba csomagolja a machine modulon belül. A machine.Pin(...) egy objektumot ad vissza, amely egy általános célú be-/kimeneti (GPIO) lábat vezérel – egy vezetéket, amelyet a chip magasra (körülbelül 3,3 V) vagy alacsonyra (körülbelül 0 V) tarthat, illetve beolvashat e két állapot egyikeként, amikor valami külső eszköz hajtja. A machine.ADC(...) az analóg-digitális átalakítót teszi elérhetővé, amely megméri egy láb feszültségét, és számként jelenti azt. A machine.UART(...) egy univerzális aszinkron adó-vevőt (UART) működtet – ez egy periféria, amely bájtokat küld és fogad bitenként egy vezetékpáron, a TX (adás) és RX (vétel) vonalon keresztül. A többi osztály a többi perifériát fedi le. A szkript Python objektumokat olvas és ír; a MicroPython minden hozzáférést a megfelelő regiszterolvasásokká és -írásokká fordít, ezek pedig biteket mozgatnak a fizikai vezetékeken.

Egyetlen chip körvonala címkézett blokkokkal -- CPU, RAM, flash memória és egy sor perifériablokk (GPIO, ADC, Timer/PWM, UART/SPI/I2C, CAN), amelyeket egy belső busz köt össze, és minden perifériából nyilak lépnek ki a chipből a fizikai lábak címkéi felé.

Egy MCU egyetlen chipbe csomagolja a CPU-t, a memóriát és a perifériákat. Minden perifériát a machine modul egy-egy osztálya tesz elérhetővé a Python számára.

3.1.1. A fő ciklus

Szinte minden mikrovezérlő-program ugyanazt a felépítést követi: egyszeri beállítás a szkript elején (modulok importálása, lábak konfigurálása, buszok megnyitása), majd egy végtelen while True: ciklus a végén. A cikluson belül a program újra és újra beolvassa a bemeneteket, döntéseket hoz és frissíti a kimeneteket. A ciklus maga a program; amikor a szkript kilép, az eszköz beszünteti minden tevékenységét.

# setup, runs once
from machine import Pin
led = Pin("P0", Pin.OUT)

# main loop, runs forever
while True:
    led.value(1)
    # ... do work ...
    led.value(0)
    # ... do other work ...

Ez a felépítés – egyszeri beállítás, majd örökös ciklus – a fő ciklus minta. Minden további arról szól, hogy mi kerül a belsejébe.

3.1.2. Valós idejű vezérlés

Egy asztali program sok másikkal együtt fut. Az operációs rendszer egy vagy több szál között ütemezi a munkáját – ezek független végrehajtási folyamok, amelyek között ezredmásodpercről ezredmásodpercre vált. Amikor az egyik szál I/O-ra vár (lemez, hálózat, az egér mozgatása a felhasználó által), az operációs rendszer átadja a CPU-t egy másiknak. A program többnyire eseményvezérelt: az ablakkezelő hívja meg a kódodat, amikor bemenet érkezik, a HTTP-könyvtár folytatja a kódodat, amikor bájtok érkeznek a socketen. Valami nagyobb dolog hív téged.

Egy mikrovezérlő-program ennek az ellenkezője. Alapértelmezés szerint nincs operációs rendszer, nincs ütemező, és nincs másik szál. Az imént bemutatott fő ciklus az egyetlen ciklus. A perifériák megszakításokat váltanak ki vagy állapotjelzőket tesznek elérhetővé; a ciklus lekérdezi ezeket, vagy közvetlenül kezeli a megszakításokat. Ha a ciklus megreked egy time.sleep_ms(1000) hívásban, az eszköz egy másodpercig semmit sem csinál; nincs másik szál, amely betöltené a rést.

Két következmény adódik ebből, és ezek mindenütt érvényesek:

  • Az idő valós. Egy láb kétszeri beolvasása egy szoros ciklusban mikromásodperceket vesz igénybe; tíz ezredmásodperc alvás tíz olyan ezredmásodpercet jelent, amely alatt semmi más nem történik. A nem blokkoló időzítés minta erre a válasz.

  • A hardver valós. A machine.Pin.value 1 értékre állítása nagyjából 3,3 V-ot helyez egy fizikai vezetékre; 0 értékre állítása nagyjából 0 V-ot helyez oda. Az áramkör többi része azonnal látja ezt a feszültséget – beleértve minden olyan alkatrészt is, amelyet a láb tönkretehet, ha helytelenül hajtják meg.