Saltar al contenido

Matriz de LED RGB

julio 10, 2021
F6E46RNJ6QQL6RJ

Busque Instructable y podrá encontrar muchos proyectos de matriz de LED. Ninguno de ellos era exactamente lo que quería, que era explorar las interacciones del diseño de hardware y software para producir algo, y producir el producto final en una PCB ordenada con un controlador que me permitiera dibujar en la “pantalla LED” usando construcciones (por ejemplo, dibujar una línea en lugar de establecer píxeles específicos). Esta parte fue importante para mí, ya que muchos de los controladores de la matriz de LED son básicos y no proporcionan mucho en la forma de crear una imagen o animación mediante programación. Esto no significa que no pueda crear imágenes y animaciones con los otros controladores, solo que tendría que hacer un trabajo más repetitivo de un proyecto a otro.

Así que me propuse lograr mi visión. El primer paso fue diseñar el hardware. Este fue probablemente el más desafiante para mí, ya que mi experiencia es más software. Una vez más, había muchos diseños prefabricados, y ciertamente los usé como inspiración, pero quería aprender haciendo, así que hice un prototipo de una matriz 4×4 en una placa de pruebas. Aprendí mucho a través de ese proceso, ya que mis primeras iteraciones no funcionaron. Pero hice un diseño de hardware que funcionó, lo que a su vez me permitió comenzar a desarrollar un controlador.

Elegí Arduino como mi plataforma de controladores porque está ampliamente disponible y tiene muchas referencias en línea. Si bien la experiencia profesional me permitió llegar a una versión funcional de un controlador más hábilmente que mis esfuerzos de hardware, todavía hubo muchas iteraciones mientras optimizaba el rendimiento del controlador para el microcontrolador ATMega y desarrollaba una API de programación que me gustó.

Este Instructuctable documenta el diseño y algunos aprendizajes clave de mi proyecto. Puede encontrar más información sobre este proyecto en mi sitio web aquí, incluidos los kits completos que puede adquirir para crear su propia matriz LED RGB.

Paso 1: Diseño de hardware

Diseño de hardware

El objetivo principal de mi diseño de hardware era crear una serie de LED RGB que pudiera programar, pero tampoco quería gastar mucho dinero. El enfoque que elegí fue usar registros de cambio 74HC595 para controlar los LED. Para minimizar el número de registros de desplazamiento necesarios, coloqué los LED RGB en un diseño de matriz donde los ánodos comunes se unían en filas y los cables de cátodo rojo, verde y azul se unían en columnas. Para la matriz 4×4, el diagrama de circuito se parecía al diagrama de circuito adjunto.

Una cosa que notará de inmediato es que, dado el circuito de matriz, hay algunas configuraciones de iluminación LED que no se pueden hacer con todos los LED deseados encendidos al mismo tiempo. Por ejemplo, la matriz no puede iluminar simultáneamente dos LED que están en diagonal entre sí porque la alimentación de las filas y columnas hará que los dos LED opuestos se enciendan en la diagonal perpendicular a los LED deseados. Para solucionar esto, usaremos la multiplexación para escanear cada fila. Hay muchos recursos en la web que cubren la técnica de multiplexación, no voy a intentar replicarlos aquí.

Como estoy usando LED de ánodo común, eso significa que las filas proporcionan energía positiva y las columnas se hunden a tierra. La buena noticia es que los registros de cambio 74HC595 pueden generar y absorber energía, pero la mala noticia es que tienen un límite en la cantidad de energía que pueden generar o absorber. Los pines individuales del 74HC595 tienen un consumo de corriente máximo de 70 mA, pero es mejor mantener menos de 20 mA. Cada uno de los colores individuales de nuestros LED RGB tiene un consumo de aproximadamente 20 mA. Esto significa que el 74HC595 no puede alimentar directamente una fila completa de LED si deseo encenderlos todos.

Entonces, en lugar de alimentar la fila directamente, el 74HC595 impulsará un transistor para cada fila, y el transistor encenderá o apagará la corriente que alimenta la fila. Dado que el diseño utiliza un LED de ánodo común, el transistor de conmutación será PNP. Si estuviéramos usando un LED de cátodo común, el transistor de conmutación sería NPN. Tenga en cuenta que con el uso de un transistor PNP para conducir una fila, la configuración del registro de desplazamiento para encenderlo ahora se vuelve baja ya que un transistor PNP necesita un voltaje negativo entre el emisor y la base para encenderse, lo que permitirá que la corriente positiva fluya hacia el fila.

