Le modeste programme présenté dans cet article est extrait d’un exercice de travaux pratiques que je propose aux participants de la formation « Programmation en C sur microcontrôleurs » que j’anime régulièrement. Cet exercice permet de réfléchir en profondeur sur le développement d’un petit projet sur microcontrôleur.
Comme l’objet même de la réalisation peut être utile au quotidien (je l’emploie personnellement), j’ai trouvé intéressant de le partager ici.
Le projet MSP-omodoro est un timer conçu pour rythmer l’activité d’un développeur. Comme expliqué dans cet article de Wikipédia, la méthode de travail par Pomodoro consiste à enchaîner des périodes de 25 minutes de concentration séparées par des pauses de 5 minutes. Toutes les 2 heures, on allonge la pause à 15 minutes.
Cela permet de conserver une bonne efficacité de travail, en évitant les périodes trop longues au cours desquelles on s’épuise intellectuellement avec une productivité diminuée. Chacun est libre d’ajuster la durée des périodes de travail et de pause à sa guise ; personnellement les durées originales me conviennent bien.
Pour rester concentré sur le projet en cours, la pause de 5 minutes ne doit pas être l’occasion d’entamer un nouveau sujet de réflexion. C’est un moment pour se lever, s’étirer, faire quelques pas, ranger un peu son bureau, etc. La pause de 15 minutes, en revanche doit permettre d’évacuer la tension accumulée pendant les phases de concentration. On peut boire un café, discuter avec des collègues, consulter Twitter, etc.
Il existe de nombreuses applications d’organisation en Pomodoro, tant sur smartphone que sur poste de travail et même en ligne. L’idée de ce projet était de montrer aux participants de mes sessions de formation comment implémenter un outil de ce type en utilisant un simple microcontrôleur.
Architecture matérielle
Microcontrôleur
J’ai choisi d’utiliser un classique Launchpad MSP-430 de Texas Instruments, bon marché, robuste et simple à utiliser. Les outils de programmation sont directement disponibles dans les dépôts Debian/Ubuntu.
Ce kit contient déjà deux leds programmables (une rouge et une verte), un bouton-poussoir pour le reset du microcontrôleur et un bouton-poussoir accessible par GPIO. La led verte que l’on voit sur la photo est simplement l’indicateur d’alimentation, il y en a une seconde à côté de la led rouge, c’est celle qui nous intéressera ici. Deux leds, un bouton, c’est parfaitement adapté pour notre application.
Notons qu’une fois le programme flashé dans la mémoire du microcontrôleur MSP430G253, ce dernier peut-être extrait et monté sur une carte indépendante comme j’en parlerai plus bas.
Outils de programmation
Pour programmer un MSP 430 de la manière la plus simple possible, il suffit d’utiliser le compilateur msp430-gcc
fourni librement sur la plupart des distributions Linux et d’employer l’outil mspdebug
pour flasher le code sur le microcontrôleur.
Chacun peut utiliser l’éditeur de texte de son choix pour écrire son code (nano
, vim
, gedit
, geany
, etc.). La présence d’un fichier Makefile
nous permettra de lancer la compilation et le flashage directement depuis la ligne de commande.
Pour ceux qui préfèrent travailler dans un IDE (Integrated Development Environment), sachez qu’il existe des plugins pour Eclipse (voir http://eclipse.xpg.dk) pour compiler et télécharger le code dans le microcontrôleur depuis le workbench Eclipse.
Enfin, il est toujours possible d’utiliser msp-gcc
sur Windows avec l’environnement Mingw, mais je ne l’ai pas testé (je n’ai pas de machines Windows dans mon bureau).
Installation sous Ubuntu :
$ sudo apt install gcc-msp430 mspdebug
Logiciel
Fonctionnement
La première partie du projet consiste à décrire le fonctionnement attendu. Voici quelques idées de description :
- Notre projet n’utilisera que les deux leds (rouge et verte) et un bouton-poussoir.
- Pendant les phases de travail, la led rouge sera allumée, pendant les pauses c’est la led verte qui sera active.
- Le système doit prévenir l’utilisateur de la proximité d’une pause et d’une reprise environ deux minutes auparavant.
- Lorsque le moment de pause ou de travail arrive, une led clignote pour avertir l’utilisateur qui doit acquitter en pressant le bouton.
- Si l’utilisateur ne presse pas le bouton pour acquitter la pause ou la reprise, le système doit s’éteindre automatiquement au bout d’un moment.
- L’utilisateur peut choisir de faire une longue pause en pressant deux fois le bouton.
- Vu la simplicité du système, les durées seront fixées à la compilation du code et non pas modifiables par l’utilisateur.
- Le système final est prévu pour être alimenté par piles et doit limiter sa consommation électrique.
Naturellement, pour un projet plus ambitieux il faudrait rédiger un cahier des charges complet avec une description et des spécifications beaucoup plus détaillées.
Automate à nombre fini d’états
La programmation d’un système pour microcontrôleur s’appuie souvent sur le concept d’automate à nombre fini d’états, souvent abrégé FSM pour Finite State Machine. Ceci peut en effet s’organiser sous forme d’un graphe que l’on peut transposer assez facilement en code séquencé par une grande boucle événementielle typique de la programmation sur microcontrôleur.
Nous devons tout d’abord commencer par lister les états possibles pour le système :
- Off : le microcontrôleur est éteint ou en sommeil très profond (CPU et horloges désactivés). La consommation est très réduite. On sort de ce mode en pressant Reset. On y entre après quelques minutes sans réponse de l’utilisateur lors d’une attente d’acquittement.
- Time to work : la led rouge clignote avec insistance et attend que l’utilisateur presse le bouton pour démarrer une séquence de travail.
- Work : la led rouge est allumée en permanence pendant une durée prédéterminée (par exemple 23 minutes).
- Prepare to take a pause : pendant les deux dernières minutes de travail, la led rouge s’éteint régulièrement pour prévenir de l’approche de la pause. Le programmeur sait qu’il ne doit pas entamer de nouvelle tâche.
- Time to take a break : la led verte clignote avec insistance en attente d’un acquittement par le bouton.
- Short break : la led verte est allumée pendant trois minutes. En cas de seconde pression sur le bouton on passe à l’état suivant.
- Long break : la led verte verte est allumée pendant 13 minutes.
- Prepare to return to work : pendant les deux dernières minutes de pause, la led verte s’éteint régulièrement pour prévenir de la prochaine période de travail.
Une fois les états déterminés, on recherche les transitions, et on les représente sur un graphe comme celui-ci :
Implémentation
L’implémentation traditionnelle d’un automate à nombre fini d’états sur un microcontrôleur consiste à boucler indéfiniment en attendant de détecter l’occurrence d’un événement déclenchant une transition à partir de l’état en cours. Toutefois la règle 8 des descriptions ci-dessus nous empêche d’utiliser une boucle active infinie. Nous devons essayer d’endormir le CPU le plus souvent possible pour limiter sa consommation d’énergie.
Nous allons donc utiliser un mécanisme d’interruptions qui réveilleront ponctuellement le CPU et tout le travail réel sera exécuté dans les routines de gestion de ces interruptions (handlers). Nous avons deux types de transitions : celles liées au temps et celles liées à la pression sur le bouton. Nous nous reposerons donc tout naturellement sur les interruptions d’un timer matériel intégré dans le MSP 430 et celles du bouton-poussoir.
Il y a plusieurs designs possibles. Celui que j’ai choisi ici consiste à utiliser l’interruption timer pour faire le travail central. À chaque tick, nous vérifierons si le temps écoulé correspond à la limite pour l’état en cours ou si le bouton a été pressé. Le timer est configuré pour déclencher des ticks tous les dixièmes de seconde, et une variable globale enregistre la pression éventuelle sur le bouton.
L’implémentation est disponible sur Github. Il y a un fichier source en C et
un fichier Makefile permettant de compiler et flasher le code dans le MSP430.
$ git clone https://github.com/cpb-/MSP-omodoro Clonage dans 'MSP-omodoro'... [...] $ cd MSP-omodoro/ $ make msp430-gcc -Wall -mmcu=msp430g2553 msp-omodoro.c -o msp-omodoro.elf
Pour pouvoir programmer le MSP430, il faut que le launchpad soit connecté sur un port USB :
$ make flash mspdebug rf2500 erase [...] Erasing... Programming... Writing 846 bytes at c000 [section: .text]... Writing 32 bytes at c34e [section: .rodata]... Writing 32 bytes at ffe0 [section: .vectors]... Done, 910 bytes total $
Et voilà, le système est dans l’étape « Time to Work » et attend une pression sur le bouton S1
(celui à côté des leds) pour entamer une période de travail.
Conclusion
Le programme ci-dessus n’est pas parfait. On pourrait dans certain cas rater un appui sur le bouton ou au contraire déclencher une pause trop longue si un rebond du poussoir se produit juste au moment du tick timer. Néanmoins, pour une utilisation simple il fonctionne très bien et remplit son rôle d’illustration pédagogique d’un développement à microcontrôleur.
Un aspect particulièrement intéressant du microcontrôleur MSP430 est sa simplicité de mise en œuvre sur un montage indépendant. Il suffit en effet de l’alimenter en +3.3 V et de relier sa broche Reset à ce niveau haut (via une résistance) pour qu’il fonctionne parfaitement avec son oscillateur interne en guise d’horloge (on peut lui ajouter un quartz si on souhaite une meilleure précision). Il suffit alors de relier les entrées-sorties désirées. Voici un petit schéma de mise en oeuvre :
La valeur précise des résistances n’est pas très importante. Dans mon petit montage en wrapping, j’ai choisi trois résistances identiques de 1,3 kOhm.
Comme on peut le voir sur la photo ci-dessous, j’ai remplacé la led verte par une bleue qui me semblait plus adaptée à l’idée de pause, de repos. Avec le bouton blanc au milieu ça donne involontairement un côté french touch à mon pomodoro !
L’alimentation est fournie par deux piles de 1,5 V (le boîtier ci-dessus peut en contenir trois, mais un emplacement est vide). Il serait intéressant de réaliser un petit boîtier en impression 3D, rappelant éventuellement la tomate du pomodoro original…
J’utilise aussi cette carte pour un projet en ce moment, elle est efficace 😉
Par contre, je n’utilise pas le compilateur et la version de mspdebug fournie dans les dépôts Ubuntu. Les versions sont assez anciennes. J’utilise donc la toolchain fournir par Texas Instrument et j’ai récupéré la dernière release de mspdebug sur GitHub. Ma motivation principale a été d’un côté le support de C++11 et de l’autre un bug lorsque je voulais faire step en debug (ça faisait une boucle infinie de step…).
N’y a t-il pas une incohérence entre le schéma et le texte ? En effet, le texte précise « relier sa broche Reset à la masse (via une résistance) » alors que le schéma montre une pin 16 (celle du reset ?) reliée à Vcc à travers une résistance.
Oui, en effet. C’est bien au niveau haut qu’il faut connecter Reset. J’ai corrigé le texte.
Merci !
C’est vrai qu’il s’agit (presque ?) toujours d’un /RESET donc c’est logique en effet de le relier à Vcc ^^