bclose

Matriz LED de 8×8

Arduino y los array de 8x8 LED

Objetivos

 

 

    • Presentar las matrices LED de 8×8.
    • Mostrar un circuito de muestra.
    • Programar un mensaje móvil.
 

Material requerido.

Imagen de Arduino UNO

Arduino UNO o equivalente.

ProtoboardconexionesUna Protoboard más cables.
componente

8 x resistencias de 330Ω.

Matriz LED 8x8

Una matriz de LEDs 8×8 1588AS ,

o bien

Una matriz de LEDs 8×8 1388ASR

tienda online prometec

Las matrices LED

 

Parece que los LEDs se fabrican en todos los tamaños y formatos imaginables, y este componente que os presentamos hoy, hace gala de esa creatividad. Las matrices de LEDs (o LED arrays) son, como su nombre indica, una matriz de diodos LED normales y corrientes que se comercializa en multitud de formatos y colores. Desde las de un solo color, a las que tienen varios colores posibles, e incluso las hay de una matriz RGB (Os dejo imaginar la de pines que tiene).

En esta sesión, de nuestro tutorial Arduino, vamos a usar una matriz de 8×8 LEDs de color rojo, que espero, sirva como demostración de cómo manejarla y de lo que se puede hacer con este tipo de material. Utilizaremos una única matriz e iremos arrastrando, letras y símbolos, para demostración de lo que podríamos hacer con una docena de estos simpáticos displays.

La idea, es que como tenemos una matriz de 8×8 podemos dibujar letras y símbolos de la misma manera que ya hicimos en el pasado, cuando definimos el símbolo de grado, para el display LCD. Es decir, definiendo matrices de puntos para representar las letras, que luego sacaremos por el Display.

Matriz LED 8x8

Circuito de la matriz

Por lo demás, son diodos LED totalmente normales, organizados en forma de matriz, que tendremos que multiplexar para poder iluminar uno u otro punto, tal y como hicimos en la sesión del teclado matricial. Este componente se presenta con dos filas de 8 pines cada una, que se conectan a las filas y las columnas.

 
  • Si los diodos se unen por el positivo, se dice que son matrices de Ánodo común (El nombre pedante del positivo) y se se une por el negativo decimos que son de  Cátodo común.
  • Dependiendo del fabricante podéis encontrar de ambos tipos.  

Si ponemos HIGH en una columna, digamos la 2, no se iluminara nada aun. Pero cuando hagamos LOW en, digamos la fila 4, se cerrara el circuito a GND (con una resistencia de limitación, por supuesto) y el pin col 2 x fila 4, se encenderá.

Si alguno creíais que las 8 filas y 8 columnas de la matriz corresponderían a las dos filas de pines, donde una fila serían las columnas y la otra las filas, lo lógico ¿no?, vais dados. Porque este es uno de esos casos en los que el fabricante, por razones inescrutables a los mortales comunes,  ha decidido mezclar unas y otras de forma aleatoria, haciendo poco menos que imposible adivinar cuál es cual sin el manual y convirtiendo el cableado en una pesadilla.

Así pues, aplicar la regla número uno. Buscad el manual del fabricante en Google (es más fácil de lo que crees).

 
  • Por cierto en Internet encontrareis muy a menudo lo de léete el manual. De hecho, hasta han acuñado un acrónimo en inglés para ello: RTFM, iniciales de una bonita frase, que me ahorraré traducir.  

Así pues vamos con el manual del 1588AS :Patillaje matriz LED 8x8Fíjate que aquí lo importantes es, la descripción de la matriz, donde nos habla de filas y columnas, pero sobre todo nos dice que pines del chip son cada fila y columna. Ya solo nos falta saber cuál de los pines es el uno, y aquí, yo no he sido capaza de localizar una marca que lo indique, a pesar de que si os fijáis, el manual marca con una cruz el pin 1, pero en mi chip, no he sido capaz de encontrar ninguna marca asimétrica.

 
  • Lo que yo he hecho ha sido conectar 5V y GND, con una resistencia de 330Ω, y buscar los pines 13 y 9 correspondientes a la columna 1, fila 1, hasta que el punto 1,1 se encendió. A partir de ahí, el resto es fácil.  

