Zpět na domů

Událostně řízené programování na Arduino: vzory a příklady

Článek demonstruje implementaci událostně orientované architektury v Arduino-projektech prostřednictvím knihovny EVA Core. Jsou zváženy principy kompozice komponent, příklady kódu pro senzory a periferii, omezení přístupu. Materiál je určen pro middle/senior vývojáře.

Událostní model pro Arduino: od teorie k praxi
Advertisement 728x90

# 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().

Google AdInline article slot

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:

Google AdInline article slot
#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:

Google AdInline article slot
  • 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

Advertisement 728x90

Číst dál