Programmation modulaire et multitaches avec arduino.

Catégorie: Arduino (Mis à jour le 14-03-2016 21:00:00)

Les cartes arduino sont des microcontrôleurs abordables et simples à programmer. Mais les programmes faits pour arduino sont souvent des usines a gaz très peu modulaires. Comme la carte n'est capable de faire tourner qu'un seul programme a la fois, il est difficile de combiner plusieurs fonctionnalités simplement.

Par exemple pour mon robot, l'arduino devra gérer un esp8266 pour la connectivité wifi, des capteurs à ultrasons et une batterie de servos et de moteurs.

Dans l'idéal tout ces sous-programmes devrons êtres séparés et se partager le temps de calcul de l'arduino. C'est ce que je vais vous montrer dans la suite. Il y a beaucoup de code et l'article est assez long, mais je vais essayer de tout détailler pour ne perdre personne en cours de route.

Dans l'idéal tout ces sous-programmes devrons êtres séparés et se partager le temps de calcul.

Le code sera réalisé en C++ car la programmation orienté objet apporte beaucoup de clareté au code. Si vous ne maitrisez pas l'objet pas de panique, je donne des extraits de code dans la suite (et sinon, il y a les commentaires en bas de page! ;) ).

Cet article est relativement long et difficle. Jespére ne perdre personne en route!

Les modules

Notre programme sera donc constitué de modules indépendants, représenté par des classes. Pour rappel, une classe est un ensemble d'attributs (variables) et de méthodes. On peux avoir plusieurs versions (instances) d'une même classe en simultané sans conflit entre elles.

Voici donc l'interface (la classe de base) de nos modules:

Chaque module est composé d'une partie d'initialisation, et d'une partie exécutée en boucle. Cela respecte l'organisation en setup/loop proposée par l'environnement de l'arduino. En gardant cette structure, on simplifie le code et on rend chaque sketch déjà écrit compatible sans modification majeure. Il y a aussi un méthode getName qui retourne le nom du module.

Mes modules s'apellent Brain. Comme je travaille sur un robot, c'est logique qu'il aie un cerveau! Libre à vous de renommer les classes pour quelque chose qui à plus de sens pour vous.

Comme les modules doivent se partager le temps de calcul de l'arduino, la méthode tick retourne un int. Cet int représente le temps (en millisecondes) a attendre avant de rapeller la fonction tick. C'est une sorte de delay, mais non bloquant. Ce temps sera utilisé pour faire tourner les autres modules.

Un module de base

Commençons par défini un module de base. Quelque chose qui va valider que tout fonctionne. Pour ça, le plus simple est de faire clignotter la led de la carte (celle qui est reliée au pin 13).

On défini donc notre module (nommé StatusLed) qui étend AbstractModule:

Ce module redéfini les méthode getName, initialize et tick comme le demande l'interface AbstractBrain. Les variables isOn et blinkFreq servent a stocker respectivement l'état de la led et la fréquence de clignottement de celle-ci.

Le code associé à cette interface est disponible via le lien en dessous:

Téléchargez le code de StatusLed.c

Nous avons donc maintenant un module de base. Passons maintenant à l'ordonnanceur, c'est a dire le coeur qui va orchestrer tout ça!

L'ordonanceur

Pour répartir le temps entre les différents modules, nous avons besoin d'un ordonnanceur. C'est lui qui s'occupera de donner la main à chaque module tour à tour.

Basiquement, le but de l'ordonanceur est de rajouter une couche entre les fonctions boot et loop d'arduino et le code qui sera executé.

Voici l'interface de cette classe:

La première structure qui contiendra les informations spécifiques a chaque Module. Cette structure contiendra un pointeur vers la classe du module, ainsi que la date de derniére execution et l'intervalle avant la prochaine. La méthode inline isDue sert a définir si le module doit être éxécuté ou non.

La seconde classe représente l'ordonnanceur en lui-même. On retrouve les méthodes initialize et tick qui iront respectivement dans le boot et le loop d'arduino. Les méthodes addModule et removeModule permettent d'ajouter/supprimmer des modules à executer. Enfin, les méthodes printModules et printModule (sans S cette fois!) servent au débuggage.

Le code actuel qui implémente cette seconde classe est disponible dessous:

Téléchargez le code de Brain.c

Premier lancement

Il est enfin temps de lancer tout ce code sur un arduino. Placez tous les fichiers .h et .c dans le dossier de votre .ino.

Voici a quoi doit ressembler un .ino maintenant.

Votre fichier ino ne sert plus qu'a déclarer les modules à executer. Tout le code est séparé dans des modules indépendants et notre classe Brain s'occupe automatiquement de partager le temps entre tous les modules !

Normalement, la led de votre arduino qui clignotte indique fiérement la fin de cet article! Merci à tout ceux qui on eu le courage de continuer jusque la. N'hésitez pas a réagir dans les commentaires si vous voulez plus d'articles de ce style.

A lire aussi:

Une sonde de temperature à distance pour arduino

[Arduino] Avec arduino et une sonde de température, on peux faire des choses intéréssantes. Voici ma démarche pour améliorer votre projet domotique avec une sonde de température esthétique et sans fil!
Suite...

Bien choisir sa carte arduino

[Arduino] Il existe une multitude de cartes arduino différentes et il est difficile de choisir la bonne. Voici mon avis sur les principales cartes arduino afn de vous aider a faire le bon choix pour votre projet.
Suite...