Matriz de led RGB WS2812B

 Buenas!

En esta entrada vamos a ver cómo utilizar una matriz de leds "inteligentes" RGB  WS2812B.

RGB es el acrónimo de RedGreenBlue (RojoVerdeAzul en castellano) y refleja la composición del color en términos de la intensidad de los colores primarios de la luz. Podemos formar cualquier matiz de color con una combinación de un valor que oscila entre 0 y 255 para cada color primario.

Según podemos leer en wikipedia;

"De este modo, el rojo se obtiene con (255,0,0), el verde con (0,255,0) y el azul con (0,0,255), obteniendo, en cada caso un color resultante monocromático. La ausencia de color, es decir el color negro, se obtiene cuando las tres componentes son 0: (0,0,0). La combinación de dos colores a su máximo valor de 255 con un tercero con valor 0 da lugar a tres colores intermedios. De esta forma, aparecen los colores amarillo (255,255,0), cian (0,255,255) y magenta (255,0,255). El color blanco se forma con los tres colores primarios a su máximo valor (255,255,255). " 

Leds RGB WS2812B en el mercado

Principalmente hay dos tipos de tiras sets RGB WS2812B que se pueden adquirir:

  •  tiras de leds con una densidad determinada (por ejemplo 60 leds por metro) y montar nuestra matriz de led pegando con el adhesivo que suelen traer y realizando las conexiones (VCC, GND y Pin de Datos)
  • o adquirir un panel de leds ya fabricado (suelen ser más pequeñas en dimensiones) y trabajar con ellas diréctamente.

Tiras de led y matrices de leds

Hay tiras de led para exteriores (impermeabilizadas -IP67-) y solo interiores  IP30.

Las tiras de leds  WS2812B realizan una transmisión de la trama de la señal desde un led al siguiente y automáticamente tras una pasada "saben" que posición ocupan dentro del conjunto de leds conectado, por lo que se puede acceder a cualquier elemento de la tira, es decir el led inicial es el 0 y el led final es es el 100, si es que tenemos una tira de led de 100 elementos, y podemos acceder o indexar cualquier elemento de esa tira mediante código para realizar cualquier efecto.

 

Consumo

La potencia que consumen y los requisitos de intensidad de corriente vienen descritos por el fabricante, suelen ser unos 3 W a máxima potencia, y unos 60 mA por led  (20 mA por cada color primario) a su máxima intensidad o color blanco RGB(255,255,255). Los leds en su conjunto se alimentan con un voltaje de 5 Voltios.

Arduino no puede controlar o suministrar más de 500 mA en total por lo que no podemos alimentar desde arduino más de 8 leds , en caso de usar un mayor número de leds deberemos utilizar una fuente externa o alimentador AC/DC que dependiendo del proyecto para unos 100 leds y no a máxima intensidad (blanco) proporcione los 2A como mínimo.

Diagrama de conexion

 La tira de Leds se compone de un componente led que se repite en cada unidad que dispone de un terminal GND para masa, otro para el PIN de Datos que es la señal que se conecta a arduino y un terminal VCC de tensión. Se puede cortar la tira de leds en los extremos (señal vertical negra) que unen un led con el siguiente.

Hay que seguir un orden a la hora de pegar la tira led , el que indica la flecha, pues ese orden es el que permitirá acceder a cada componente de la misma desde la programación de Arduino.

Para un buen uso de nuestra cinta led RGB es necesario conocer sus características técnicas principales y tener en consideración algunas pautas para evitar algún posible daño, entre ellas citamos:


- Recordar que cada pixel o led individual de nuestra cinta RGB requiere 60 miliamperios como máximo cuando trabaja en su brillo completo (color blanco). Los colores mezclados y ajustes inferiores de brillo utilizarán proporcionalmente menos energía. Esto es necesario conocer a la hora de elegir la capacidad de nuestra fuente de alimentación.

- Antes de conectar nuestra cinta led RGB a cualquier fuente de alimentación, añadir un gran condensador (1000 uF, 6.3V o superior) a través de los terminales de alimentación positivo y negativo aunque normalmente las fuentes de alimentación ya proporcionan la función de estabilizar la corriente.

- Colocar una resistencia de 300 a 500 Ohm entre el pin de salida de datos del Arduino y la entrada al primer led o pixel para prevenir que este se dañe debido a posibles picos en la línea de datos.

- Minimizar la distancia entre la cinta led RGB y el controlador Arduino.
Si va a utilizar una fuente de energía externa, aplicar energía a la cinta LED antes de aplicar energía al microcontrolador.

- Conectar GND del adaptador a GND de Arduino para que tengan la misma referencia GND.

 Podemos fabricar nuestro propio adaptador AC/DC con un cable USB y un alimentador de móvil que suele proporcionar los 2 Amperios que se necesitan utilizando una ficha de empalme a modo de protección. El cable USB lo pelamos y seleccionamos solo los cables de color rojo y negro que unimos a la ficha de conexión. No olvidar conectar el GND (cable negro) del adaptador al GND de Arduino a través de la misma ficha de empalme.

