Panel de texto con Arduino

En la revista Elektor nº 255 de agosto de 2001 se publicó un artículo para montar un panel de texto. Ese mismo mes empecé a hacerme con el material necesario.
Primero lo hice sólo con tres módulos, pero no iba bien, ya que en el circuito de Elektor usan un 74LS164 para activar los leds y no los mantiene encendidos mientras se carga la línea siguiente. El efecto era muy malo.
Lo dejé algún tiempo y lo retomé añadiendo un integrado más entre cada 74LS164 y los leds. Todo se controlaba desde un 16F84A.
No recuerdo qué paso ni por qué lo dejé aparcado.
Un tiempo después apareció el Arduino y decidí retomarlo.
Encontré un integrado que hacía la misma función que los dos anteriores, el MBI-5026, que controla 16 LEDs cada uno y es muy fácil de manejar.
No sé por qué volví a aparcar el asunto.
Como cada vez cacharreo menos y a este paso se me va a olvidar la electrónica, lo he vuelto a retomar.
Antes hacía las placas con el EAGLE y con insoladora. Ya no me acuerdo del EAGLE y he hecho las placas con rotulador a mano y también he usado placas de estas con agujeros.

De momento y después de 21 años este es el resultado. Todo el hardware y software es diseño mío, menos la placa del Arduino.



El panel va con un Arduino nano, pero no sé por qué, funcionan sólo una vez y se quedan inutilizados, ya me he cargado dos, por eso de momento he puesto un Arduino UNO. No sé si tendrá algo que ver el Windows 10 y el CH340, ya que hasta hace poco tenía el Windows 7.



Cada fila está controlada por un darlington TIP125. Entre el pin de salida del Arduino y la base del TIP125 hay una resistencia de 6K8 ohms, que es suficiente para que entre en saturación.



Una cosa curiosa que ocurre es que la primera línea sale desplazada un led a la izquierda, como si al acabar la primera línea se produjera un impulso extra de CLK. Es raro que sólo ocurra en la primera línea y no en las otras, ya que el código es igual para las siete.
De momento lo he solucionado desplazando los datos de esa línea una posición a la derecha.

Código:
// Visualiza palabra => HOLA GENTE
#define CLK 5
#define SDI 4
#define OE 3
#define LE 2

const byte elementos[7][8] = {
  {0x02,0x4C,0x83,0x03,0x3D,0x2F,0xA5,0xE6},
  {0x04,0xA5,0x09,0x09,0x43,0x44,0x48,0x52},
  {0x04,0xA5,0x09,0x08,0x42,0xC4,0x48,0x92},
  {0x07,0xA5,0x0F,0x0B,0x72,0x44,0x49,0x1E},
  {0x04,0xA5,0x09,0x09,0x42,0x44,0x4A,0x12},
  {0x04,0xA5,0x09,0x09,0x42,0x44,0x4A,0x12},
  {0x04,0x99,0xE9,0x06,0x7A,0x44,0x33,0xD2},
};

void setup() {

  DDRD = DDRD | 0b11111100; // D2 a D12
  DDRB = DDRB | 0b00011111; // OUTPUTs
  PORTD = PORTD | 0b11000000; // Salidas TIP125
  PORTB = PORTB | 0b00011111; // apagadas
}

void loop() {

  for (byte fila=0; fila < 8; fila++) {
    digitalWrite(LE, LOW);
    for (byte columna=0; columna < 8; columna++) {
      digitalWrite(SDI, (elementos[fila][columna] & 0x80) ? HIGH : LOW);
      digitalWrite(CLK, HIGH);
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x40) ? HIGH : LOW);
      digitalWrite(CLK, HIGH);
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x20) ? HIGH : LOW);
      digitalWrite(CLK, HIGH);
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x10) ? HIGH : LOW);
      digitalWrite(CLK, HIGH);
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x08) ? HIGH : LOW);
      digitalWrite(CLK, HIGH);
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x04) ? HIGH : LOW);
      digitalWrite(CLK, HIGH);
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x02) ? HIGH : LOW);
      digitalWrite(CLK, HIGH); 
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
      digitalWrite(SDI, (elementos[fila][columna] & 0x01) ? HIGH : LOW);
      digitalWrite(CLK, HIGH); 
      delayMicroseconds(10);
      digitalWrite(CLK, LOW);
}

  digitalWrite(fila + 5, HIGH);
  digitalWrite(fila + 6, LOW);
  digitalWrite(LE, HIGH);
  delayMicroseconds(10);
  }
}

