PetaJoule (18 hrs)
WHIP Nodes: Mikrokontroléry v chytré domácnosti
V prvním díle jsem představil WHIP jako celek. Nyní se podíváme na nejnižší vrstvu - nodes. Ty malé STM32 desky, co sedí v rozvaděčích a starají se o skutečnou práci.
Hardware: Proč STM32?
Na Arduino jsem se díval v rámci MySensors evaluace. Výsledek: za stejnou cenu dostanu 10x výkonnější STM32 + FreeRTOS místo "while(1) loop + mišmaš". RasPi Pico mám taky - ten WHIP umí integrovat jako
celkem inteligentní a výkonnou periferii, ale ne jako hlavní
node. Plus potřebuju:
Integrovaný CAN kontroler (ne externí modul)
Deterministické real-time chování
Průmyslovou kvalitu a dlouhodobou dostupnost
Rozumnou cenu při větších objemech
STM32 tohle všechno splňuje. Konkrétně používám dvě rodiny:
STM32F103 (Cortex-M3, 72 MHz)
128 KB flash, 20 KB RAM
Obě rodiny mají nativní bxCAN kontroler - žádný externí MCP2515, žádné SPI bottlenecky
STM32F303 (Cortex-M4F, 72 MHz)
FPU pro floating-point operace
Lepší ADC (dual simultaneous sampling)
Používám ho tam, kde potřebuju víc výkonu nebo přesnější měření
Podporované desky:
Nucleo-F103RB - reference pro F103
Blue Pill - levné, ale pozor na kvalitu
RobotDyn Black Pill - kvalitnější varianta Blue Pill
Green Pill - vlastní PCB od PetaJoule, přesně pro WHIP potřeby
STM32F3Discovery - reference pro F303
Nucleo-F303K8 - kompaktní F303 varianta
Tenhle výčet ukazuje genericitu - firmware běží na různých deskách od různých výrobců, stačí změnit konfiguraci.
Software: FreeRTOS + libopencm3
Mohl jsem psát bare-metal, ale proč? FreeRTOS mi dává:
Přepínání úloh - každý modul běží ve vlastní úloze
Timery a synchronizaci
Soft real-time garantie (milisekundová přesnost stačí)
Pro HAL používám libopencm3 místo STM32Cube. Důvody:
Transparentní - vidím, co se generuje
Žádná vendor lock-in magie
Open source, dlouhodobě udržitelné
Funguje napříč STM32 rodinami
STM32Cube je fajn pro prototypování, ale nechci být závislý na ST code
generatoru pro systém, co má běžet 50 let.
Modulární architektura
Tady to začíná být zajímavé. Firmware není monolitický blob - je
složený z modulů. Momentálně jich mám přes 115:
Kategorie:
Senzory: teplota/vlhkost (BME280, SHT4x, DHT), světlo (BH1750, TSL256x), proud/napětí (INA2xx), vzdálenost (VL53Lxx, HCSR04)...
Expandéry: PCF8574, PCF8575, MCP230xx, PCA9548 (I2C mux)
Displeje: SSD1306, SH110x, ST7789, HD44780, TM1637, MAX72xx
Aktory: switch-core, buzzer, ws281x, steppery (A4988, DRV8825)
Paměti: AT24Cxx (EEPROM), MB85RCxx (FRAM), W25Qxx (SPI flash)
1-Wire: DS18x20, DS2401, DS2408, DS2413, DS2431, DS2438, DS2450
Komunikace: ganglion (CAN), NRF24L01, SX1276 (LoRa)
Každý modul má:
cfg.yaml - metadata, závislosti, CAN příkazy
src/*.c, *.h - implementace
doc/README.md - dokumentace
Kombinatorika: Závislosti a konfigurace
Tady to začíná být zajímavé.
115 modulů. Teoreticky 2^115 možných kombinací - číslo s 35
číslicemi. Samozřejmě ne každá kombinace má smysl a ne každá se vejde
do paměti. Ale prakticky? Na F103 se vejde tak 10 modulů, na F303
třeba 20. To je pořád C(115,10) respektive C(115,20) - miliardy až
biliony reálných konfigurací.
Jeden node může mít BME280 (teplota/vlhkost/tlak) + INA226
(proud/napětí) + PCF8574 (8 relé) + SSD1306 (displej) + buzzer. Jiný
jen DS18B20 a switch_core pro žaluzie. Každá kombinace je jiný
firmware, automaticky sestavený ze stejných stavebních bloků.
K tomu závislosti mezi moduly. Každý modul v cfg.yaml deklaruje:
Resolver funguje jako strážce. Když povolím switch_core:
Podívá se na requires - potřebuje (pcf8574 | pcf8575)
Zkontroluje, že uživatel povolil alespoň jeden z nich
Pokud ne → chyba, build selže s jasnou hláškou
Rekurzivně zkontroluje závislosti všech povolených modulů
Topologicky seřadí inicializační pořadí
Vygeneruje směrovací tabulky pro CAN příkazy
Systém nevybírá za vás - hlídá, že vaše volba dává smysl. Trochu jako
konfigurace linuxového jádra, kterou jsem se nechal inspirovat.
Z tohohle build systém vygeneruje:
Makefile definice (které moduly kompilovat)
Hlavičky s výčty (kódy CAN příkazů)
Směrovací tabulky (směrování CAN zpráv)
Inicializační sekvenci (topologicky seřazenou)
Výsledek: Jeden YAML soubor definuje celý node. Zbytek je automatický.
Build systém
Centrální nástroj je wm_generator (Perl). Jeden příkaz:
...a máte zkompilovaný firmware. Co se děje pod kapotou:
Načte konfiguraci nodu + všechny cfg.yaml modulů
Vyřeší závislosti
Vygeneruje hlavičky a Makefile definice
Spustí make (arm-none-eabi-gcc)
Archivuje sestavení s časovým razítkem
Vývoj běží pod gitem na vlastním GitLabu. Od roku 2024 s pomocí AI,
ale pod mým přísným dohledem - AI generuje dle mé specifikace, já
reviduju a rozhoduju. Žádné slepé copy-paste.
Jinak na sebe i AI šiju neustále bič. Testy testy testy testy! Hlavně
proti regresi. Pro CI/CD mám i test kombinatoriky:
Tohle zkompiluje všechny kombinace zadaných modulů a reportuje, které
projdou a které ne (přetečení paměti, konflikty, atd.).
Co dál?
Není realistické zde představit veškeré moduly, ale pár zajímavých modulů bych v příštím článku rád představil v detailu:
bootloader - vlastní CAN bootloader, nody se dají flashovat přes CAN bez fyzického přístupu
switch-core - centrální modul pro řízení výstupů: relé, žaluzie, PWM, vše jednotně
bme280 - teplota/vlhkost/tlak, plus výpočet rosného bodu přes Magnusovu formuli přímo na nodu
buzzer - melodie a signalizace
heartbeat - "tep" signalizace stavu node
pp-flow - měření průtoku (pulsní průtokoměry)
ws281x - adresovatelné LED pásky. Pro víc pásků najednou může RasPi Pico jako inteligentní periferie řídit až 4 stringy.