Afficheur 4x7+1 segments et Arduino

Bonjour, L'idée de cette réalisation est de créer un afficheur 4x7+1 segments générique, piloté par un Arduino. Je le voulais aussi petit que possible, il prend à peu près le volume d'un pouce.IMG_20171001_104923.jpg

CABLÂGE de l'AFFICHEUR

La base est un Arduino minuscule le A-Star 3101 de Polulu. 0J5288.1200.jpg
Je vais aussi utiliser un afficheur à anodes communes 4x7+1 segments. IMG_20171002_225542.jpg

Vous trouverez le brochage sur mon dessin. Neuf résistances de 330 ohms (10mA / segments) sont soudées côte à côte sur une plaque à bandes, percées au pas de 2,54mm. Les pattes sont espacées avec 1 seul trou de séparation, ce qui est à peine suffisant, même pour des 1/4W déjà très petites, mais ça loge.

IMG_20171001_173825.jpg

La qualité des soudures ne souffre aucun défaut, la place est comptée et le retour sur une erreur ne sera pas possible. Je conseille l'utilisation d'une station de soudage de qualité et la vérification de chaque soudure à la loupe.

IMG_20171001_174115.jpg

Les bandes de la plaque sont découpée à l'aide d'un disque diamanté monté sur une mini perceuse (type Dremel). Une première découpe doit être faite au milieu des résistances et une deuxième immédiatement sur les bords d'un côté. On gardera les pattes de résistances de ce côté là pour y souder l'Arduino à venir. Il ne reste qu'une pastille pour faire tenir la résistance.

On va maintenant souder l'afficheur au dessus des résistances en faisant coïncider les broches 9 à 16, on garde la 9ième résistance du côté des broches 8-9 de l'afficheur. Pour faciliter le repérage, j'inscris au marqueur le brochage de l'afficheur sur les côtés de celui-ci. Les cathodes des segments B, G, A, C, ":", F, vont recevoir immédiatement une résistance dont l'autre patte se retrouvera sur l'Arduino lui-même. Noter que les broches 9 et 10 qui alimentent un "dot" unique situé sur sur le 3ème digit, ne seront pas utilisés, coupez les pour libérer les résistances adjacentes. Ces résistances seront utilisées pour les segments D et E situés sur l'autre bord de l'afficheur. La 9ième résistance servira pour le "dp" (dot point). Vous remarquerez que la 5ième résistance se trouve connectée à la cathode du ":" qui n'est pas utilisé dans mon montage, mais qui peut vous servir pour un affichage de l'heure par exemple.

Les broches 1 à 8 de l'afficheur se retrouvent isolées sur l'autre bord. Il va falloir relier les segments D, E, "dp", aux résistances libres.

Les pattes des résistances du côté des segments B, G, A, C, ":", F sont coupées, On conserve les 3 autres qui elles sont coupées à l'opposé (contrairement à ma photo. Ben ouais, on peut se rater, j'ai dû compenser par des fils libres).

Voilà pour la 1ère étape. Pas très difficile sur le principe, mais qui demande une grosse attention et une certaine dextérité pour la réalisation.

AJOUT de l'ARDUINO

J'ai opté pour un A-Star3101 de chez Polulu, pour sa compacité (je crois que c'est le plus petit que j'ai trouvé !). Il assez complet en entrées/sorties et gros avantage, tout un côté n'est fait que de broches d'I/O (v. brochage).

L'A-Star est un 2x10 broches. Les broches 2 à 9 sont soudées sur les pattes des résistances (conservées... J'espère !) avec la correspondance suivante pour les cathodes: (Ard. | aff.) 2|B, 3|G, 4|A, 5|C, 6|:, 7|F, puis 19|D, 8|E, et enfin 18|"dp". Les 3 derniers sont câblés à la "main", c.à d. à l'aide de straps.

Il nous reste à connecter les anodes de nos 4 digits, plus l'anode du ":" si on veut l'utiliser. Le câblage se fera par des straps, de l'afficheur à l'Arduino directement. J'ai choisi l'association suivante : (Ard. | aff.) 19|4, 10|3, 11|2, 16|1, si on utilise le ":", sont anode peut utiliser la broche 12|: .

Vous remarquerez que j'ai volontairement libéré les broches 0, 1, 14 et 15, ce qui permet de garder la fonction "port série" de notre Arduino, utile dans le cas d'une utilisation de ce montage, dans une pure utilisation de type contrôleur d'affichage, en liaison avec un autre Arduino ou un Raspberry Pi, par exemple.
Si la fonction "RTS" du port série est nécessaire, il faudra libérer la broche 11 et connecter l'anode 2 sur une autre broche, comme la 6 par exemple, avec l'abandon du ":".
On peut aussi récupérer la fonction du bus SPI, ce qui suppose l'abandon là aussi du ":".
Enfin les broches 0 et 1 peuvent recevoir des interruptions, pour les adeptes de cette solution.

Tout ceci n'est pas très simple, mais les usages sont variés en fonction des options choisies.

 

PROGRAMMATION

Pour la partie programme, c'est relativement simple, mais on va utiliser des astuces pour minimiser le programme et en faire un afficheur générique, tout à fait utilisable dans tout un tas de projets.

DÉCLARATIONS

  // pour allumer un segment il faut positionner l'anode commune de l'afficheur à 1 et la cathode du segment à 0.
  // une résistance de 330 ohms est insérée entre la broche de l'arduino et le segment pour une limitation du courant à 10ma. 
