Expérience 016 : Les matrices de LEDs.
Légions sont les dispositifs industriels qui organisent leurs afficheurs sous forme de matrices Lignes / Colonnes. Certaines matrices sont de type 5 x 7 pour pouvoir afficher des caractères alphanumériques, d’autre sont de type 8 x 8 pour présenter des figures géométriques quelconques, y compris du texte. (Pour mémoire car déjà vu en Fiche n°15 une matrice est un arrangement de type grille rectangulaire organisée en lignes et colonnes.) Dans les deux cas ces afficheurs sont prévus pour pouvoir être placés les uns contre les autres et former ainsi une grille plus grande. Pour illustrer ce propos nous allons commencer par faire appel à un afficheur TC07-11 HWA montré sur la Fig.27 et toujours d’actualité. Le brochage interne est précisé sur la Fig.28 et le composant est donné pour un courant par point de 10mA. Nous allons minimiser le nombre des résistances de limitation de courant en les plaçant sur les colonnes en les branchant comme précisé par le schéma la Fig.28 la valeur des résistances étant de 100Ω. Le courant crête avoisine 30mA compatible avec la sortance des broches de l’ATmega328. Le courant moyen dans les LEDs est d’environ 30 / 7 » 4,3mA. L’afficheur se trouve alors un peu sous-alimenté mais reste d’une luminosité suffisante pour tester le démonstrateur P016. Comme tout système matriciel on doit effectuer un balayage de tous les points. Dans cet exemple on a décidé
de balayer « verticalement » ligne à ligne, la Fig.29 proposant l’organigramme représentatif de l’algorithme utilisé. La difficulté réside dans la répartition des broches de sortie d’Arduino. Dans ce logiciel il est décidé de réserver D0 et D1 pour le téléversement. Du coup on dispose de six broche sur le PORT D et également de six sorties sur le PORT B. Il va falloir balayer verticalement en associant les deux ports. Les affectations présentées sur la Fig.28 peuvent sembler étranges, alors que si on consulte la Fig.30 l’arrangement semble plus ordonné. On y voit aussi que pour balayer verticalement l’afficheur on va devoir commencer par balayer du haut vers le bas entre L1 et L6 avec le PORT B. Puis, pour L7 c’est la sortie D7 du PORT D qui sera sollicitée. Ce « chassé-croisé » complique un peu le programme. Le principe du balayage des 37 points est présenté sur la Fig.31 qui montre le traitement de la ligne L4 lorsque le caractère « G » est affiché sur le petit écran matriciel. Au début du balayage de la matrice les sept sorties « verticales » sont à « 0 » pour « noircir » l’intégralité de l’afficheur. Pour activer l’une des lignes, le logiciel commence par placer sur le PORT D « l’empreinte » des cinq points de la ligne. Les sorties des PIXELs à éteindre seront à l’état « 1 » alors que celles des points à allumer seront placés à « 0« . (Sur la Fig.31 les « 0« sont en vert et les « 1« en rouge.) Lorsque le modèle est présent sur les cinq colonnes, le logiciel fait passer à « 1 » la sortie qui pilote la ligne à valider suivi d’une petite temporisation d’une milliseconde. Puis le programme passe à la ligne suivante et recycle sans s’arrêter. La photographie de la Fig.32 prouve que la luminosité est suffisante. Bien que l’appareil photographique utilisé saisit l’image avec un temps de pose relativement court, le balayage de l’afficheur est suffisamment rapide pour donner l’impression d’un « G » complet alors que dans la réalité une seule ligne est allumée à la fois.
Expérience 017 : Tout l’alphabet majuscule.
Fondamentalement la procédure Balayer_afficheur() constitue un générateur de caractère. Logiquement, et sans faire un jeu de mots, lorsqu’un tel afficheur est inséré dans un système, c’est qu’il va servir d’interface Homme/Machine. De ce fait on va devoir associer le programme à une police de caractères constituée d’un tableau informatique tel que LIGNE[7] ne comportant la description que d’un seul caractère. Pour enrichir l’interface de dialogue, il va falloir un tableau dont la taille sera ici de 7 Octets x Nombre d’empreintes. Par exemple pour l’alphabet majuscule et les dix chiffres il faut un tableau de (26 + 10) * 7 = 252 octets. Dans le premier exercice que l’on va tester avec Experience_017.ino la table des caractères réside directement dans le programme. Il faut la compléter par une procédure qui sert à extraire l’empreinte complète du caractère avant d’afficher ce dernier par balayage. Le codage du « G » par exemple est le suivant :
REMARQUE : Le codage d’un caractère, est symbolisé sur la Fig.33 pour la lettre « G » par exemple. Quand on précise une valeur, qu’elle soit binaire ou décimale, l’indication des zéros en tête n’est pas obligatoire. C’est la raison pour laquelle les « 0 » n’encombrent pas l’écriture du programme source. Les « 00 » correspondent à D1 et D0. Avant de passer à l’exercice suivant, je vous invite fortement à modifier P017 pour y ajouter les lettres minuscules et la ponctuation. Vous disposeriez alors d’une police de caractère complète. Vous allez au passage constater que créer un tel tableau est assez indigeste … mais il faut bien qu’un « esclave informatique » s’y cogne ! Noter au passage que la valeur d’un octet peut parfaitement se coder en décimal, il suffit d’additionner les poids binaires de chaque BIT. Par exemple le codage du « G » deviendrait : 68, 56, 60, 32, 56, 56, 68, qui tient bien moins de place dans le listage mais devient totalement illisible.
Expérience 018 : Loger la table de caractères en EEPROM.
Autant des petits démonstrateurs comme ceux de ce didacticiel n’ont pas besoin d’être optimisés car on dispose de bien plus de place en mémoire qu’il est nécessaire, autant quand on développe une « application importante » on va devoir surveiller la moindre perte d’octet, car plus le programme sera optimisé, plus il sera possible d’ajouter du « confort » dans notre application. Hors l’un des moyens les plus commodes pour gagner de la place en mémoire dédiée au programme consiste à loger les tableaux de constantes dans la mémoire non volatile EEPROM de l’ATmega 328. Le démonstrateur Experience_018.ino va nous montrer comment loger un texte en EEPROM et le suivant Experience_018.ino sert à prouver le gain manifeste apporté par une telle approche. Téléverser Experience_017.ino pour loger le démonstrateur sur Arduino. Il ne se passe rien en apparence. Dans la réalité le programme démarre, inscrit les données en EEPROM, liste « dans le vide » le contenu de la mémoire volatile et passe à void loop() qui boucle définitivement sans rien faire de plus. Pour visualiser le résultat il faut cliquer sur « la puce » qui active le Moniteur de l’IDE et provoque un redémarrage du programme. On voit alors sur l’écran le listage complet de l’EEPROM se terminant par la copie d’écran de la Fig.34 à condition que la vitesse de transfert soit initialisée à 57600baud. Le listage est effectué en HEXADÉCIMAL. Verticalement les adresses relatives des cellules sont en décimal dans la zone verte. En revanche le complément de l’adresse est en hexadécimal dans la zone bleue pastel. L’encadré rouge correspond au codage du « G » dont l’adresse de la première cellule est en 0880 + 04 = 0884. Noter que le logiciel ne liste la mémoire qu’à partir de la zone qui a été modifiée. Le reste est remplacé par des « ..« . Dans le dossier <! OUTILS> se trouve un petit utilitaire nommé Lister_EEPROM_en_HEXAdecimal.ino qui liste l’intégralité du contenu de l’EEPROM, toujours en HEXADÉCIMAL. (Astuce : Faire précéder le nom d’un fichier ou d’un dossier d’un « !« permet de le faire passer en tête si le listage est effectué par ordre alphabétique.) Si l’EEPROM n’a jamais été programmée, elle ne contient que des états « 1 » c’est à dire des $FF en HEXADÉCIMAL. Je vous invite à téléverser ce petit outil et à le tester en cliquant sur la « puce » pour ouvrir le Moniteur de l’IDE et ainsi voir le contenu actuel de l’EEPROM dans votre carte Arduino UNO.
Expérience 019 : Utiliser les données logées en EEPROM.
Avec ce démonstrateur qui se comporte exactement comme 017 on va puiser les empreintes en EEPROM. Le sketch est donc presque identique. La seule chose qui change c’est le traitement d’extraction des empreintes qui doit chercher les données en mémoire non volatile. Nous allons faire appel à EEPROM.h native dans l’IDE. Il suffit comme c’était le cas avec Experience_018.ino de la déclarer en tête de programme. On téléverse le démonstrateur P019 et immédiatement l’affichage se déroule exactement comme c’était le cas dans P017. Par contre on constate sur le montage de la Fig.35 que le programme a maigri de 196 octets et la mémoire dynamique s’est allégée de 249 octets. Le bénéfice est considérable, et en plus EEPROM.h étant intégrée au logiciel, les routines d’exploitation d’un projet plus conséquent disposent de cette ressource pour échanger des données qui seront sauvegardées dans la mémoire non volatile du microcontrôleur.
ATTENTION : Le conseil prodigué dans l’encadré en bas de la page 5 du petit livret Bibliothèques Arduino.pdf reste judicieux. C’est uniquement pour tester EEPROM.h que cette bibliothèque est utilisée dans ce démonstrateur. Nous verrons plus avant comment faire usage à avr/eeprom.h pour échanger des données avec la mémoire non volatile.
Expérience 020 : Une matrice carrée de 8 x 8 points.
Gérer un grand nombre d’afficheurs 7 segments ou un nombre important de LED ne se conçoit plus sans le secours d’un circuit intégré de multiplexage tel que le MAX 7219 dont vous prenez immédiatement connaissance en consultant avec attention la Fiche n°21 et la Fiche n°22. Des matrices de LED existent à profusion dans le commerce, dont les dimensions sont variables. Parmi les plus courantes actuellement on trouve le module 1088AS par exemple dont la popularité à généré des kits « clef en main » tel que celui de la Fig.36 facilitant grandement la concrétisation de petites applications. Le 1088AS comporte 64 LED arrangée en huit lignes et huit colonnes. La Fig.37 en présente le brochage lorsque ce composant est vu par le dessus. Les broches sont numérotées comme celles d’un circuit intégré de type DIL, toujours observé par dessus. Le petit montage électronique de la Fig.36 tient compte des caractéristiques de cet afficheur matriciel. Comme montré sur la Fig.38 les connecteurs sont conformes à son brochage interne. Notons au passage que si l’espacement entre deux broches sur le 1088AS fait bien les 2,54mm standard, la distance entre les deux lignes de broches n’est pas normalisée puisqu’elle fait 24,5mm ce qui ne correspond pas à exactement un pouce.
La bibliothèque LedControl.h permet de gérer l’allumage des LED soit individuellement soit par « Rangées ». Pour programmer facilement une application en usant des procédures setLed et setRow il importe de faire le lien entre les coordonnées indiquées et la position de l’afficheur sur le module électronique. La Fig.39 précise l’ordre des lignes et des colonnes quand on programme LED par LED avec setLed en précisant leurs coordonnées. La Fig.41 pour son compte précise l’ordre des « rangées » pour setRow avec le symbole de l’OCTET dans lequel on précise par des « 1 » et des « 0 » l’état des LED dans le groupement traité. Mais comme nous codons librement les coordonnées ou le contenu
des octets, on peut orienter l’afficheur comme on le désire. Par exemple, pour le petit programme d’application nommé Experience_020.ino le circuit imprimé est orienté comme montré sur la Fig.40 de façon à ne pas être masqué par les fils de liaison pour l’ISP. Cette interface série réputée plus rapide que l’I2C (Interface Serial Peripheral) est gérée par la bibliothèque LedControl.h décrite en page 07 du petit livret. Particulièrement bien adaptée à la gestion de matrices ou d’afficheurs à segments, elle permet d’affecter à notre convenance Les broches d’Arduino dédiées à la SPI.
Ce premier démonstrateur se contente d’afficher quelques figures géométriques avec le minimum de courant largement suffisant pour engendrer un éclairage très lumineux. Pour interfacer le petit module à la carte Arduino UNO il suffit d’effectuer les trois branchements définis dans le tableau de la Fig.42 et d’ajouter le +5Vcc et GND. On ne peut rêver plus simple. Par ailleurs il serait aussi facile de chainer plusieurs afficheurs en les « pontant » avec cinq fils de plus.
Expérience 021 : Scintillation aléatoire.
Toujours dans le cadre des affichages « graphiques », avec ce démonstrateur qui émule encore un automatisme aveugle, nous allons aborder le chapitre de la génération de nombres aléatoires. Par définition, « aléatoire » semble totalement incompatible avec le comportement d’une machine qui fonctionne de façon déterministe. Et pourtant avec l’instruction random décrite en page 19 du livret SYNTAXE à imprimer.pdf on va voir que c’est possible et facile. Il n’y a rien à modifier pour le matériel, il suffit de téléverser Experience_021 .ino et le petit écran va scintiller joyeusement. Notez au passage que le rapport cyclique diminue par rapport à P020, donc il faut augmenter la luminosité avec l’instruction Matrice.setIntensity(0,7).
Expérience 022 : Afficher « Arduino » sur une matrice 8 x 8.
Strictement rien à faire si ce n’est de téléverser Experience_022 .ino et observer le résultat sur l’afficheur matriciel 1088AS. On stagne dans le cadre des automatismes aveugles pour présenter à l’écran le texte « Arduino » lettre après lettre durant une seconde. il n’y a pas de spécificité à souligner, mis à part le fait que la table des textes ne contient que sept empreintes, dont six permettent de visualiser des lettres minuscules. Contrairement aux exercices précédents, cette fois ce ne sont plus les lignes qui sont codées, mais les colonnes. Quand on compile ce démonstrateur on obtient le résultat de la Fig.43 en A. Les 5 x 7 = 35 octets de la police de caractères consomment cette taille à la fois dans la mémoire de programme et dans la mémoire dynamique. Comme on va le voir dans l’exercice suivant on peut gagner cette place en mémoire dynamique avec la bibliothèque avr/pgmspace.h explicitée en page 34 du livret Bibliothèques Arduino.pdf .
Expérience 023 : Constantes logées dans le programme.
Dommage que la bibliothèque avr/pgmspace.h n’accepte pas les tableaux de constantes, il faut déclarer un à un les octets ce qui rend la lecture du programme plus indigeste. Pourtant dans le descriptif de avr/pgmspace.h on a bien ROGMEM type NomConstante[] = {}; // Accepté. en page 34 qui laisse à penser que l’on pourrait utiliser une formulation du genre tableau de constantes dont on énumère les valeurs telle que LA[5] = {B01111110, B10001000, etc. Pour extraire colonne par colonne on utiliserait alors une instruction de balayage de type for compacte en nombre d’octets de programme consommés. Le compilateur accepte une telle formulation mais le programme ne se déroule absolument pas correctement et le pavé de LEDs affiche n’importe quoi. Dommage …
Du coup il faut explorer les empreintes octet par octet ce qui alourdit considérablement le sketch. Téléverser Experience_024.ino et sur la Fig.43 B constatez la différence en mémoire dynamique.
Expérience 024 : Un « journal défilant ».
Avant dernier démonstrateur avec des LEDs ou des matrices de LEDs qui comme beaucoup de ceux qui précèdent est un automatisme aveugle. Le « journal défilant » est un procédé qui consiste à visualiser un texte qui se déplace de la droite vers la gauche sur un dispositif optoélectronique dont le nombre d’emplacements est bien plus faible que la longueur du texte à afficher. Généralement on utilise un module qui peut afficher plusieurs caractères. Toutefois, même avec un seul afficheur la lisibilité devient infiniment plus conviviale que lettre par lettre avec temporisation. Comme pour P023 il n’y a strictement rien à changer aux branchements électriques, il suffit ici aussi de téléverser Experience_024.ino et vogue la galère. (Ou plus exactement : Défile le texte !) La particularité de ce programme réside dans la gestion du tableau de
texte. En première approche on envisagerait l’algorithme de la Fig.44 qui réalise un registre à décalage sur 46 octets. On commence par inscrire les 46 octets avec des « 1 » et des « 0 » pour représenter les 46 colonnes. Puis la boucle de base voidloop() visualise sur l’afficheur les huit octets de gauche mis en évidence dans le carré marron. Après une temporisation de 0,2S l’ensemble du tableau est décalé vers la gauche avec recirculation du premier octet vers celui de droite. Ce déplacement global est symbolisé par la grosse flèche verte. Pour réaliser cette opération de permutation circulaire sur l’ensemble du tableau, la procédure Decaler_a_gauche_le_tableau() commence par sauvegarder l’octet de gauche jaune. Puis, en partant de la gauche vers la droite elle va copier Octet + 1 dans Octet. Enfin, montré par la flèche violette l’octet jaune est recopié dans la dernière position orange. Simple non ?
Pourtant, quand on observe la Fig.46 qui traduit l’algorithme réellement utilisé, on est en droit de rester perplexe. L’ordre des lettres semble inversé, quand au déplacement des octets dans la table il se fait de gauche à droite. Curieux non ? On continue à visualiser les huit octets de gauche. Mais compte tenu de l’orientation de l’afficheur montré en Fig.40 il faut le balayer en sens réciproque, d’où ce chanbourlouboulé des données et de la permutation circulaire globale inversée.
Expérience 025 : Un graphe avec des « bâtons verticaux ».
Pour terminer avec le paragraphe de l’usage des LEDs dans Arduino, et des matrices de points, nous allons prendre comme exemple l’affichage d’un voltmètre à huit entrées présentant les données sous la forme d’un diagramme à barres. L’idée consiste à mesurer huit tensions variant de 0 à +5Vcc avec les convertisseurs CAN de l’ATmega328. Le problème c’est que sur la carte Arduino UNO on ne possède que six entrées de mesures analogiques et c’est bien dommage, car l’ATmega328 comporte huit de ces fonctions en interne. Il est peut-être temps de changer de carte électronique et de passer à la carte Arduino NANO qui est considérablement moins encombrante, qui met à notre disposition huit entrées analogiques au lieu de six et qui est moins coûteuse à l’achat. Comme elle ne présente que des avantages, personnellement ne n’utilise plus que ce type de carte.
Pour vous convaincre de l’opportunité de ce choix, vous consultez la Fiche n°5 et la Fiche n°6 qui précisent les caractéristiques de ce petit bijou qui dépasse en performances celles de sa grande sœur la carte UNO présentée sur les Fiches n°3 et Fiche n°4. Pour la faire dialoguer avec l’IDE il ne faudra pas oublier de la déclarer dans les onglets d’options [Outils] > [Type de carte] et dans la liste valider [Arduino Nano]. Pour vous donner une idée de la différence d’encombrement des deux cartes électroniques, la Fig.47 les montre toutes les deux. On remarque que les platines de
prototypage étant au pas standard du dixième de pouce, la NANO peut se brocher sans problème dans la zone centrale. Sur la Fig.47 les branchements des démonstrateurs précédents ont été repris pour ce nouvel exercice. Lorsque le démonstrateur Experience_025.ino est téléversé, on obtient le résultat de la Fig.48 sachant que pour simplifier et effectuer la manipulation je n’ai branché qu’un seul potentiomètre sur A6 qui sur la photographie était au maximum de +Vcc. L’entrée A7 pour sa part est réunie à GND ainsi que A5. L’entrée A4 est réunie au +3,3V disponible sur le broche n°2 à coté de D13. Les entrées A0 à A3 sont laissées « en l’air ». Comme elles sont à haute impédance, il suffit de les toucher avec un doigt pour faire fluctuer rapidement leur affichage entre les deux limites les autres barres restant stables. Sur P025 on peut noter que :
• Avec l’instruction Mesure[n] = map(analogRead(Entree_n), 0,1000,0,7) on s’attendrait à la valeur maximale de la CAN de 1023. Mais avec la tension mesurée ce maximum n’est pas atteint.
• Par le codage Matrice.setRow(Module,7-I,OCTET) on balaye de droite à gauche pour les raisons déjà évoquée pour expliquer le « chanbourlouboulé » de l’exercice précédent.
• La consigne for (byte J = 0; J < (7 – Mesure[I]); J++) OCTET = OCTET >> 1 a pour effet de transformer un nombre compris entre 0 et 7 en un binaire allant de B0000001 à B1111111. On retrouve l’opérateur de décalage à droite >> qui introduit des « 0 » à gauche.
Vous pouvez trouver exagéré que pour explorer le domaine du traitement des LEDs nous avons effectué un quart du cheminement complet de ce didacticiel qui était annoncé à l’origine pour 100 démonstrateurs. Il ne faut pas perdre de vue que cette ballade dans le monde de l’optoélectronique nous avons déjà analysé bon nombre d’instructions du langage C++ et abordé plusieurs techniques classiques en algorithmiques. Un grand pas a été franchi …
La suite est ici.