Os recomiendo que una vez que lo hayáis localizado, vayáis conectando el resto de los pines poco a poco y vayáis probando las conexiones. En mi caso he conectado las columnas de la siguiente manera:

Matriz1334106111516
Arduino23456789

Y las filas:

Matriz9148121725
Arduino10111213A0A1A2A3

 

Kit de Inicio Prometec.net 

Para los que uséis el nuevo kit de inicio de Prometec, el display que viene es un 1388ASR, que es un modelo de Ánodo comun, la disposición de los pines es diferente y su definición es esta:

Disposicion de pines

 

La conexión a vuestro Arduino es como sigue:

Matriz12611713144
Arduino23456789

Y para las filas:

Matriz121510165938
Arduino10111213A0A1A2A3

Fijaros en que como conectamos la misma disposición de filas y columnas a nuestro Arduinoy en el mismo orden de pines, la configuración e sintercambiable.

Aquí os dejo un programita que va barriendo la matriz y os ayudara comprobar las conexiones Prog_37_0

Creo que esta va a ser la primera, y espero que ultima vez, que no vamos a incluir  esquema ni protoboard, para mostrar las conexiones, porque no he encontrado ninguna pieza para Fritzing con una matriz como esta, y porque creo que añadiría muy poco, a las tablas de arriba.  

El Programa de control

 

El programa de barrido que hemos usado para comprobar que teníamos bien conectados los puntos, contiene ya la base de nuestro programa de control.

void setup()                           // Prog_37_1
   {   
        for (int j=2; j<19; j++)
        pinMode(j, OUTPUT);
   }

void loop()
   {
        for (int j=2; j<10; j++)
           {
              digitalWrite(j, HIGH);     //Levantamos la columna
              for (int k= 10 ; k<18 ; k++)
                 {
                     digitalWrite(k, LOW);   //Encendemos el punto
                     delay(250);
                     digitalWrite(k, HIGH);  //Apagamos el punto
                 }
              digitalWrite(j, LOW);                //Bajamos la columna
           }
    }

Lo importante en el, es que en primer lugar definimos en el setup como salidas de los pines 2 al 19.

¿ AL 19 ?. ¡No existen tantos pines!. Bueno, en realidad sí.

Ya vimos en su momento que los pines analógicos e A0 al A5 se podían usar como pines digitales normales. Y cuando es así podemos numerarlos como pines digitales del 14 al 19.

Me he aprovechado de esta curiosidad, para que sea más cómodo escribir el programa. Para iluminar un punto concreto, en primer lugar poner en LOW todas las columnas y en HIGH todas las filas, lo que apaga todo.

Después levantar la columna que contiene el punto a iluminar. Fíjate que esto de por sí, no va a encender nada aun. Sera cuando pongamos una de las filas en LOW, cuando se cerrara el circuito y un punto se iluminara. La curiosidad de esto, es que el diodo se ilumina cuando ponemos 0 en una fila, no un 1 como hasta ahora.

A esto se le llama, lógica negativa, porque la acción se ejecuta con un valor bajo y no alto.

Entonces ¿ Cómo hacemos para mostrar un carácter, digamos la P? Pues tal y como vimos en la sesión previa. Dibujando cuadraditos en un papel cuadriculado.

Pero, ¿Entonces, tenemos que definir una matriz por cada letra que quiero representar?

La respuesta, querido amigo, es un rotundo SI. Y no solo para cada letra, mayúscula y minúscula, sino también para cada número y símbolo que quiera representar.

 
  • De hecho este es el primer sistema que los ordenadores han usado desde el principio para dibujar los caracteres en pantalla.
 