Detalle de la conexión al adaptador AC, cable USB



Ahora muestro un prototipo realizado con cables obtenidos de cables de alimentación para PC  o electrodomésticos extremadamente gruesos y tensos y una vieja caja de zapatos, con un soldador de gama media-baja, sin crema de soldar, solo con estaño. Uno de los cables de datos (que se pasan por debajo de la cubierta) estaba medio partido, los leds a partir de esa fila se volvían locos "se iluminaban a su aire" finalmente tras probar otras soluciones (puntos de soldadura VCC o GND en mal estado), por fin localicé el error y al cambiarlo por otro todo funcionó según lo esperado. Y por qué no utilizar materiales más adecuados? Porque no disponía de tiempo libre salvo en ese moment (solo unas horas)  y es en el que pude llevar a cabo toda creación de "esta obra".

Detalle del prototipo de la matriz de leds

Y ahora mostramos el panel flexible de leds de 8x8 conectado también a Arduino y a nuestro adaptador fabricado de 5 V de voltaje y amperaje de 2.1 A

Detalle del panel flexible de leds de 8 x 8 (64)

En este caso los leds no se encuentran ordenados por fila de izquierda a derecha, sino que al venir más encapsulado empiezan desde la derecha en la primera fila y la recorren en la siguiente fila desde la izquierda (lo podéis ver en el vídeo del canal), lo que requiere ajustes en el código para realizar el scroll de texto y cualquier otro tipo de animaciones o efectos sobre este tipo de paneles.

Código para las tiras de led posicionadas de izquierda a derecha en cada fila

Para comenzar a realizar algunos efectos debemos instalar por ejemplo la librería adafruit neopixel desde el ide de arduino e incluirla en nuestro código
#include <Adafruit_NeoPixel.h>
Definimos constantes como el pin de
#define PIXEL_PIN 8
#define NUMPIXELS 100
#define INTENSIDAD 5

Referenciar un objeto neopixel con los parámetros de  número de pixels y pin de datos de arduino  y a partir de ahí
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
iniciar el objeto desde setup
void setup() {
   pixels.begin();
..
}
y empezar a hacer uso de los métodos en el loop para gestionar individualmente el color de cualquier pixel.
void loop() {
Serial.println(F("Entramos en loop"));
 
  //Definimos nuestras variables de tipo uint32 para cada color que utilizaremos
  // pixels.Color toma valores en RGB, desde 0,0,0 hasta 255,255,255
   uint32_t rojo = pixels.Color(INTENSIDAD,0,0);
   uint32_t verde = pixels.Color(0,INTENSIDAD,0);
   uint32_t azul = pixels.Color(0,0,INTENSIDAD);
     uint32_t amarillo = pixels.Color(INTENSIDAD,INTENSIDAD,0);
   uint32_t morado = pixels.Color(INTENSIDAD,0,INTENSIDAD);
   uint32_t celeste = pixels.Color(0,INTENSIDAD,INTENSIDAD);
   uint32_t blanco = pixels.Color(INTENSIDAD,INTENSIDAD,INTENSIDAD);
    int delayval = 100; // Pausa de cincuenta milisegundos

color_pixel(rojo);
}
void color_pixel(uint32_t color)
{
   int delayval = 100; // Pausa de cincuenta milisegundos

 for(int i=0;i<NUMPIXELS;i++){

    pixels.setPixelColor(i, color); // Brillo moderado en azul

    pixels.show();   // Mostramos y actualizamos el color del pixel de nuestra cinta led RGB

    delay(delayval); // Pausa por un periodo de tiempo (en milisegundos).

  }

 
}

Código para el panel flexible de led 8x8

En este caso utilizaremos varias librerías adicionales de Adafruit, que habrá que instalar de igual manera a como se hizo con neopixel
Haremos uso de un objeto constructor de matrices Adafruit_NeoMatrix incluido en la libería NeoMatrix. Aquí es importante identificar la posición de tu matriz, si el scrolling muestra caracteres inversos o en distinto orden al adecuado tendremos que jugar con los valores de los parámetros. Como siempre hay que actualizar la variable con el PIN en el sketch
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#define PIN 8
 
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(8, 8, PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_RIGHT +
  NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
  NEO_GRB            + NEO_KHZ800);

const uint16_t colors[] = {
  matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255) };

void setup() {
  matrix.begin();
  matrix.setTextWrap(false);
  matrix.setBrightness(40);
  matrix.setTextColor(colors[0]);
}

int x    = matrix.width();
int pass = 0;

