Descoperă cum MicroPython înghesuie un interpretor complet Python 3 în microcontrollere bare-metal. Explorăm identitatea sa de bază, diferențele față de CPython și cum reușește să ruleze în medii extrem de constrânse.
3m 46s
2
Puntea hardware: Modulul machine
Învață cum să controlezi perifericele microcontrollerului direct din Python. Aprofundăm modulul machine, explorând modul de interacțiune cu Pins, PWM și memoria brută.
3m 56s
3
Live Coding pe MCU: REPL și mpremote
Revoluționează-ți fluxul de lucru în dezvoltarea embedded. Acoperim MicroPython REPL și instrumentul de linie de comandă mpremote pentru automatizarea conexiunilor seriale și execuția live.
3m 58s
4
Trei linii până la WiFi: Modulul network
Transformă un microcontroller într-un nod IoT conectat. Explorăm modulul network, detaliind cum să te conectezi la WiFi ca station sau să găzduiești propriul Access Point.
4m 21s
5
Supraviețuind constrângerilor: RAM și GC
Stăpânește arta de a scrie cod Python eficient din punct de vedere al memoriei. Discutăm despre fragmentarea heap-ului, prealocarea de buffers și garbage collection manual pentru a menține microcontrollerul funcționând fără probleme.
3m 54s
6
Compilat vs. Frozen: Implementarea în producție
Învață cum să implementezi aplicații masive fără a rămâne fără RAM. Explorăm fișierele .mpy precompilate și freezing-ul bytecode-ului direct în memoria flash a microcontrollerului.
3m 49s
7
Determinism în Python: Timere și Întreruperi
Obține un comportament real-time în MicroPython folosind timere hardware și interrupt service routines. Acoperim regulile stricte pentru scrierea ISR-urilor și evitarea alocării de memorie.
4m 25s
Episoade
1
Python-ul care încape în 256K
3m 46s
Descoperă cum MicroPython înghesuie un interpretor complet Python 3 în microcontrollere bare-metal. Explorăm identitatea sa de bază, diferențele față de CPython și cum reușește să ruleze în medii extrem de constrânse.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 1 din 7. Python pe desktop consumă în mod normal megabytes de memorie doar pentru a porni. Încearcă să pui asta pe un cip minuscul, de doi dolari, și sistemul rămâne imediat fără resurse. Pentru a scrie Python pentru microcontrollere, ai nevoie de un interpretor care să încapă într-o fracțiune din acel spațiu fără a pierde funcționalitățile de bază ale limbajului pe care te bazezi. Exact asta oferă MicroPython.
MicroPython este o implementare minimalistă și extrem de eficientă a limbajului de programare Python 3. Este conceput special pentru a rula în medii cu resurse limitate. Python-ul standard, adesea numit CPython, presupune că rulează peste un sistem de operare complet, cum ar fi Linux sau Windows, cu gigabytes de stocare și multă memorie RAM. MicroPython inversează această presupunere. Este construit pentru a rula bare metal. Nu există un sistem de operare subiacent care să gestioneze hardware-ul. În schimb, MicroPython acționează ca sistem de operare. Interacționează direct cu hardware-ul, astfel încât să poți scrie scripturi high-level pentru a controla dispozitive fizice.
Ingineria din spatele acestui proiect se concentrează în întregime pe limitările severe de resurse. MicroPython se poate executa în întregime în doar 256 de kilobytes de spațiu de cod compilat. Și mai impresionant este că necesită doar 16 kilobytes de RAM pentru a funcționa. În cadrul acestor limite stricte, oferă un mediu Python complet funcțional. Python-ul standard include o standard library masivă, faimoasă pentru abordarea batteries included. MicroPython reduce asta la un subset de module atent ales, păstrând doar ceea ce are sens pentru un sistem embedded.
În ciuda acestor optimizări masive, limbajul în sine rămâne autentic Python 3. Asta înseamnă că acel cod pe care îl scrii pe desktop se traduce direct pe device-ul embedded. MicroPython suportă feature-uri avansate ale limbajului, cum ar fi closures, list comprehensions, generators și standard exception handling. Gestionează chiar și arbitrary precision integers. Dacă logica ta necesită înmulțirea unor numere masive, MicroPython scalează memoria dinamic pentru a-ți oferi răspunsul corect fără a se lovi de o limită arhitecturală hard, exact ca Python-ul pe desktop.
Iată ideea cheie. Pentru că întregul engine Python încape pe cip, primești un prompt interactiv live direct pe hardware. Acest read-eval-print loop schimbă modul în care scrii cod embedded. În mod normal, programarea unui microcontroller implică scrierea codului în C, compilarea lui pe desktop, flash-uirea pe placă și așteptarea să ruleze. Cu MicroPython, conectezi placa la computer, deschizi un terminal serial și tastezi comenzi Python direct în cip. Poți testa logica, citi valorile senzorilor sau declanșa acțiuni instantaneu.
Pentru a face asta posibil, MicroPython include module built-in specifice care merg dincolo de Python-ul standard. Deoarece Python-ul standard nu știe nimic despre citirea pinilor fizici sau configurarea de hardware timers, MicroPython oferă interfețe specializate, extrem de optimizate pentru aceste task-uri. Acestea sunt integrate direct în firmware-ul pentru cipul tău specific, oferindu-ți control raw asupra lumii fizice fără a încărca amprenta de memorie.
Prin eliminarea sistemului de operare și micșorarea interpretorului pentru a încăpea în 256 de kilobytes, MicroPython transformă hardware-ul ieftin și cu resurse limitate într-un mediu de development dinamic și interactiv. Dacă vrei să susții emisiunea, ne poți găsi căutând DevStoriesEU pe Patreon. Mulțumim că ne-ai ascultat. Pe data viitoare!
2
Puntea hardware: Modulul machine
3m 56s
Învață cum să controlezi perifericele microcontrollerului direct din Python. Aprofundăm modulul machine, explorând modul de interacțiune cu Pins, PWM și memoria brută.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 2 din 7. Nu mai recompila cod C și nu mai da flash la firmware doar ca să testezi un senzor sau să apeși un buton. Vrei control direct asupra microcontrolerului tău, fără boilerplate, și exact asta îți oferă modulul machine.
Modulul machine este puntea ta hardware. El traduce codul Python în semnalele electrice care controlează pinii fizici de pe placa ta. Îți oferă acces la funcții hardware de bază, cum ar fi frecvența CPU-ului, sleep modes și digital input și output. Dar, pentru că rulează atât de aproape de metal, vine cu un avertisment. Acest modul nu te ține de mână. Dacă configurezi un hardware register greșit sau scrii la o memory address protejată, placa ta va da crash și își va da reboot.
Fundația acestui modul este clasa Pin. Un pin este o conexiune fizică pe microcontroler care poate trimite sau primi tensiune electrică. Pentru a controla o componentă de bază, cum ar fi un LED, trebuie să trimiți tensiune către un pin specific. Faci asta importând modulul machine și creând un obiect Pin. Oferi numărul pinului fizic și definești dacă pinul ar trebui să acționeze ca input sau output. Pentru un LED, îl configurezi ca output pasând o constantă de output. Odată ce obiectul este creat, îl folosești pentru a seta state-ul. Aplicarea unei valori de unu duce linia hardware pe high și aprinde LED-ul. Aplicarea unei valori de zero o duce pe low și îl stinge. Tu manipulezi state-ul digital al hardware-ului în timp real, dintr-un prompt Python.
Uneori, stările de bază de on și off nu sunt suficiente. Dacă vrei să dai dim la acel LED sau să controlezi viteza unui motor, ai nevoie de Pulse Width Modulation, sau PWM. Modulul machine are o clasă PWM dedicată pentru asta. În loc de un flux constant de tensiune, PWM trece pinul pe on și off extrem de rapid. Creezi un obiect PWM dându-i obiectul Pin pe care l-ai configurat deja. Apoi, setezi doi parametri hardware: frequency și duty cycle.
Aici e partea cheie. Frequency dictează de câte ori pe secundă face un ciclu semnalul, în timp ce duty cycle dictează ce procent din acel timp semnalul este efectiv pe on. Dacă setezi duty cycle la cincizeci la sută, LED-ul primește curent doar jumătate din timp, făcându-l să pară pe jumătate la fel de luminos pentru ochiul uman. Modificând treptat acea valoare de duty cycle în interiorul unui loop, instruiești hardware-ul să creeze un efect fin de fading.
Pentru use case-uri avansate, modulul machine oferă acces direct la hardware registers de la nivelul de bază prin obiecte numite mem8, mem16 și mem32. Acestea îți permit să citești și să scrii raw bytes, half-words sau 32-bit words direct la anumite memory addresses. Nu folosești un obiect Pin pentru asta. Folosești bracket notation standard, pasând physical memory address pe care vrei să o accesezi, exact ca atunci când cauți o key într-un dictionary. Atribuirea unei valori la o adresă mem32 dă overwrite instantaneu acelui hardware register. Așa interacționezi cu funcții obscure ale microcontrolerului pe care MicroPython nu le-a dat wrap explicit într-o clasă încă. Îți oferă autoritate absolută asupra siliciului.
Adevărata putere a modulului machine nu este doar că face hardware-ul accesibil, ci că elimină complet bariera dintre scrierea de logică software high-level și manipularea tensiunii fizice.
Mersi de ascultare. Aveți grijă de voi, tuturor.
3
Live Coding pe MCU: REPL și mpremote
3m 58s
Revoluționează-ți fluxul de lucru în dezvoltarea embedded. Acoperim MicroPython REPL și instrumentul de linie de comandă mpremote pentru automatizarea conexiunilor seriale și execuția live.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 3 din 7. Uită de ciclul plictisitor de compile, flash și reboot. Schimbi o variabilă într-un proiect embedded tipic, aștepți minute în șir pentru un build, scrii în memoria flash și speri să funcționeze. MicroPython ocolește complet asta, permițându-ți să vorbești direct cu chip-ul în timp real. Acest episod acoperă Live Coding pe MCU folosind REPL și mpremote.
REPL vine de la Read-Eval-Print Loop. Este un prompt interactiv care rulează direct pe microcontrolerul tău. Conectezi placa prin USB, deschizi un terminal serial, scrii cod Python, iar chip-ul îl execută instant. REPL-ul standard este conceput pentru oameni. Oferă auto-indentation, command history și auto-completion de bază. Este perfect pentru a testa un toggle rapid pe un pin hardware.
Totuși, există un al doilea mod numit raw REPL. Lumea îl confundă adesea cu o versiune limitată de MicroPython, dar de fapt este doar un input mode diferit, declanșat prin trimiterea unui control character specific prin conexiunea serială. Raw REPL dezactivează character echo și auto-indentation. Tool-urile folosesc raw REPL pentru a injecta programatic blocuri mari de cod în microcontroler. Dacă un script ar încerca să dea paste la text în REPL-ul standard, acel auto-indentation gândit pentru oameni ar crea un efect de cascadă și ar strica complet formatarea Python. Raw REPL garantează că acel cod intră exact așa cum a fost scris.
Asta ne aduce la mpremote. Acesta este command-line tool-ul oficial pentru interacțiunea cu device-urile MicroPython și folosește raw REPL under the hood pentru a face treaba grea. Pentru live coding, mpremote oferă două comenzi puternice: run și mount.
Folosești comanda run pentru a executa un script local de pe computerul tău direct pe placă. Îți scrii codul în text editor-ul preferat, deschizi terminalul și apelezi mpremote run urmat de numele fișierului tău. Aici este ideea de bază. Codul este trimis prin conexiunea serială și executat în întregime în memoria RAM a microcontrolerului. Nu este niciodată scris în memoria flash a device-ului. Dacă scrii o buclă proastă și dai crash la placă, pur și simplu dai un hard reset la chip. Memoria flash rămâne neatinsă, economisind write cycles, iar development loop-ul tău durează doar câteva secunde.
Când proiectul tău crește dincolo de un singur script, folosești comanda mount. Această comandă îi spune lui mpremote să ia un director local de pe PC-ul tău și să-l mapeze prin conexiunea serială. Microcontrolerul face un override temporar la propriul storage și tratează acel folder de pe computerul tău ca și cum ar fi propriul său filesystem intern.
Imaginează-ți un scenariu în care scrii un display driver complex. În mod normal, ar trebui să copiezi fișierul driverului pe placă, să rulezi scriptul principal, să observi un screen glitch, să editezi fișierul pe PC și să-l copiezi din nou. Cu comanda mount, microcontrolerul execută driverul direct din storage-ul PC-ului tău. Dai save în text editor-ul de pe laptop, dai restart la script pe placă, iar modificările se aplică imediat. Iterezi la fel de repede cum tastezi, eliminând complet pasul de flashing din workflow-ul tău.
Adevărata putere a MicroPython nu constă doar în sintaxa Python în sine, ci în modul în care tool-uri precum mpremote șterg granița dintre development environment-ul tău local și hardware-ul embedded fizic. Asta e tot pentru acest episod. Mulțumesc pentru audiție și continuă să construiești!
4
Trei linii până la WiFi: Modulul network
4m 21s
Transformă un microcontroller într-un nod IoT conectat. Explorăm modulul network, detaliind cum să te conectezi la WiFi ca station sau să găzduiești propriul Access Point.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 4 din 7. Să conectezi un microcontroler simplu la o rețea WiFi folosind cod C tradițional necesită de obicei sute de linii de boilerplate doar pentru a inițializa radioul și a gestiona handshake-ul. Este o treabă anevoioasă și predispusă la erori. În MicroPython, poți stabili o conexiune wireless în literalmente trei linii. Asta e treaba modulului network, mai exact a clasei WLAN.
Modulul network abstractizează interfețele de rețea hardware subiacente. Pentru operațiuni WiFi, te bazezi pe clasa network dot WLAN. Un cip WiFi standard poate funcționa în două roluri distincte. Trebuie să definești explicit ce rol vrei atunci când creezi obiectul WLAN.
Primul rol este modul Station, specificat folosind constanta STA underscore IF. Folosești modul Station atunci când hardware-ul tău trebuie să se conecteze ca un client la un router upstream, exact la fel cum un smartphone se conectează la rețeaua de acasă. Al doilea rol este modul Access Point, specificat folosind AP underscore IF. În acest mod, microcontrolerul acționează el însuși ca un router, difuzând propria rețea wireless, astfel încât dispozitivele externe să se poată conecta direct la el. Modul Access Point este incredibil de util atunci când faci deploy la hardware în locații izolate unde nu există o rețea externă, permițându-ți să te conectezi local pentru configurare.
Conectarea plăcii tale online necesită o secvență specifică. Mai întâi creezi obiectul WLAN folosind constanta pentru modul Station. Implicit, radioul WiFi fizic este oprit pentru a economisi energie. Trebuie să îl pornești pasând True metodei active de pe obiectul tău WLAN. Odată ce interfața este activă, apelezi metoda connect cu numele și parola rețelei tale wireless.
Aici e partea esențială. Metoda connect este strict non-blocking. Când o apelezi, MicroPython pasează credențialele către procesorul de rețea și continuă imediat să execute scriptul tău. În mod deliberat, nu așteaptă ca autentificarea în rețea să se termine. Acest design permite aplicației tale principale să actualizeze un display sau să citească un senzor în timp ce radioul negociază cu routerul în background. Totuși, dacă codul tău încearcă să trimită date imediat după apelarea metodei connect, operațiunea va da crash, deoarece placa nu are de fapt o conexiune încă.
Gestionezi asta făcând polling pe interfață. Obiectul WLAN oferă o metodă numită isconnected, care returnează o simplă valoare boolean. Pattern-ul standard este să scrii un while loop care evaluează dacă isconnected este false. În interiorul acestui loop, introduci un scurt delay, cum ar fi un sleep de o jumătate de secundă. Execuția se pune pe pauză aici, verificând în mod repetat starea hardware-ului până când routerul acceptă în sfârșit conexiunea, iar isconnected returnează true.
Odată ce loop-ul se termină, hardware-ul este oficial online. Pentru a verifica detaliile rețelei, apelezi metoda ifconfig pe obiectul tău WLAN. Această metodă returnează o colecție de patru elemente specifice: adresa IP alocată, subnet mask-ul, gateway-ul și serverul DNS principal. Poți extrage primul element din această colecție și îl poți printa în consolă pentru a vedea exact ce adresă IP a alocat routerul plăcii tale.
Natura non-blocking a metodei connect înseamnă că ești mereu responsabil să verifici starea hardware-ului înainte să încerci să rutezi date prin rețea.
Asta e tot pentru azi. Mulțumesc pentru audiție — mergi și construiește ceva cool.
5
Supraviețuind constrângerilor: RAM și GC
3m 54s
Stăpânește arta de a scrie cod Python eficient din punct de vedere al memoriei. Discutăm despre fragmentarea heap-ului, prealocarea de buffers și garbage collection manual pentru a menține microcontrollerul funcționând fără probleme.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 5 din 7. Python adoră să aloce dinamic memorie, generând obiecte noi pentru fiecare calcul. Asta funcționează perfect pe un server, dar pe un microcontroller, acest obicei îți va da crash la placă în cele din urmă, lăsându-te să te uiți la o eroare de memorie chiar și atunci când aparent ai RAM de rezervă. Astăzi ne concentrăm pe supraviețuirea constrângerilor: RAM și GC.
Memoria în care trăiesc obiectele tale Python se numește heap. În MicroPython, heap-ul este incredibil de mic. Când creezi obiecte, ele ocupă blocuri de spațiu. Când acele obiecte nu mai sunt necesare, sunt curățate. Asta lasă goluri în memoria ta. În timp, pe măsură ce obiecte de diferite dimensiuni sunt create și distruse, heap-ul tău ajunge să arate ca o brânză elvețiană. Asta este fragmentarea heap-ului. Iată ideea cheie. Când trebuie să aloci un obiect nou, MicroPython are nevoie de un singur bloc contiguu de memorie în care să încapă. Dacă heap-ul tău este puternic fragmentat, s-ar putea să ai douăzeci de kilobytes de RAM liber în total, dar niciun gol mai mare de un kilobyte. Dacă ceri doi kilobytes, programul tău dă crash.
Trebuie să nu mai irosești RAM, începând cu variabilele tale globale. Dacă ai valori integer care nu se schimbă niciodată, cum ar fi numere de pini sau adrese hardware, nu le atribui în mod normal. MicroPython oferă o declarație specială numită const. Dacă pui valoarea integer în această declarație const, compilatorul înlocuiește numele variabilei cu numărul efectiv peste tot în codul tău în timpul compilării. Asta previne cu totul crearea unei variabile în RAM.
Apoi, uită-te la loop-urile tale. Crearea dinamică de obiecte în interiorul unui loop care rulează rapid este cauza principală a fragmentării. Citești un senzor printr-un bus SPI de o sută de ori pe secundă. Dacă folosești o comandă standard de read, MicroPython creează o secvență complet nouă de bytes în memorie pentru fiecare citire în parte. Acele obiecte se adună rapid, umplând golurile și distrugându-ți spațiul contiguu.
În loc să creezi obiecte noi, refolosește-le pe cele pe care le ai deja. Înainte să înceapă loop-ul, creează un bytearray de dimensiunea corectă. Un bytearray este un bloc de memorie mutabil. Apoi, în interiorul loop-ului, folosește o metodă hardware numită readinto. Îi pasezi bytearray-ul tău preexistent lui readinto. Hardware-ul pune datele senzorului direct în același bloc de memorie, suprascriind datele vechi. Procesezi datele, loop-ul se repetă și se alocă zero memorie nouă.
Chiar și cu un cod scris cu atenție, crearea unor obiecte este inevitabilă, ceea ce ne aduce la garbage collector. By default, garbage collector-ul rulează automat atunci când alocarea memoriei eșuează. El scanează după obiecte nefolosite și le eliberează spațiul. Totuși, acest proces ia timp. Dacă se declanșează automat în timpul unei operațiuni time-sensitive, codul tău se va pune pe pauză în mod imprevizibil. Ca să repari asta, preiei tu controlul. Apelează explicit funcția collect din modulul gc. Găsește un loc sigur în codul tău, cum ar fi sfârșitul main loop-ului, și declanșează colectarea acolo. Asta menține heap-ul curat conform programului tău, prevenind delay-urile neașteptate.
În Python pe desktop, memoria este ceva ce limbajul gestionează pentru tine, dar în MicroPython, memoria este un container fizic pe care trebuie să-l împachetezi manual.
Asta e tot pentru acest episod. Mulțumesc pentru audiție și continuă să construiești!
6
Compilat vs. Frozen: Implementarea în producție
3m 49s
Învață cum să implementezi aplicații masive fără a rămâne fără RAM. Explorăm fișierele .mpy precompilate și freezing-ul bytecode-ului direct în memoria flash a microcontrollerului.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 6 din 7. Încarci un fișier Python perfect valid pe microcontroler, dai import, iar placa dă crash instantaneu cu o eroare de out-of-memory. Codul în sine este în regulă, dar procesul de încărcare tocmai ți-a consumat toată memoria disponibilă. Ca să repari asta, trebuie să ocolești compiler-ul de pe device, ceea ce ne aduce la cod compilat versus cod frozen pentru deployment-uri de producție.
Când rulezi un script Python standard pe un desktop, memoria este practic infinită. Pe un microcontroler, memoria este strict limitată. Când pui un fișier sursă Python standard pe device și rulezi comanda de import, MicroPython nu doar citește fișierul. Compiler-ul pornește chiar acolo, pe microcontroler. Acesta face parse la text, construiește un abstract syntax tree și generează bytecode. Fiecare dintre acești pași alocă memorie în RAM.
Gândește-te la un framework IoT mare care gestionează networking, securitate și date de la senzori. Dacă încerci să faci import la acest modul masiv dintr-un fișier sursă standard, compiler-ul va epuiza probabil memoria heap disponibilă înainte ca prima linie din aplicația ta să se execute. Spike-ul de utilizare a memoriei RAM în timpul fazei de compilare omoară procesul.
Pentru a ocoli asta, trebuie să elimini pasul de compilare de pe microcontroler. Faci asta prin pre-compilarea codului tău folosind un tool de desktop numit cross-compiler, sau mpy-cross. Rulezi acest tool pe calculatorul tău principal. Acesta preia fișierul sursă Python și generează un fișier compilat cu extensia M-P-Y. Acest fișier conține bytecode-ul pre-generat.
Când transferi acest fișier compilat pe microcontroler și îi dai import, MicroPython recunoaște formatul și sare complet peste faza de compilare. Eviți complet spike-ul de memorie cauzat de compiler. Aici devine interesant. Deși pre-compilarea te scapă de spike-ul de memorie de la compilare, microcontrolerul tot încarcă bytecode-ul propriu-zis din file system în RAM pentru a-l executa. Dacă framework-ul tău IoT este suficient de mare, doar bytecode-ul în sine va consuma prea mult RAM, lăsându-ți foarte puțin spațiu pentru variabilele și datele aplicației tale.
Când fișierele pre-compilate nu sunt suficiente, pasul final este să faci freeze la bytecode. Freezing înseamnă să integrezi codul compilat direct în firmware-ul MicroPython. În loc să copiezi fișierul compilat în file system-ul plăcii, îl pui într-un director specific de module din codul sursă MicroPython de pe calculatorul tău. Apoi dai rebuild de la zero la toată imaginea de firmware MicroPython și dai flash acestui firmware custom pe placa ta.
Asta schimbă exact modul în care este executat codul. Când dai import la un modul frozen, MicroPython nu copiază deloc bytecode-ul în RAM. Pentru că acest cod este integrat în firmware, el stă permanent în memoria flash a microcontrolerului. MicroPython execută bytecode-ul direct din flash. Prin executarea din flash, amprenta de RAM pentru importul acelui framework IoT masiv scade la aproape zero. Tot RAM-ul tău rămâne complet liber pentru procesarea datelor în timp real.
Diferența fundamentală se reduce la locul în care stă codul tău în timp ce rulează. Pre-compilarea salvează memorie în timpul pasului de import, dar freezing-ul salvează memorie pe toată durata de viață a programului, forțând execuția să aibă loc în întregime în memoria flash. Dacă vrei să susții emisiunea, poți căuta DevStoriesEU pe Patreon. Asta e tot pentru acest episod. Mulțumesc pentru audiție și continuă să construiești!
7
Determinism în Python: Timere și Întreruperi
4m 25s
Obține un comportament real-time în MicroPython folosind timere hardware și interrupt service routines. Acoperim regulile stricte pentru scrierea ISR-urilor și evitarea alocării de memorie.
Salut, sunt Alex de la DEV STORIES DOT EU. MicroPython, episodul 7 din 7. Să scrii un hardware interrupt service routine într-un limbaj high-level, cu garbage collection, sună ca și cum ai cere un crash imediat al sistemului. Dar MicroPython chiar permite asta, atâta timp cât respecți o regulă strictă: zero alocare de memorie. Acest episod acoperă Determinismul în Python: Timers și Interrupts.
Când trebuie să citești un senzor de exact o mie de ori pe secundă, un loop standard cu o funcție sleep va eșua. Garbage collection-ul și background task-urile introduc delay-uri random, distrugându-ți timing-ul. Pentru a obține un comportament determinist, ai nevoie de un hardware timer. Folosind modulul machine, configurezi un obiect Timer să se declanșeze periodic și să execute o funcție callback specifică. Acest callback este Interrupt Service Routine-ul tău, sau ISR.
Timerele declanșează fie soft interrupts, fie hard interrupts. Un soft interrupt este planificat de virtual machine-ul MicroPython atunci când este safe să facă asta. Scrii un soft ISR exact ca un cod Python normal. Poate crea obiecte, poate da append la liste și poate gestiona numere floating-point. Dezavantajul este latența. Dacă garbage collector-ul rulează activ când timer-ul se declanșează, soft interrupt-ul tău pur și simplu așteaptă la rând.
Dacă ai nevoie de o acuratețe strictă a timing-ului, configurezi timer-ul să declanșeze un hard interrupt. Un hard interrupt oprește procesorul imediat. Face bypass la virtual machine și îți rulează callback-ul instant. Iată ideea cheie. Pentru că un hard interrupt face preempt la starea curentă a sistemului, ar putea întrerupe chiar memory manager-ul. Dacă ISR-ul tău încearcă să aloce memorie pe heap în timp ce heap-ul este în plin proces de modificare, microcontroller-ul va da crash.
Această constrângere dictează exact cum scrii hard ISR-uri. Nu poți aloca deloc memorie. Fără să creezi liste. Fără să construiești dicționare. Fără manipulare de string-uri. Chiar și matematica floating-point este strict interzisă, deoarece în Python, fiecare float este un obiect nou alocat pe heap. Codul tău trebuie să se execute rapid, să se bazeze pe integer math și să folosească structuri de memorie preexistente.
Ia în considerare un scenariu în care un hardware timer se declanșează la 1000 de Hertzi. În fiecare milisecundă, hard ISR-ul citește o valoare a senzorului. Din moment ce nu poți da append citirii într-o listă, trebuie să îți prealocezi spațiul de stocare înainte de a porni timer-ul. Creezi un bytearray de o mie de bytes în programul tău principal. De asemenea, definești o variabilă globală de index.
Când timer-ul se declanșează, ISR-ul citește senzorul. Actualizează indexul global, stochează integer-ul raw în bytearray la acea poziție și iese. Spațiul de memorie a fost rezervat în întregime dinainte. Interrupt-ul doar îl actualizează in place, garantând o execuție fără jitter. Odată ce buffer-ul este plin, ISR-ul trebuie să predea datele programului principal. Nu poți declanșa o funcție complexă de procesare a datelor direct din hard ISR. În schimb, folosești micropython dot schedule. Această funcție ia o referință către un callback și îl pune în queue pentru a rula imediat ce sistemul revine la o stare de execuție safe, de tip soft.
Gestionarea de hardware interrupts te obligă să nu te mai gândești la Python ca la un resource pool infinit și să începi să urmărești exact când și unde îți este alocată memoria. Verifică documentația oficială MicroPython pentru comportamentul specific al interrupt-urilor pe hardware port-ul tău și încearcă să încalci intenționat regulile de memorie pe propria placă pentru a vedea cum reacționează sistemul. Dacă vrei să sugerezi subiecte pentru următoarea noastră serie, intră pe devstories dot eu. Aș vrea să îmi iau un moment să îți mulțumesc pentru că ne asculți — ne ajută foarte mult. Să ai o zi super!
Tap to start playing
Browsers block autoplay
Share this episode
Episode
—
Copy this episode in another language:
Acest site nu folosește cookie-uri. Furnizorul nostru de hosting ar putea înregistra adresa ta IP în scopuri de analiză. Află mai multe.