Partage
  • Partager sur Facebook
  • Partager sur Twitter

Contrôle d'une matrice à leds

Sujet résolu
    1 novembre 2018 à 14:26:12

    Bonjour, je me suis récemment lancé dans la fabrication d'une matrice à leds de 5*16 de A à Z j'ai réaliser avec une CNC les 80 trous dans du bois MDF peint en noir puis j'ai soudé toutes les leds. Pour contrôler le tout j'utilise une carte Arduino NANO qui pilote 5 transistors NPN pour les  lignes et un TLC5940 pour les 16 colonnes. Jusqu'ici tout va bien, je fait du multiplexage.

    Sur le schéma il y a qu'une seule ligne de représentée car c'est le même principe cinq fois avec toutes les cathodes connectées au TLC et un transistor pour chaque ligne.

    Concernant la programmation j'ai testé dans un premier temps la méthode avec plein de digitalWrite(x,x) pour allumer chaque ligne pour ensuite faire plein de Tlc.set(x,x) pour chaque colonne. L'inconvénient de cette méthode c'est la taille du code pour un simple chiffre à afficher, de plus l'utilisation de digitalWrite(x,x) prend du temps.

    J'ai donc testé une seconde méthode beaucoup plus astucieuse à mes yeux : utiliser un tableau booléen à deux dimensions qui nécessite d'être juste parcouru selon les lignes et les colonnes. L'avantage est de pourvoir faire un tableau pour chaque chiffre ou lettre au lieu d'une dizaine de lignes de codes. D'ailleurs décidé de toucher au registres au lieu de faire des digitalWrite(x,x) pour optimiser un peu plus la chose x).

    #include "Tlc5940.h"
    
    #define NB_LIGNES 5
    #define NB_COLONNES 16
    
    #define BIT0 0b00000001
    #define BIT1 0b00000010
    #define BIT2 0b00000100
    #define BIT3 0b00001000
    #define BIT4 0b00010000
    #define BIT5 0b00100000
    #define BIT6 0b01000000
    #define BIT7 0b10000000
    
    #define SORTIES_LIGNES 0b00011111; // de A0 ---> A4 donc de BIT0 ---> BIT4 soit sorties
    
    bool matrice[5][16]={
      {0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1},
      {0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1},
      {0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1},
      {0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1}, 
      {0,0,0,1,0,1,1,1,0,1,1,1,0,1,1,1}
    }; // Permet d'afficher 9888
    
    
    void setup() {
    	Tlc.init(0); // On initialise toutes les sorties du Tlc à 0;
    	DDRC = SORTIES_LIGNES; // Definit les sorties pour contrôler les lignes	
    }
    
    void loop() {
    	for (int iL = 0; iL < 5; iL++) { // On parcourt les lignes
    		PORTC = 1 << iL; // On allume la ligne 
    		for (int iC = 0; iC < 16; iC++) { // On parcourt les colonnes
    			if (matrice[iL][iC] == 1) { // Test si la colonnes de la matrice contient un 1
    				Tlc.set(iC, 4095); // Allume la colonne
    				Tlc.update();
    			}
    			delayMicroseconds(800); //Délai pour voir la lumière
    		}
    		Tlc.setAll(0); //On éteint toutes les colonnes en fin de ligne
    		Tlc.update();
    		delayMicroseconds(500); //Délai entre chaque ligne
    	}
    }

    En testant à une fréquence de rafraichissement faible (l'affichage n'est pas encore "fixe") tout fonctionne : on voit bien chaque ligne s'allume correctement lorsqu'il le faut puis enfin elle s’éteint et ça passe la suivante. Le problème est que si on diminue le temps entre chaque lignes au bout d'un certain délai (200µs) des leds s'allument alors qu'elles ne devraient pas ou d'autres s’éteignent.

    A première vue le problème semble venir du TLC5940 qui nécessite un Tlc.update() après chaque Tlc.set(x,x), un manque de timing ? Pas le bon composant pour ce genre d'application ? Mauvaise idée les tableaux à deux dimensions ? Je suis à l'écoute de toutes solutions/propositions (si certains veulent une courte vidéo pour voir ce qu'il ce passe c'est possible) :D merci d'avance !

    -
    Edité par ClémentSALOU 1 novembre 2018 à 14:48:26

    • Partager sur Facebook
    • Partager sur Twitter
      1 novembre 2018 à 22:13:08

      La lib TLC garde en mémoire l'état de chaque sortie du TLC.

      Il est possible de changer l'état de la mémoire avec la fonction TLC.set

      Cette fonction est très rapide puisqu'elle ne fait que changer la mémoire interne de l'arduino.

      Il faut ensuite appeler la fonction TLC.update dont le but et d'envoyer la contenu de la mémoire de l'arduino sur le chip TLC.

      Cette fonction update est donc beaucoup plus lente mais indispensable pour mettre à jour le TLC.

      Maintenant que cela est dit, observons ton code ;)

      for (int iC = 0; iC < 16; iC++) { // On parcourt les colonnes
          if (matrice[iL][iC] == 1) { // Test si la colonnes de la matrice contient un 1
              Tlc.set(iC, 4095); // Allume la colonne
              Tlc.update();
          }
          delayMicroseconds(800); //Délai pour voir la lumière
      }

      Première remarque :

      Tu as une boucle for qui va parcourir ta matrice pour faire un set, un update et un delay.

      Si la première LED de ta matrice doit être allumée, elle le sera avec le set, puis le update met à jour la sortie et le delay temporise un peu.

      Puis la boucle passe à la LED suivante, et ainsi de suite...

      Cependant, pendant qu'elle traite l'état de la deuxième LED, la première LED reste dans le même état qu'elle était.

      Du coup, si la deuxième LED s'allume, la première LED reste allumée elle aussi.

      Si l'on considère que set et update sont instantanés, la première LED aura donc été allumée 1600us (2x le  délay de 800us) alors que la deuxième LED n'aura été allumée que 800us.

      Puis la boucle passe à la troisième LED, sans toucher à l'état des 2 précédentes.

      Et ainsi de suite...

      Au final, ta dernière LED de la colonne ne s'allumera que pendant 800us alors que la première LED de la colonne aura eu droit à 16x ce délay de 800us, ce qui la rend bien plus lumineuse.

      Bref, tout ça pour dire que ce n'est pas logique et clairement pas optimisé car tu fais de nombreux update et nombreux délay.

      Il serait plus judicieux de faire tous les set, puis un seul update et enfin le delay.

      Seconde remarque :

      Une fois que ta boucle est finit, tu remets toutes les sorties à 0 avec un TLC.setAll(0) et un update, sauf que cela prend du temps, surtout le update.

      Si tu veux éteindre toutes tes LED, il te suffit de couper le PORTC, ce sera bien plus rapide que d'envoyer des données au TLC.

      Du coup, un code bien optimisé prenant en compte ce 2 remarques serait le suivant :

      void loop() {
      	
      	for (int iL = 0; iL < 5; iL++) { // On parcourt les lignes
      		
      		// 1: On configure le TLC pour la ligne actuel
      		for (int iC = 0; iC < 16; iC++) { // On parcourt les colonnes
      			if (matrice[iL][iC] == 1) {
      				Tlc.set(iC, 4095); // On
      			} else {
      				Tlc.set(iC, 0); // Off
      			}
      		}
      		
      		// 2: On éteint la ligne précédante
      		// (cf le reste du code pour bien comprendre pourquoi on le fait ici)
      		PORTC = 0;
      		
      		// 3: On envoie les données au TLC
      		Tlc.update();
      		
      		// 4: On allume la ligne
      		PORTC = 1 << iL;
      		
      		// 5: On attend un peu (pour l'effet visuel)
      		delayMicroseconds(500);
      		
      		// 6: FIN !
      		// En effet, plutôt que d'éteindre la ligne avant de passer à la suivante, on la laisse allumée
      		// Comme ça, pendant que l'on fait les TLC.set de la ligne suivante, les LED restent allumées dans le même état qu'actuellement
      		// Cela permet de gagner un peu en luminosité le temps de faire tous les appels à set 
      		// Et cela ne fera pas de glitch car le set ne fait que changer la mémoire et non l'état des sorties
      		// La ligne sera ensuite éteinte juste avant de faire le update qui changera l'état des sorties du TLC
      		
      	}
      	
      }



      Après, on pourrait aussi parler du fait que ton tableau de bool prend un place énorme en mémoire RAM et mémoire PROGRAM mais ce message est déjà bien assez long ;)



      -
      Edité par lorrio 1 novembre 2018 à 22:19:37

      • Partager sur Facebook
      • Partager sur Twitter

      Contrôle d'une matrice à leds

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown