# WS2812 Module
| Since  | Origin / Contributor  | Maintainer  | Source  |
| :----- | :-------------------- | :---------- | :------ |
| 2015-02-05 | [Till Klocke](https://github.com/dereulenspiegel), [Thomas Soëte](https://github.com/Alkorin) | [Till Klocke](https://github.com/dereulenspiegel) | [ws2812.c](../../app/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).

The library uses UART1 routed on GPIO2 (Pin D4 on NodeMCU DEVKIT) to
generate the bitstream. It can use UART0 routed to TXD0 as well to
handle two led strips at the same time.

**WARNING**: In dual mode, you will loose access to the Lua's console
through the serial port (it will be reconfigured to support WS2812-like
protocol). If you want to keep access to Lua's console, you will have to
use an other input channel like a TCP server (see [example](https://github.com/nodemcu/nodemcu-firmware/blob/release/lua_modules/telnet/telnet.lua))

!!! caution

    This module has an _optional_ dependency to the [pixbuf module](pixbuf.md) i.e. it can work without. However, if you compile the firmware without pixbuf the respective features will be missing from this module.

## ws2812.init()
Initialize UART1 and GPIO2, should be called once and before write().
Initialize UART0 (TXD0) too if `ws2812.MODE_DUAL` is set.

#### Syntax
`ws2812.init([mode])`

#### Parameters
- `mode` (optional) either `ws2812.MODE_SINGLE` (default if omitted) or `ws2812.MODE_DUAL`

In `ws2812.MODE_DUAL` mode you will be able to handle two strips in parallel but will lose access to Lua's serial console as it shares the same UART and PIN.

#### Returns
`nil`

## ws2812.write()
Send data to one or two led strip using its native format, which is generally
Green, Red, Blue for RGB strips and Green, Red, Blue, White for RGBW strips.
(However, ws2812 drivers have been observed wired up in other orders.)

Because this function uses the hardware UART(s), it is able to return and allow
Lua to resume execution up to 300 microseconds before the data has finished
being sent.  If you wish to perform actions synchronous with the end of the
data transmission, [`tmr.delay()`](../tmr#tmr.delay()) for 300 microseconds.

Separately, because this function returns early, back-to-back invocations may
not leave enough time for the strip to latch, and so may appear to the ws2812
drivers to be simply writes to a longer LED strip.  Please ensure that you have
more than 350 microseconds between the return of `ws2812.write()` to your Lua
and the next invocation thereof.

#### Syntax
`ws2812.write(data1, [data2])`

#### Parameters
- `data1` payload to be sent to one or more WS2812 like leds through GPIO2
- `data2` (optional) payload to be sent to one or more WS2812 like leds through TXD0 (`ws2812.MODE_DUAL` mode required)

Payload type could be:

- `nil` nothing is done
- `string` representing bytes to send
- a [pixbuf](pixbuf) object containing the bytes to send.  The pixbuf's type is not checked!

#### Returns
`nil`

#### Example
```lua
ws2812.init()
ws2812.write(string.char(255, 0, 0, 255, 0, 0)) -- turn the two first RGB leds to green
```

```lua
ws2812.init()
ws2812.write(string.char(0, 0, 0, 255, 0, 0, 0, 255)) -- turn the two first RGBW leds to white
```

```lua
ws2812.init(ws2812.MODE_DUAL)
ws2812.write(string.char(255, 0, 0, 255, 0, 0), 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.init(ws2812.MODE_DUAL)
ws2812.write(nil, string.char(0, 255, 0, 0, 255, 0)) -- turn the two first RGB leds to red on the second strip, do nothing on the first
```

# Pixbuf support
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 [pixbuf](pixbuf) library offers a read/write buffer and
convenient functions for pixel value manipulation.

For backwards-compatibility, `pixbuf.newBuffer()` is aliased as
`ws2812.newBuffer()`, but this will be removed in the next nodemcu-firmware
release.

#### Example
Led chaser with a RGBW strip

```lua
ws2812.init()

i, buffer = 0, pixbuf.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(buffer)
end)
```
