Table des matières:
2025 Auteur: John Day | [email protected]. Dernière modifié: 2025-01-13 06:57
Par jumbleviewJumbleview.infoSuivez plus par l'auteur:
À propos: Je travaille comme ingénieur logiciel dans l'une des sociétés de la Bay Area (Californie). Chaque fois que j'ai du temps, j'aime programmer des microcontrôleurs, construire des jouets mécaniques et réaliser des projets de rénovation domiciliaire. En savoir plus sur jumbleview »
Ce projet montre comment contrôler deux LED à anode commune tricolore de 10 mm (yeux multicolores de Pumpkin Halloween Glitter) avec la puce Attiny85. Le but du projet est d'initier le lecteur à l'art de la programmation concurrente et à l'utilisation de la bibliothèque protothreads d'Adam Dunkels. Ce projet suppose que le lecteur connaît les contrôleurs AVR 8 bits, peut écrire un programme C et a une certaine expérience avec le studio Atmel.
Code du projet publié sur GitHub:
Fournitures
Avant de programmer, il faut encore construire le circuit. Voici les composants:
- Contrôleur Attiny85 (tout fournisseur électronique).
- Deux LED tricolores de 10 mm avec anode commune. LED Adafruit
- Résistances 100 Ohm, 120 Ohm, 150 Ohm 0,125 ou 0,250 Wt (tout fournisseur électronique).
- En-tête à six broches pour l'interface AVR ISP. Peut être fabriqué à partir de cet en-tête Adafruit
- Une planche à pain ou une planche à gabarit imprimée. J'ai utilisé celui-ci
- Interface AVR ISP MKII et Atmel Studio 6.1 (la version ultérieure devrait également fonctionner).
Étape 1: Circuit
La conception utilise cinq broches à puce:
- Deux broches utilisées pour contrôler les anodes: chaque anode LED attachée à la broche dédiée.
- Trois broches attachées (à travers des résistances) aux cathodes des LED (la cathode de même couleur de chaque LED attachée à la même broche)
On pourrait se demander: pourquoi ne pas utiliser les six broches d'entrée/sortie de la puce pour que les anodes LED soient connectées directement au +5 v et que chaque cathode ait sa broche dédiée ? Cela rendra la programmation simple. Hélas, il y a le problème: la broche PB5 (RESET) est une broche faible capable de fournir seulement ~2 mA du courant, alors qu'il faut environ 20 mA.
Bien sûr, on peut construire un amplificateur à transistor pour cette broche faible, mais je préfère moi-même, chaque fois que cela est possible, résoudre le problème via le code.
Étape 2: chronogramme
Le chronogramme nous aide à comprendre ce que nous devons programmer.
Les deux premières rangées du diagramme montrent le changement de tension sur les anodes LED. La tension sur les broches connectées aux anodes LED oscille avec une fréquence ~ 250 Hz. Cette oscillation de tension pour la LED gauche est l'opposé de l'oscillation de la LED droite. Lorsque la tension sur l'anode est élevée, la LED correspondante peut être lumineuse. Lorsqu'il est bas, la LED correspondante est sombre. Cela signifie que chaque LED peut être lumineuse pendant un intervalle de 2 millisecondes et s'éteindre pendant 2 millisecondes supplémentaires. Parce que l'œil humain a une certaine inertie, le clignotement à 250 Hz n'est pas perceptible par l'observateur. Les trois rangées du bas sur le diagramme montrent le changement de tension sur les broches connectées aux cathodes des LED. Regardons la première colonne du diagramme. Il montre le cas lorsque la LED gauche est de couleur rouge et la LED droite de couleur verte. Ici, les cathodes ROUGES restent basses tandis que l'anode gauche est haute, la cathode VERTE reste basse tandis que l'anode droite est haute et la cathode BLEUE reste basse tout le temps. D'autres colonnes sur le diagramme montrent des combinaisons de tension de cathode et d'anode pour différentes couleurs.
Comme nous pouvons le voir, il existe une interdépendance de l'état des broches. Sans cadre, ce ne serait pas facile à résoudre. Et c'est là que la bibliothèque protothread est utile.
Étape 3: Programmation. Macros et définitions
L'exemple dans les étapes de programmation représente une version légèrement simplifiée. Le programme est raccourci et certaines définitions symboliques sont remplacées par des constantes explicites.
Commençons par le commencement. Le programme comprend les fichiers fournis avec Atmel Studio ainsi que l'en-tête de la bibliothèque protothread. Ensuite, il y a deux macros pour manipuler les niveaux des broches et quelques définitions pour donner des noms logiques aux signaux des broches. Pour l'instant rien de spécial.
Étape 4: Programmation. Boucle principale
Ensuite, regardons à la fin pour voir ce que contient la procédure principale.
La fonction main après avoir effectué une initialisation reste en boucle permanente. Dans cette boucle, les étapes suivantes sont effectuées:
- Appelle la routine protothread pour la LED gauche. Cela change la tension de certaines broches.
- Faites un délai de deux millisecondes. Il n'y a pas de changement dans la tension des broches.
- Invoque protothread pour la LED de droite. Cela change une certaine tension des broches.
- Faites un délai de 2 MS. Il n'y a pas de changement dans la tension des broches.
Étape 5: Programmation. Fonctions auxiliaires
Avant de commencer à discuter des protothreads, nous devons examiner certaines fonctions d'assistance. D'abord, il y a des fonctions pour définir une couleur particulière. Ils sont simples. Il existe autant de fonctions telles que le nombre de couleurs prises en charge (sept) et une fonction supplémentaire pour régler la LED sombre (NoColor).
Et il y a une autre fonction qui sera directement invoquée par la routine protothread. Son nom est DoAndCountdown().
Techniquement parlant, l'utilisation d'une telle fonction n'est pas obligatoire mais j'ai trouvé cela pratique. Il a trois arguments:
- Pointeur vers la couleur de la LED de réglage de la fonction (comme RedColor ou GreenColor ou etc.)
- Valeur initiale du compteur inversé: nombre de fois où cette fonction doit être appelée à un stade particulier du protothread.
- Pointeur pour inverser le compteur. Il est supposé que lorsqu'il y a un changement de couleur, ce compteur inverse est égal à 0, donc à la première itération, le code affectera à ce compteur la valeur initiale. Après chaque itération, le compteur est décrémenté.
La fonction DoAndCountdown() renvoie la valeur du compteur inverse.
Étape 6: Programmation. Routines Protothread
Et voici le framework core: la routine protothread. Par souci de simplicité, l'exemple est limité à trois étapes: pour le changement de couleur en ROUGE, en VERT et en BLEU.
La fonction est invoquée avec deux arguments:
- Pointeur vers la structure protothread. Cette structure a été initialisée par main avant le début de la boucle principale.
- Pointeur pour inverser le compteur. Il a été mis à 0 par main avant le démarrage de la boucle principale.
La fonction définit les tensions pour activer la LED gauche, puis démarre le segment protothread. Ce segment se situe entre les macros PT_BEGIN et PT_END. À l'intérieur, il y a du code qui dans notre cas ne répète que les macros PT_WAIT_UNTIL. Cette macro s'exécute ensuite:
- Invocation de la fonction DoAndCountdown. Cela définit la tension sur les cathodes LED pour émettre une couleur particulière.
- Résultat renvoyé par rapport à 0. Si la condition est 'false', la fonction protothread renvoie immédiatement et cède le contrôle à la boucle principale.
- Lorsque protothread est invoqué la prochaine fois, il exécute à nouveau le code avant PT_BEGIN, puis saute directement dans les macros PT_WAIT_UNTIL à partir desquelles il est retourné la dernière fois.
- Ces actions sont répétées jusqu'à ce que le résultat de DoAndCountdown soit 0. Dans ce cas, il n'y a pas de retour, le programme reste dans protothread et exécute la ligne suivante du code. Dans notre cas, il s'agit de PT_WAIT_UNTIL mais de manière générale, il pourrait s'agir de presque n'importe quel code C.
- Lors de l'exécution initiale du deuxième compteur inverse PT_WAIT_UNTIL est 0, donc la procédure DoAndCountdown() le met à la valeur initiale. Les deuxièmes macros seront à nouveau exécutées 250 fois jusqu'à ce que le compteur d'inversion atteigne 0.
- L'état de la structure pt est réinitialisé dès que le contrôle atteint les macros PT_END. Lorsque la fonction protothread est invoquée la prochaine fois que le segment protothread démarre, exécutez la ligne du code juste après PT_BEGIN.
Il existe une routine de protothread similaire pour la bonne LED. Dans notre exemple, il applique simplement un ordre de couleurs différent, mais si nous pouvons le faire complètement différemment: il n'y a pas de couplage étroit entre la routine LED gauche et droite.
Étape 7: Internes
L'ensemble du programme contient moins de 200 lignes de code (avec des commentaires et des lignes vides) et prend moins de 20% de la mémoire de code Attiny85. Si nécessaire, il est possible d'utiliser ici plusieurs autres routines de protothread et de leur attribuer une logique beaucoup plus compliquée.
La bibliothèque Protothreads est la forme la plus simple de programmation informatique concurrente. La programmation concurrente est une approche permettant de diviser le programme en parties logiques: parfois elles sont appelées coroutines, parfois threads, parfois tâches. Le principe est que chacune de ces tâches peut partager la même puissance de processeur tout en gardant le code plus ou moins linéaire et indépendant des autres parties. Les tâches du point de vue logique peuvent être exécutées simultanément.
Pour les systèmes avancés, les contrôles de ces tâches sont effectués soit par le noyau du système d'exploitation, soit par le langage d'exécution intégré dans l'exécutable par le compilateur. Mais dans le cas de protothreads, le programmeur d'application le contrôle manuellement en utilisant la bibliothèque de macros protothreads dans les routines de tâches et en invoquant de telles routines (généralement en dehors de la boucle principale).
Vous voulez probablement savoir comment fonctionne réellement protothread ? Où se cache la magie ? Les protothreads reposent sur une fonctionnalité spéciale du langage C: le fait que l'instruction C switch case puisse être intégrée dans if ou dans un autre bloc (comme while ou for). Détails que vous pouvez trouver sur le site d'Adam Dunkels
L'électronique interne de ce projet est très simple. La photo ci-dessus vous donne un indice. Je suis sûr que vous pouvez faire mieux.