const byte SEG[8] = {4,2,5,9,8,7,3,18}; // déclare un tableau de 8 constantes de broches segments (A,B,C,D,E,F,G,"dp") les poids forts sont à droite
const byte AFF[4] = {16,11,10,19}; // déclare un tableau de 4 constantes des broches afficheurs 18,19,10,11
  // --- tableau des segments traduis en valeurs numériques ---
const byte CODE[10] = {63,6,91,79,102,109,124,7,127,103}; // les 10 chiffres de (base en décimal) (ex.: 7 == segmengts "A,B,C" == 00000111 = 1+2+4=7) 
  //                   0  1 2  3   4   5   6  7  8   9

La déclaration de mon tableau "CODE" mérite peut-être quelques éclaircissements. Si vous maîtrisez le binaire vous avez le droit de passer le chapitre qui suit.

petit rappel sur le binaire

L'idée est d'affecter un bit à chaque segment. Ça tombe bien nous avons 7+1 segments, ce qui nous fait tout juste 1 octet (byte). nous donnons de manière arbitraire (enfin, pas tout à fait !), un bit pour chaque segment : "dp"GFEDCBA avec les poids faibles à droite. Donc le segment A "pèse" 0 ou 1(10), le segment B "pèse" 0 ou 2(10), le segment C "pèse" 0 ou 4(10), etc... Si un segment est utilisé, on le met à 1(binaire) sinon à 0(binaire). En fonction de sa place dans l'octet, son poids est ajouté à la somme total.

exemples : le chiffre "7" == segments "C,B,A" == 00000111(2) = 1+2+4(10) = 7(10) (c'est rigolo, "7" vaut 7 !)

                le chiffre "4" == segm.     "G,F,C,B" == 01100110(2) = 2+4+32+64 = 102(10)

Vous retrouverez toutes les valeurs dans le tableau "CODE".

Il nous faudra trouver une commande Arduino, capable d'extraire les bits de l'octet de codage, elle existe, c'est : bitRead( octet , positionDuBit )

Une boucle de 0 à 7 suffira à "lire" l'octet que l'on récupérera dans la table "CODEchiffre". Concernant le "dp", il suffira d'ajouter +128 à notre valeur renvoyée par "CODEchiffre".

Le programme est optimisé.

Fin de la digression... Vous pouvez reprendre la lecture à partir de là >

INITIALISATION

void setup() {
    
  // ------- Broches en sortie -------  
      // met les 8 broches des segments en sortie à 1 (éteint)
    for (int i=0; i<8; i++) { // boucle de défilement des 8 broches
      pinMode(SEG[i], OUTPUT); //met la broche en sortie
      digitalWrite(SEG[i],1);
    }
      // met les 4 broches des afficheurs en sortie à 0 (éteint)
    for (int i=0; i<4; i++) { // boucle de défilement des 8 broches
      pinMode(AFF[i], OUTPUT); //met la broche en sortie 
      digitalWrite(AFF[i],0);
    }
    pinMode(CCOMA, OUTPUT);
    digitalWrite(CCOMA, 0);
    pinMode(ACOMA, OUTPUT);
    digitalWrite(ACOMA, coma);
}

 

FONCTION D'AFFICHAGE

void affichage(byte mot[4]) {  
  
    for (byte af = 0; af <= 3; af++) {    // balayage des 4 afficheurs
      digitalWrite(AFF[af],1);                // activation des afficheurs à leur tour
      
      for (byte sg = 0; sg <= 7; sg++) {  // balayage des 7 segments
        // "mot" contient les 4 caractères à afficher. On récupère dans CODE la séquence des segments à afficher
        // attention les bits sont inversés, c'est un 0 qui allume le segment
        
        digitalWrite(SEG[sg],!bitRead(CODE[mot[af]],sg)); // Voilà, tout le secret est ici !
      }
      
      delayMicroseconds(2380);        // ~2,5ms par digit (caller sur la 1")
      digitalWrite(AFF[af],0);            // l'afficheur en cours est éteint
    }
  }

Vous apprécierez avec moi la concision du programme grâce à l'utiilisation de la table de codage "CODE[chiffre]".
Il suffira maintenant de remplir MOT[ch1,ch2,ch3,ch4], et de l'envoyer à l'affichage...
Voici un exemple de chronomètre (précis à 1"/12') :

PROGRAMME PRINCIPAL

void loop() {
  // boucle principale
  for (int j=0; j<2; j++) {             // boucle de 2*100ms=200ms
    for (int i=0; i<25; i++) {          // boucle de 25*4*2,4ms=~100ms
      MOT[0]=cpt / 1000;
      MOT[1]=cpt / 100 % 10;     // les centaines
      MOT[2]=cpt / 10 % 10;  // les dizaines
      MOT[3]=cpt % 10;       // les unités
      cpt++;
      cpt=cpt % 6000;       // ça c'est pour revenir à 0 après 59"99
      
      affichage (MOT);      // appel de la fonction d'affichage avec passage du paramètre MOT à afficher

    }
    digitalWrite(voyant, j%2); // clignotement du voyant(13)
  }
  coma = !coma ;          // clignotement du ":" (coma) central ttes les secondes
  digitalWrite(ACOMA, coma);
}

Cet afficheur en l'état peut déjà servir bien des projets : compteur, horloge, etc... On peut jouer avec la table "CODE" pour par exemple, créer des caractères de l'alphabet. Bon c'est vrai avec quelques manquements et un mélange de minuscules et majuscules. Mais notre cerveau s'en accommode et est capable de lire des phrases défilantes.
Une autre idée de l'utilisation pourrait aussi être un bargraphe stéréo, ou un défilé de barres et de traits dans des séquences esthétiques.