Les 2 · Module 1 · De ESP32 als sensorknooppunt
Projectstructuur: boot.py, main.py en modules
Deel de code van het meetstation op in modules met een eigen lib-map, een config-bestand en een veilig opstartpad, en leer hoe imports, geheugen en bytecode op een microcontroller werken.
🎯 Na deze les kun je
- een MicroPython-project opdelen in modules en een lib-map
- een veilig opstartpad maken zodat je nooit buitengesloten raakt
- bestanden synchroniseren met mpremote en een klein script
- geheugen besparen met mpy-cross en const()
Een meetstation wordt al snel honderden regels: sensoren, scherm, wifi, MQTT, configuratie. Alles in main.py is onoverzichtelijk en
lastig te testen. In deze les zet je de structuur neer die je de rest van de cursus gebruikt.
De mappen
Op je computer:
meetstation/
boot.py
main.py
config.py # instellingen (les 17 haalt geheimen hieruit)
lib/
sensor.py # les 3
filter.py # les 4
scherm.py # les 5
net.py # les 8
tools/
upload.sh
MicroPython zoekt modules in / en /lib (zie import sys; print(sys.path)). Bibliotheken van anderen (bijv. ssd1306.py) horen ook in lib/.
main.py als dirigent
# main.py
import time
import config
from lib import sensor # of: import sensor (lib staat in sys.path)
def start():
print("meetstation", config.NAAM, "start")
while True:
print("meting...")
time.sleep(config.INTERVAL_S)
try:
start()
except KeyboardInterrupt:
print("gestopt")
# config.py
NAAM = "woonkamer"
INTERVAL_S = 10
Een veilig opstartpad
Voorspel eerst: je zet een main.py met een fout die meteen machine.deepsleep() aanroept, of een lus die de USB-poort volspamt. Hoe
kom je nog bij je bordje?
Uitkomst
Lastig: het bordje herstart, draait main.py meteen opnieuw, en mpremote krijgt geen tijd om te verbinden. Vaak lukt het nog door
direct na het aansluiten heel snel Ctrl+C te sturen, en anders moet je opnieuw flashen (en ben je je bestanden kwijt). Voorkom het met een
ontsnappingsluik bovenaan main.py: als een knop bij het opstarten ingedrukt is, stopt main.py meteen en kom je in de REPL.
# main.py (bovenaan)
from machine import Pin
import time
BOOTKNOP = Pin(0, Pin.IN, Pin.PULL_UP) # BOOT-knop op de meeste DevKits
time.sleep_ms(300)
if BOOTKNOP.value() == 0:
print("veilige modus: programma niet gestart")
raise SystemExit
Een exception die main.py beëindigt, brengt je naar de REPL. Houd de BOOT-knop ingedrukt, druk kort op EN (reset) en laat BOOT na een
seconde los: je komt in de veilige modus. Houd boot.py zelf zo klein mogelijk; een fout dáár is lastiger te herstellen. Daarnaast is een
paar seconden wachten in main.py vóór een deep sleep een goede gewoonte (les 15).
Uploaden
#!/usr/bin/env bash
# tools/upload.sh
set -e
mpremote mkdir :lib 2>/dev/null || true
for f in boot.py main.py config.py; do mpremote cp "$f" ":$f"; done
for f in lib/*.py; do mpremote cp "$f" ":$f"; done
mpremote reset
Tijdens ontwikkelen: mpremote mount . run main.py gebruikt je bestanden direct vanaf je computer, zonder kopiëren.
Geheugen en bytecode
Bij een import compileert MicroPython de broncode naar bytecode, in het RAM. Grote modules kunnen daardoor een MemoryError geven bij
het importeren. Twee hulpmiddelen:
pip install mpy-cross
mpy-cross lib/sensor.py # maakt lib/sensor.mpy: voorgecompileerd, kleiner, sneller te laden
Kopieer dan sensor.mpy in plaats van sensor.py (de mpy-cross-versie moet bij je firmware passen). En voor constanten:
from micropython import const
ADRES = const(0x76) # wordt bij compileren ingevuld; kost geen geheugen voor een variabele
Typische fouten
ImportError: no module named 'sensor': bestand niet gekopieerd, of in de verkeerde map. Kijk metmpremote ls :lib.- Oude code draait nog: je kopieerde naar het bordje, maar er staat ook een oude
.mpydie voorrang heeft. Verwijder hem. ValueError: incompatible .mpy file: mpy-cross-versie past niet bij de firmware.
Oefenen
- Zet de mappenstructuur op met
boot.py,main.py,config.pyen een legelib/sensor.py. - Voeg het ontsnappingsluik toe bovenaan
main.pyen test het. - Schrijf
tools/upload.sh(of een.bat/PowerShell-versie) en gebruik hem. - Meet met
gc.mem_free()het vrije geheugen vóór en naimport sensor, met.pyen met.mpy.
Modelantwoord oefening 1
mpremote ls toont boot.py, main.py, config.py en de map lib/; mpremote ls :lib toont sensor.py.
Modelantwoord oefening 2
Houd BOOT ingedrukt, druk kort op EN (reset), laat BOOT na een seconde los. In mpremote zie je "veilige modus" en de prompt >>>.
Modelantwoord oefening 3
Zie Uploaden. Op Windows in PowerShell: foreach ($f in "boot.py","main.py","config.py") { mpremote cp $f ":$f" }.
Modelantwoord oefening 4
import gc
gc.collect(); voor = gc.mem_free()
import sensor
gc.collect(); print(voor - gc.mem_free(), "bytes")
Met een .mpy is het verschil kleiner, omdat de compilatie niet op het bordje gebeurt. Doe een reset tussen de metingen, want een module wordt maar één keer geïmporteerd.
Lokaal oefenen
Geen live lab. Werk met mpremote mount . zodat je na elke wijziging alleen main.py opnieuw hoeft te starten.
Samenvatting
- Code in modules in
lib/, instellingen inconfig.py,main.pyals dirigent. - Een ontsnappingsluik bovenaan
main.pyvoorkomt dat je buitengesloten raakt. - Upload met een script; ontwikkel met
mount. mpy-crossenconst()besparen geheugen.- Volgende les: sensoren via I2C.