bunex-industries

Contrôle d'un afficheur LED

Il y a quelques années, j'ai déniché ce panneau d'affichage à LED hors d'usage dans une benne à gravats.

Moyennant un bon nettoyage et quelques menues réparations, il s'était montré parfaitement fonctionnel, recommençant à exécuter l'animation publicitaire d'un snack, avec un remarquable sens du devoir.

Un beau projet de reverse-engineering, mais le bidule a fini... à la cave. Les strates se sont accumulées, et dans les profondeurs de l'oubli, indifférent à l'agitation des hommes, promis à la fossilisation, il s'est lentement bonifié...

À la faveur de fouilles entreprises il y peu, j'ai exhumé et ramené à la lumière pour la seconde fois ce mystérieux artefact...

Fonctionnement

La matrice d'affichage est constituée de 16 x 96 LEDs rouges. Cette matrice est elle-même divisée en 3 blocs de 16 x 32 leds.

Le driver d'origine, doté d'un port USB, est assez obscur et quelques recherches sur le net m'avaient conduit vers des sites en chinois, et peut-être des applications pour windows. j'ai rapidement abandonné cette voie que j'avais emprunté sans entrain et me suis attelé à la fabrication de mon propre système de contrôle. La panneau contient son propre bloc d'alimentation 5V à brancher sur le secteur.

Voici le circuit d'une des 3 dalles (elles sont parfaitement identiques). Les dalles sont reliées par une petite nappe.

Multiplexage !

Comme d'habitude quand il s'agit de piloter beaucoup de leds, on s'attend à les trouver câblées sous une forme ou une autre de multiplexage.

L'idée étant de ne surtout pas piloter les leds individuellement (trop de fils, dépasse de loin le nombre de sorties d'un Arduino, inélégant !...) mais profiter de la persistance rétinienne et allumer successivement (très très rapidement) des groupes de leds (lignes, colonnes ou autre groupe).

Comme il faut diminuer au maximum le nombre de fils de commande, on utilise souvent un ou plusieurs registre(s) à décalage, c'est à dire des convertisseurs 8 bits série vers parallèle (le 74HC595 par exemple). Les données sont transmises du contrôleur au panneau sur 2 fils seulement : data / clock. Ces données "série" se propagent jusqu'au bout de la chaîne de registres à décalages. Cette chaîne de 16 registres de 8 bits distribue l'information d'état aux les leds concernées. Un compteur/décodeur ou autre dispositif s'occupe de faire alterner les groupes en boucle.

Voici une animation qui expose le principe du multiplexage au ralenti (il y a de nombreuses variantes) :

La dalle n'est pas constituée uniquement de leds. En inspectant le PCB, on remarque circuits intégrés dédiés au multiplexage. Un peu de d'ingénierie inverse nous confirme la présence de 16 registres à décalage 8 bits par dalle (74HC595). Cela nous donne 16x8 = 128 états électroniques différents pour une dalle.

En observant le câblage des sorties de ces registres, on découvre que chaque sortie parmi les 128 est connectée en parallèle à 4 leds.

Une dalle contenant 16x32 leds, soit 512 leds, soit 4x128, on devine qu'une série complète de données sur 16 registres ne sera visible que sur un quart des leds à la fois (multiplexage sur 4 groupes).

Cette sélection du groupe de leds à afficher est effectuée avec un décodeur binaire 2 bits vers 4 sorties :

Ce circuit intégré va permettre l'activation successive des lignes dans le cadre du multiplexage. Ainsi les 128 états activent 4 lignes d'une dalle (Lignes 0,4,8,12), puis les 4 lignes suivantes (1,5,9,13), puis les lignes (2,6,10,14) et enfin les dernières (3,7,11,15). Le tout étant reproduit pour toutes les dalles.

Code Arduino pour l'affichage

L'idée est de partir d'une matrice d'états rectangulaire de 16x96 "pixels", facile à manipuler (un canvas, quoi !), et de former le stream de données bit par bit dans l'ordre exact (et pas cartesien du tout) attendu par le système de multiplexage.

Voici la boucle de code qui effectue cette conversion et génère les données binaires série. Les données de l'image 16x96 sont reçues par WebSocket et stockées dans l'array STATES sous la forme de 192 octets. Le premier octet de cette liste code les 8 leds du coin supérieur gauche, puis de gauche à droite et de bas en haut. Le dernier octet code donc les 8 leds en bas à droite.


// pour chaque ligne (1 parmi 4)
for (int line = 0 ; line < 4 ; line++) {                   
    // pour chaque dalle (1 parmi 3)
    for (int board = 0 ; board < 3 ; board++) {            
      // pour chaque registre à décalage (1 parmi 16)
      for (int shiftReg = 0 ; shiftReg < 16 ; shiftReg++) {
        // for chaque bit d'un registre
        for (int k = 0 ; k < 8 ; k++) {                    
          // x,y coordonnées cartésiennes dans la grille 16x96
          int xx = 95 - (board*32 + 8*(shiftReg/4) + k)%96;
          int yy = (3-line) + 4*(shiftReg%4);
          // index index du bit dans l'octet
          int xxx = xx%8;                                  
          // index de l'octet dans la liste des états "STATES"
          int ind = yy*12 + xx/8;                          
          //  get bit state
          int state = bitRead(STATES[ind],xxx);            
          
          // send bit state serially, with a clock tick
          digitalWrite(DATA, !state);
          digitalWrite(CLK, HIGH);
          digitalWrite(CLK, LOW);
        }
      }
    }
    // Ceci est exécuté à chaque ligne.
    // LEDs are set off while changing line
    ledcWrite(OE_CHANNEL, 0);
    // the 1-2-3_4 line is selected with two bits
    digitalWrite(CHA, line % 2);
    digitalWrite(CHB, (line / 2));
    // line data are stored
    digitalWrite(RST, HIGH);
    digitalWrite(RST, LOW);
    // LEDs are set ON, the line is visible.
    ledcWrite(OE_CHANNEL, pwm);
  }

Logiciel embarqué sur ESP32

Les cartes ESP32 disponibles depuis quelques années, sont étonnantes. Si elles n'avaient pas le gros défaut d'avoir des convertisseurs analogiques/numérique très mauvais, je crois que je les préfèrerais aux Arduino !

Très bon marché (sourcil froncé...), compatibles avec le langage et l'IDE Arduino, équipés d'une puce wifi-bluetooth et d'un système de fichier (le luxe !), ils représentent une alternatives très intéressante parfois au Raspberry Pi lorsque l'Arduino ne suffit plus.

Au code embarqué ci-dessus (qui pourrait tourner sur Arduino) s'ajoutent des fonctions exclusivement propres aux ESP32 :

L'esp32 rejoint WLAN existant ou crée le sien, un ordinateur ou téléphone sur le réseau peut se connecter à l'ESP32 et se voir servir une page HTML / JS de contrôle, connectée en temps réel à l'ESP32 via une websocket.

Cette page permet de dessiner sur un canvas HTML 16x96, écrire, exécuter un jeu de la vie, afficher un spectre ou un niveau audio, et pourrait facilement être encore augmentée. La création et l'animation du contenu graphique ne concerne pas l'ESP32, qui se contente juste d'afficher les donnée créées et envoyés par la page.

Voici une capture du spectre audio. C'est le navigateur du client qui capte le son et réalise cette analyse fréquentielle (avec WebAudioAPI). Si la connexion wifi est forte, la latence est très faible.

Quelques images