ws2812 effects library (#2215)

* ws2812 effects and color utils modules added

* Added documentation for new modules to mkdocs.yml

* changed mode option to string, documentation, default modules fixed

* updated user_modules.h
This commit is contained in:
Konrad Hübner 2018-01-23 21:05:04 +01:00 committed by Arnim Läuger
parent 316a5fc566
commit ed56d949ee
9 changed files with 1675 additions and 31 deletions

View File

@ -28,6 +28,7 @@
//#define LUA_USE_MODULES_BME280 //#define LUA_USE_MODULES_BME280
//#define LUA_USE_MODULES_BME680 //#define LUA_USE_MODULES_BME680
//#define LUA_USE_MODULES_COAP //#define LUA_USE_MODULES_COAP
//#define LUA_USE_MODULES_COLOR_UTILS
//#define LUA_USE_MODULES_CRON //#define LUA_USE_MODULES_CRON
//#define LUA_USE_MODULES_CRYPTO //#define LUA_USE_MODULES_CRYPTO
#define LUA_USE_MODULES_DHT #define LUA_USE_MODULES_DHT
@ -82,6 +83,7 @@
//#define LUA_USE_MODULES_WPS //#define LUA_USE_MODULES_WPS
//#define LUA_USE_MODULES_WS2801 //#define LUA_USE_MODULES_WS2801
//#define LUA_USE_MODULES_WS2812 //#define LUA_USE_MODULES_WS2812
//#define LUA_USE_MODULES_WS2812_EFFECTS
//#define LUA_USE_MODULES_XPT2046 //#define LUA_USE_MODULES_XPT2046
#endif /* LUA_CROSS_COMPILER */ #endif /* LUA_CROSS_COMPILER */

246
app/modules/color_utils.c Normal file
View File

@ -0,0 +1,246 @@
#include "module.h"
#include "lauxlib.h"
#include "lmem.h"
#include "platform.h"
#include "c_stdlib.h"
#include "c_math.h"
#include "c_string.h"
#include "user_interface.h"
#include "osapi.h"
#include "color_utils.h"
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
#define abs(a) ((a) > 0 ? (a) : (0-a))
#define min3(a,b, c) min((a), min((b), (c)))
#define max3(a,b, c) max((a), max((b), (c)))
#define CANARY_VALUE 0x37383132
// convert hsv to grb value
uint32_t hsv2grb(uint16_t hue, uint8_t sat, uint8_t val)
{
uint16_t H_accent = (hue % 360) / 60;
uint16_t bottom = ((255 - sat) * val)>>8;
uint16_t top = val;
uint8_t rising = ((top-bottom) *(hue%60 ) ) / 60 + bottom;
uint8_t falling = ((top-bottom) *(60-hue%60) ) / 60 + bottom;
uint8_t r;
uint8_t g;
uint8_t b;
switch(H_accent) {
case 0:
r = top;
g = rising;
b = bottom;
break;
case 1:
r = falling;
g = top;
b = bottom;
break;
case 2:
r = bottom;
g = top;
b = rising;
break;
case 3:
r = bottom;
g = falling;
b = top;
break;
case 4:
r = rising;
g = bottom;
b = top;
break;
case 5:
r = top;
g = bottom;
b = falling;
break;
}
uint32_t result = (g << 16) | (r << 8) | b;
return result;
}
// convert hsv to grbw value
uint32_t hsv2grbw(uint16_t hue, uint8_t sat, uint8_t val) {
uint32_t grb = hsv2grb(hue, sat, val);
uint8_t g = ((grb & 0x00FF0000) >> 16);
uint8_t r = ((grb & 0x0000FF00) >> 8);
uint8_t b = (grb & 0x000000FF);
// calculate white component
uint8_t w = min3(g, r, b);
g = g - w;
r = r - w;
b = b - w;
uint32_t grbw = (g << 24) | (r << 16) | (b << 8) | w;
return grbw;
}
// convert grb to hsv value
uint32_t grb2hsv(uint8_t g, uint8_t r, uint8_t b) {
uint8_t m = min3(r, g, b);
uint8_t M = max3(r, g, b);
uint8_t delta = M - m;
int hue = 0;
int saturation = 0;
int value = 0;
if(delta == 0) {
/* Achromatic case (i.e. grayscale) */
hue = -1; /* undefined */
saturation = 0;
} else {
int h;
if(r == M)
h = ((g-b)*60) / delta;
else if(g == M)
h = ((b-r)*60) / delta + 120;
else /*if(b == M)*/
h = ((r-g)*60) / delta + 240;
if(h < 0)
h += 360;
hue = h;
/* The constatnt 8 is tuned to statistically cause as little
* tolerated mismatches as possible in RGB -> HSV -> RGB conversion.
* (See the unit test at the bottom of this file.)
*/
saturation = (256*delta-8) / M;
}
value = M;
uint32_t result = (hue << 16) | (saturation << 8) | value;
return result;
}
/*
* Put a value 0 to 360 in to get a color value.
* The colours are a transition r -> g -> b -> back to r
* Inspired by the Adafruit examples.
*/
uint32_t color_wheel(uint16_t pos) {
return hsv2grb(pos, 255, 255);
}
// convert hsv to grb value
static int cu_hsv2grb(lua_State *L) {
const int hue = luaL_checkint(L, 1);
const int sat = luaL_checkint(L, 2);
const int val = luaL_checkint(L, 3);
luaL_argcheck(L, hue >= 0 && hue <= 360, 1, "should be a 0-360");
luaL_argcheck(L, sat >= 0 && sat <= 255, 2, "should be 0-255");
luaL_argcheck(L, val >= 0 && val <= 255, 3, "should be 0-255");
// convert to grb
uint32_t tmp_color = hsv2grb(hue, sat, val);
// return
lua_pushnumber(L, (tmp_color & 0x00FF0000) >> 16);
lua_pushnumber(L, (tmp_color & 0x0000FF00) >> 8);
lua_pushnumber(L, (tmp_color & 0x000000FF));
return 3;
}
// convert hsv to grbw value
static int cu_hsv2grbw(lua_State *L) {
const int hue = luaL_checkint(L, 1);
const int sat = luaL_checkint(L, 2);
const int val = luaL_checkint(L, 3);
luaL_argcheck(L, hue >= 0 && hue <= 360, 1, "should be a 0-360");
luaL_argcheck(L, sat >= 0 && sat <= 255, 2, "should be 0-255");
luaL_argcheck(L, val >= 0 && val <= 255, 3, "should be 0-255");
// convert to grbw
uint32_t tmp_color = hsv2grbw(hue, sat, val);
// return g, r, b, w
lua_pushnumber(L, (tmp_color & 0xFF000000) >> 24);
lua_pushnumber(L, (tmp_color & 0x00FF0000) >> 16);
lua_pushnumber(L, (tmp_color & 0x0000FF00) >> 8);
lua_pushnumber(L, (tmp_color & 0x000000FF));
return 4;
}
// create a color wheel value
static int cu_color_wheel(lua_State *L) {
const int wheel_index = luaL_checkint(L, 1);
luaL_argcheck(L, wheel_index >= 0 && wheel_index <= 360, 1, "should be a 0-360");
uint32_t color = color_wheel(wheel_index);
uint8_t r = (color & 0x00FF0000) >> 16;
uint8_t g = (color & 0x0000FF00) >> 8;
uint8_t b = (color & 0x000000FF) >> 0;
// return
lua_pushnumber(L, g);
lua_pushnumber(L, r);
lua_pushnumber(L, b);
return 3;
}
// convert grb values to hsv
static int cu_grb2hsv(lua_State *L) {
const int g = luaL_checkint(L, 1);
const int r = luaL_checkint(L, 2);
const int b = luaL_checkint(L, 3);
luaL_argcheck(L, g == r && g == b, 1, "greyscale value cannot be converted to hsv");
uint32_t hsv = grb2hsv(g, r, b);
uint16_t h = (hsv & 0xFFFF0000) >> 16;
uint8_t s = (hsv & 0x0000FF00) >> 8;
uint8_t v = (hsv & 0x000000FF) >> 0;
// return
lua_pushnumber(L, h);
lua_pushnumber(L, s);
lua_pushnumber(L, v);
return 3;
}
static const LUA_REG_TYPE color_utils_map[] =
{
{ LSTRKEY( "hsv2grb" ), LFUNCVAL( cu_hsv2grb )},
{ LSTRKEY( "hsv2grbw" ), LFUNCVAL( cu_hsv2grbw )},
{ LSTRKEY( "colorWheel" ), LFUNCVAL( cu_color_wheel )},
{ LSTRKEY( "grb2hsv" ), LFUNCVAL( cu_grb2hsv )},
{ LNILKEY, LNILVAL}
};
NODEMCU_MODULE(COLOR_UTILS, "color_utils", color_utils_map, NULL);

39
app/modules/color_utils.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef APP_MODULES_COLOR_UTILS_H_
#define APP_MODULES_COLOR_UTILS_H_
#include "module.h"
#include "lauxlib.h"
#include "lmem.h"
#include "platform.h"
#include "c_stdlib.h"
#include "c_math.h"
#include "c_string.h"
#include "user_interface.h"
#include "osapi.h"
/**
* Convert hsv to grb
* hue is 0-360, sat and val are 0-255
*/
uint32_t hsv2grb(uint16_t hue, uint8_t sat, uint8_t val);
/**
* Convert hsv to grbw
* hue is 0-360, sat and val are 0-255
*/
uint32_t hsv2grbw(uint16_t hue, uint8_t sat, uint8_t val);
/**
* Convert grb to hsv
* g, r, b are 0-255
*/
uint32_t grb2hsv(uint8_t g, uint8_t r, uint8_t b);
/**
* The color wheel function provides colors from r -> g -> b -> r.
* They are fully saturated and with full brightness.
* degree is from 0-360
*/
uint32_t color_wheel(uint16_t degree);
#endif /* APP_MODULES_COLOR_UTILS_H_ */

View File

@ -3,26 +3,22 @@
#include "lmem.h" #include "lmem.h"
#include "platform.h" #include "platform.h"
#include "c_stdlib.h" #include "c_stdlib.h"
#include "c_math.h"
#include "c_string.h" #include "c_string.h"
#include "user_interface.h" #include "user_interface.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "osapi.h" #include "osapi.h"
#include "ws2812.h"
#define CANARY_VALUE 0x32383132 #define CANARY_VALUE 0x32383132
#define MODE_SINGLE 0 #define MODE_SINGLE 0
#define MODE_DUAL 1 #define MODE_DUAL 1
#define FADE_IN 1
#define FADE_OUT 0
#define SHIFT_LOGICAL 0
#define SHIFT_CIRCULAR 1
typedef struct {
int size;
uint8_t colorsPerLed;
uint8_t values[0];
} ws2812_buffer;
// Init UART1 to be able to stream WS2812 data to GPIO2 pin // Init UART1 to be able to stream WS2812 data to GPIO2 pin
// If DUAL mode is selected, init UART0 to stream to TXD0 as well // If DUAL mode is selected, init UART0 to stream to TXD0 as well
@ -65,7 +61,7 @@ static int ws2812_init(lua_State* L) {
// ws2812.init() should be called first // ws2812.init() should be called first
// //
// NODE_DEBUG should not be activated because it also uses UART1 // NODE_DEBUG should not be activated because it also uses UART1
static void ICACHE_RAM_ATTR ws2812_write_data(const uint8_t *pixels, uint32_t length, const uint8_t *pixels2, uint32_t length2) { void ICACHE_RAM_ATTR ws2812_write_data(const uint8_t *pixels, uint32_t length, const uint8_t *pixels2, uint32_t length2) {
// Data are sent LSB first, with a start bit at 0, an end bit at 1 and all inverted // Data are sent LSB first, with a start bit at 0, an end bit at 1 and all inverted
// 0b00110111 => 110111 => [0]111011[1] => 10001000 => 00 // 0b00110111 => 110111 => [0]111011[1] => 10001000 => 00
@ -194,6 +190,7 @@ static ws2812_buffer *allocate_buffer(lua_State *L, int leds, int colorsPerLed)
return buffer; return buffer;
} }
// Handle a buffer where we can store led values // Handle a buffer where we can store led values
static int ws2812_new_buffer(lua_State *L) { static int ws2812_new_buffer(lua_State *L) {
const int leds = luaL_checkint(L, 1); const int leds = luaL_checkint(L, 1);
@ -209,17 +206,11 @@ static int ws2812_new_buffer(lua_State *L) {
return 1; return 1;
} }
static int ws2812_buffer_fill(lua_State* L) {
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer"); int ws2812_buffer_fill(ws2812_buffer * buffer, int * colors) {
// Grab colors // Grab colors
int i, j; int i, j;
int * colors = luaM_malloc(L, buffer->colorsPerLed * sizeof(int));
for (i = 0; i < buffer->colorsPerLed; i++)
{
colors[i] = luaL_checkinteger(L, 2+i);
}
// Fill buffer // Fill buffer
uint8_t * p = &buffer->values[0]; uint8_t * p = &buffer->values[0];
@ -231,6 +222,23 @@ static int ws2812_buffer_fill(lua_State* L) {
} }
} }
return 0;
}
static int ws2812_buffer_fill_lua(lua_State* L) {
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer");
// Grab colors
int i;
int * colors = luaM_malloc(L, buffer->colorsPerLed * sizeof(int));
for (i = 0; i < buffer->colorsPerLed; i++)
{
colors[i] = luaL_checkinteger(L, 2+i);
}
ws2812_buffer_fill(buffer, colors);
// Free memory // Free memory
luaM_free(L, colors); luaM_free(L, colors);
@ -266,13 +274,10 @@ static int ws2812_buffer_fade(lua_State* L) {
} }
static int ws2812_buffer_shift(lua_State* L) { int ws2812_buffer_shift(ws2812_buffer * buffer, int shiftValue, unsigned shift_type, int pos_start, int pos_end) {
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer");
const int shiftValue = luaL_checkinteger(L, 2);
const unsigned shift_type = luaL_optinteger( L, 3, SHIFT_LOGICAL );
ptrdiff_t start = posrelat(luaL_optinteger(L, 4, 1), buffer->size); ptrdiff_t start = posrelat(pos_start, buffer->size);
ptrdiff_t end = posrelat(luaL_optinteger(L, 5, -1), buffer->size); ptrdiff_t end = posrelat(pos_end, buffer->size);
if (start < 1) start = 1; if (start < 1) start = 1;
if (end > (ptrdiff_t)buffer->size) end = (ptrdiff_t)buffer->size; if (end > (ptrdiff_t)buffer->size) end = (ptrdiff_t)buffer->size;
@ -280,7 +285,7 @@ static int ws2812_buffer_shift(lua_State* L) {
int size = end - start; int size = end - start;
size_t offset = start * buffer->colorsPerLed; size_t offset = start * buffer->colorsPerLed;
luaL_argcheck(L, shiftValue > 0-size && shiftValue < size, 2, "shifting more elements than buffer size"); //luaL_argcheck(L, shiftValue > 0-size && shiftValue < size, 2, "shifting more elements than buffer size");
int shift = shiftValue >= 0 ? shiftValue : -shiftValue; int shift = shiftValue >= 0 ? shiftValue : -shiftValue;
@ -290,7 +295,7 @@ static int ws2812_buffer_shift(lua_State* L) {
return 0; return 0;
} }
uint8_t * tmp_pixels = luaM_malloc(L, buffer->colorsPerLed * sizeof(uint8_t) * shift); uint8_t * tmp_pixels = c_malloc(buffer->colorsPerLed * sizeof(uint8_t) * shift);
int i,j; int i,j;
size_t shift_len, remaining_len; size_t shift_len, remaining_len;
// calculate length of shift section and remaining section // calculate length of shift section and remaining section
@ -330,11 +335,27 @@ static int ws2812_buffer_shift(lua_State* L) {
} }
} }
// Free memory // Free memory
luaM_free(L, tmp_pixels); c_free(tmp_pixels);
return 0; return 0;
} }
static int ws2812_buffer_shift_lua(lua_State* L) {
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer");
const int shiftValue = luaL_checkinteger(L, 2);
const unsigned shift_type = luaL_optinteger( L, 3, SHIFT_LOGICAL );
const int pos_start = luaL_optinteger(L, 4, 1);
const int pos_end = luaL_optinteger(L, 5, -1);
ws2812_buffer_shift(buffer, shiftValue, shift_type, pos_start, pos_end);
return 0;
}
static int ws2812_buffer_dump(lua_State* L) { static int ws2812_buffer_dump(lua_State* L) {
ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer"); ws2812_buffer * buffer = (ws2812_buffer*)luaL_checkudata(L, 1, "ws2812.buffer");
@ -392,7 +413,7 @@ static int ws2812_buffer_mix(lua_State* L) {
ws2812_buffer *src_buffer = (ws2812_buffer*) luaL_checkudata(L, pos + 1, "ws2812.buffer"); ws2812_buffer *src_buffer = (ws2812_buffer*) luaL_checkudata(L, pos + 1, "ws2812.buffer");
luaL_argcheck(L, src_buffer->size == buffer->size && src_buffer->colorsPerLed == buffer->colorsPerLed, pos + 1, "Buffer not same shape"); luaL_argcheck(L, src_buffer->size == buffer->size && src_buffer->colorsPerLed == buffer->colorsPerLed, pos + 1, "Buffer not same shape");
source[src].factor = factor; source[src].factor = factor;
source[src].values = src_buffer->values; source[src].values = src_buffer->values;
} }
@ -528,7 +549,7 @@ static int ws2812_buffer_concat(lua_State* L) {
int colorsPerLed = lhs->colorsPerLed; int colorsPerLed = lhs->colorsPerLed;
int leds = lhs->size + rhs->size; int leds = lhs->size + rhs->size;
ws2812_buffer * buffer = allocate_buffer(L, leds, colorsPerLed); ws2812_buffer * buffer = allocate_buffer(L, leds, colorsPerLed);
c_memcpy(buffer->values, lhs->values, lhs->colorsPerLed * lhs->size); c_memcpy(buffer->values, lhs->values, lhs->colorsPerLed * lhs->size);
@ -569,17 +590,18 @@ static int ws2812_buffer_tostring(lua_State* L) {
return 1; return 1;
} }
static const LUA_REG_TYPE ws2812_buffer_map[] = static const LUA_REG_TYPE ws2812_buffer_map[] =
{ {
{ LSTRKEY( "dump" ), LFUNCVAL( ws2812_buffer_dump )}, { LSTRKEY( "dump" ), LFUNCVAL( ws2812_buffer_dump )},
{ LSTRKEY( "fade" ), LFUNCVAL( ws2812_buffer_fade )}, { LSTRKEY( "fade" ), LFUNCVAL( ws2812_buffer_fade )},
{ LSTRKEY( "fill" ), LFUNCVAL( ws2812_buffer_fill )}, { LSTRKEY( "fill" ), LFUNCVAL( ws2812_buffer_fill_lua )},
{ LSTRKEY( "get" ), LFUNCVAL( ws2812_buffer_get )}, { LSTRKEY( "get" ), LFUNCVAL( ws2812_buffer_get )},
{ LSTRKEY( "replace" ), LFUNCVAL( ws2812_buffer_replace )}, { LSTRKEY( "replace" ), LFUNCVAL( ws2812_buffer_replace )},
{ LSTRKEY( "mix" ), LFUNCVAL( ws2812_buffer_mix )}, { LSTRKEY( "mix" ), LFUNCVAL( ws2812_buffer_mix )},
{ LSTRKEY( "power" ), LFUNCVAL( ws2812_buffer_power )}, { LSTRKEY( "power" ), LFUNCVAL( ws2812_buffer_power )},
{ LSTRKEY( "set" ), LFUNCVAL( ws2812_buffer_set )}, { LSTRKEY( "set" ), LFUNCVAL( ws2812_buffer_set )},
{ LSTRKEY( "shift" ), LFUNCVAL( ws2812_buffer_shift )}, { LSTRKEY( "shift" ), LFUNCVAL( ws2812_buffer_shift_lua )},
{ LSTRKEY( "size" ), LFUNCVAL( ws2812_buffer_size )}, { LSTRKEY( "size" ), LFUNCVAL( ws2812_buffer_size )},
{ LSTRKEY( "sub" ), LFUNCVAL( ws2812_buffer_sub )}, { LSTRKEY( "sub" ), LFUNCVAL( ws2812_buffer_sub )},
{ LSTRKEY( "__concat" ),LFUNCVAL( ws2812_buffer_concat )}, { LSTRKEY( "__concat" ),LFUNCVAL( ws2812_buffer_concat )},
@ -588,6 +610,7 @@ static const LUA_REG_TYPE ws2812_buffer_map[] =
{ LNILKEY, LNILVAL} { LNILKEY, LNILVAL}
}; };
static const LUA_REG_TYPE ws2812_map[] = static const LUA_REG_TYPE ws2812_map[] =
{ {
{ LSTRKEY( "init" ), LFUNCVAL( ws2812_init )}, { LSTRKEY( "init" ), LFUNCVAL( ws2812_init )},

32
app/modules/ws2812.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef APP_MODULES_WS2812_H_
#define APP_MODULES_WS2812_H_
#include "module.h"
#include "lauxlib.h"
#include "lmem.h"
#include "platform.h"
#include "c_stdlib.h"
#include "c_math.h"
#include "c_string.h"
#include "user_interface.h"
#include "driver/uart.h"
#include "osapi.h"
#define FADE_IN 1
#define FADE_OUT 0
#define SHIFT_LOGICAL 0
#define SHIFT_CIRCULAR 1
typedef struct {
int size;
uint8_t colorsPerLed;
uint8_t values[0];
} ws2812_buffer;
void ICACHE_RAM_ATTR ws2812_write_data(const uint8_t *pixels, uint32_t length, const uint8_t *pixels2, uint32_t length2);
int ws2812_buffer_shift(ws2812_buffer * buffer, int shiftValue, unsigned shift_type, int pos_start, int pos_end);
int ws2812_buffer_fill(ws2812_buffer * buffer, int * colors);
#endif /* APP_MODULES_WS2812_H_ */

1060
app/modules/ws2812_effects.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,61 @@
# COLOR_UTILS Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2017-12-30 | [Konrad Huebner](https://github.com/skycoders) | [Konrad Huebner](https://github.com/skycoders) | [color_utils.c](../../../app/modules/color_utils.c)|
The color_utils module provides some basic color transformations useful for color LEDs. It is used by the WS2812_EFFECTS module.
## color_utils.hsv2grb()
Convert HSV color to GRB color.
#### Syntax
`color_utils.hsv2grb(hue, saturation, value)`
#### Parameters
- `hue` is the hue value, between 0 and 360.
- `saturation` is the saturation value, between 0 and 255.
- `value` is the value value, between 0 and 255.
#### Returns
`green`, `red`, `blue` as values between 0 and 255
## color\_utils.hsv2grbw()
Convert HSV color to GRB color and explicitly return a white value. This can be useful for RGB+W LED strips. The white value is simply calculated as min(g, r, b) and then removed from the colors. This does NOT take into account if the white chip used later creates an appropriate color.
#### Syntax
`color_utils.hsv2grbw(hue, saturation, value)`
#### Parameters
- `hue` is the hue value, between 0 and 360.
- `saturation` is the saturation value, between 0 and 255.
- `value` is the value value, between 0 and 255.
#### Returns
`green`, `red`, `blue`, `white` as values between 0 and 255
## color\_utils.grb2hsv()
Convert GRB color to HSV color.
#### Syntax
`color_utils.grb2hsv(green, red, blue)`
#### Parameters
- `green` is the green value, between 0 and 255.
- `red` is the red value, between 0 and 255.
- `blue` is the blue value, between 0 and 255.
#### Returns
`hue`, `saturation`, `value` as values between 0 and 360, respective 0 and 255
## color\_utils.colorWheel()
The color wheel function makes use of the HSV color space and calculates colors based on the color circle. The colors are created with full saturation and value. This function is a convenience function of the hsv2grb function and can be used to create rainbow colors.
#### Syntax
`color_utils.colorWheel(angle)`
#### Parameters
- `angle` is the angle on the color circle, between 0 and 359
#### Returns
`green`, `red`, `blue` as values between 0 and 255.

View File

@ -0,0 +1,179 @@
# WS2812_EFFECTS Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2017-11-01 | [Konrad Huebner](https://github.com/skycoders) | [ws2812_effects.c](../../../app/modules/ws2812_effects.c)|
The ws2812_effects module provides effects based on the ws2812 library. Some effects are inspired by / based on the [WS2812FX Library](https://github.com/kitesurfer1404/WS2812FX) but have been adopted to the specifics of the ws2812 library. The effects library works based on a buffer created through the ws2812 library and performs the operations on this buffer.
ATTENTION: Dual mode is currently not supported for effects.
#### Example usage
```lua
-- init the ws2812 module
ws2812.init(ws2812.MODE_SINGLE)
-- create a buffer, 60 LEDs with 3 color bytes
strip_buffer = ws2812.newBuffer(60, 3)
-- init the effects module, set color to red and start blinking
ws2812_effects.init(strip_buffer)
ws2812_effects.set_speed(100)
ws2812_effects.set_brightness(50)
ws2812_effects.set_color(0,255,0)
ws2812_effects.set_mode("blink")
ws2812_effects.start()
```
## ws2812_effects.init()
Initialize the effects library with the provided buffer for the connected LED strip.
#### Syntax
`ws2812_effects.init(buffer)`
#### Parameters
- `buffer` is a `ws2812.buffer` for the connected strip.
#### Returns
`nil`
## ws2812_effects.start()
Start the animation effect.
#### Syntax
`ws2812_effects.start()`
#### Parameters
`none`
#### Returns
`nil`
## ws2812_effects.stop()
Stop the animation effect.
#### Syntax
`ws2812_effects.stop()`
#### Parameters
`none`
#### Returns
`nil`
## ws2812_effects.set_brightness()
Set the brightness
#### Syntax
`ws2812_effects.set_brightness(brightness)`
#### Parameters
- `brightness` brightness between 0 and 255
#### Returns
`nil`
## ws2812_effects.set_color()
Set the color
#### Syntax
`ws2812_effects.set_color(g, r, b, [w])`
#### Parameters
- `g` is the green value between 0 and 255
- `r` is the red value between 0 and 255
- `b` is the blue value between 0 and 255
- `w` (optional) is the white value between 0 and 255
#### Returns
`nil`
## ws2812_effects.set_speed()
Set the speed
#### Syntax
`ws2812_effects.set_speed(speed)`
#### Parameters
- `speed` speed between 0 and 255
#### Returns
`nil`
## ws2812_effects.get_speed()
Get current speed
#### Syntax
`ws2812_effects.get_speed()`
#### Parameters
`none`
#### Returns
`speed` between 0 and 255
## ws2812_effects.set_delay()
Set the delay between two effect steps in milliseconds.
#### Syntax
`ws2812_effects.set_delay(delay)`
#### Parameters
- `delay` is the delay in milliseconds, minimum 10ms
#### Returns
`nil`
## ws2812_effects.get_delay()
Get current delay
#### Syntax
`ws2812_effects.get_delay()`
#### Parameters
`none`
#### Returns
`delay` is the current effect delay in milliseconds
## ws2812_effects.set_mode()
Set the active effect mode.
#### Syntax
`ws2812_effects.set_mode(mode, [effect_param])`
#### Parameters
- `mode` is the effect mode as a string, can be one of
- `static` fills the buffer with the color set through `ws2812_effects.set_color()`
- `blink` fills the buffer with the color set through `ws2812_effects.set_color()` and starts blinking
- `gradient` fills the buffer with a gradient defined by the color values provided with the `effect_param`. This parameter must be a string containing the color values with same pixel size as the current buffer configuration. Minimum two colors must be provided. If more are provided, the strip is split in equal parts and the colors are used as intermediate colors. The gradient is calculated based on HSV color space, so no greyscale colors are supported as those cannot be converted to HSV.
- `gradient_rgb` similar to `gradient` but uses simple RGB value interpolation instead of conversions to the HSV color space.
- `random_color` fills the buffer completely with a random color and changes this color constantly
- `rainbow` animates through the full color spectrum, with the entire strip having the same color
- `rainbow_cycle` fills the buffer with a rainbow gradient. The optional second parameter states the number of repetitions (integer).
- `flicker` fills the buffer with the color set through `ws2812_effects.set_color()` and begins random flickering of pixels with a maximum flicker amount defined by the second parameter (integer, e.g. 50 to flicker with 50/255 of the color)
- `fire` is a fire flickering effect
- `fire_soft` is a soft fire flickering effect
- `fire_intense` is an intense fire flickering effect
- `halloween` fills the strip with purple and orange pixels and circles them
- `circus_combustus` fills the strip with red/white/black pixels and circles them
- `larson_scanner` is the K.I.T.T. scanner effect, based on the color set through `ws2812_effects.set_color()`
- `color_wipe` fills the strip pixel by pixel with the color set through `ws2812_effects.set_color()` and then starts turning pixels off again from beginning to end.
- `random_dot` sets random dots to the color set through `ws2812_effects.set_color()` and fades them out again
- `cycle` takes the buffer as-is and cycles it. With the second parameter it can be defined how many pixels the shift will be. Negative values shift to opposite direction.
- `effect_param` is an optional effect parameter. See the effect modes for further explanations. It can be an integer value or a string.
#### Returns
`nil`
#### Examples
Full initialization code for the strip, a buffer and the effect library can be found at top of this documentation. Only effect examples are shown here.
```lua
-- rainbow cycle with two repetitions
ws2812_effects.set_mode("rainbow_cycle", 2)
-- gradient from red to yellow to red
ws2812_effects.set_mode("gradient", string.char(0,200,0,200,200,0,0,200,0))
-- random dots with fading
ws2812_effects.set_mode("random_dot",3)
```

View File

@ -46,6 +46,7 @@ pages:
- 'bmp085': 'en/modules/bmp085.md' - 'bmp085': 'en/modules/bmp085.md'
- 'cjson': 'en/modules/cjson.md' - 'cjson': 'en/modules/cjson.md'
- 'coap': 'en/modules/coap.md' - 'coap': 'en/modules/coap.md'
- 'color-utils': 'en/modules/color-utils.md'
- 'cron': 'en/modules/cron.md' - 'cron': 'en/modules/cron.md'
- 'crypto': 'en/modules/crypto.md' - 'crypto': 'en/modules/crypto.md'
- 'dht': 'en/modules/dht.md' - 'dht': 'en/modules/dht.md'
@ -99,6 +100,7 @@ pages:
- 'wps': 'en/modules/wps.md' - 'wps': 'en/modules/wps.md'
- 'ws2801': 'en/modules/ws2801.md' - 'ws2801': 'en/modules/ws2801.md'
- 'ws2812': 'en/modules/ws2812.md' - 'ws2812': 'en/modules/ws2812.md'
- 'ws2812-effects': 'en/modules/ws2812-effects.md'
- 'xpt2046': 'en/modules/xpt2046.md' - 'xpt2046': 'en/modules/xpt2046.md'
#- Deutsch: #- Deutsch:
# - Home: 'de/index.md' # - Home: 'de/index.md'