Réveil à base d'Atmega32
From Eric
Contents |
Objectifs
Réaliser un réveil moins bruyant que mon téléphone portable...
(Au 28/04/2011: et bien, c'est raté... le son est encore plus désagréable...)
Réalisation
Voici la carte, vue côté composants, à la date du 4 avril 2011 :
La carte comprend essentiellement :
- un Atmega32 (un peu luxueux, mais j'ai besoin de pas mal d'entrées / sorties),
- une horloge sur bus I2C (PCF8253 de NXP, le DIL8 à droite...),
- un FT232RL pour la pouvoir connecter le réveil à un PC et charger ainsi les sonneries et les rendez-vous (la "break-out board" en bas),
- une matrice de 8x8 LEDs avec les quelques composants nécessaires à son pilotage (un ULN2803 pour débiter les 8x10mA et un LS138 pour sélectionner la ligne à activer parmi les 8 de la matrice).
Le schéma (version brouillon) est disponible ici.
Ordonnancement des tâches
Le réveil utilise un ordonanceur cyclique trivial : il s'agit d'une routine d'interruption (timer 2) appelée périodiquement (toutes les ms) et dont le rôle est d'appeler des fonctions (les "tâches") conformément à une période donnée.
Chaque "tâche" est définie par un descripteur comprenant les données suivantes :
- un pointeur sur une fonction (le corps de la tâche),
- une valeur de période, exprimée en nombre de cycle de la tâche d'interruption,
- un compteur.
A chaque activation du handler d'interruption, celui-ci parcourt la liste des tâches, vérifie si le compteur associé est nul et si tel est le cas, appelle le corps de la tâche via le pointeur de fonction. Dans le cas contraire, il décrémente le compteur.
Bref, du très simple, suffisant pour ce type de fonction. Une solution plus sophistiquée, basée sur l'utilisation des primitives setjmp / longjmp est en cours d'élaboration.
Gestion de la matrice de LEDs
Une tâche est spécifiquement affectée au rafraîchissement de la matrice de LEDs. Son rôle consiste à prendre successivement les 8 octets qui constituent la "mémoire écran" et à recopier la valeur sur les sorties de contrôle des anodes, pendant que les sorties de contrôle des cathodes sont successivement activées.
La deuxième tâche est chargée d'afficher un message en faisant scroller les symboles qui le composent. Cette tâche modifie le contenu de la mémoire écran qui est affichée par la première tâche.
Les "bitmaps" correspondant aux différents caractéres ont été générés par le logiciel PixelFont (chercher "8x8 pixel rom font editor" sous Google). L'image ci-après donne un aperçu de la rotation à effectuer pour que les messages s'affichent correctement :
Le résultat (une constante C) est stocké dans la flash du composant (la taille de la RAM est beaucoup trop petite).
La localisation en Flash (en d'autres termes, en mémoire programme) se fait grace à la macro PROGMEM. Se référer à la documentation de la bibliothèque AVR (libavr), qui donne en outre les différentes macros permettant d'accéder aux variables stockées en Flash.
Gestion des mélodies
Les mélodies sont monophoniques. Elles sont produites par un buzzer soumis à un signal rectangulaire généré par le timer 0 de l'Atmega32, en mode CTC. Dans ce mode, le timer fait changer d'état la sortie de commande du buzzer une fois que la valeur du compteur a atteint la valeur de consigne. Ainsi, le CPU est complètement déchargé de la production du son ; il ne doit plus que se charger de séquencer les notes de musique et les silences.
La correspondance entre la fréquence des notes et les valeur du compteur et du prescaler sont calculées au moyen de la table Excel suivante AVRsounds.xlsx. Attention, la fréquence générée par le timer doit être double de celle voulue car à chaque tic d'horloge l'état du signal change, ce qui signifie que la période du signal attaquant le buzzer est 1/2 de la période du signal généré par le timer.
Une fois passé "J'ai du bon tabac", je suis à court de notes... aussi ai-je décidé d'extraire directement les notes de fichiers MIDI. Pour ce faire j'ai copié/collé quelques lignes de Java honteusement glanées sur le net : elles me permettent d'extraire mécaniquement les notes d'un canal MIDI. Bon, je ne me suis pas fatigué et ne me suis absolument pas préoccupé de gérer les durées et les silences. Ca donne un résultat assez effroyable, mais suffisant pour l'instant.
On trouvera le bout de code ici. Grace à lui, je génère directement la constante C de définition d'une mélodie. On trouvera par exemple l'extraction du canal 1 du fichier midi de notre hymne national transcodé en C, ici.
Conclusions et leçons
Bennnnn... pas de conclusions ni véritablement de leçons : le montage est extrêmement pauvre du point de vue électronique, et pas très compliqué du point de vue logiciel.
Ah si... bien se souvenir de la façon de stocker les constantes en Flash avec l'AVR. Se référer à la page A retenir.