Control de LEDs direccionables WS2812B con Arduino
Si estás buscando darle un toque vibrante y dinámico a tus proyectos de electrónica, no hay mejor opción que los LEDs WS2812B, también conocidos como NeoPixels. Estas luces direccionables individualmente han ganado popularidad en el mundo del bricolaje y la iluminación decorativa. En este artículo, profundizaremos en el funcionamiento, la conexión y el control de estas fascinantes luces utilizando un Arduino, lo que te permitirá desatar tu creatividad y explorar un mundo de posibilidades.
- Visión general del hardware WS2812B
- Protocolo de transferencia de datos WS2812B
- Pinout de la tira WS2812B
- Estimación de requisitos de energía
- Protegiendo los LEDs WS2812B
- Conectando una tira de LEDs WS2812B a un Arduino
- Encadenamiento y distribución de energía
- Instalación de la biblioteca
- Ejemplos de sketches de NeoPixel
- Ejemplo 1 – Barrido de color simple
- Ejemplo 2 – Ciclo del arcoíris
- Ejemplo 3 – Efecto de luces en marquesina de teatro
- Ejemplo 4 – Copos de nieve
Visión general del hardware WS2812B
Los LEDs WS2812B, a primera vista, pueden parecer un LED RGB SMD estándar de 5050 (5x5mm), pero en realidad, son mucho más que eso. Estos LEDs son una solución integrada que combina la tecnología de iluminación LED con un circuito de control, lo que les permite ser direccionables.
Dentro de cada LED, encontrarás un pequeño chip negro, junto con finos hilos de conexión que unen el chip con los segmentos rojo, verde y azul del LED. Esto es lo que les permite funcionar de manera independiente, controlando el color y la intensidad de cada segmento.
Dato curioso: El WS2812 fue lanzado por la WorldSemi Corporation a finales de 2013. La compañía se destacó previamente por sus soluciones de control de LED, particularmente el WS2811, que permitió convertir un LED RGB de ánodo común en un LED controlable en serie.
Profundidad de color
Los WS2812B operan en un rango de 8 bits por color, lo que significa que cada segmento del LED puede alcanzar 256 niveles de brillo diferentes. Esto se traduce en una paleta de colores de 24 bits, permitiendo mostrar un total de 16,777,216 colores diferentes, desde el más sutil teal hasta un blanco brillante.
Facilidad de encadenamiento
Una de las características más impresionantes de los WS2812B es su capacidad de encadenarse. El output de un LED se puede conectar al input de otro, formando tiras de cientos de LEDs. Además, solo se necesita un pin en tu microcontrolador para controlar toda la tira.
Las tiras de LEDs WS2812B tienen flechas impresas que indican la dirección del flujo de datos. Al conectar la tira al microcontrolador, asegúrate de que las flechas apunten en la dirección correcta.
Requisitos de energía
Los WS2812B operan en un rango de voltaje de 3.3V a 5V. Por ejemplo, la salida de 5V de un Arduino es ideal para alimentar estos LEDs. Cuando están a máximo brillo, cada segmento (rojo, verde y azul) consume aproximadamente 20 mA, sumando un total de 60 mA por LED. Esto implica que incluso con solo diez LEDs conectados, la corriente total puede superar los 600 mA.
Si planeas usar muchos de estos LEDs, asegúrate de que tu fuente de energía pueda manejar esta demanda adicional. Para una estimación más precisa, consulta la sección sobre Estimación de Requisitos de Energía.
Protocolo de transferencia de datos WS2812B
El protocolo de control de los WS2812B es único y altamente sensible al tiempo, lo que lo diferencia de una interfaz UART estándar. Aunque miles de WS2812B pueden ser controlados a través de un solo cable, los pulsos de datos son cruciales para su funcionamiento.
Los pulsos de lógica 0 y 1 se determinan por la longitud del pulso: un pulso corto (0.35 μs) representa un cero, mientras que un pulso largo (0.7 μs) representa un uno. La serie de datos se envía en una secuencia de 24 bits, seguida de un pulso bajo de 50 µs como "reset".
El tiempo entre los bordes ascendentes consecutivos debe ser de 1.25 μs. El valor de cada color determina su brillo: si todos están en cero, el LED está apagado; si todos están en 255, el LED brilla con la máxima intensidad.
Es importante notar que, aunque se dice que los WS2812B son direccionables, en realidad funcionan en una cadena en la que cada LED recibe y almacena los primeros 24 bits de datos que recibe antes de pasar el resto de la información al siguiente LED. Esto requiere un microcontrolador en tiempo real, como un Arduino, ya que cualquier retraso puede cambiar el color de un LED.
Pinout de la tira WS2812B
Cada tira de LEDs tiene tres puntos de conexión: el conector de entrada, los cables de alimentación auxiliares y el conector de salida. El strip utiliza conectores JST SM de 3 pines.
Conector de entrada
El conector de entrada es un conector hembra JST SM de 3 pines:
- 5V (Rojo): este es el cable de alimentación y debe conectarse a una fuente de voltaje regulada entre 3.3V y 5V.
- Data In (Verde): transmite datos hacia la tira.
- GND (Blanco): es la tierra común.
Conector de salida
Este conector tiene tres pines macho que se ensamblan con el conector de entrada de otra tira de LED, lo que permite conectar múltiples tiras juntas.
- 5V (Rojo): cable de alimentación.
- Data Out (Verde): transmite datos fuera de la tira.
- GND (Blanco): tierra común.
Cables de alimentación auxiliares
Ambos conectores incluyen cables de 5V y GND auxiliares, permitiendo agregar energía a la tira en cualquiera de sus extremos o en múltiples puntos, lo que previene una caída excesiva de voltaje a lo largo de la tira. Si no vas a usar estos cables, recorta cualquier punta expuesta y/o aísla con un tubo termocontraíble para evitar cortocircuitos.
Estimación de requisitos de energía
Cada LED WS2812B consume aproximadamente 60 mA cuando está a máximo brillo (blanco brillante) y alimentado a 5 voltios. Esto significa que, incluso con solo 60 LEDs encendidos, la tira podría estar consumiendo hasta 3.6 A.
Sin embargo, en la práctica, es raro que todos los LEDs se enciendan al mismo tiempo. Al mezclar colores y mostrar animaciones, el consumo de corriente es mucho menor. Aunque es difícil proporcionar una estimación precisa para cada escenario, hay una regla general que sugiere utilizar un tercio del total del consumo (20 mA por LED) sin efectos negativos. Sin embargo, si estás seguro de que cada píxel debe estar encendido, utiliza la cifra completa de 60 mA.
Los requisitos de energía se pueden estimar multiplicando el número total de LEDs WS2812B por 20, y luego dividiendo por 1000 para obtener una calificación de fuente de energía (en Amperios). Para mayor seguridad, utiliza 60 en lugar de 20 en el cálculo. Por ejemplo:
- 60 LEDs WS2812B × 20 mA ÷ 1000 = 1.2 Amperios como mínimo
- 60 LEDs WS2812B × 60 mA ÷ 1000 = 3.6 Amperios como mínimo
La elección de la fuente de energía depende de ti, pero un suministro de energía sobredimensionado añade una capa de seguridad y fiabilidad.
Protegiendo los LEDs WS2812B
Es fundamental recordar que los LEDs WS2812B son muy sensibles, por lo que se recomienda tomar las siguientes precauciones para protegerlos:
- Agrega un gran capacitor (100 a 1000 µF, 6.3V o superior) entre los terminales + y - lo más cerca posible de tu WS2812B. Este capacitor ayuda a estabilizar la fuente de energía y protege los LEDs de la corriente inicial.
- Considera agregar resistencias de 220 y 470 Ohmios entre la salida de datos de tu microcontrolador y la entrada de la tira LED para reducir el ruido. Algunos productos WS2812B ya incluyen esta resistencia; si tienes dudas, no dudes en agregar una.
- Minimiza la distancia entre el microcontrolador y la tira LED para asegurar una señal clara. Las distancias cortas suelen ser seguras, pero si es mucho mayor, la caída de voltaje puede causar problemas.
- Asegúrate de que el nivel lógico de la línea de datos coincida con el voltaje de entrada. Si alimentas la tira con 5V, conecta la línea de datos con un nivel lógico de 5V.
- Evita hacer o modificar conexiones mientras el circuito esté alimentado. Si es necesario, conecta primero la tierra, luego el +5V y luego los datos, y desconéctalos en orden inverso.
- Cuando uses una fuente de energía separada para la tira LED, aplica energía a la tira antes de encender el microcontrolador para evitar que los LEDs intenten extraer energía a través de la línea de datos.
- Evita tocar la tira LED con las manos desnudas, ya que la electricidad estática de tu cuerpo puede dañarlos y provocar malfuncionamientos.
Conectando una tira de LEDs WS2812B a un Arduino
Las tiras de LEDs WS2812B vienen con un conector hembra JST-SM estándar y un cable macho, lo que facilita la conexión a un microcontrolador y el encadenamiento de múltiples tiras.
La conexión es bastante sencilla. Primero, identifica el extremo de "entrada" de la tira, que tendrá un pad de soldadura etiquetado como "DIN", "DI" o "I" (entrada de datos), así como una flecha que indica hacia dónde fluye el dato.
Conecta el cable rojo (+5V o +) de la tira LED a la salida de 5V del Arduino y el cable blanco/amarillo (GND o -) al pin GND del Arduino. Finalmente, conecta el cable verde (DIN o DI o I) de la tira LED al pin digital 6 del Arduino, a través de una resistencia de 330 Ohmios.
Se recomienda además agregar un capacitor grande (100 a 1000 µF, 6.3V o superior) entre los terminales + y - lo más cerca posible de tu WS2812B.
Si tienes pocas LEDs, puedes alimentar la tira directamente desde el pin de 5V del Arduino. Este puede suministrar alrededor de 500 mA de forma continua. Cada WS2812B puede consumir hasta 60 mA a máximo brillo, así que si solo usas unos pocos LEDs y mantienes el brillo bajo (alrededor del 25%), puedes omitir la fuente de alimentación separada. En caso de duda, utiliza un suministro externo.
Si tienes un proyecto más grande que requiere más LEDs, la alimentación USB no será suficiente. Debes inyectar energía en la tira desde una fuente externa.
Encadenamiento y distribución de energía
Múltiples tiras de LEDs pueden encadenarse conectando los conectores de entrada a los de salida. Cuando las tiras están encadenadas de esta manera, pueden ser controladas y alimentadas como una sola tira continua. Sin embargo, a medida que las cadenas se alargan, la tensión comienza a disminuir, lo que provoca que el extremo más alejado de la tira se atenúe, cambie de color (hacia un tono más rojizo) o deje de funcionar por completo.
Esta caída de tensión es proporcional a la corriente que fluye a través de la tira, lo que significa que aumenta cuando los LEDs están configurados a un brillo más alto. Se observaron los siguientes resultados al medir la caída de tensión y la corriente de tiras de LED de diferentes longitudes con todos los LEDs configurados a máximo brillo:
- La tira de 30 LEDs de 1 m consumió 1.5 A y tuvo una caída de tensión de 0.2 V.
- La tira de 60 LEDs de 2 m consumió 2.9 A y tuvo una caída de tensión de 0.8 V.
- La tira de 120 LEDs de 2 m consumió 4.7 A y tuvo una caída de tensión de 1.4 V.
- La tira de 150 LEDs de 5 m consumió 4.1 A y tuvo una caída de tensión de 2.0 V.
Para solucionar este problema, se recomienda alimentar cada conjunto de 180 LEDs por separado utilizando los cables de alimentación auxiliares. Recuerda que si utilizas diferentes fuentes de alimentación para cada conjunto, corta los cables de alimentación entre los conjuntos para evitar cortocircuitos.
Instalación de la biblioteca
Controlar los LEDs WS2812B "desde cero" puede ser un desafío, por lo que utilizaremos la excelente biblioteca NeoPixel de Adafruit para centrarnos en las partes divertidas e interesantes en lugar de lidiar con el extraño protocolo.
Para instalar la biblioteca, navega a Sketch > Include Library > Manage Libraries… Espera a que el Administrador de Bibliotecas descargue el índice de bibliotecas y actualice la lista de bibliotecas instaladas.
Filtra tu búsqueda ingresando 'neopixel'. Busca Adafruit NeoPixel por Adafruit. Haz clic en esa entrada y luego elige Instalar.
Adafruit NeoPixel no es la única biblioteca disponible; hay otras, como la biblioteca FastLED, que tiene más características avanzadas y soporta otros conjuntos de LED.
Ejemplos de sketches de NeoPixel
La biblioteca NeoPixel de Adafruit incluye varios sketches de ejemplo. Puedes utilizar estos sketches como base para desarrollar tu propio código.
Para acceder a los sketches de ejemplo, navega a File > Examples > Adafruit NeoPixel. Verás una selección de ejemplos.
Ejemplo 1 – Barrido de color simple
Este primer ejemplo es muy simple; solo llena los LEDs de la tira uno a uno con color verde. Este ejemplo te dará una idea de cómo usar la biblioteca NeoPixel para crear tus propias animaciones.
Antes de cargar el sketch, debes hacer un pequeño cambio para que funcione para ti. Las constantes LED_PIN y LED_COUNT deben ajustarse, respectivamente, al pin del Arduino conectado al pin "DIN" de la tira y al número total de LEDs en la tira.
// Pin a usar para enviar señales a WS2812B
#define LED_PIN 6
// Número de LEDs WS2812B conectados al Arduino
#define LED_COUNT 12
Una vez que hayas hecho esto, ¡prueba el sketch!
#include
// Pin a usar para enviar señales a WS2812B
#define LED_PIN 6
// Número de LEDs WS2812B conectados al Arduino
#define LED_COUNT 12
// Configuración de la biblioteca NeoPixel
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin(); // Inicializa el objeto NeoPixel
strip.setBrightness(10); // Establece el BRILLO a aproximadamente 4% (máx = 255)
}
void loop() {
strip.clear(); // Establece todos los colores de los píxeles a 'apagado'
// El primer NeoPixel en una cadena es #0, el segundo es 1, hasta el conteo de píxeles menos uno.
for(int i = 0; i < LED_COUNT; i++) {
// Establece el i-ésimo LED a puro verde:
strip.setPixelColor(i, 0, 255, 0);
strip.show(); // Envía los colores actualizados a la hardware.
delay(500); // Pausa antes de la siguiente pasada por el bucle
}
}Si los LEDs están correctamente conectados y alimentados, deberías ver algo similar a esto.
El archivo WS2812_Definitions.h define una gran lista de colores estándar. Allí encontrarás desde teal hasta sienna, pasando por blanco fantasma. Simplemente descarga el archivo y colócalo en tu carpeta de sketches antes de abrir el sketch, impórtalo en tu sketch.
#include "WS2812_Definitions.h"Y úsalo para establecer el color de un píxel, como en la línea a continuación que cambia el color de un píxel a teal.
strip.setPixelColor(i, TEAL);Explicación del código:
Para aprender a escribir tus propios sketches, comencemos desmenuzando este sketch simple.
El sketch comienza incluyendo el archivo de encabezado Adafruit_NeoPixel.
#include En la misma área global, se definen dos constantes LED_PIN y LED_COUNT, que especifican el pin del Arduino conectado al pin "DIN" de la tira y el número total de LEDs en la tira.
// Pin a usar para enviar señales a WS2812B
#define LED_PIN 6
// Número de LEDs WS2812B conectados al Arduino
#define LED_COUNT 12A continuación, se crea una instancia de la clase Adafruit_NeoPixel llamada strip. A partir de ahora, te referirás a ella para controlar la tira. Hay tres argumentos en los paréntesis: LED_COUNT, LED_PIN y un valor que indica el tipo de NeoPixels que están conectados. En la mayoría de los casos, puedes omitir esto y pasar solo dos argumentos.
// Configuración de la biblioteca NeoPixel
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argumento 1 = Número de píxeles en la tira
// Argumento 2 = Número del pin del Arduino
// Argumento 3 = Flags de tipo de píxel, suma según sea necesario:
// NEO_KHZ800 800 KHz bitstream (la mayoría de los productos NeoPixel con LEDs WS2812)
// NEO_KHZ400 400 KHz (clásico 'v1' (no v2) píxeles FLORA, controladores WS2811)
// NEO_GRB Píxeles están cableados para GRB bitstream (la mayoría de los productos NeoPixel)
// NEO_RGB Píxeles están cableados para RGB bitstream (píxeles FLORA v1, no v2)
// NEO_RGBW Píxeles están cableados para RGBW bitstream (productos NeoPixel RGBW)En la función setup(), se llama al método begin() para preparar el pin de datos para salida.
A continuación, se ajusta el brillo general de todos los LEDs usando setBrightness(). Este método acepta un solo argumento, un número entre 0 (apagado) y 255 (brillo máximo). En este caso, el brillo se establece en 10 (aproximadamente 4%).
strip.setBrightness(10); // Establece el BRILLO a aproximadamente 4% (máx = 255)Lo primero que sucede en la función loop() es una llamada a clear(), que llena la tira con negro o "apagado".
Finalmente, un bucle for se utiliza para llenar los LEDs de la tira uno a uno.
Dentro del bucle for, se utiliza setPixelColor() para establecer el color de un píxel. El primer argumento especifica la posición del LED a lo largo de la tira, que varía de 0 al número de píxeles menos uno. Los siguientes tres argumentos son el color del LED, expresado como niveles de brillo rojo, verde y azul, donde 0 es el más tenue (apagado) y 255 es el brillo máximo.
El método setPixelColor() por sí solo no hace nada; debes usar show() para “empujar” los datos de color a la tira.
for(int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, 0, 255, 0);
strip.show();
delay(500);
}Para tu información, hay varias maneras diferentes de llamar a setPixelColor(). Cada una de las siguientes líneas puede hacer que el i-ésimo LED brille en puro verde.
strip.setPixelColor(i, 0, 255, 0);
strip.setPixelColor(i, 0x00FF00);
strip.setPixelColor(i, 0x00, 0xFF, 0x00);
uint32_t green = strip.Color(0, 255, 0);
strip.setPixelColor(i, green);Ejemplo 2 – Ciclo del arcoíris
Este es, sin duda, el ejemplo más popular. Este efecto desplaza los colores del arcoíris, distribuyendo uniformemente el espectro de colores a lo largo de la tira LED.
#include
// Pin a usar para enviar señales a WS2812B
#define LED_PIN 6
// Número de LEDs WS2812B conectados al Arduino
#define LED_COUNT 12
// Configuración de la biblioteca NeoPixel
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin(); // Inicializa el objeto NeoPixel
strip.setBrightness(10); // Establece el BRILLO a aproximadamente 4% (máx = 255)
strip.show(); // Inicializa todos los píxeles a 'apagado'
}
void loop() {
rainbow(10);
}
// Ciclo arcoíris a lo largo de toda la tira. Pasa el tiempo de retraso (en ms) entre cuadros.
void rainbow(int wait) {
// 5 ciclos de todos los colores en la rueda
for(long firstPixelHue = 0; firstPixelHue < 5 * 65536; firstPixelHue += 256) {
strip.rainbow(firstPixelHue);
strip.show(); // Actualiza la tira con el nuevo contenido
delay(wait); // Pausa por un momento
}
}¡Solo sube el código y disfruta del espectáculo!
Ejemplo 3 – Efecto de luces en marquesina de teatro
Este es un homenaje a las antiguas marquesinas de teatro. Hace que los LEDs parpadeen en serie, dando la impresión de que están persiguiendo alrededor.
#include
// Pin a usar para enviar señales a WS2812B
#define LED_PIN 6
// Número de LEDs WS2812B conectados al Arduino
#define LED_COUNT 12
// Configuración de la biblioteca NeoPixel
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin(); // Inicializa el objeto NeoPixel
strip.setBrightness(10); // Establece el BRILLO a aproximadamente 4% (máx = 255)
strip.show(); // Inicializa todos los píxeles a 'apagado'
}
void loop() {
// Realiza un efecto de marquesina de teatro en varios colores...
theaterChase(strip.Color(255, 255, 255), 50); // Blanco
theaterChase(strip.Color(255, 0, 0), 50); // Rojo
theaterChase(strip.Color(0, 0, 255), 50); // Azul
}
// Efecto de luces en marquesina de teatro. Pasa un color y un tiempo de retraso (en ms) entre cuadros.
void theaterChase(uint32_t color, int wait) {
for(int a = 0; a < 10; a++) { // Repite 10 veces...
for(int b = 0; b < 3; b++) { // 'b' cuenta de 0 a 2...
strip.clear(); // Establece todos los píxeles en RAM a 0 (apagado)
// 'c' cuenta desde 'b' hasta el final de la tira en pasos de 3...
for(int c = b; c < strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Establece el píxel 'c' al valor 'color'
}
strip.show(); // Actualiza la tira con el nuevo contenido
delay(wait); // Pausa por un momento
}
}
}Así es como se verá.
Ejemplo 4 – Copos de nieve
Esta animación crea un conjunto de píxeles blancos parpadeantes al azar que se asemejan a la caída de nieve.
#include
// Pin a usar para enviar señales a WS2812B
#define LED_PIN 6
// Número de LEDs WS2812B conectados al Arduino
#define LED_COUNT 12
// Configuración de la biblioteca NeoPixel
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin(); // Inicializa el objeto NeoPixel
strip.setBrightness(10); // Establece el BRILLO a aproximadamente 4% (máx = 255)
strip.show(); // Inicializa todos los píxeles a 'apagado'
}
void loop() {
snowflakes(100);
}
void snowflakes(uint8_t wait) {
// Configura el arreglo de píxeles
int pixel[60];
for(int p = 0; p < 60; p++){
pixel[p] = random(0, 255);
}
// Realiza algunos ciclos de copo de nieve
for(int j = 0; j < 200; j++) {
// Cada cinco ciclos, enciende un nuevo píxel
if((j % 5) == 0){
strip.setPixelColor(random(0, 60), 255, 255, 255);
}
// Atenúa todos los píxeles en 10
for(int p = 0; p < 60; p++){
strip.setPixelColor(p, pixel[p], pixel[p], pixel[p]);
pixel[p] = pixel[p] - 10;
}
strip.show();
delay(wait);
}
}Así es como se verá.
Deja una respuesta

Estos temas te pueden interesar