troglodita dijo:
Una cosa curiosa que ocurre es que la primera línea sale desplazada un led a la izquierda, como si al acabar la primera línea se produjera un impulso extra de CLK. Es raro que sólo ocurra en la primera línea y no en las otras, ya que el código es igual para las siete.
De momento lo he solucionado desplazando los datos de esa línea una posición a la derecha.
Este problema estaba causado porque en un momento del programa me dirigía al pin 5 que es el CLK y metía un impulso de más. Ya está corregido con la función "if" añadida.

Otro problema curioso es que en la fila de arriba aparecía una secuencia fantasma que se puede ver en este vídeo:


Con respecto a ese problema, después de tirar de osciloscopio, ver que todas las señales son un caos, con lo cual el osciloscopio me ha liado más todavía y hacer muchos cambios y programas y usar varios arduinos distintos, uno antiguo con chip DIL y otro con chip pequeño, he llegado a la conclusión de que en los arduinos el pin 6 está embrujado.

Todo ese "ruido" sale por el pin 6 y entra por la base del TIP 125, sale por el colector, atraviesa los LEDs y llega a los MBI-5026. Esto no tiene mucho sentido pero es la conclusión a la que he llegado.

Para deshacerme del pin 6 he usado los pines del 7 al 13, pero el pin 13 de mis arduinos no funcionan en este circuito.

Como el pin 3 (señal OE), está siempre a cero, he pasado la última fila a ese pin y he hecho una chapucilla momentánea (poco elegante) para dirigirme a ese pin a su tiempo.

Aunque con los cambios anteriores ya funciona bien, he vuelto a dejarlo como al principio para seguir investigando lo de la secuencia fantasma en la primera fila.
Si conecto otra fila al pin 6 la secuencia fantasma aparece en esa otra fila, luego se descarta el TIP125 de la primera fila, ya que todos lo hacen si se conectan al pin 6.
Esa secuencia fantasma aparece en los LEDs controlados por los MBI-5026 1º, 2º y 4º, no en el 3º. Si cambio el 3º por el 2º sigue apareciendo en el 2º y no el 3º, luego se descartan los MBI-5026.

Si desconecto el TIP125 del pin 6 y lo conecto directamente a GND (se activa por 0) sigue apareciendo la secuencia fantasma, luego no le entra por el pin 6 como parecía lógico. :cry:
Es decir, si uso en el programa el pin 6, aunque luego no lo use físicamente, aparece el problema. Sólo desaparece si en el programa no uso el pin 6.
Después de hacer muchas pruebas y usar otros Arduinos, (he usado Nano, Uno con chip pequeño, Uno con chip DIL y Diecimilla con ATmega 168), con todos ocurría lo mismo.
La frecuencia de esa secuencia fantasma no variaba si aumentaba los delays o incluso si los quitaba (he visto que no hacen falta).
Por si fuese por la fuente de alimentación conmutada, lo he conectado a una fuente con transformador, puente, condensador y 7805, pero sigue igual. Esa secuencia tiene que salir de los arduinos.

Lo siguiente que he hecho ha sido desactivar las interrupciones, ya que no uso ni interrupciones ni delays, con "noInterrupts()" y mano de santo. Ha desaparecido la secuencia fantasma. :D
He pasado el programa a un Arduino Nano para dejarlo integrado en el panel (sólo he conseguido programarlo con el IDE 1.0.3). :unsure:
Y así es como ha quedado el programa:



Código:
// Visualiza => HOLA GENTE

#define CLK 5 //Relog para MBI-5026
#define SDI 4 //Datos al MBI-5026
#define OE 3 //MBI-5026 enable
#define LE 2 //Pasar información de los latches a los LEDs

const byte elementos[7][8] = { //Texto en exadecimal {fila}[columna}

{0x02, 0x27, 0x20, 0x70, 0x73, 0xE8, 0xBE, 0xF8},
{0x02, 0x28, 0xA0, 0x88, 0x8A, 0x0C, 0x88, 0x80},
{0x02, 0x28, 0xA0, 0x88, 0x82, 0x0A, 0x88, 0x80},
{0x03, 0xE8, 0xA0, 0xF8, 0xBB, 0xC9, 0x88, 0xF0},
{0x02, 0x28, 0xA0, 0x88, 0x8A, 0x08, 0x88, 0x80},
{0x02, 0x28, 0xA0, 0x88, 0x8A, 0x08, 0x88, 0x80},
{0x02, 0x27, 0x3E, 0x88, 0x73, 0xE8, 0x88, 0xF8},
};

