matriz-led-ws2812b-arduino

Como controlar una matriz LED WS2812b de forma sencilla con Arduino

Hoy vamos a ver cómo conectar una matriz led de una forma sencilla y controlar a través de un procesador como Arduino.

El tipo de matriz que vamos a usar es una matriz con píxeles Neopixel WS2812b, como vimos en esta entrada. Podemos encontrar estas matrices en soporte flexible con 16x16 pixels RGB por unos 12€ en vendedores internacionales como AliExpress o eBay. matriz-ws2812b-conexion

Lógicamente nos gustaría poder controlar nuestra matriz led de la forma más sencilla posible. Idealmente, nos gustaría disponer de una librería que nos permita realizar funcionar gráficas básicas como, por ejemplo, encender un píxel, dibujar una línea, un círculo, o incluso mostrar una imagen.

La buena noticia es esa librería no sólo existe, sino que además existen varias librerías con esta función. Además, son muy conocidas y populares y es probable que hasta la hayáis usado anteriormente.

En concreto, nos referimos a cualquiera de las librerías que empleamos frecuentemente para conectar con una TFT. La mayoría de estas librerías tienen un interface similar a la librería Adafruit Adafruit-GFX.

Probablemente la más conocida sea la librería TFT_eSPI. Tanto esta librería así como algunas de sus “competidoras” añaden el concepto de Sprite a la gestión pura de hardware de la pantalla.

El sprite es una representación de la pantalla en memoria que nos permite acelerar el dibujo de los gráficos. Por tanto, es un buffer de tamaño width * height, donde cada celda es un pixel con un color y que dispone de las mismas funciones de dibujo que una TFT. Es decir, exactamente lo que estábamos buscando.

matriz-ws2812b-formas

Ahora únicamente debemos hacer una función que lea el color de un pixel del sprite, y transmita secuencialmente todos los pixels al panel WS2812b, mediante la librería Neopixel o FastLED.

La función que necesitamos es muy sencilla y os la paso en este en este código.

#include "./constants.h"

CRGB leds[LED_MATRIX_NUM_LEDS];

void InitLed()
{
    auto correction = CRGB(0xFF, 0xE0, 0x1C);
    LEDS.addLeds<ws2812b, data_pin,="" grb="">(leds, LED_MATRIX_NUM_LEDS).setCorrection(correction);
    LEDS.setBrightness(BRIGHTNESS);
}

void SendToLed(TFT_eSprite&amp; sprite)
{
    for (auto y = 0; y < LED_MATRIX_WIDTH; y++)
    {
        for (auto x = 0; x < LED_MATRIX_WIDTH; x++)
        {
            uint16_t rgb565 = sprite.readPixel(x, y);

            ESP_Color::Color color(rgb565);
            auto rgb = CRGB(color.R_Byte(), color.G_Byte(), color.B_Byte());

            auto ix = y;
            auto iy = x;
            leds[(iy % 2 ? LED_MATRIX_WIDTH - ix - 1 : ix) + iy * LED_MATRIX_WIDTH] = rgb;
        }
    }

}

De esta forma tenemos la sencillez de usar las funciones de la pantalla TFT para dibujar en nuestra matriz LED. Estas incluyen desde dibujar formas geométricas a importar ficheros PNG o JPEG.

Es más, podemos ejecutar cualquier programa que encontremos, o que hagamos nosotros mismos, si puede funcionar en funcionar en una pantalla TFT. Esto incluye desde videojuegos, hasta incluso hacer stream de vídeo desde el ordenador.

Aquí tenemos algunos ejemplos de lo que podemos, como cargar un PNG con un sprite de Mario Bross.

matriz-ws2812b-mario

O dibujar un cubo en 3D.

matriz-ws2812b-cubo

Para ejecutar el código necesitaréis las librerías /libreria-esp-color/

En ocasiones tendremos el problema de tener que escalar un grafico con mayor resolución (una imagen, o un render) a la resolución de la matriz que, en general, será mucho menor. Dependiendo del cambio de escala podemos tener problemas de aliasing.

Para evitar el problema del escalado a baja resolución puede que sea necesario que tengamos aplicar filtros de imagen de escalado como vimos en esta entrada.

Y así de sencillo podemos controlar una matriz de LED WS2812b con un procesador como Arduino, de forma muy sencilla, como si fuera cualquier otro display LCD o TFT.

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full .