Control de múltiples LED con Arduino y TLC5940NT

Estoy trabajando en un proyecto de bricolaje en casa que necesita aproximadamente 150 LED para encenderse con diferentes niveles de brillo. Eventualmente, también me gustaría tener estos LED encendidos en ciertos patrones, por lo que realmente necesitan ser controlados por un microcontrolador (una matriz de LED controlable, por así decirlo).

Después de considerarlo un poco, comencé a incursionar con Ardunio, ya que parece ser adecuado para la tarea en cuestión y me permite multiplexar LED, etc.

Tengo tanto el Arduino Uno como el Arduino Mega 2560. Para las pruebas, utilicé el Mega, ya que tiene 15 canales PWM, por lo que puedo ajustar el brillo de cada LED, etc. una buena idea de lo que está pasando.

Tenía una buena prueba de concepto funcionando con el LED1 encendido durante 1800 microsegundos, luego lo apagué y el LED2 se encendió... y así sucesivamente para los 15 LED. Ninguno de los LED se encendió al mismo tiempo, pero dio la persistencia del efecto de visión (todos los LED aparecen encendidos al mismo tiempo) y no atrajo una gran cantidad de corriente. Esto es lo que busco, en una escala mayor de ~ 150 LED.

Entonces, a continuación necesitaba escalar esto. La siguiente prueba de concepto vino en la forma de utilizar el controlador LED TLC5940 después de leer algunos artículos y blogs en línea.

Conecté el TLC5940 al Arduino Uno más pequeño y conecté 16 LED a los 16 canales de salida del chip. Ejecuté un programa de prueba (creo que se desvaneció/ejecutó patrones a lo largo de los LED y funcionó bien).

Luego comencé a escribir un bucle que encendería nuevamente el primer LED, esperaría una fracción de segundo, luego lo apagaría y pasaría al siguiente LED.

El código funcionó hasta aproximadamente 3 LED, pero tan pronto como llegó al 4º LED, se pudo observar un parpadeo. En el momento en que se amplió a los 16 LED, había un patrón visible claro (como una ola mexicana) atravesando los LED.

Intenté cambiar el tiempo de retardo, reduciéndolo hasta 1 microsegundo, pero esto tuvo poco efecto.

Mi código era algo como esto:

#include "Tlc5940.h"
int DELVAR = 1

void setup()
{
  Tlc.init(0); // initialise TLC5940 and set all channels off
}


void loop()
{
    Tlc.clear();
    Tlc.set(1, 4096);
    Tlc.update();
    delayMicroseconds(DELVAR);
    Tlc.set(1, 0);
    Tlc.update();

    Tlc.clear();
    Tlc.set(2, 4096);
    Tlc.update();
    delayMicroseconds(DELVAR);
    Tlc.set(2, 0);
    Tlc.update();

    Tlc.clear();
    Tlc.set(3, 4096);
    Tlc.update();
    delayMicroseconds(DELVAR);
    Tlc.set(3, 0);
    Tlc.update();   


    // ....and so on for all 16 channels .....   
    // (not optimal I know but at this point I'm still just getting my head around the logic)
}

¿Existe una limitación en la "velocidad" del TLC5940 o los canales que está utilizando desde el Arduino?

¿Cómo puedo evitar esto para que todos los LED parezcan estar iluminados al mismo tiempo? ¿Tengo razón al pensar que el ciclo de trabajo del Arduino es de 16 MHz? y si es así, ¿no debería teóricamente poder encender y apagar> 50,000 LED secuencialmente en menos de un segundo?

Descargo de responsabilidad: tengo conocimientos electrónicos muy básicos de cuando estaba en la escuela hace unos 15 años, ¡así que todo esto es una curva de aprendizaje muy empinada para mí!


NOTA: *Para cualquiera que se pregunte en qué estoy trabajando, es un mapa mundial gigante, los LED representan las principales áreas urbanas o pobladas (ciudades, etc.) como se ven desde el espacio por la noche. Eventualmente me gustaría que estos se conectaran en tiempo real para que los LED encendidos representen áreas urbanas reales iluminadas por la noche en ese momento particular; aquí es donde el Arduino sería muy útil.

Es un mapa de arte de cuerdas basado en uno que hice el año pasado (abajo)

Es un mapa de arte de cuerdas basado en uno que hice el año pasado (abajo)

Solo que mucho más grande - será de 8 pies x 4 pies - progreso hasta ahora - los agujeros para los LED perforados están listos:

ingrese la descripción de la imagen aquí