Para escribir PROMETEC, tendremos que definir las letras correspondientes:

byte P[] = { 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x40 };
byte R[] = { 0x78, 0x44, 0x44, 0x78, 0x70, 0x58, 0x4C, 0x46 };
byte O[] = { 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C };
byte M[] = { 0x66, 0x7E, 0x5A, 0x42, 0x42, 0x42, 0x42, 0x42 };
byte E[] = { 0x7C, 0x40, 0x40, 0x78, 0x78, 0x40, 0x40, 0x7C };
byte T[] = { 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 };
byte C[] = { 0x7c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C };
byte N[] = { 0x42, 0x62, 0x72, 0x5A, 0x4E, 0x46, 0x42, 0x42 };
byte dot[]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06 };
byte sp[]= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

Vamos ahora, a ver como sacamos una de estas letras en el display. Lo primero es que vamos a usar la función GetBit de la sesión anterior para sacar la información a presentar en el display.

bool GetBit( byte N, int pos)
   {                 // pos = 7 6 5 4 3 2 1 0
       int b = N >> pos ;         // Shift bits
       b = b & 1 ;                // coger solo el ultimo bit
       return b ;
   }

Por tanto barreremos filas y columnas, para posicionar cada punto, y leeremos con GetBit si debemos iluminarlo o no. Vamos a empezar definiendo el setup y ell array para la P:

 byte P[] = { 0x78, 0x44, 0x44, 0x78, 0x40, 0x40, 0x40, 0x40 };
 void setup()                                        
    {   for (int j=2; j<19; j++)
        pinMode(j, OUTPUT);
        Serial.begin(9600);
   }

Y ahora definimos un esqueleto que barra filas y columnas, sin preocuparnos de los números de pin:

void loop()
   {
       for (int fil = 0; fil <8 ; fil++)
          {
              byte F = P[fil] ;
              for (int col =7; col >= 0 ; col--)
                 {
                 }
              Serial.print(F, HEX);
              Serial.print(",  ");
          }
       Serial.println();
   }

Los print centrales han sido para comprobar que lee correctamente (que nunca se sabe).  Vamos ahora a buscar el bit para cada fila y columna, y lo sacaremos en pantalla, para asegurarnos de que lee bien los bitss:

void loop()
   {
       for (int fil = 0; fil <8 ; fil++)
          {
              byte F = P[fil] ;
              for (int col =7; col >= 0 ; col--)
                 {
                     bool b = GetBit(F, col)  ;
                     Serial.print(b);
                     Serial.print(",");
                 }
              Serial.println();
          }
       Serial.println("----------------------");
   }

Detalle consoloa ArduinoVolvemos a comprobar, que presenta correctamente los valores de cada bit, con lo que ya hemos desempaquetado el valor de cada punto del display. Si entornáis los ojos casi se ve la P entre los 1s y 0s Ahora nos queda convertir los valores fila y columna a pines de Arduino. Recordad que las columnas van del pin2 al pin9 de Arduino, pero la dos corresponde a nuestra columna 7, según lo definimos en GetBit, Como este no es mi primer baile, vamos  a ver despacito como hacemos esto. Queremos convertir valores de columnas que van del 7 al 0, en valores de pin que van del 2 al 9. ¿Qué formula aplicamos?. ¡VA! Pensad un poco. Basta con esto,  Pin = 9  – col , y no hay más. Vamos a comprobarlo

Col01234567
9 – 09 -19-29-39-49-59-69-7
pin98765432

A que no era para tanto. Vamos ahora a ver como convertimos las filas del 0 al 7 en pines del 10 al 17….con este sí que os atrevéis, ¿No?    Pin = fil  + 10. Nos falta otra pequeña función antes de escribir el programa completo. Una que apague todos los puntos LED para borrar el display:

