Bonjour
Je me suis aperçu que beaucoup de débutants ne savait pas bien comment découper leur code proprement pour gérer plusieurs tâches sur un système qui n'a pas de noyau multi-tâches.
D'habitude, je pousse beaucoup sur l'utilisation de machines d'états qui sont de mon point de vue une manière propre, claire, maintenable de subdiviser une tâche principale en sous-tâches élémentaires et à gérer à la fois leur séquencement propre et "l'entremelage" manuel qu'il faut effectuer pour obtenir ce que j'appelle du multi-tâche coopératif.
Avant d'élaborer sur ce sujet (peut être dans un tuto), un problème récurrent est la gestion des opérations répétitives ou liées à l'expiration d'un délai. On voit trop souvent dans les codes des appels à la fonction delay() ou des attentes bloquantes. Or ces fonctions vont monopoliser le coeur de l'Arduino à ne rien faire qu'attendre alors qu'on a peut être d'autres choses à faire qui vont alors prendre du retard. Adieu le temps réel.
C'est pourquoi je vous propose une lib qui implémente une classe appellée SoftTimer. Ayant l'habitude d'autres environnements tels que .Net (C#) ou une telle classe existe de manière native je me suis empressée de la recréer.
Le principe est de gérer pour vous des timers purement logiciels, soit à usage unique (gestion de délai, timeout, ...) soit répétitifs. Ces timers doivent être basés sur une classe dérivée de SoftTimer. Une fois définie la période du timer, son mode (SINGLE ou REPEAT) et qu'on l'a démarré par start(), il vit sa vie. A condition bien sur d’appeler la fonction manage() depuis la loop() principale.
Cette lib n'utilise aucun timer hard ni interruption, donc elle a besoin que vous fassiez encore des efforts pour que loop() tourne bien et qu'il ne traine aucun code bloquant à l'intérieur.
Je comptais faire aussi une lib avancée basée timer hard et interruption mais je viens de m'appercevoir qu'elle existait déjà (TimerOne).
L'avantage de cette version purement soft est que n'utilisant aucun timer hard, elle ne rentre pas en conflit avec les libs PWM ou Servo.
Vous pouvez télécharger le ZIP de la lib incluant un soft d'exemple en bas de ce post, sur l'historique (On ne peut pas attacher de fichier à un post sur ce forum ?)
Les commentaires du code étant en anglais, je vous fais ici un résumé de l'utilisation en français.
But Permettre de gérer facilement des évènements répétitifs ou retardés.
La bibliothèque fournit une classe de base qu'il faut dériver afin de surcharger la méthode handler() qui fait le boulot pour laquelle le timer est créé.
Méthode de la classe
SoftTimer( period = -1, mode = REPEAT)
Constructeur.
Permet de définir une période initiale (par défaut égale au max possible) ainsi que le mode de fonctionnement par défaut.
Les 2 paramètres peuvent être changés à tout moment durant la vie du timer par les membres setPeriod() et start().
void begin( void )
Méthode statique la classe de base. Il faut impérativement appeller SoftTimer::begin() une fois dans setup() avant d'utiliser toute fonction de la bibliothèque.
void manage( void )
Méthode statique de la classe de base. Il faut impérativement appeller SoftTimer::manage() une fois dans loop().
void setPeriod( period )
Permet de changer a tout moment la période d'un timer, même quand il est actif.
Par défaut, la bibliothèque marche en microsecondes (changeable par un #define dans le code source)
void start()
Rend le timer actif avec le mode définit lors de la construction, ou le dernier mode utilisé par start( mode ).
void start( mode )
Rend le timer actif avec le mode passé en paramètre (SINGLE ou REPEAT). Ce mode devient le mode par défaut pour les prochains appels à start() sans paramètres.
void stop()
Rend le timer inactif.
bool isActive()
Renvoie true si le timer est actif. Permet par exemple de tester si un timer en mode SINGLE est arrivé à expiration (gestion de timeout par exemple).
void reset()
Remet le compteur à zéro et repart pour une période pleine.
void handler()
Fonction de traitement qu'il faut surcharger dans la classe dérivée. Le handler() sera appellé chaque fois que le compteur atteint la période programmée.
#define TIMER_DEBUG 1
Dans SoftTimer.h, cette macro (définie à 1 par défaut) active la définition de 2 méthodes supplémentaires pour le debug (voir ci-dessous).
En mettant cette ligne en commentaire, les 2 fonctions sont désactivées ce qui peut économiser quelques octets supplémentaires en flash.
void SoftTimer::printActive()
Méthode statique qui liste sur Serial tous les timers actifs avec leur paramètres.
void print()
Méthode qui affiche sur Serial les paramètres courant du timer (actif ou non).
Je vous invite à regarder le code exemple qui de mon point de vue montre bien combien il est facile d'utiliser cette bibliothèque de classe.
J'ai choisit volontairement le concept où il faut dériver sa propre classe de SoftTimer car je trouve que cela permet un code plus clair.
Commentaire ? Questions ?
Historique:
1.0 17 avril 2012 - Version Initiale
1.0a 18 avril 2012 - Support automatique IDE pre-1.0 et 1.0
SoftTimer-1_0a.zip (6.36 KB)