No, la frecuencia de reloj de Arduino es de 16 MHz, la frecuencia de PWM es de solo unos 500 Hz y el ciclo de trabajo es un concepto completamente diferente.
Gracias Dmitri. Entonces, ¿hay algún método que pueda emplear para "acelerar" la frecuencia de encendido/apagado de estos LED?
Sí, puede acelerar las cosas al no usar PWM.
Entonces, una pregunta rápida: ¿podría usar el bus I2C como alternativa? ¿Es eso más rápido?
El periférico SPI integrado de Arduino es la forma más rápida de manejar un TLC5940. El TLC6940 no es compatible con SPI. Además, SPI es significativamente más rápido que I2C. Ya tiene todas las piezas para admitir el control de brillo LED de 16 canales en un TLC5940, y se puede actualizar aproximadamente 5 veces por milisegundo. Compre 10 más y su proyecto estará listo.
Leeré un poco sobre la conexión de los TLC5940 al SPI. Gracias por tu consejo, muy útil.
Vuelve y haz una nueva pregunta si necesitas más ayuda. Toda la suerte. Publique una foto o un video si logra que funcione, y actualice su pregunta con un enlace, me imagino que podría verse encantador.
Actualizado con fotos: si alguna vez logré descifrar las cosas de SPI y hacer que todo funcione, ¡me aseguraré de publicar una foto actualizada!
¡Guau! Eso se ve muy impresionante. ¡Tal vez tenga que hacer uno también!
No es necesario resolver SPI. Incluso actualizar los 10 TLC5940 con software 'bit banging' solo tomará alrededor de 10 milisegundos. como escribí, no tendría mucho sentido actualizar más rápido que la frecuencia de actualización de TV. Incluso si cambió el brillo de todos los LED a la frecuencia de actualización del televisor, todavía hay bastante tiempo de CPU libre. Me imagino que cambiar los LED una vez por segundo sería lo suficientemente rápido para una pantalla en "tiempo real". El TLC5940 PWM admite 4096 niveles de brillo, por lo que un solo nivel de cambio de brillo está muy por debajo de la percepción humana.

Respuestas (1)

Tu publicación suena un poco confusa. Parece que está intentando simular PWM actualizando el TLC5940, lo cual no es necesario.

Un TLC5940 contiene 16 canales PWM, cada canal PWM impulsa el brillo de un LED. Por lo tanto, solo actualiza el TLC5940 cuando es necesario cambiar el brillo de un LED. El resto del tiempo, el TLC5940 mantendrá el brillo establecido de cada LED utilizando sus propios canales PWM.

El tiempo entre cada actualización debe ser visible para el ojo humano, así que use delay()cuál es milisegundos, y nunca delayMicroseconds()cuál es bueno solo para unas decenas de milisegundos.

Es probable que el efecto que está viendo se deba a que la totalidad de loop() se completa en un milisegundo más o menos.

Es probable que el código actualice el TLC5940 en menos de un ciclo de su tasa de PWM (no recuerdo si hay lógica en el TLC594 para forzar algo más útil, pero no lo creo). Entonces, es posible que esté viendo el equivalente visual de un 'ritmo' entre las dos frecuencias (actualización frente a PWM).

Podrías probar esta hipótesis rápidamente cambiando todos
delayMicrosecond()los
delay(1000)

Actualice su pregunta si esto no lo soluciona o si ya lo ha intentado.

Su código no necesita controlar el brillo visual de los LED, el TLC5940 lo hace por usted. Cuando configura el brillo de un LED, el TLC5940 utilizará continuamente PWM para mantener ese brillo para ese LED.

Entonces, para su proyecto, podría estar actualizando toda la escena una vez cada pocos segundos, suponiendo que cada LED esté controlado por un solo canal, y use varios TLC5940 con hasta 16 LED en cada uno.

No he leído todo el código en esa biblioteca, pero el hardware SPI de Arduino debería poder actualizar un TLC5940 (192 bits) a aproximadamente 4 Mbits (u 8 Mbits con la configuración correcta).

Por lo tanto, los 16 LED de un TLC5940 deben actualizarse unas 5 veces por milisegundo. Por lo tanto, 160 LED serían 10 TLC5940 y se actualizarían cada 2 milisegundos, lo que es mucho mejor que la respuesta de la visión humana.

Cada uno de esos LED está bajo el control de brillo del TLC5940, por lo que el código no tiene nada que hacer hasta que una de las 'ciudades' necesite cambiar el brillo.

Editar:
el punto clave es que su Arduino no hace nada sobre PWM. Los programas de Arduino envían los valores TLC5940 que son el brillo de cada LED. Eso es todo, nada más que hacer.

El TLC5940 tiene 16 canales PWM, hace el control de brillo del LED usando sus canales PWM, todo por sí mismo, de forma autónoma, sin ninguna participación adicional del Arduino.

El programa Arduino solo habla con el TLC5940 cuando es necesario cambiar el brillo de uno o más LED.

Creo que es inconcebible que cambie los LED más rápido que 50/60 fotogramas por segundo (frecuencia de actualización de TV), lo que 10 TLC5940 sería fácilmente capaz de hacer. Entre cada cambio de brillo de LED, el TLC5940s mantendrá esos brillos establecidos.

Edit2:
¿Quizás tenía la intención de comprar registros de desplazamiento 74HC595? Son dispositivos mucho más simples. Un LED estaría encendido o apagado. Con esos, el microcontrolador anfitrión sería responsable de actualizar el 74HC595 para simular un control de brillo similar a PWM.

Lo siento si suena confuso: el efecto PoV en este caso para mí implica que todos los LED parecen estar encendidos al mismo tiempo, ese es el efecto que estoy tratando de lograr. Originalmente comencé usando solo retraso (some_small_number) pero esto enciende los LED muy lentamente.
Entonces, esto es puramente una limitación con el uso de PWM: ¿simplemente no puedo hacer lo que pretendo usar los canales PWM del Arduino? ¿Es demasiado lento para mis requisitos?
Creo que he explicado que su código le dice al TLC5940 qué brillo desea, luego lo hace por usted, para los 16 LED. Dispone de 16 canales PWM, uno por LED.
Lo siento, acabo de ver su párrafo sobre el hardware SPI, parece que podría valer la pena investigar más a fondo.