Saltar al contenido principal

Módulo LED

El módulo LED maneja tiras y matrices de LEDs de colores WS2812 (también llamados NeoPixel): las que llevan un chip en cada LED y se encadenan por un solo cable de datos. LED.new crea una tira en un pin; con sus métodos pones el color de cada LED y el brillo de toda la tira, y show() lo manda a los LEDs.

use LED

Plataformas​

WindowsESP32 / ESP32-S3ESP32-P4ESP32-S31
Dónde se veEn la tarjeta WS2812 Strip del simulador GPIOEn la tira conectada al pinEn la tira conectada al pinEn la tira conectada al pin
Tiras a la vez8, con 2.048 LEDs entre todasUna por canal RMT de transmisión del chip: 8 en el ESP32 y 4 en el ESP32-S3Una por canal RMT libreUna por canal RMT libre
Memoria por LED3 bytes99 bytes: una tira de 1.024 LEDs gasta unos 100 KB6 bytes6 bytes
setOrderNo cambia lo que se veCambia el orden en que se mandan los coloresIgualIgual
setBrightness con un decimalPone el brillo a 255Usa la parte enteraIgualIgual

En Windows, el módulo no necesita el simulador abierto: guarda la tira en una memoria que comparte con él, y la tarjeta la pinta en cuanto la ve. En el recorrido del simulador tienes el ejemplo LedStrip paso a paso.

Funciones​

FunciónQué haceDevuelve
LED.new(pin, n)Crea una tira de n LEDs en un pinLa tira

new(pin, n)​

Crea una tira de n LEDs conectada al pin pin.

ParámetroTipoDescripción
pinenteroEl GPIO al que va el cable de datos de la tira. La VM no comprueba que el pin exista ni que esté libre.
nenteroCuántos LEDs tiene la tira, de 1 a 1024.

Devuelve la tira, con todos los LEDs a negro, el brillo a 255 y el orden de colores LED.GRB. No enciende nada hasta el primer show().

Si algo falla, lanza una excepción, que se captura con try (ver Errores y excepciones):

ErrorCuándo
ERR_INVALID_ARG_NUMBERNo le pasas dos argumentos.
ERR_INVALID_VALUEn no está entre 1 y 1024.
ERR_TYPE_MISMATCHEn las placas, pin o n no son enteros. En Windows, un pin que no es entero cuenta como 0, y un n que no es entero da el error de arriba.
ERR_INVALID_OPERATIONNo cabe otra tira: en Windows, ya hay 8 o se pasaría de 2.048 LEDs; en la placa, no queda ningún canal RMT libre.
ERR_OUT_OF_MEMORYNo hay memoria para la tira.
use LED

var tira = LED.new(17, 8) // 8 LEDs en el GPIO 17
println(tira.length()) // 8

Métodos de la tira​

La tira guarda el color de cada LED en memoria. Los métodos que ponen colores solo cambian esa memoria: los LEDs no cambian hasta que llamas a show().

Los LEDs se cuentan desde 0: en una tira de n, van de 0 a n - 1. Los colores van en tres números de 0 a 255 (rojo, verde y azul) o en HSV: el tono en grados y la saturación y el valor de 0 a 255.

MétodoQué haceDevuelve
setPixel(i, r, g, b)Pone el color de un LEDtrue
setHSV(i, h, s, v)Pone el color de un LED, en HSVtrue
getPixel(i)Lee el color de un LEDUna lista [r, g, b]
fill(r, g, b)Pone todos los LEDs del mismo colortrue
fillHSV(h, s, v)Lo mismo, en HSVtrue
clear()Pone todos los LEDs a negrotrue
setBrightness(v)Fija el brillo de toda la tira, de 0 a 255true
setOrder(orden)Dice en qué orden espera la tira los colorestrue
show()Manda los colores a los LEDstrue
length()Cuántos LEDs tiene la tiraUn entero
close()Apaga los LEDs y libera la tiratrue

Errores comunes a todos ellos (excepciones):

  • ERR_INVALID_ARG_NUMBER si el número de argumentos no es el que pide el método.
  • ERR_INDEX_OUT_OF_RANGE si el LED i no está en la tira.
  • ERR_INVALID_OPERATION si la tira está cerrada con close().