Otra cosa a considerar es la disposición de bits deseada de los registros de desplazamiento. Es decir, entre los registros de desplazamiento, qué bits controlan qué filas o columnas en la matriz. El diseño con el que envié es donde el primer bit, o “bit más significativo”, enviado a los registros de desplazamiento encadenados controlan la columna de LED elemento rojo, el segundo bit controla el elemento verde de la primera columna, el tercer bit controla el elemento verde de la primera columna elemento azul, el cuarto bit controla el elemento rojo de la segunda columna, … este patrón se repite en las columnas de izquierda a derecha. Luego, el siguiente bit enviado controla la última fila, o la última fila, la siguiente la segunda a la última fila, … esto se repite hasta que el último bit enviado, o “bit menos significativo”, controla la primera fila o la superior en la matriz.

Finalmente, necesitaba determinar qué resistencias usaría para cada uno de los LED en el LED RGB. Si bien puede usar la fórmula estándar que combina el voltaje directo y la corriente deseada para calcular la resistencia requerida, descubrí que configurar la corriente de cada LED en 20 miliamperios daba como resultado un color blanquecino cuando todos los LED rojos, verdes y azules estaban encendidos . Así que comencé a mirarlo. Demasiado rojo en el blanco significaba aumentar los ohmios de la resistencia del LED rojo para reducir la corriente. Repetí intercambiando resistencias de diferentes ohmios hasta que encontré una combinación que produjo un color blanco que sentí que era correcto. La combinación final fue de 180 Ω para el LED rojo, 220 Ω para el LED verde y 100 Ω para el LED azul.

Paso 2: Construcción del hardware – Placa de pruebas

Construcción de hardware: tablero de pruebasConstrucción de hardware: tablero de pruebas

La primera fase del constructor de hardware fue el breadboarding. Aquí hice una matriz 4×4 con los LED RGB. Esta matriz requeriría 16 bits para controlar, 12 para las columnas RGB y 4 para cada fila. Dos registros de cambios 74HC595 pueden manejarlo todo. Primero investigué y diseñé un circuito que pensé que funcionaría, luego lo construí en la placa de pruebas.

Probablemente el mayor desafío de la construcción de la placa de pruebas fue administrar todos los cables. Cogí un kit de cables preformados para placas de prueba, pero luego fue un poco difícil de manejar. Un truco que me pareció útil fue crear un “puerto” para conectarse a la placa Arduino. Es decir, en lugar de conectar los pines del Arduino directamente a los diversos pines IC en la placa de pruebas, dedique algunas filas en la placa de pruebas para que sean el punto de conexión para el Arduino y luego conecte los pines de identificación relevantes a esas filas. Para este proyecto, solo necesita cinco conexiones al Arduino: + 5V, tierra, datos, reloj y pestillo.

Una vez que se hizo la construcción de la placa de pruebas, necesitaba probarla. Sin embargo, sin algún tipo de controlador para enviar las señales correctas a los registros de turno, no pude probar para ver si el diseño del hardware funcionaba.

Paso 3: Diseño del software del controlador

