Bonjour à tous,
Je viens de réaliser un affichage multiplexé avec mon Arduino. J'ai réalisé le montage avec un IC décodeur 7 segments et trois transistors commandés par l'Arduino pour le multiplexage Je suis parti de la doc d'Eskimon page 169 et j'ai adapté son programme. J'ai rencontré quelques difficultés, mais finalement, ça marche.
Pour mémoire, voici le logiciel d'Eskimon: Il sert à gérer le nombre de voitures d'un parking. Je n'ai repris que les parties qui servent à réaliser un affichage multiplexé à 3 chiffres. Et j'y ai ajouté un simple compteur de 0 à 999.
Eskimon (qui vient du C) utilise des variables de type char, c'est-à dire qu'il s'agit d'un octet. Il le fait de préférence à int, qui en utilise deux.Code://les broches du décodeur 7 segments const int bit_A = 2; const int bit_B = 3; const int bit_C = 4; const int bit_D = 5; //les broches des transistors pour l'afficheur des dizaines et celui des unités const int alim_dizaine = 6; const int alim_unite = 7; //les broches des boutons const int btn_entree = 8; const int btn_sortie = 9; //les leds de signalements const int led_rouge = 12; const int led_verte = 11; //les mémoires d'état des boutons int mem_entree = HIGH; int mem_sortie = HIGH; int etat = HIGH; //variable stockant l'état courant d'un bouton char place_dispo = 10; //contenu des places dispos bool afficheur = false; long temps; void setup() { //Les broches sont toutes des sorties (sauf les boutons) pinMode(bit_A, OUTPUT); pinMode(bit_B, OUTPUT); pinMode(bit_C, OUTPUT); pinMode(bit_D, OUTPUT); pinMode(alim_dizaine, OUTPUT); pinMode(alim_unite, OUTPUT); pinMode(btn_entree, INPUT); pinMode(btn_sortie, INPUT); pinMode(led_rouge, OUTPUT); pinMode(led_verte, OUTPUT); //Les broches sont toutes mises à l'état bas (sauf led rouge éteinte) digitalWrite(bit_A, LOW); digitalWrite(bit_B, LOW); digitalWrite(bit_C, LOW); digitalWrite(bit_D, LOW); digitalWrite(alim_dizaine, LOW); digitalWrite(alim_unite, LOW); digitalWrite(led_rouge, HIGH); digitalWrite(led_verte, LOW); //vert par défaut temps = millis(); //enregistre "l'heure" } void loop() { //si ca fait plus de 10 ms qu'on affiche, on change de 7 segments if((millis() temps) > 10) { //on inverse la valeur de "afficheur" pour changer d'afficheur (unité ou dizaine) afficheur = !afficheur; //on affiche afficher_nombre(place_dispo, afficheur); temps = millis(); //on met à jour le temps } //on test maintenant si les boutons ont subi un appui (ou pas) //d'abord le bouton plus puis le moins etat = digitalRead(btn_entree); if((etat != mem_entree) && (etat == LOW)) place_dispo += 1; mem_entree = etat; //on enregistre l'état du bouton pour le tour suivant //et maintenant pareil pour le bouton qui décrémente etat = digitalRead(btn_sortie); if((etat != mem_sortie) && (etat == LOW)) place_dispo = 1; mem_sortie = etat; //on enregistre l'état du bouton pour le tour suivant //on applique des limites au nombre pour ne pas dépasser 99 ou 0 if(place_dispo > 99) place_dispo = 99; if(place_dispo < 0) place_dispo = 0; //on met à jour l'état des leds //on commence par les éteindre digitalWrite(led_verte, HIGH); digitalWrite(led_rouge, HIGH); if(place_dispo == 0) //s'il n'y a plus de place digitalWrite(led_rouge, LOW); else digitalWrite(led_verte, LOW); } //fonction permettant d'afficher un nombre void afficher_nombre(char nombre, bool afficheur) { long temps; char unite = 0, dizaine = 0; if(nombre > 9) dizaine = nombre / 10; //on récupère les dizaines unite = nombre ( dizaine*10); //on récupère les unités if(afficheur) { //on affiche les dizaines digitalWrite(alim_unite, LOW); digitalWrite(alim_dizaine, HIGH); afficher(dizaine); } else { //on affiche les unités digitalWrite(alim_dizaine, LOW); digitalWrite(alim_unite, HIGH); afficher(unite); } } //fonction écrivant sur un seul afficheur void afficher(char chiffre) { //on commence par écrire 0, donc tout à l'état bas digitalWrite(bit_A, LOW); digitalWrite(bit_B, LOW); digitalWrite(bit_C, LOW); digitalWrite(bit_D, LOW); if(chiffre >= 8) { digitalWrite(bit_D, HIGH); chiffre = chiffre 8; } if(chiffre >= 4) { digitalWrite(bit_C, HIGH); chiffre = chiffre 4; } if(chiffre >= 2) { digitalWrite(bit_B, HIGH); chiffre = chiffre 2; } if(chiffre >= 1) { digitalWrite(bit_A, HIGH); chiffre = chiffre 1; } }
Or, si on se plonge dans la doc Arduino, on voit que:
INT are your primary data-type for number storage.
alors que:
CHAR is a data type that takes up 1 byte of memory that stores a character value.
Je me suis dit que si mon Arduino essayait d'envoyer des caractères ASCII aux afficheurs 7 segments, cela pourrait poser problème, mais à la réflexion, non puisque le contenu de l'octet reste le même. Cependant, si l'on utilise print pour voir ce que l'Arduino envoie aux afficheurs, on voit bel et bien des caractères ASCII, pas des chiffres.
N'étant pas en manque de place mémoire, j'ai remplacé les CHAR par des INT.
Le second problème que j'ai rencontré a été que les afficheurs ne s'allumaient pas séquentiellement, avec le code que voici:Seul l'afficheur des centaines s'allumait. Je n'ai toujours pas compris pourquoi! Si quelqu'un arrive à me l'expliquer, je l'en remercie d'avance!Code:void afficher_nombre(int nombre, int afficheur) { int centaine = nombre / 100; //on récupère les centaines int dizaine = (nombre / 10) - (centaine * 10); //on recupere les dizaines int unite = nombre - (centaine * 100) - (dizaine*10); //on recupere les unités if(afficheur= 1) { digitalWrite(alim_unite, HIGH); digitalWrite(alim_dizaine, LOW); digitalWrite(alim_centaine, LOW); afficher(unite); } else if(afficheur= 2) { digitalWrite(alim_unite, LOW); digitalWrite(alim_dizaine, HIGH); digitalWrite(alim_centaine, LOW); afficher(dizaine); } else if(afficheur= 3) { digitalWrite(alim_unite, LOW); digitalWrite(alim_dizaine, LOW); digitalWrite(alim_centaine, HIGH); afficher(centaine); }
J'ai résolu le problème en utilisant la fonction suivante:
La seconde difficulté que j'ai rencontrée était un manque de contraste de l'affichage, c'est-à-dire que les segments non utilisés des afficheurs ne s'éteignaient pas complètement.Code://fonction permettant d'afficher un nombre void afficher_nombre(int nombre, int afficheur) { int centaine = nombre / 100; //on récupère les centaines int dizaine = (nombre / 10) - (centaine * 10); //on recupere les dizaines int unite = nombre - (centaine * 100) - (dizaine*10); //on recupere les unités switch (afficheur) { case 1: digitalWrite(alim_unite, HIGH); digitalWrite(alim_dizaine, LOW); digitalWrite(alim_centaine, LOW); afficher(unite); break; case 2: digitalWrite(alim_unite, LOW); digitalWrite(alim_dizaine, HIGH); digitalWrite(alim_centaine, LOW); afficher(dizaine); break; case 3: digitalWrite(alim_unite, LOW); digitalWrite(alim_dizaine, LOW); digitalWrite(alim_centaine, HIGH); afficher(centaine); break; } }
La situation s'est améliorée en introduisant une pause de 5 millisecondes entre les allumages des afficheurs.
Dans le programme d'Eskimon, on a la boucle principale (loop) qui teste à chaque passage si 10 millisecondes se sont écoulées depuis le dernier changement d'afficheur.
J'ai modifié le délai de 10 à 5 msec. Et j'ai introduit un délai de 5 msec après l'envoi du mot BCD au décodeur 7 segments.Code:void loop() { //si ca fait plus de 5 ms qu'on affiche, on change de 7 segments if ((millis() - temps) >5) { //on update la valeur de "afficheur" afficheur = afficheur+1; if (afficheur >3) {afficheur = 1;} temps = millis(); //on update la valeur de "compteur" compteur=compteur+1; } if(compteur>9999){compteur = 0;} int comptaff= compteur/10; //on affiche afficher_nombre(comptaff, afficheur); }
Et comme ça, ça ne fonctionne pas trop mal. Y aurait-il moyen de faire mieux?Code://fonction écrivant sur un seul afficheur void afficher(int chiffre) { //on commence par écrire 0, donc tout à l'état bas digitalWrite(bit_A, LOW); digitalWrite(bit_B, LOW); digitalWrite(bit_C, LOW); digitalWrite(bit_D, LOW); if(chiffre >= 8) { digitalWrite(bit_D, HIGH); chiffre = chiffre - 8; } if(chiffre >= 4) { digitalWrite(bit_C, HIGH); chiffre = chiffre - 4; } if(chiffre >= 2) { digitalWrite(bit_B, HIGH); chiffre = chiffre - 2; } if(chiffre >= 1) { digitalWrite(bit_A, HIGH); chiffre = chiffre - 1; } delay (5); }
Merci d'avance,
Yvan
-----