LED module
The LED module drives strips and matrices of WS2812 color LEDs (also called NeoPixel): the ones with a chip in each LED, chained along a single data wire. LED.new creates a strip on a pin; with its methods you set the color of each LED and the brightness of the whole strip, and show() sends it to the LEDs.
use LED
Platforms
| Windows | ESP32 / ESP32-S3 | ESP32-P4 | ESP32-S31 | |
|---|---|---|---|---|
| Where you see it | On the WS2812 Strip card of the GPIO simulator | On the strip wired to the pin | On the strip wired to the pin | On the strip wired to the pin |
| Strips at once | 8, with 2,048 LEDs among all of them | One per transmit RMT channel of the chip: 8 on the ESP32 and 4 on the ESP32-S3 | One per free RMT channel | One per free RMT channel |
| Memory per LED | 3 bytes | 99 bytes: a strip of 1,024 LEDs takes about 100 KB | 6 bytes | 6 bytes |
setOrder | Doesn't change what you see | Changes the order in which the colors are sent | Same | Same |
setBrightness with a decimal | Sets the brightness to 255 | Uses the integer part | Same | Same |
On Windows, the module doesn't need the simulator to be open: it keeps the strip in a memory it shares with it, and the card paints it as soon as it sees it. The simulator walkthrough takes you through the LedStrip example step by step.
Functions
| Function | What it does | Returns |
|---|---|---|
LED.new(pin, n) | Creates a strip of n LEDs on a pin | The strip |
new(pin, n)
Creates a strip of n LEDs wired to pin pin.
| Parameter | Type | Description |
|---|---|---|
pin | integer | The GPIO the strip's data wire goes to. The VM doesn't check that the pin exists or is free. |
n | integer | How many LEDs the strip has, from 1 to 1024. |
It returns the strip, with every LED set to black, the brightness at 255 and the color order LED.GRB. Nothing lights up until the first show().
If something goes wrong, it throws an exception, which you catch with try (see Errors and exceptions):
| Error | When |
|---|---|
ERR_INVALID_ARG_NUMBER | You don't pass two arguments. |
ERR_INVALID_VALUE | n isn't between 1 and 1024. |
ERR_TYPE_MISMATCH | On the boards, pin or n aren't integers. On Windows, a pin that isn't an integer counts as 0, and an n that isn't an integer gives the error above. |
ERR_INVALID_OPERATION | There's no room for another strip: on Windows, there are already 8 or it would go over 2,048 LEDs; on a board, there's no free RMT channel left. |
ERR_OUT_OF_MEMORY | There's no memory for the strip. |
use LED
var strip = LED.new(17, 8) // 8 LEDs on GPIO 17
println(strip.length()) // 8
Strip methods
The strip keeps the color of each LED in memory. The methods that set colors only change that memory: the LEDs don't change until you call show().
LEDs are counted from 0: on a strip of n, they go from 0 to n - 1. Colors come as three numbers from 0 to 255 (red, green and blue) or in HSV: the hue in degrees, and the saturation and the value from 0 to 255.
| Method | What it does | Returns |
|---|---|---|
setPixel(i, r, g, b) | Sets the color of one LED | true |
setHSV(i, h, s, v) | Sets the color of one LED, in HSV | true |
getPixel(i) | Reads the color of one LED | A list [r, g, b] |
fill(r, g, b) | Sets every LED to the same color | true |
fillHSV(h, s, v) | The same, in HSV | true |
clear() | Sets every LED to black | true |
setBrightness(v) | Sets the brightness of the whole strip, from 0 to 255 | true |
setOrder(order) | Says in which order the strip expects the colors | true |
show() | Sends the colors to the LEDs | true |
length() | How many LEDs the strip has | An integer |
close() | Turns the LEDs off and frees the strip | true |
Errors shared by all of them (exceptions):
ERR_INVALID_ARG_NUMBERif the number of arguments isn't the one the method asks for.ERR_INDEX_OUT_OF_RANGEif LEDiisn't on the strip.ERR_INVALID_OPERATIONif the strip has been closed withclose().
setPixel(i, r, g, b)
Sets the color of LED i. r, g and b are red, green and blue, from 0 to 255: anything outside that range is clipped (300 stays at 255, and -5, at 0).
All four have to be integers. A decimal color counts as 0, and a decimal i gives ERR_INDEX_OUT_OF_RANGE: turn decimals into integers first with int() or Math.floor.
use LED
var strip = LED.new(17, 8)
strip.setPixel(0, 255, 0, 0) // the first one, red
strip.setPixel(7, 0, 0, 255) // the last one, blue
strip.setPixel(1, 300, -5, 128) // it gets clipped
println(strip.getPixel(1)) // [255, 0, 128]
strip.show()
setHSV(i, h, s, v)
Sets the color of LED i in HSV, which is handier for rainbows and gradients:
h, the hue, in degrees: 0 is red, 120 green and 240 blue. It wraps around: 480 is 120, and -120 is 240.s, the saturation, from 0 to 255. With 0, the LED is gray (or white), at the level ofv.v, the value (how much light), from 0 to 255.
s and v aren't clipped: outside 0 to 255 you get a different color. As with setPixel, all four have to be integers.
use LED
var strip = LED.new(17, 3)
strip.setHSV(0, 0, 255, 255) // red
strip.setHSV(1, 120, 255, 255) // green
strip.setHSV(2, 240, 255, 255) // blue
println(strip.getPixel(1)) // [0, 255, 0]
strip.show()
getPixel(i)
Returns the color of LED i as a list [r, g, b]. It's the color the strip keeps, without the brightness: after setBrightness(32), a red LED is still [255, 0, 0]. A color set in HSV comes back converted to red, green and blue.
fill(r, g, b)
Sets every LED to the same color. The values are clipped and have to be integers, as in setPixel.
fillHSV(h, s, v)
Sets every LED to the same color, in HSV, as setHSV does.
use LED
var strip = LED.new(17, 8)
strip.fillHSV(30, 255, 255) // orange
println(strip.getPixel(0)) // [255, 127, 0]
strip.fillHSV(0, 0, 100) // gray
println(strip.getPixel(0)) // [100, 100, 100]
strip.show()
clear()
Sets every LED to black. Like the others, it turns nothing off until the next show().
setBrightness(v)
Sets the brightness of the whole strip, from 0 (off) to 255 (the default). Anything outside that range is clipped.
The brightness is applied when show() sends the colors: each color is multiplied by (v + 1) / 256. The colors the strip keeps don't change, so you can turn the brightness up and down without losing them, and getPixel returns them without it.
use LED
var strip = LED.new(17, 8)
strip.fill(255, 120, 0) // all orange
strip.setBrightness(32) // at an eighth of the brightness
strip.show()
println(strip.getPixel(0)) // [255, 120, 0]
On the boards, a decimal counts as its integer part, and a value that isn't a number gives ERR_TYPE_MISMATCH. On Windows, anything that isn't an integer sets the brightness to 255. Pass the brightness as an integer.
setOrder(order)
Says in which order the strip expects the three colors. Most WS2812s want them as green, red and blue, which is the default (LED.GRB). If your strip shows red when you ask for green, try another of the constants.
setPixel, fill and getPixel still speak red, green and blue: the order only changes what is sent to the strip. A value that isn't one of the constants gives ERR_INVALID_VALUE.
use LED
var strip = LED.new(17, 8)
strip.setOrder(LED.RGB) // this strip expects red, green and blue
On Windows, the simulator card shows the colors just as the program sets them, and setOrder changes nothing.
show()
Sends the strip's colors to the LEDs, with the brightness applied. On a board, the program waits until they have all been sent. On Windows, the simulator's WS2812 Strip card is painted at that moment.
It returns true; on a board, false if they couldn't be sent.
length()
Returns how many LEDs the strip has: the n of LED.new. It still works after close().
close()
Turns the LEDs off (it sends black to the whole strip) and frees its memory and its channel, so that another strip can use it. Afterwards, the methods that touch colors give ERR_INVALID_OPERATION. Calling it again does nothing and returns true.
use LED
var strip = LED.new(17, 8)
strip.fill(0, 255, 0)
strip.show()
pause(1000)
strip.close() // the strip goes dark
Constants
The color order for setOrder:
| Constant | Value | Order in which they're sent |
|---|---|---|
LED.GRB | 0 | Green, red, blue. It's the default, the one most WS2812s use. |
LED.RGB | 1 | Red, green, blue. |
LED.BRG | 2 | Blue, red, green. |
LED.RBG | 3 | Red, blue, green. |
LED.GBR | 4 | Green, blue, red. |
LED.BGR | 5 | Blue, green, red. |
Complete example
A rainbow that spins along a strip of 30 LEDs for 5 seconds. Then it turns the strip off:
use LED
const NUM_LEDS = 30
var strip = LED.new(17, NUM_LEDS) // 30 LEDs on GPIO 17
strip.setBrightness(64) // at a quarter of the brightness
var spin = 0
var start = clock()
while (clock() - start < 5000)
for (var i = 0; i < NUM_LEDS; i++)
var hue = (i * 360) div NUM_LEDS + spin
strip.setHSV(i, hue, 255, 255)
end
strip.show()
spin = (spin + 6) % 360
pause(30)
end
strip.close() // turns the strip off and frees it
The LedStrip example
JARU IDE comes with the LedStrip example project: 17 programs for an 8 × 8 LED matrix (a strip of 64) on GPIO 17, with plasma, fire, fireworks, the game of life, a countdown… You create it from Home › Project › New, in Example Projects. Its main program is Code/Matrix8x8Plasma.aru; to try another one, pick it in the explorer's Main File list and press Run (Projects).
The programs count the LEDs row by row, with a function like this one:
use LED
const WIDTH = 8
var strip = LED.new(17, 64)
func xy(x, y)
return y * WIDTH + x // row by row, from left to right
end
strip.setPixel(xy(3, 2), 255, 0, 0) // column 3, row 2
strip.show()
If your matrix is wired in a zigzag (every other row backwards), change that calculation. On Windows, the shape and the wiring of the matrix are chosen on the simulator card, in Layout and Wiring.
Pitfalls and known issues
- Nothing shows until
show().setPixel,fill,clearandsetBrightnessonly change what the strip keeps. - Colors as integers. A decimal color counts as 0, with no error:
strip.setPixel(0, 127.5, 0, 0)leaves the LED off. Useint(),divorMath.floor. - In HSV, the saturation and the value aren't clipped. Outside 0 to 255 you get colors you don't expect.
- Brightness with decimals, on Windows.
setBrightnesswith a decimal sets the brightness to 255 on Windows and uses the integer part on a board. Pass it as an integer. - Without
close(), the LEDs stay on. If the program ends without closing the strip, on a board the LEDs keep the last colors they received. - Memory on the ESP32 and ESP32-S3. Each LED takes 99 bytes of the VM's memory while the strip is open. On a board without PSRAM, a long strip can leave the program short of memory.
- The room of a closed strip, on Windows. When you close a strip, its space among the 2,048 LEDs isn't reused while another strip created after it is still open.
All the known issues of JARU, together, are in Known issues.