Dada mi propia experiencia profesional con el desarrollo de software, esta fue la parte del proyecto en la que probablemente tuve más claro el camino a seguir. Estudié muchos de los otros controladores de matriz LED basados ​​en Arduino. Si bien es cierto que hay buenos controladores disponibles, ninguno tenía el diseño que yo quería. Mis objetivos de diseño del controlador fueron:

  • Proporcione una API de alto nivel para poder crear imágenes y animaciones mediante programación. La mayoría de los conductores que vi estaban más enfocados en imágenes codificadas. Además, dado que soy un programador de C ++ de oficio, quería utilizar un buen diseño orientado a objetos para implementar y administrar las actividades de dibujo en la matriz de LED.
  • Utilice un enfoque de doble búfer para administrar la imagen en la pantalla. Un búfer es el que se introduce mediante programación, mientras que el otro representa el estado de los píxeles de la matriz en un momento dado. La ventaja de este enfoque es que no es necesario que renderice completamente la siguiente actualización de fotogramas para la pantalla entre los ciclos de actualización de la multiplexación.
  • Utilice PWM para permitir más de los siete colores primitivos que un RGB puede representar mediante combinaciones simples de elementos rojo, verde y azul.
  • Escriba el controlador de manera que “simplemente funcione” con matrices LED RGB de diferentes tamaños que siguieron mi enfoque general de diseño de matrices. Tenga en cuenta que, si bien el diseño de mi hardware utiliza registros de cambio 74HC595, esperaría que mi controlador funcione con cualquier mecanismo de activación / desactivación de estilo de registro de cambio que esté diseñado con un diseño de bits similar al diseño de mi hardware. Por ejemplo, esperaría que mi controlador funcione con un diseño de hardware que usa chips DM13A para controlar las columnas y un chip 74HC595 para controlar las filas.

Si desea ir directamente a buscar el código del controlador, puede encontrarlo en GitHub aquí.

La primera iteración de mi controlador fue una pequeña curva de aprendizaje sobre las capacidades de la plataforma Arduino. La limitación más obvia es la RAM, que es de 2K bytes para Arduino Uno y Nano. El uso de objetos C ++ en tal escenario con frecuencia no se recomienda debido a la sobrecarga de memoria de los objetos. Sin embargo, sentí que si se hacía bien, el beneficio de los objetos en C ++ superaba su costo (en RAM).

El segundo gran desafío fue averiguar cómo implementar la modulación de ancho de pulso a través de los registros de desplazamiento para poder generar más de los siete colores primitivos del LED RGB. Habiendo programado durante muchos años en plataformas Linux, estaba acostumbrado a usar construcciones como subprocesos para administrar procesos que requieren una sincronización constante. El tiempo de la operación de actualización del registro de desplazamiento termina siendo bastante crítico cuando se crea un controlador para una matriz de LED que usa multiplexación. La razón es que a pesar de que la multiplexación ocurre tan rápido que sus ojos no pueden ver los LED individuales parpadeando encendidos y apagados, sus sí pueden detectar diferencias en el tiempo agregado total que cualquiera de los LED está encendido. Si una fila de LED está encendida de manera constante durante un período de tiempo más largo que las demás, se verá más brillante durante la multiplexación. Esto puede provocar un brillo desigual en la matriz o un estroboscopio periódico de la matriz en su conjunto (esto ocurre cuando un ciclo de actualización lleva más tiempo que los demás).

Como necesitaba un mecanismo de temporización consistente para hacer que las actualizaciones del registro de desplazamiento fueran consentidas, pero Arduino no admite formalmente el hilo, tuve que crear mi propio mecanismo similar al de un hilo. Mi primera iteración de esto fue simplemente para crear un temporizador de bucle que dependiera de la función loop () de Arduino y dispararía una acción cuando haya transcurrido una cierta cantidad de tiempo desde la última vez que se disparó la acción. Esta es una forma de “multitarea cooperativa“. Suena bien, pero en la práctica esto resultó ser inconsistente cuando la velocidad de disparo se midió en microsegundos. La razón de esto es que si tuviera dos de estos temporizadores de bucle funcionando, una de sus acciones con frecuencia tomó el tiempo suficiente para hacer que la segunda acción se apagara. fuego más tarde de lo deseado.

Descubrí que la solución a este problema es utilizar el mecanismo de interrupción del reloj nativo de Arduino. Este mecanismo le permite ejecutar una pequeña cantidad de código a intervalos muy consistentes. Así que diseñé el código del controlador en torno al elemento de diseño de usar una interrupción de reloj para activar el código para enviar los registros de desplazamiento de la matriz la próxima actualización en el ciclo de multiplexación. Para hacer esto y permitir que se produzcan actualizaciones en la imagen de la pantalla para que no interfieran con un volcado activo en los registros de desplazamiento (algo que llamaríamos “condición de carrera“), Utilicé un enfoque de tener búferes gemelos para los bits del registro de desplazamiento, uno para escribir y otro para leer. Cuando …

close