332 lines
10 KiB
Markdown
332 lines
10 KiB
Markdown
# WS2812 Module
|
|
| Since | Origin / Contributor | Maintainer | Source |
|
|
| :----- | :-------------------- | :---------- | :------ |
|
|
| 2015-02-05 | [Till Klocke](https://github.com/dereulenspiegel), [Thomas Soëte](https://github.com/Alkorin), [Christoph Thelen](https://github.com/docbacardi) | [Arnim Läuger](https://github.com/devsaurus) | [ws2812.c](../../components/modules/ws2812.c)|
|
|
|
|
ws2812 is a library to handle ws2812-like led strips.
|
|
It works at least on WS2812, WS2812b, APA104, SK6812 (RGB or RGBW).
|
|
|
|
!!! note
|
|
|
|
The API on ESP32 differs from the API on ESP8266. For backwards compatibility please refer to [`lua_compat/ws2812_compat.lua`](../../lua_compat/ws2812_compat.lua`).
|
|
|
|
## ws2812.write()
|
|
Send data to up to 8 led strip using its native format which is generally Green,Red,Blue for RGB strips and Green,Red,Blue,White for RGBW strips.
|
|
|
|
#### Syntax
|
|
`ws2812.write(table, ...)`
|
|
|
|
#### Parameters
|
|
Variable number of tables, each describing a single strip. Required elements are:
|
|
|
|
- `pin` IO index, see [GPIO Overview](gpio.md#gpio-overview)
|
|
- `data` payload to be sent to one or more WS2812 like leds through GPIO2
|
|
|
|
Optional elements are:
|
|
|
|
- `reset` duration of the reset signal in multiples of 100ns. A duration of 0 generates no reset. The minimum possible value is 0. The maximum is 65534. The default value is 512 which generates a reset of 51.2us.
|
|
- `t0h` duration of the high period for a 0 code in multiples of 100ns. The minimum possible value is 1. The maximum is 32767. The default value is 4 which results in a high period of 400ns for each 0 code.
|
|
- `t0l` duration of the low period for a 0 code in multiples of 100ns. The minimum possible value is 1. The maximum is 32767. The default value is 7 which results in a low period of 700ns for each 0 code.
|
|
- `t1h` duration of the high period for a 1 code in multiples of 100ns. The minimum possible value is 1. The maximum is 32767. The default value is 8 which results in a high period of 800ns for each 1 code.
|
|
- `t1l` duration of the low period for a 1 code in multiples of 100ns. The minimum possible value is 1. The maximum is 32767. The default value is 6 which results in a low period of 600ns for each 1 code.
|
|
|
|
Payload type could be:
|
|
|
|
- `string` representing bytes to send
|
|
- `ws2812.buffer` see [Buffer module](#buffer-module)
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
ws2812.write({pin = 4, data = string.char(255, 0, 0, 255, 0, 0)}) -- turn the two first RGB leds to green
|
|
```
|
|
|
|
```lua
|
|
ws2812.write({pin = 4, string.char(0, 0, 0, 255, 0, 0, 0, 255)}) -- turn the two first RGBW leds to white
|
|
```
|
|
|
|
```lua
|
|
ws2812.write({pin = 4, data = string.char(255, 0, 0, 255, 0, 0)},
|
|
{pin = 14, data = string.char(0, 255, 0, 0, 255, 0)}) -- turn the two first RGB leds to green on the first strip and red on the second strip
|
|
```
|
|
|
|
```lua
|
|
ws2812.write({pin = 8, reset = 800, t0h = 3, t0l = 9, t1h = 6, t1l = 6, data = string.char(1, 0, 0)}) -- turn the SK6812 GRB led on the ESP32-C3-DevKitM-1 to green
|
|
```
|
|
|
|
# Buffer module
|
|
For more advanced animations, it is useful to keep a "framebuffer" of the strip,
|
|
interact with it and flush it to the strip.
|
|
|
|
For this purpose, the ws2812 library offers a read/write buffer. This buffer has a `__tostring` method so that it can be printed. This is useful for debugging.
|
|
|
|
#### Example
|
|
Led chaser with a RGBW strip
|
|
```lua
|
|
local i, buffer = 0, ws2812.newBuffer(300, 4); buffer:fill(0, 0, 0, 0); tmr.create():alarm(50, 1, function()
|
|
i = i + 1
|
|
buffer:fade(2)
|
|
buffer:set(i % buffer:size() + 1, 0, 0, 0, 255)
|
|
ws2812.write({pin = 4, data = buffer})
|
|
end)
|
|
```
|
|
|
|
## ws2812.newBuffer()
|
|
Allocate a new memory buffer to store led values.
|
|
|
|
#### Syntax
|
|
`ws2812.newBuffer(numberOfLeds, bytesPerLed)`
|
|
|
|
#### Parameters
|
|
- `numberOfLeds` length of the led strip
|
|
- `bytesPerLed` 3 for RGB strips and 4 for RGBW strips
|
|
|
|
#### Returns
|
|
`ws2812.buffer`
|
|
|
|
## ws2812.buffer:get()
|
|
Return the value at the given position
|
|
|
|
#### Syntax
|
|
`buffer:get(index)`
|
|
|
|
#### Parameters
|
|
- `index` position in the buffer (1 for first led)
|
|
|
|
#### Returns
|
|
`(color)`
|
|
|
|
#### Example
|
|
```lua
|
|
buffer = ws2812.newBuffer(32, 4)
|
|
print(buffer:get(1))
|
|
0 0 0 0
|
|
```
|
|
|
|
## ws2812.buffer:set()
|
|
Set the value at the given position
|
|
|
|
#### Syntax
|
|
`buffer:set(index, color)`
|
|
|
|
#### Parameters
|
|
- `index` position in the buffer (1 for the first led)
|
|
- `color` payload of the color
|
|
|
|
Payload could be:
|
|
- `number, number, ...` you should pass as many arguments as `bytesPerLed`
|
|
- `table` should contains `bytesPerLed` numbers
|
|
- `string` should contains `bytesPerLed` bytes
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
buffer = ws2812.newBuffer(32, 3)
|
|
buffer:set(1, 255, 0, 0) -- set the first led green for a RGB strip
|
|
```
|
|
|
|
```lua
|
|
buffer = ws2812.newBuffer(32, 4)
|
|
buffer:set(1, {0, 0, 0, 255}) -- set the first led white for a RGBW strip
|
|
```
|
|
|
|
```lua
|
|
buffer = ws2812.newBuffer(32, 3)
|
|
buffer:set(1, string.char(255, 0, 0)) -- set the first led green for a RGB strip
|
|
```
|
|
|
|
## ws2812.buffer:size()
|
|
Return the size of the buffer in number of leds
|
|
|
|
#### Syntax
|
|
`buffer:size()`
|
|
|
|
#### Parameters
|
|
none
|
|
|
|
#### Returns
|
|
`int`
|
|
|
|
## ws2812.buffer:fill()
|
|
Fill the buffer with the given color.
|
|
The number of given bytes must match the number of bytesPerLed of the buffer
|
|
|
|
#### Syntax
|
|
`buffer:fill(color)`
|
|
|
|
#### Parameters
|
|
- `color` bytes of the color, you should pass as many arguments as `bytesPerLed`
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
buffer:fill(0, 0, 0) -- fill the buffer with black for a RGB strip
|
|
```
|
|
|
|
## ws2812.buffer:dump()
|
|
Returns the contents of the buffer (the pixel values) as a string. This can then be saved to a file or sent over a network.
|
|
|
|
#### Syntax
|
|
`buffer:dump()`
|
|
|
|
#### Returns
|
|
A string containing the pixel values.
|
|
|
|
#### Example
|
|
```lua
|
|
local s = buffer:dump()
|
|
```
|
|
|
|
## ws2812.buffer:replace()
|
|
Inserts a string (or a buffer) into another buffer with an offset.
|
|
The buffer must have the same number of colors per led or an error will be thrown.
|
|
|
|
#### Syntax
|
|
`buffer:replace(source[, offset])`
|
|
|
|
#### Parameters
|
|
- `source` the pixel values to be set into the buffer. This is either a string or a buffer.
|
|
- `offset` the offset where the source is to be placed in the buffer. Default is 1. Negative values can be used.
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
buffer:replace(anotherbuffer:dump()) -- copy one buffer into another via a string
|
|
buffer:replace(anotherbuffer) -- copy one buffer into another
|
|
newbuffer = buffer.sub(1) -- make a copy of a buffer into a new buffer
|
|
```
|
|
|
|
## ws2812.buffer:mix()
|
|
This is a general method that loads data into a buffer that is a linear combination of data from other buffers. It can be used to copy a buffer or,
|
|
more usefully, do a cross fade. The pixel values are computed as integers and then range limited to [0, 255]. This means that negative
|
|
factors work as expected, and that the order of combining buffers does not matter.
|
|
|
|
#### Syntax
|
|
`buffer:mix(factor1, buffer1, ...)`
|
|
|
|
#### Parameters
|
|
- `factor1` This is the factor that the contents of `buffer1` are multiplied by. This factor is scaled by a factor of 256. Thus `factor1` value of 256 is a factor of 1.0.
|
|
- `buffer1` This is the source buffer. It must be of the same shape as the destination buffer.
|
|
|
|
There can be any number of factor/buffer pairs.
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
-- loads buffer with a crossfade between buffer1 and buffer2
|
|
buffer:mix(256 - crossmix, buffer1, crossmix, buffer2)
|
|
|
|
-- multiplies all values in buffer by 0.75
|
|
-- This can be used in place of buffer:fade
|
|
buffer:mix(192, buffer)
|
|
```
|
|
|
|
## ws2812.buffer:power()
|
|
Computes the total energy requirement for the buffer. This is merely the total sum of all the pixel values (which assumes that each color in each
|
|
pixel consumes the same amount of power). A real WS2812 (or WS2811) has three constant current drivers of 20mA -- one for each of R, G and B. The
|
|
pulse width modulation will cause the *average* current to scale linearly with pixel value.
|
|
|
|
#### Syntax
|
|
`buffer:power()`
|
|
|
|
#### Returns
|
|
An integer which is the sum of all the pixel values.
|
|
|
|
#### Example
|
|
```lua
|
|
-- Dim the buffer to no more than the PSU can provide
|
|
local psu_current_ma = 1000
|
|
local led_current_ma = 20
|
|
local led_sum = psu_current_ma * 255 / led_current_ma
|
|
|
|
local p = buffer:power()
|
|
if p > led_sum then
|
|
buffer:mix(256 * led_sum / p, buffer) -- power is now limited
|
|
end
|
|
```
|
|
|
|
## ws2812.buffer:fade()
|
|
Fade in or out. Defaults to out. Multiply or divide each byte of each led with/by the given value. Useful for a fading effect.
|
|
|
|
#### Syntax
|
|
`buffer:fade(value [, direction])`
|
|
|
|
#### Parameters
|
|
- `value` value by which to divide or multiply each byte
|
|
- `direction` ws2812.FADE\_IN or ws2812.FADE\_OUT. Defaults to ws2812.FADE\_OUT
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
buffer:fade(2)
|
|
buffer:fade(2, ws2812.FADE_IN)
|
|
```
|
|
## ws2812.buffer:shift()
|
|
Shift the content of (a piece of) the buffer in positive or negative direction. This allows simple animation effects. A slice of the buffer can be specified by using the
|
|
standard start and end offset Lua notation. Negative values count backwards from the end of the buffer.
|
|
|
|
#### Syntax
|
|
`buffer:shift(value [, mode[, i[, j]]])`
|
|
|
|
#### Parameters
|
|
- `value` number of pixels by which to rotate the buffer. Positive values rotate forwards, negative values backwards.
|
|
- `mode` is the shift mode to use. Can be one of `ws2812.SHIFT_LOGICAL` or `ws2812.SHIFT_CIRCULAR`. In case of SHIFT\_LOGICAL, the freed pixels are set to 0 (off). In case of SHIFT\_CIRCULAR, the buffer is treated like a ring buffer, inserting the pixels falling out on one end again on the other end. Defaults to SHIFT\_LOGICAL.
|
|
- `i` is the first offset in the buffer to be affected. Negative values are permitted and count backwards from the end. Default is 1.
|
|
- `j` is the last offset in the buffer to be affected. Negative values are permitted and count backwards from the end. Default is -1.
|
|
|
|
#### Returns
|
|
`nil`
|
|
|
|
#### Example
|
|
```lua
|
|
buffer:shift(3)
|
|
```
|
|
|
|
## ws2812.buffer:sub()
|
|
This implements the extraction function like `string.sub`. The indexes are in leds and all the same rules apply.
|
|
|
|
#### Syntax
|
|
`buffer1:sub(i[, j])`
|
|
|
|
#### Parameters
|
|
- `i` This is the start of the extracted data. Negative values can be used.
|
|
- `j` this is the end of the extracted data. Negative values can be used. The default is -1.
|
|
|
|
#### Returns
|
|
A buffer containing the extracted piece.
|
|
|
|
#### Example
|
|
```
|
|
b = buffer:sub(1,10)
|
|
```
|
|
|
|
## ws2812.buffer:__concat()
|
|
This implements the `..` operator to concatenate two buffers. They must have the same number of colors per led.
|
|
|
|
#### Syntax
|
|
`buffer1 .. buffer2`
|
|
|
|
#### Parameters
|
|
- `buffer1` this is the start of the resulting buffer
|
|
- `buffer2` this is the end of the resulting buffer
|
|
|
|
#### Returns
|
|
The concatenated buffer.
|
|
|
|
#### Example
|
|
```
|
|
ws2812.write({pin = 4, data = buffer1 .. buffer2})
|
|
```
|