LOCODUINO

Parlons Arduino => Modélisation, Architectures logicielles et matérielles => Discussion démarrée par: Marc-Henri le mars 14, 2017, 02:50:43 pm

Titre: Tâches quasi parallèles et protothreads
Posté par: Marc-Henri le mars 14, 2017, 02:50:43 pm
Bonjour à tous,

Lorsqu'un logiciel doit gérer plusieurs activités en parallèle, il s'avère intéressant de le structurer en tâches donnant l'illusion de se dérouler en parallèle. Plusieurs approches sont possibles et j'aimerais partager l'une d'elles, tout à fait applicable aux microcontrôleurs et à l'Arduino.

Un thread, traduction du mot "fil" ou une tâche est une suite d'instructions. Sur un système à processeur unique, les threads donnent l'illusion de se dérouler en parallèle. En réalité, lorsqu'un thread rend la main, un autre thread continue son exécution. Lorsque le premier thread est à nouveau activé, il reprend l'exécution des instructions où il avait rendu la main.

Un protothread est un thread ultra simplifié, mécanisme dont on trouve plusieurs réalisations. L'une d'elles, décrite dans http://dunkels.com/adam/pt/ (http://dunkels.com/adam/pt/) est facile à mettre en oeuvre. Je l'ai décrite sur mon blog à cette adresse https://savignyexpress.wordpress.com/2014/01/17/gare-du-reseau-dun-ami-programmation/ (https://savignyexpress.wordpress.com/2014/01/17/gare-du-reseau-dun-ami-programmation/).

Ma première utilisation des protothreads est la commande des 2 PN de mon réseau N. 3 protothreads assurent simultanément:
Voir le programme C ci-joint pour Attiny2313.

C'est certainement facilement adaptable à l'Arduino. Il n'y a aucune librairie à installer, tout est réalisé sous forme de macros C contenues dans des fichiers *.h. Les protothreads exploitent l'instruction switch du langage C, les étiquettes permettant de reprendre le protothread où il a rendu la main.

Il faut toutefois mentionner quelques restrictions:
Meilleures salutations à tous.
Titre: Re : Tâches quasi parallèles et protothreads
Posté par: DDEFF le mars 14, 2017, 03:49:46 pm
Merci Marc Henri,

J'aime bien l'idée. ;)

Je ne jure pas  que je vais m'en servir demain matin , mais je garde ça dans un coin de ma tête. Je suis sûr que c'est utile.
On maîtrise tout, puis qu'on fait tout soi-même. Et ça, j'aime bien.

Amicalement
Denis

Titre: Re : Tâches quasi parallèles et protothreads
Posté par: Dominique le mars 14, 2017, 10:28:45 pm
« Par ma foi ! il y a plus de quarante ans que je dis de la prose sans que j'en susse rien, et je vous suis le plus obligé du monde de m'avoir appris cela. »

Bonsoir Marc-Henri,

Comme le dirai Monsieur Jourdain, je viens de découvrir que je fais du thread sans le savoir ! Si, en fait et je donne un exemple :

Dans un programme Arduino, il y a le Setup() qui est éxécuté une seule fois en premier, puis la Loop() qui est éxécutée ensuite de façon répétitive. C'est exactement comme un while(1) { ………}. Le compilateur l'ajoute subrepticement sans qu'on le voit !

Quand je programme mon gestionnaire de réseau, je fais donc éxécuter dans la Loop(), toute une série de tâches qui ne vont occuper le processeur qu'une petite fraction du temps en le libérant le plus vite possible, pour que la suivante prenne la main, et ainsi de suite.

Ces tâches sont (dans mon gestionnaire, mais tout le monde reconnaitra des cas qu'il rencontre aussi) :


J'ai décrit là 5 types de threads qui sont, en fait, programmés comme des sous-programme (une entrée et une sortie) et qui ne s'interdisent aucune contrainte de programmation.

En particulier le switch / case est totalement permis et fort heureusement car il faut bien agir en fonction de la commande reçue et une suite de if ne serait pas agréable. Les Macros ne sont pas obligatoires non plus.

Ces tâches correspondent bien à un gestionnaire de réseau, mais mon Arduino Mega qui commande des aiguilles est fait de la même façon, avec les tâches liées aux messages, mais aussi les commandes des moteurs d'aiguilles qui sont décalées dans le temps d'au moins une 1/2 seconde pour éviter les appels de courant simultanés (j'ai fait sauter un fusible avent cela !)

La seule contrainte est de bien respecter le non-blocage du processeur pendant l'éxécution d'une tâche (pas de delay(), des while() bien contrôlés, des tests sur toutes les limites) et que chaque tâche puisse reprendre la main sans perdre d'événement d'où quelques tests de Debug pour mesurer les temps d'exécution. D'une manière générale, je n'ai jamais eu de surprise (hors bug évidemment).

Voilà comment on fait du thread sans le savoir !

Amicalement

Titre: Re : Tâches quasi parallèles et protothreads
Posté par: Marc-Henri le mars 14, 2017, 11:23:58 pm
Bonsoir Denis et Dominique,

Merci beaucoup pour vos encouragements et vos messages.

Merci à Dominique d'avoir mentionné qu'il ne faut pas bloquer le processeur et rendre la main au plus vite pour qu'une autre tâche puisse tourner. Implantées sous forme de sous-programmes, chaque tâche doit mémoriser l'état ainsi que d'autres variables entre 2 appels consécutifs. Une approche de type machine à états finis est la mieux adaptée. Le protothread tel que décrit est adéquat pour des activités essentiellement séquentielles. Il est par exemple possible de quitter une boucle pour la reprendre où on l'avait laissée à l'appel suivant: très pratique pour baisser et lever les barrières du PN.

Ma première application ferroviaire d'un microcontrôleur est la gestion du TCO de mon réseau (https://savignyexpress.wordpress.com/2016/10/12/mon-reseau-panneau-de-controle-tco/ (https://savignyexpress.wordpress.com/2016/10/12/mon-reseau-panneau-de-controle-tco/)). Le programme comporte 2 tâches: une tâche principale destinée à gérer les états du système selon les poussoirs pressés, une seconde tâche destinée à commander les aiguilles en 2 groupes pour éviter la surcharge de l'alimentation. Ces 2 tâches sont des machines à états appelées l'une après l'autre dans le programme principal.

Les 2 approches peuvent cohabiter dans la boucle principale d'un programme: while dans mon cas ou dans la fonction loop en Arduino.

Meilleures salutations de Suisse romande.