void Clear()
   {
      for (int j=2; j<10; j++)  // Valores de los pines de columna
      digitalWrite(j, LOW);     // Todos apagados
      for (int k= 10 ; k<18 ; k++)
           digitalWrite(k, HIGH);    // Todas las filas cortadas
   }

Las columnas son activas en HIGH, así que ponemos todas a LOW. Y las filas son activas en LOW, por lo que que todas a HIGH. Esto nos garantiza que todos los puntos se apaguen. Ya encenderemos luego los que nos interesen. El programa quedara más o menos así

void loop()            // Prog_37_1
   {
      Clear();
      for (int fil = 0; fil <8 ; fil++)
         {
             digitalWrite( fil + 10 , LOW) ; // Activamos la fila para el barrido
             byte F = P[fil] ;
 
             for (int col =7; col >= 0 ; col--)
               {
                  bool b = GetBit(F, col)  ;
                  if (b)
                      digitalWrite( 9 - col  ,HIGH); //Levantamos la columna
                   else
                      digitalWrite( 9 - col  ,LOW); // Si 0, apagamos
                }                                   
             digitalWrite( fil + 10 , HIGH) ; // Apagamos fila antes de salir
         }
   }

Podéis comprobar que pinta una bonita P en el display.Array P en marcha  Bueno, vamos bastante bien. Claro que estaría bien, poder elegir que letra vamos a dibujar. Y eso es lo que haremos con el siguiente programa. Para ello, vamos a escribir otra función , a la que llamaremos pasándole el carácter que queremos dibujar y la fila en que nos encontramos (para que nos devuelva la fila correspondiente):Prog_37_2

byte Selecciona( char c, byte fil)
   {
       if ( c == 'P')          return(P[fil]) ;
       if ( c == 'R')          return( R[fil]) ;
       if ( c == 'O')          return( O[fil]);
       if ( c == 'M')          return( M[fil]);
       if ( c == 'E')          return( E[fil]);
       if ( c == 'T')          return( T[fil]);
       if ( c == 'C')          return( C[fil]);
       if ( c == 'N')          return( N[fil]);
       if ( c == '.')          return( dot[fil]);
       if ( c == ' ')          return( sp[fil]);
   }

Y además, modificaremos nuestro anterior loop, para convertirlo en una función, a la que pasamos el carácter que queremos mostrar, y dentro de esta función llamaremos a Selecciona () para leer la información del array correspondiente.

void SetChar(char p)
   {
       Clear();
       for (int fil = 0; fil <8 ; fil++)
          {
             digitalWrite( fil + 10 , LOW) ; // Activamos la fila para el barrido
             byte F = Selecciona( p, fil);
             for (int col =7; col >= 0 ; col--)
                {
                    digitalWrite(8-col, LOW);   //Bajamos la columna
                    bool b = GetBit(F, col)  ;
                    if (b)   //Levantamos la columna, con su pin
                          digitalWrite( 9 - col  ,HIGH); 
                    else
                          digitalWrite( 9 - col  ,LOW); // Si 0, apagamos
                }
             digitalWrite( fil + 10 , HIGH) ;   // Apagamos fila antes de salir
          }
   }

Ya solo falta escribir el loop:

void loop()
   {
       String s = "PROMETEC.NET  " ;
       int l = s.length();          // Calcula la longitus de s
       for ( int n = 0; n< l; n++ )
          {
              long t = millis();
              char c = s[n];
              while ( millis()< t+ 400)
              SetChar(c);
          }
   }

Que lo único que hace, es ir tomando una a una, las letras del String s y llamar a Setchar para que la represente. Pero con una complicación adicional, para que no os aburráis. Ya comentamos en alguna sesión previa, que cuando multiplexas segmentos, o en este caso puntos, cualquier intento de utilizar un delay acabará en desastre ( No me creáis, probadlo) porque la imagen en el display depende de la velocidad a la que refrescas los puntos, y el delay sencillamente lo impide. Cuando necesitéis un retraso, como ahora, y no podáis poner un delay, utilizar un while como este suele ser seguro.

 
  • Fijaros que he añadido un par de espacios al final del string s. Como he definido los espacios como todo apagado. Esto nos da un retraso adicional, antes de que vuelva a empezar con la función.
 