setPixel(i, r, g, b)​

Pone el color del LED i. r, g y b son el rojo, el verde y el azul, de 0 a 255: lo que se pase de ese rango se recorta (300 se queda en 255, y -5, en 0).

Los cuatro tienen que ser enteros. Un color decimal cuenta como 0, y un i decimal da ERR_INDEX_OUT_OF_RANGE: pasa antes los decimales a entero con int() o Math.floor.

use LED

var tira = LED.new(17, 8)
tira.setPixel(0, 255, 0, 0) // el primero, rojo
tira.setPixel(7, 0, 0, 255) // el último, azul
tira.setPixel(1, 300, -5, 128) // se recorta
println(tira.getPixel(1)) // [255, 0, 128]
tira.show()

setHSV(i, h, s, v)​

Pone el color del LED i en HSV, que es más cómodo para arcoíris y degradados:

  • h, el tono, en grados: 0 es rojo, 120 verde y 240 azul. Da la vuelta: 480 es 120, y -120 es 240.
  • s, la saturación, de 0 a 255. Con 0, el LED es gris (o blanco), del valor de v.
  • v, el valor (cuánta luz), de 0 a 255.

s y v no se recortan: fuera de 0 a 255 sale otro color. Como en setPixel, los cuatro tienen que ser enteros.

use LED

var tira = LED.new(17, 3)
tira.setHSV(0, 0, 255, 255) // rojo
tira.setHSV(1, 120, 255, 255) // verde
tira.setHSV(2, 240, 255, 255) // azul
println(tira.getPixel(1)) // [0, 255, 0]
tira.show()

getPixel(i)​

Devuelve el color del LED i como una lista [r, g, b]. Es el color que guarda la tira, sin el brillo: después de setBrightness(32), un LED rojo sigue siendo [255, 0, 0]. Un color puesto en HSV sale convertido a rojo, verde y azul.

fill(r, g, b)​

Pone todos los LEDs del mismo color. Los valores se recortan y tienen que ser enteros, como en setPixel.

fillHSV(h, s, v)​

Pone todos los LEDs del mismo color, en HSV, como setHSV.

use LED

var tira = LED.new(17, 8)
tira.fillHSV(30, 255, 255) // naranja
println(tira.getPixel(0)) // [255, 127, 0]
tira.fillHSV(0, 0, 100) // gris
println(tira.getPixel(0)) // [100, 100, 100]
tira.show()

clear()​

Pone todos los LEDs a negro. Como los demás, no apaga nada hasta el siguiente show().

setBrightness(v)​

Fija el brillo de toda la tira, de 0 (apagada) a 255 (el de serie). Lo que se pase de ese rango se recorta.

El brillo se aplica al mandar los colores con show(): cada color se multiplica por (v + 1) / 256. Los colores que guarda la tira no cambian, así que puedes subir y bajar el brillo sin perderlos, y getPixel los devuelve sin él.

use LED

var tira = LED.new(17, 8)
tira.fill(255, 120, 0) // todos naranja
tira.setBrightness(32) // a un octavo de brillo
tira.show()
println(tira.getPixel(0)) // [255, 120, 0]

En las placas, un decimal vale por su parte entera, y un valor que no es un número da ERR_TYPE_MISMATCH. En Windows, cualquier cosa que no sea un entero pone el brillo a 255. Pasa el brillo como entero.

setOrder(orden)​

Dice en qué orden espera la tira los tres colores. La mayoría de las WS2812 los quieren en verde, rojo y azul, que es lo de serie (LED.GRB). Si tu tira enseña el rojo cuando pides verde, prueba con otra de las constantes.

setPixel, fill y getPixel siguen hablando en rojo, verde y azul: el orden solo cambia lo que se manda a la tira. Un valor que no es una de las constantes da ERR_INVALID_VALUE.

use LED

var tira = LED.new(17, 8)
tira.setOrder(LED.RGB) // esta tira espera rojo, verde y azul

En Windows, la tarjeta del simulador enseña los colores tal cual los pone el programa, y setOrder no cambia nada.

show()​

