# Programmation pilotée par les événements sur Arduino : Motifs d'entreprise pour l'embarqué
Arduino est traditionnellement associé à des croquis linéaires et à la boucle cyclique loop(). Mais à mesure que les projets deviennent plus complexes, cette approche conduit à du code spaghetti. Nous présentons une méthode pour importer l'architecture pilotée par les événements des applications d'entreprise dans le développement embarqué en utilisant la bibliothèque EVA Core.
Le problème de la structure dans les microcontrôleurs
Dans les applications de bureau et serveur, le code est organisé autour de gestionnaires d'événements : clics, minuteries, paquets réseau. Arduino, en revanche, force tout dans une unique loop(), où il faut suivre manuellement les états avec millis() et des drapeaux. Cela crée deux limitations critiques :
- Incapacité à isoler la logique des composants — les temporisations se propagent à travers toute la hiérarchie d'objets
- Absence de contrats clairs entre modules concernant les exigences de temporisation
Les bibliothèques standard Arduino n'abordent cela que de manière fragmentaire : il y a des gestionnaires de boutons, des minuteries séparées, mais pas de système d'événements unifié. Les tentatives de construire une solution « tout-en-un » aboutissent à un couplage serré avec une implémentation spécifique de loop().
EVA Core : Trois composants dans un système unifié
La bibliothèque EVA Core (Event-Driven Architecture) résout le problème grâce à trois couches interactives :
- Mécanisme de callback pour les méthodes de classe — permet de s'abonner aux événements sans fonctions globales
- Interface Tickable — donne aux objets accès à la boucle temporelle via la méthode tick()
- Survival Kit — un ensemble de composants prêts à l'emploi (boutons, minuteries) basés sur les deux premiers principes
Innovation clé — séparer la logique de temporisation des règles métier. Le capteur gère ses propres temporisations, tandis que l'application réagit uniquement aux événements. Cela permet :
- D'isoler les algorithmes de filtrage et d'antirebond dans les composants
- De garantir le rythme de mise à jour pour les objets imbriqués
- D'éliminer la nécessité de propager les appels à travers la hiérarchie
Voici un exemple d'implémentation avec un capteur de température :
#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
}
Avantages de l'approche :
- TempSensor encapsule la logique de polling et de filtrage
- ClimateControl ne connaît que les événements, pas les détails de temporisation
- Ajouter de nouveaux capteurs ne nécessite pas de modifier loop()
- Tester la logique métier isolée de la temporisation
Architecture LEGO pour les périphériques
Survival Kit implémente le principe de composition via des templates à temps de compilation. Par exemple, la gestion multi-boutons sur une entrée analogique est construite comme une chaîne de transformateurs :
template <int PIN, int PIN_MODE, signed short... LEVELS>
using PinMultiButton = Button<QuantizeDecor<DebounceDecor<AnalogPinReader<PIN, PIN_MODE>>, LEVELS...>>;
Architecture de traitement du signal :
- Signal analogique →
- Antirebond →
- Quantification par niveaux →
- Logique bouton →
- Événements
Ce motif permet d'assembler des gestionnaires personnalisés à partir de composants prêts à l'emploi. Exemple — un clavier à partir de boutons discrets :
#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);
Chaque couche gère sa propre responsabilité. Si nécessaire, vous pouvez remplacer l'antirebond par un algorithme plus sophistiqué ou ajouter un filtrage de durée d'appui — sans modifier la logique métier principale.
Limitations et cas d'usage
EVA Core est positionnée comme un outil méthodologique, pas une solution universelle. Utilisez-la quand :
- Vous construisez des projets avec des hiérarchies d'objets complexes
- Vous avez besoin d'une séparation claire entre temporisation et logique métier
- Vous enseignez les principes d'architecture pilotée par les événements sur des dispositifs simples
Limitations critiques :
- Augmentation de l'utilisation de la RAM due aux tables virtuelles
- Complexité pour les débutants (nécessite la connaissance des templates et des pointeurs de méthodes)
- Excès pour les projets simples (ex. : contrôle d'une unique LED)
Important à comprendre : l'objectif de la bibliothèque est de démontrer des motifs architecturaux, pas d'optimiser les ressources. Pour des projets de production avec des contraintes serrées, il faudra analyser le surcoût.
Points clés à retenir
- Le modèle événementiel isole les dépendances de temporisation dans les composants
- L'interface Tickable assure des mises à jour régulières pour les objets imbriqués
- La composition par templates offre de la flexibilité sans surcoût à l'exécution
- Plus de propagation d'appels simplifie la refactorisation et les tests
- Arduino devient un terrain de jeu pour les motifs d'entreprise
Cette approche prouve que même sur des microcontrôleurs à ressources limitées, on peut appliquer des méthodes de conception professionnelles. L'avantage clé — le code devient prévisible et scalable, plutôt que simplement « faire le job ».
— Editorial Team
Aucun commentaire pour le moment.