Do programowania ESP32 w domu zwykle używa się ESPHome, Tasmoty albo środowiska Arduino. Jest jednak jeszcze jedna możliwość, wygodna dla osób znających Pythona: MicroPython. To interpreter Pythona działający bezpośrednio na mikrokontrolerze. Polecenia wpisujesz w interaktywnej konsoli (REPL), wyniki widzisz od razu, a pliki .py kopiujesz na płytkę jak na pendrive’a. W tym poradniku wgrasz MicroPythona na klasyczną płytkę ESP32, odczytasz czujnik DHT22 i wyślesz odczyty do brokera MQTT razem z ostatnią wolą. Wszystkie narzędzia i funkcje pochodzą z oficjalnej dokumentacji.
Czego potrzebujesz
- Płytki rozwojowej ESP32 z co najmniej 4 MiB pamięci flash (większość płytek z modułem WROOM).
- Kabla USB do transmisji danych, a nie tylko do ładowania.
- Czujnika DHT22 (AM2302). MicroPython ma do niego wbudowany sterownik, dzięki czemu pierwszy projekt jest prostszy. Jeśli zależy ci na dokładności, zajrzyj do naszego porównania czujników temperatury i wilgotności.
- Brokera MQTT w sieci lokalnej, na przykład Mosquitto.
- Pythona 3 na komputerze.
Zainstaluj narzędzia
Do wszystkiego wystarczą dwa narzędzia wiersza poleceń:
pip install esptool mpremote
esptool to narzędzie Espressif do wgrywania oprogramowania. mpremote to oficjalne narzędzie MicroPythona do obsługi konsoli REPL, plików i pakietów.
Uwaga na wersje esptool: od wersji 5 polecenie nazywa się esptool (a nie esptool.py), a w nazwach poleceń zamiast podkreślników są łączniki, na przykład write-flash zamiast write_flash. Według przewodnika migracji Espressif stare nazwy nadal działają z ostrzeżeniem, ale znikną w następnej wersji głównej. Na stronie pobierania MicroPythona wciąż widnieje stara forma; poniższe polecenia używają nowej.
Pobierz i wgraj oprogramowanie
Otwórz stronę pobierania MicroPythona dla ESP32 / WROOM (ESP32_GENERIC) i pobierz najnowszy plik .bin z pierwszej sekcji. Na stronie są też warianty dla płytek z pamięcią SPIRAM (WROVER), układów jednordzeniowych, układów D2WD z 2 MiB pamięci flash i płytek wymagających aktualizacji przez sieć (OTA). Jeśli nie masz pewności, dla większości płytek właściwy będzie wariant podstawowy. Inne układy (ESP32-S2, -S3, -C3, -C6) mają osobne strony pobierania.
Podłącz płytkę i wyczyść pamięć flash. Przy pierwszej instalacji MicroPythona jest to konieczne:
esptool erase-flash
esptool zwykle sam znajduje port szeregowy. Jeśli go nie znajdzie albo podłączonych jest kilka płytek, dodaj --port, na przykład --port /dev/ttyUSB0 w Linuksie lub --port COM4 w Windows.
Następnie wgraj oprogramowanie. Dla klasycznego ESP32 na stronie pobierania podano adres 0x1000:
esptool --baud 460800 write-flash 0x1000 ESP32_GENERIC-DATA-WERSJA.bin
Zamień nazwę pliku na pobraną. Jeśli wgrywanie przerwie się w połowie, na stronie MicroPythona zalecono usunięcie --baud 460800, żeby wgrać oprogramowanie z wolniejszą, domyślną prędkością. Jeśli esptool w ogóle nie może nawiązać połączenia, w samouczku MicroPythona dla ESP32 opisano ręczne przejście w tryb pobierania: przytrzymaj przycisk BOOT (lub IO0), naciśnij i puść przycisk reset, a potem puść BOOT.
Przywitaj się w konsoli REPL
Uruchom mpremote bez argumentów. Narzędzie łączy się z pierwszym znalezionym urządzeniem szeregowym USB i otwiera konsolę REPL (jeśli używasz innego programu terminalowego, prędkość to 115200 bodów). Naciśnij Enter, a powinien pojawić się znak zachęty >>>:
>>> import sys
>>> sys.implementation
Z mpremote wychodzi się skrótem Ctrl+] lub Ctrl+X.
Połącz się z Wi-Fi
W skróconym opisie MicroPythona dla ESP32 podano taki wzorzec łączenia z siecią:
import network
wlan = network.WLAN()
wlan.active(True)
if not wlan.isconnected():
wlan.connect('ssid', 'key')
while not wlan.isconnected():
pass
print('network config:', wlan.ipconfig('addr4'))
Według tego opisu po wywołaniu connect() ESP32 domyślnie bez końca ponawia próby połączenia, nawet przy złym haśle albo braku punktu dostępowego w zasięgu.
Odczytaj DHT22
Podłącz czujnik: VCC do 3,3 V, GND do GND, a DATA do GPIO4. Moduły na małej płytce zwykle mają już rezystor podciągający na linii DATA; sam czujnik wymaga dodania takiego rezystora między DATA a 3,3 V. Następnie w konsoli REPL:
import dht, machine
d = dht.DHT22(machine.Pin(4))
d.measure()
d.temperature(), d.humidity()
Te same wywołania znajdziesz w skróconym opisie. Między pomiarami zachowaj co najmniej 2 sekundy, bo taki jest okres pomiarowy czujnika.
Zainstaluj klienta MQTT
Klient MQTT umqtt.simple jest częścią micropython-lib. Zainstalujesz go z komputera poleceniem:
mpremote mip install umqtt.simple
mpremote pobiera pakiet i kopiuje go na płytkę przez USB, więc na tym etapie płytka nie potrzebuje dostępu do internetu.
Warto znać dwa ograniczenia, oba widoczne w kodzie źródłowym biblioteki: umqtt.simple nie łączy się ponownie automatycznie i nie obsługuje publikowania z QoS 2. Dla czujników QoS 0 i 1 w zupełności wystarczą. Do automatycznego ponawiania połączenia służy osobny pakiet umqtt.robust; w przykładzie poniżej błędy kończą się po prostu ponownym uruchomieniem płytki.
Cały program
Po starcie płytki MicroPython wykonuje najpierw boot.py, a potem main.py, więc program umieść w main.py. Uzupełnij nazwę sieci, hasło, adres brokera i konto MQTT:
import time, machine, network, dht
from umqtt.simple import MQTTClient
WIFI_SSID = 'nazwa-sieci'
WIFI_KEY = 'haslo-wifi'
BROKER = '192.168.1.10'
MQTT_USER = 'sensor'
MQTT_PASSWORD = 'haslo-mqtt'
BASE = b'home/livingroom/esp32'
def wifi():
wlan = network.WLAN()
wlan.active(True)
if not wlan.isconnected():
wlan.connect(WIFI_SSID, WIFI_KEY)
for _ in range(30):
if wlan.isconnected():
break
time.sleep(1)
if not wlan.isconnected():
raise OSError('no wifi')
def main():
wifi()
sensor = dht.DHT22(machine.Pin(4))
client = MQTTClient('esp32-livingroom', BROKER, user=MQTT_USER,
password=MQTT_PASSWORD, keepalive=120)
client.set_last_will(BASE + b'/status', b'offline', retain=True)
client.connect()
client.publish(BASE + b'/status', b'online', retain=True)
while True:
sensor.measure()
client.publish(BASE + b'/temperature', str(sensor.temperature()).encode(), retain=True)
client.publish(BASE + b'/humidity', str(sensor.humidity()).encode(), retain=True)
time.sleep(60)
try:
main()
except Exception as e:
print('error:', e)
time.sleep(10)
machine.reset()
Co robi program:
- Ostatnia wola. Przed połączeniem klient rejestruje w temacie stanu zachowywaną wiadomość
offline. Jeśli płytka straci zasilanie albo Wi-Fi, broker opublikuje ją po upływie czasu podtrzymania. Zaraz po połączeniu program publikuje zachowywaneonline. - Zachowywane odczyty. Panel uruchomiony później od razu dostaje ostatnią temperaturę i wilgotność.
- Czas podtrzymania 120 sekund przy odczycie co 60 sekund, więc regularne publikacje podtrzymują połączenie bez dodatkowych pakietów kontrolnych.
- Prosta obsługa błędów. Każda awaria (Wi-Fi, broker, czujnik) kończy się ponownym uruchomieniem po 10 sekundach. To rozwiązanie toporne, ale niezawodne w czujniku, który nie ma innych zadań.
Skopiuj plik na płytkę i uruchom ją ponownie:
mpremote cp main.py :main.py
mpremote reset
Obserwuj wiadomości na komputerze:
mosquitto_sub -h 192.168.1.10 -u UŻYTKOWNIK -P 'HASŁO' -t 'home/livingroom/esp32/#' -v
Odłącz płytkę od zasilania, a w ciągu około trzech minut (półtora czasu podtrzymania) stan zmieni się na offline.
Co dalej
- Przechowuj hasła do Wi-Fi i MQTT w osobnym pliku na płytce zamiast w
main.py, żeby móc udostępniać kod bez nich. - Podczas pracy nad kodem używaj
mpremote mount .: lokalny katalog jest wtedy widoczny na płytce jako/remotei nie trzeba kopiować plików po każdej zmianie. - Przy zasilaniu bateryjnym użyj
machine.deepsleep(). Płytka uruchamia się wtedy od nowa po każdym uśpieniu i wykonujemain.pyod początku, więc program trzeba zbudować inaczej. - Jeśli później wolisz plik konfiguracyjny zamiast kodu, na tej samej płytce można uruchomić ESPHome albo Tasmotę. MicroPython sprawdza się lepiej, gdy zależy ci na pełnej kontroli w znanym już języku.