# Událostně řízené programování na Arduino: návrhové vzory z enterprise do embedded
Arduino je tradičně spojováno s lineárními sketchemi a cyklickým loop(). Při složitění projektů však tento přístup vede ke spaghetti kódu. Představujeme metodiku přenosu událostně orientované architektury z enterprise aplikací do embedded vývoje s pomocí knihovny EVA Core.
Problém struktury v mikrokontrolérech
V desktopových a serverových aplikacích je kód organizován kolem obsluh událostí: kliky, časovače, síťové pakety. Arduino však nutí psát vše uvnitř jediného loop(), kde je třeba manuálně sledovat stavy přes millis() a vlajky. To vytváří dvě kritická omezení:
- Nemožnost izolovat logiku komponent – časování se „protáhnou“ přes celou hierarchii objektů
- Absence jasných kontraktů mezi moduly ohledně časových požadavků
Standardní knihovny pro Arduino řeší věci fragmentárně: jsou obsluhy tlačítek, zvlášť časovače, ale chybí jednotný systém událostí. Pokusy posbírat „vše do jednoho“ narazí na tuhou vazbu na konkrétní implementaci loop().
EVA Core: tři komponenty v jednotném systému
Knihovna EVA Core (Event-Driven Architecture) řeší problém prostřednictvím tří interagujících vrstev:
- Callback-ově mechanismus pro metody tříd – umožňuje přihlašovat se k událostem bez globálních funkcí
- Rozhraní Tickable – dává objektům přístup k časovému cyklu přes metodu tick()
- Survival Kit – sada připravených komponent (tlačítka, časovače), postavených na prvních dvou principech
Klíčová inovace – oddělení časové logiky od business pravidel. Senzor sám řídí svá časování, aplikace reaguje pouze na události. To umožňuje:
- Izolovat algoritmy filtrování a debounce v komponenty
- Garantovat rytmus aktualizace pro vnořené objekty
- Odstranit nutnost „protáhnutí“ volání přes hierarchii
Podívejme se na implementaci na příkladu senzoru teploty:
#include <evaTickable.h>
#include <evaHandler.h>
using namespace eva;
class TempSensor : public Tickable {
private:
IHandler* listener = nullptr;
unsigned long lastRead = 0;
public:
void subscribe(IHandler* handler) {
listener = handler;
}
private:
void tick() override {
if (millis() - lastRead > 1000) { // Interval 1 sek
int value = readTemperature();
if (listener && value != lastValue) {
CallbackInfo info;
info.eventType = TEMP_UPDATE;
info.eventArg = value;
listener->invoke(this, info);
}
lastRead = millis();
}
}
};
class ClimateControl : public IHandler {
private:
TempSensor sensor;
void onTempUpdate(int value) {
if (value > 25) activateCooling();
}
public:
ClimateControl() {
sensor.subscribe(this);
}
void invoke(void* sender, CallbackInfo info) override {
if (info.eventType == TEMP_UPDATE) {
onTempUpdate(info.eventArg);
}
}
};
void setup() {
static ClimateControl system;
}
void loop() {
eva::tac(); // Edinaya point update
}
Výhody přístupu:
- TempSensor kapsuluje logiku pollingu a filtrování
- ClimateControl zná pouze události, ne časové detaily
- Přidání nových senzorů nevyžaduje změnu loop()
- Testování business logiky izolovaně od času
LEGO architektura pro periferii
Survival Kit realizuje princip kompozice prostřednictvím šablon kompilace. Například zpracování multi-tlačítka na analogovém vstupu se staví řetězcem dekorátorů:
template <int PIN, int PIN_MODE, signed short... LEVELS>
using PinMultiButton = Button<QuantizeDecor<DebounceDecor<AnalogPinReader<PIN, PIN_MODE>>, LEVELS...>>;
Architektura zpracování signálu:
- Analogový signál →
- Debounce →
- Kvantizace podle úrovní →
- Logika tlačítka →
- Události
Tento vzor umožňuje sestavovat vlastní obsluhy z hotových komponent. Příklad – klávesnice z diskrétních tlačítek:
#include <evaSwitch.h>
class MyKeypad {
public:
MyKeypad() {
pinMode(2, INPUT_PULLUP);
// ... initialization ostalnykh pinov
}
signed short getValue() {
if (digitalRead(2) == LOW) return 'u';
// ... processing drugikh knopok
return 0;
}
};
// Withborka chains processing
Switch<DebounceDecor<MyKeypad>> keypad;
// Podpiska on events
keypad.setListener(new Handler<App>(this, &App::onKeyPress), ON_PRESS);
Každá vrstva odpovídá za svou oblast odpovědnosti. Při potřebě lze nahradit debounce složitějším algoritmem nebo přidat filtrování podle délky stisku – bez změny hlavní logiky aplikace.
Omezení a scénáře použití
EVA Core se pozicionuje jako metodický nástroj, nikoli univerzální řešení. Používat ho při:
- Vytváření projektů se složitou hierarchií objektů
- Potřebě jasného oddělení časové a business logiky
- Výuce principů event-driven architektury na jednoduchých zařízeních
Kritická omezení:
- Vyšší spotřeba RAM kvůli virtuálním tabulkám
- Složitost pro začátečníky (vyžaduje znalosti šablon a pointerů na metody)
- Nadbytečnost v jednoduchých projektech (např. ovládání jedné LED)
Důležité si uvědomit: cíl knihovny je demonstrace návrhových vzorů, ne optimalizace zdrojů. Pro produkční projekty s přísnými limity bude nutná analýza overheadu.
Co je důležité
- Událostní model umožňuje izolovat časové závislosti v komponenty
- Rozhraní Tickable zaručuje pravidelnou aktualizaci vnořených objektů
- Šablonová kompozice poskytuje flexibilitu bez runtime overheadu
- Odmítnutí „protáhnutí“ volání usnadňuje refactoring a testování
- Arduino se stává platformou pro studium enterprise vzorů
Tento přístup dokazuje, že i na omezených mikrokontrolérech lze aplikovat profesionální návrhové metody. Klíčový přínos – kód je předvídatelný a škálovatelný, ne „jen ať to jede".
— Editorial Team
Zatím žádné komentáře.