Aqui os dejo un pequeño video con el resultado

Resumen de la sesión

 
    • Hemos visto, como rerpresentar caracteres graficos, en una matriz de puntos, y como codificar de modo compacto esta información bit a bit.
    • Hemos creado un programa que va sacando esa informacion, bit a bit, para representar un caracter en el display.
    • A medida que los prgramas se van complicando, vamos viendo como partir problemas, en pequeños pedazos que sean acometibles.
 

 

(82) Comments

  • Bueno parece que les quedo grande el problema, Yo esperaba una mejor colaboracion, era mas asunto de programacion, pero nada de nda como todas las cosas que aparecen hoy en dia de internet y por favor no me mandan a buscar en otras direcciones porque ya hice una investigacion sobre el asunto; esperaba que este foro fuera mejor, pero parece que es igual a los demas.

  • señor administrador veo que no me ha podido colaborar, le deje un ejemplo de un programa pero nada de nada; si no es mucha molestia le agradeceria me ayudara soy una persona mayor, tengo muy pocos conceptos en cuanto a la programacion, se algo de electronica.
    He buscado por internet y tampoco, no he encontrado una guia didactica secuencial que explique partiendo del uso de la matriz 8×8, utilizando los 16 pines que van a arduino, luego pasar de a emplear un integrado 74hc595, reduciendo asi los pines del arduino ya sea manejando las columnas o las filas, como es el ejemplo expuesto, luego usando dos 74hc595 uno para las filas y el otro para las columnas, ahorrandose asi los pines a arduino,; de esta manera solo se usan tres pines del arduino, pues se conectan los pines latch, clock y data unidos entre si de los dos integrados (595) y llevandolos anteriores tres a arduino; gracias

  • int latchPin = 4; // pis connected to shift registors
    int clockPin = 5;
    int dataPin = 3;
    int pins [8] = {6, 7, 8, 9, 10, 11, 12, 13}; // common cathode pins
    byte A[8] = { B00000000, B00011000, B00100100, B01000010, B01111110, B01000010, B01000010, B00000000 };
    byte B[8] = { B00000000, B11111100, B10000010, B10000010, B11111100, B10000010, B10000010, B11111110 };
    byte blank[8] = { B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000 };

    void setup() {
    pinMode(latchPin, OUTPUT); // Pin configuration
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
    for (int i = 0; i < 8; i++) { // for loop is used to configure common cathodes
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], HIGH);
    }

    }
    void loop() {

    for (int k = 0; k < 1000; k++) { // showing each letter for 1 second
    display_char(A);

    }

    for (int k = 0; k < 1000; k++) {
    display_char(B);

    }

    void display_char(byte ch[8]) { // Method do the multiplexing
    for (int j = 0; j < 8; j++) {
    digitalWrite(latchPin, LOW);
    digitalWrite(pins[j], LOW);

    shiftOut(dataPin, clockPin, LSBFIRST, ch[j]);
    digitalWrite(latchPin, HIGH);
    //delay(1);
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, B00000000); // to get rid of flicker when
    digitalWrite(latchPin, HIGH);
    digitalWrite(pins[j], HIGH);

    }

    }
    Según el programa se gastan 13 pines del Arduino incluida la alimentación, mi pregunta se relaciona es usando un segundo integrado 74hc595 para manejar los catodos, pues con ello me ahorro 8 pines del arduino; Como modifico el programa, se que se puede hacer y con ello se reduce a 5 pines del Arduino incluida la alimentación.
    Le agradezco si me puede ayudar, gracias

Give a Reply

WordPress Anti-Spam by WP-SpamShield