void setup() {

  DDRD = DDRD | 0b11111100; // D2 a D12
  DDRB = DDRB | 0b00011111; // OUTPUTs
  PORTD = PORTD | 0b11000000; // Salidas TIP125
  PORTB = PORTB | 0b00011111; // apagadas
  noInterrupts(); // Evita secuencia fantasma tenue en fila 1

}

void loop() {
  for (byte fila=0; fila < 8; fila++) { //elementos{fila}[columna}
    digitalWrite(LE, LOW);
    for (byte columna=0; columna < 8; columna++) {
      byte data = elementos[fila][columna];
      for (byte bits=0; bits < 8; bits++) {
       digitalWrite(SDI, (data & 0x80) ? HIGH : LOW);
       digitalWrite(CLK, HIGH);
       digitalWrite(CLK, LOW);
       data<<=1;
    }
  }
if (fila == 0) {                             //Este if es para evitar que al apagar la
  digitalWrite(12, HIGH);            //fila anterior cuando estamos en la fila
 }                                                 //primera (pin 6) meta un impulso de CLK
else {                                          //en el pin 5, ya que los TIP125 se apagan
  digitalWrite(fila + 5, HIGH);     //con HIGH y se encienden con LOW.
}

  digitalWrite(fila + 6, LOW);
  digitalWrite(LE, HIGH);
  }
}

La simplificación de la tercera secuencia "for" ha sido trabajo de Heli de CCAA.
 
Hola Don Troglodita, con tu relato y montaje has logrado "desviejarme", entonces decidí escribir un software para tu montaje, pues siempre llamaron mi atención esas historias de los leds display cuando son de a muchos (muchísimos).

No tengo posibilidad alguna de montar tu hardware y probar en el mundo real, por eso estoy aquí, pues en Argentina (super devaluados) y en un pueblito igual o peor que Macondo, imposible hacerme con los componentes, por ello va solo la simulación en Proteus.

Obviamente todos sabemos que existen módulos armados de matríz de puntos o integrados controladores como el MAX 7219 o los TM16xx (tm1637, tm1638 y otros)
Sin embargo como somos unos Viejos Mañosos, de la Vieja Escuela, lo haremos a fuerza de conmutaciones desde el micro mísmo, de eso se tratan estos programas.

El código está compilado con AVR-GCC, es lenguaje C, lo simulé en el Isis Proteus 8.6 SP2, se trata de una matríz de leds de 7x60, controlada por columnas con shift register 74hc595 que serían los sumideros o tierras, el "barrido" es por filas, serían siete conmutaciones, que a primera se corresponden a tu montaje y son los Vcc controlados por los transistores TIP, en mi simulador no hay modelo del MBI5026, por eso los H595, creo que para el caso es lo mísmo, no use en el montaje ni en el software las líneas EN (enable), están todas puenteadas en ON.

Como se darán cuenta, están faltando las resistencias que limitan las corrientes en los leds. El control de las filas requiere de transistores de cierta potencia como los empleados en el montaje de Troglodita. Además de capacitores de filtrado, o el cristal del micro y demás yerbas (componentes), están ausentes para no hacer lenta y complicada la simulación, ya sabemos que son necesarios todos estos componentes en un montaje real.


1ro-
La primer simulación es el archivo:
TrogloditaArduino.pdsprj
y el micro 328p a 16mHz con cristal externo idem a la placa Arduino, con el archivo objeto
text2.troglodita.ino.hex <-- text2.troglodita.ino
que salió de compilar Tú código, el segundo del post, sin tocar nada. Es el texto estático que propones, considerando eso supongo que las conexiones del simulador se corresponden con las de tu montaje, dado que se deja ver el mensaje sin problemas, el mísmo archivo del simulador también funciona con el .hex de tu primer código.
text1.troglodita.ino.hex <-- text1.troglodita.ino
TrogloditaArduino.pdsprj
text2.troglodita.jpg

2do-
Seguimos con nuestra primer simulación, pero el archivo objeto cargado en el micro, salió de un programa escrito en C plano,
TrogloditaText.hex <-- TrogloditaText.hex
(TrogloditaText.c)
digamos que traduje la filosofía Tú código, entonces emplea los mísmos pines del AVR y el SPI es haciendo bit bangins (software).
A primera veo que el archivo .hex, es más chico y se ejecuta más rápido que el obtenido del código Arduino, eso lo deduzco mirando el frecuencimetro que puse en el simulador, en uno de los pines del barrido.