Manda a los LEDs los colores de la tira, con el brillo aplicado. En la placa, el programa espera a que acabe de mandarlos. En Windows, la tarjeta WS2812 Strip del simulador se pinta en ese momento.

Devuelve true; en una placa, false si no se ha podido mandar.

length()​

Devuelve cuántos LEDs tiene la tira: el n de LED.new. Sigue funcionando después de close().

close()​

Apaga los LEDs (manda negro a toda la tira) y libera su memoria y su canal, para que otra tira pueda usarlo. Después, los métodos que tocan colores dan ERR_INVALID_OPERATION. Llamarlo otra vez no hace nada y devuelve true.

use LED

var tira = LED.new(17, 8)
tira.fill(0, 255, 0)
tira.show()
pause(1000)
tira.close() // la tira se apaga

Constantes​

El orden de los colores para setOrder:

ConstanteValorOrden en que se mandan
LED.GRB0Verde, rojo, azul. Es el de serie, el de la mayoría de las WS2812.
LED.RGB1Rojo, verde, azul.
LED.BRG2Azul, rojo, verde.
LED.RBG3Rojo, azul, verde.
LED.GBR4Verde, azul, rojo.
LED.BGR5Azul, verde, rojo.

Ejemplo completo​

Un arcoíris que da vueltas por una tira de 30 LEDs durante 5 segundos. Después, la apaga:

use LED

const NUM_LEDS = 30

var tira = LED.new(17, NUM_LEDS) // 30 LEDs en el GPIO 17
tira.setBrightness(64) // a un cuarto de brillo

var giro = 0
var inicio = clock()
while (clock() - inicio < 5000)
for (var i = 0; i < NUM_LEDS; i++)
var tono = (i * 360) div NUM_LEDS + giro
tira.setHSV(i, tono, 255, 255)
end
tira.show()
giro = (giro + 6) % 360
pause(30)
end

tira.close() // apaga la tira y la libera

El ejemplo LedStrip​

JARU IDE trae el proyecto de ejemplo LedStrip: 17 programas para una matriz de 8 × 8 LEDs (una tira de 64) en el GPIO 17, con plasma, fuego, fuegos artificiales, el juego de la vida, una cuenta atrás… Lo creas desde Home › Project › New, en Example Projects. Su programa principal es Code/Matrix8x8Plasma.aru; para probar otro, elígelo en la lista Main File del explorador y pulsa Run (Proyectos).

Los programas cuentan los LEDs fila a fila, con una función como esta:

use LED

const ANCHO = 8

var tira = LED.new(17, 64)

func xy(x, y)
return y * ANCHO + x // fila a fila, de izquierda a derecha
end

tira.setPixel(xy(3, 2), 255, 0, 0) // columna 3, fila 2
tira.show()

Si tu matriz va cableada en zigzag (una fila de cada dos al revés), cambia esa cuenta. En Windows, la forma y el cableado de la matriz se eligen en la tarjeta del simulador, en Layout y Wiring.

Trampas y problemas conocidos​

  • Nada se ve hasta show(). setPixel, fill, clear y setBrightness solo cambian lo que guarda la tira.
  • Los colores, en enteros. Un color decimal cuenta como 0, sin error: tira.setPixel(0, 127.5, 0, 0) deja el LED apagado. Usa int(), div o Math.floor.
  • En HSV, la saturación y el valor no se recortan. Fuera de 0 a 255 salen colores que no esperas.
  • El brillo con decimales, en Windows. setBrightness con un decimal pone el brillo a 255 en Windows y usa la parte entera en la placa. Pásalo como entero.
  • Sin close(), los LEDs se quedan encendidos. Si el programa acaba sin cerrar la tira, en la placa los LEDs siguen con los últimos colores que les llegaron.
  • La memoria en ESP32 y ESP32-S3. Cada LED gasta 99 bytes de la memoria de la VM mientras la tira está abierta. En una placa sin PSRAM, una tira larga puede dejar al programa sin memoria.
  • El sitio de una tira cerrada, en Windows. Al cerrar una tira, su hueco entre los 2.048 LEDs no se aprovecha mientras siga abierta otra creada después.

Todos los problemas conocidos de JARU, juntos, están en Problemas conocidos.