void loop() {
  matrix.fillScreen(0);
  matrix.setCursor(x, 0);
  matrix.print(F("Hola mundo!"));
  if(--x < -84) {
    x = matrix.width();
    if(++pass >= 3) pass = 0;
    matrix.setTextColor(colors[pass]);
  }
  matrix.show();
  delay(100);
Dejo un ejemplo de un sketch que permite mostrar el scrolling de texto con la librería NeoPixel y si pulsamos el botón reset, gracias al cual guardamos el estado de la última carga en la EEPROM de Arduino, hacemos uso de las funciones, objetos y métodos de la librería Fastled para crear varios efectos, así que podemos hacer una comparación entre estas dos librerías.

Fastled y lectura del array de visualizacion desde la flash 

Este ejemplo también incluye el uso de la función pgm_read_dword dentro de la librería FastLed para obtener los datos de una imagen codificada en hexadecimal editada con una herramienta externa como gimp e importada en la aplicación lcd image converter (cuyo link se ha dejado en el siguiente apartado) para obtener el valor de cada led en bloques de 24 bits. 


Eligiendo la dirección del scan

 
Obteniendo el código de la imagen en hexadecimal 24 bits

Debido a que el panel flexible enlaza en forma de zigzag cada fila, deberemos tenerlo en cuenta para obtener el código correcto en hexadecimal para las filas que van "contracorriente",  para ello haremos uso de la opción que se muestra en la captura de pantalla y comentaremos y copiaremos aquellas líneas de la imagen que van en contrasentido ya que el efecto forward o backward se aplica a toda la imagen, por lo que en resumen, deberemos elegir un sentido (por ejemplo backward) copiar el código y luego comentar las líneas pares (en mis caso) para cambiar el sentido (a forward) y copiar las líneas pares de la matriz.
const long smiley[] PROGMEM =
{
0x3300ff, 0x3300ff, 0x3300ff, 0x3300ff, 0x3300ff, 0x3300ff, 0x3300ff, 0x3300ff,
//0x3300ff, 0x3300ff, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0x3300ff, 0x3300ff,
0x3300ff, 0x3300ff, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0x3300ff, 0x3300ff,
0x3300ff, 0xffff00, 0x000000, 0xffff00, 0xffff00, 0x000000, 0xffff00, 0x3300ff,
//0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00,
0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00,
0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00,
//0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00,
0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00, 0x000000, 0xffff00, 0xffff00,
0x3300ff, 0xffff00, 0xffff00, 0x000000, 0x000000, 0xffff00, 0xffff00, 0x3300ff,
//0x3300ff, 0x3300ff, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0x3300ff, 0x3300ff
0x3300ff, 0x3300ff, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0x3300ff, 0x3300ff
};
...
 
void read_display_array_fromflash_smiley(){

  for(byte i=0; i<NUM_LEDS;i++){
    leds[i]=pgm_read_dword(&(smiley[i]));
  }

}

Ejemplos

Es posible jugar con los colores y crear imágenes y animaciones pixeladas como por ejemplo

Para la librería Adafruit tenemos varios ejemplos e incluso un generador de código
Si bien, para una mayor vistosidad requiere una vez has conexionado toda la matriz de instalar una rejilla 3D a la que se le coloca cinta de pintar por ejemplo y permite mostrar cada led en un pixel cuadrado del tamaño del cuadrado de la rejilla 3D.
Con la librería FastLed se pueden conseguir efectos más complejos, podemos ayudarnos de un conversor de imágenes a lcd https://sourceforge.net/projects/lcd-image-converter/ y una fuente en bmp, para codificar la imagen en hexadecimal con 8 bits y obtener el resultado en Arduino mediante pgm_read_byte.

Que faltaría para lograr algo parecido a lo que se muestra en la última foto:
  • Obtener una rejilla 3D (o tienes una impresora 3D o tienes que realizar el pedido online para montarla, no he encontrado muchos proveedores) partiendo de un prototipo ajustando las medidas, por ejemplo con la aplicación 3D Builder para generar la impresión 3D.
  • Desoldar las conexiones de todas las tiras y utilizar una base mejor adaptada al tamaño de los leds, y volver a conectar todos los leds con cable más fino
  • Poner la rejilla 3D encima de las tiras y cubrir con papel de pintar por ejemplo
 
Y eso es todo
Gracias por tu tiempo y atención
Un saludo

Referencias

  • https://www.naylampmechatronics.com/blog/20_Tutorial-cinta-LED-RGB-WS2812B.html
  • https://es.wikipedia.org/wiki/RGB
  • https://giancr.com/calculadora-rgb-escala-0-255-0-1-hexadecimal/
  • https://www.instructables.com/Getting-Started-With-NeoPixle-WS2812-RGB-LED/
  • https://www.youtube.com/watch?v=euXBfKmLtz0
  • https://www.youtube.com/watch?v=_cXA2WV_Ouo
  • https://www.youtube.com/watch?v=QIijJGk0uCk