3ro-
El circuito es el mísmo, excepto que tiene otra conexión las líneas del barrido y las del SPI es tal que permite emplear el SPI del micro por hardware, o sea que el trabajo de empujar todos esos bits, se lo dejamos al módulo SPI del AVR y está funcionando con interrupciones, entonces cada vez que inicia la transmisión de un byte, continúa en segundo plano, liberando al micro de esa tarea y podría ocuparse de otra actividad, p.e. encender y apagar ese led que está en la simulación.
El programa es el mísmo anterior, el texto estático que Vos has escrito.
TrogloditaHardware.pdsprj <-- TrogloditaHardware.hex
(TrogloditaHardware.c)
El SPI, está a la velocidad mínima de transmisión posible, para aprovechar e involucar éstos tiempos en el tema de refresco (barrido) de los leds para lograr la persistencia visual. Con esto de la velocidad mínima nos evitamos que nuestros cables se conviertan en antenas irradiadoras de interferencias, o que la línea SCK se vea afectada e interferida por la más mínima interferencia externa.


4to-
Aquí viene lo bueno, el conexionado idem al anterior, para poder emplear SPI por hardware, ahora el texto se desplaza letra a letra, por el arreglo de leds. Todo a fuerza de conmutaciones y envios SPI desde el microcontrolador que se hace en segundo plano empleando interrupciones.
TrogloditaHardware.pdsprj <-- TrogloditaHardBanner.hex
TrogloditaHardBanner.c
Se podría poner cualquier texto en la variable 'msg[]' que sería mostrado en el arreglo de leds.


Los patrones (bits maps) de las letras son tomadas crudamente de la libreria Nokia5510 que andan dando vuelta por ahí, esos son caracteres de 8x6 (ocho lineas por 6 columnas), así que algunos no se verán bien, porque falta la octava línea, especialmente en los caracteres minúscula altos (q, g ...)

Los .hex los pueden subir facilmente desde WinGate, empleando AVRDUDESS, eso lo bajan desde aquí, también un video de U2 de su empleo:


Los archivos .pdf son las capturas del circuito del simulador Proteus.
El archivo "prnBits.exe.RenameMe" deben renombrarlo, a "prnBits.exe" si lo quieren correr, es un demo para la consola de Windows, mostrando lo que en realidad sucede en esas matrices de led, pero a puro texto plano ASCII, "prnBits.txt" es la salida de este código.

Si requieren re-compilar (seguramente), pues deberían hacerlo con el AVR-GCC, o el Atmel Studio, o la mounstrosidad de Microchip y su IDE, pero con maña cambiando los path del archivo makefile, puenden hacerlo directamente con la instalación de Arduino IDE que tienen instalada.

Si te animas, subí estos codigos .hex en tu montaje, deberían funcionar a primera, los dos últimos, requieren modificar la conexión, pero es fácil, porque solo son los pines de salida de la placa Arduino.
Si tenés interés, te comento una mejora que se le puede implementar facilmente al montaje de los leds, cualquier duda pregunta (o pregunten).
 

Adjuntos

  • TrogloditaMatrixLed.ZIP
    290.3 KB · Visitas: 14
Gracias por tus comentarios.
Tengo previsto hacerle mejoras, como por ejemplo desplazar el texto. Además ahora está hecho al aire, sin meter dentro de una caja.
El MBI5026 es más o menos como el 74HC595 pero con 16 salidas y control de intensidad para no necesitar resistencias en los LEDs.
He aprovechado material que tenía, como por ejemplo los darlington TIP125, que al ser PNP me han complicado un poco el circuito.
 
Buenos días.

Me da que te chupa más corriente que la que te soporta la alimentación en general, por eso los Led apagados.

Mejor saber cuanta corriente total gasta encender todos los Led por haber, a parte de esto, todos los ingragados, en general, todo lo que consume a su potencia máxima del dispositivo completo.

Saludos.
 
¿Qué LEDs apagados?.
El consumo máximo de corriente es una de las primeras cosas que calculé.
Cada LED consume 17mA, a 60 LEDs en cada fila 0.017 x 60 = 1,02 amperios. Como las 7 filas van multiplexadas, ese es el consumo máximo de los LEDs.
Cada fila va controlada por un TIP125 que aguanta 5A continuos y picos de 8A. Van sobrados. Se mantienen fríos y sin disipador.
El resto de los integrados consume muy poco. Con todos los LEDs encendidos (420) apenas consumiría un poco más de un amperio.
 
Si vas sobrado de corriente. Hacer más pruebas.

Nota, estamos mirando la parte física, no de programación.

En cada IC. ¿Haz comprobado que te de 5 V?

Se que su referencia son entre 4.5 V a 5.5 V siendo su estandar 5 V, si sale de ese rango, mal asunto. Con todos los Led encendido, cuando digo todos, son todos, ¿puedes comprobar la tensión de cada IC?
 
Si vas sobrado de corriente. Hacer más pruebas.

Nota, estamos mirando la parte física, no de programación.

En cada IC. ¿Haz comprobado que te de 5 V?

Se que su referencia son entre 4.5 V a 5.5 V siendo su estandar 5 V, si sale de ese rango, mal asunto. Con todos los Led encendido, cuando digo todos, son todos, ¿puedes comprobar la tensión de cada IC?
... eso por no ver el software, y entender el tema del barrido o conmutaciones por filas, en el algoritmo, NUNCA SE ENCIENDEN TODOS LOS LEDs juntos, a lo sumo se enciende una fila completa, como dijo Troglodita, 60 leds, no la matríz completa (7x60=420).

Si le estas buscando la vuelta a ese fantasma pienso que puede ser la conmutación, primera prueba que haria, es alimentar la placa del micro con pilas/baterías y los leds con su fuente totalmente independiente de la placa.

Como segunda opción, pienso que es el soft de Arduino, personalmente no me piacche, por eso programo los AVR directamente en C, con el compilador AVR-GCC. Es la razón por la cual le sugiero a Trogoldita subir mis .hex a su hardware y ver que sucede....
 
Última edición:
En cada IC. ¿Haz comprobado que te de 5 V?
Se que su referencia son entre 4.5 V a 5.5 V siendo su estandar 5 V, si sale de ese rango, mal asunto. Con todos los Led encendido, cuando digo todos, son todos, ¿puedes comprobar la tensión de cada IC?
Eso ya lo comprobé en su momento. También lo alimenté con baterías separadas pero compartiendo neutro.
De momento no he vuelto a hacer nada con él pero tengo previsto dar movimiento al texto. Espero que no pasen otros 22 años.:rolleyes:
 
Con todos los Led encendido, cuando digo todos, son todos
Esto lo dices a modo interactivo, o porque piensas que las pantallas de LED encienden todos a la vez?

Si es lo segundo, entonces lee sobre multiplexacion, y te daras cuenta que en fracciones muy pequeñas de segundos enciendes todos los LED, de a tandas, con lo que el ojo humano solo ve todos encendidos a la vez, pero no es así, por lo que reduces el consumo a solo el consumo total de esa "tanda" de LEDs encendidos...
 
Esto lo dices a modo interactivo, o porque piensas que las pantallas de LED encienden todos a la vez?

Si es lo segundo, entonces lee sobre multiplexacion, y te daras cuenta que en fracciones muy pequeñas de segundos enciendes todos los LED, de a tandas, con lo que el ojo humano solo ve todos encendidos a la vez, pero no es así, por lo que reduces el consumo a solo el consumo total de esa "tanda" de LEDs encendidos...
Lo dije de encender todos, fijo, para ver el consumo real y, si hay algún led defectuoso. La única ventaja que tiene así, es al grabarle un vídeo en esos display, no parpadean.

El proyecto final, que se llama display de barrido, como los antiguos TV TRC, barrido, que el ojo humano no lo aprecia ya que tiene frecuencia entre 50 ó 60 Hz depende del país. Es más bien para ahorrar recursos, energía. Aquí si ves parpadeo en los vídeo si lo haces.

Se de que va el tema, y te entiendo.
 
Lo dije de encender todos, fijo, para ver el consumo real y, si hay algún led defectuoso. La única ventaja que tiene así, es al grabarle un vídeo en esos display, no parpadean.

El proyecto final, que se llama display de barrido, como los antiguos TV TRC, barrido, que el ojo humano no lo aprecia ya que tiene frecuencia entre 50 ó 60 Hz depende del país. Es más bien para ahorrar recursos, energía. Aquí si ves parpadeo en los vídeo si lo haces.

Se de que va el tema, y te entiendo.

Eso de que al reproducir un vídeo de tomas de estos carteles leds y se ve que conmutan o "flotan", de debe a una mala elección de la frecuencia de refresco, barrido de los leds, tenés que usar un número que no sea 50/60 o frecuencia de la cámara, ni alguno de sus múltiplos, p.e. 41, 43, 47, 53, o sea números primos.

Ésto lo podes comprobar en un videito que hice hace unos años, medio en serio, medio en broma (el mensaje en el cartel led es la broma), fíjate que el mensaje de los led display 7 segmentos de fondo no tienen nada raro, siempre se ven encendidos.

 
Atrás
Arriba