Added Ripple and revamped twinkle effects

This commit is contained in:
cschwinne 2019-01-31 23:42:48 +01:00
parent 48d20c02a1
commit 10c51eea2c
8 changed files with 135 additions and 80 deletions

View File

@ -6,7 +6,7 @@
//see https://github.com/Aircoookie/WLED/issues/2 for flicker free ESP32 support
//PIN CONFIGURATION
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266
#define LEDPIN 5 //strip pin. Any for ESP32, gpio2 is recommended for ESP8266
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#define IR_PIN 4 //infrared pin.
#define AUXPIN 15 //unused auxiliary output pin

View File

@ -43,7 +43,7 @@
#include "palettes.h"
#define LED_SKIP_AMOUNT 1
#define LED_SKIP_AMOUNT 24
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
{
@ -100,7 +100,8 @@ void WS2812FX::clear()
bool WS2812FX::modeUsesLock(uint8_t m)
{
if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE || m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH) return true;
if (m < FX_MODE_FIRE_2012) return false;
if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE || m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH || m == FX_MODE_RIPPLE) return true;
return false;
}
@ -736,7 +737,7 @@ uint16_t WS2812FX::mode_dynamic(void) {
setPixelColor(i, color_wheel(random8()));
}
}
setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), color_wheel(random8()));
setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), color_wheel(random8()));
return 50 + (15 * (uint32_t)(255 - SEGMENT.speed));
}
@ -917,22 +918,14 @@ uint16_t WS2812FX::mode_theater_chase_rainbow(void) {
* Running lights effect with smooth sine transition.
*/
uint16_t WS2812FX::mode_running_lights(void) {
uint8_t w = ((SEGMENT.colors[0] >> 24) & 0xFF);
uint8_t r = ((SEGMENT.colors[0] >> 16) & 0xFF);
uint8_t g = ((SEGMENT.colors[0] >> 8) & 0xFF);
uint8_t b = (SEGMENT.colors[0] & 0xFF);
uint8_t x_scale = (SEGMENT.intensity >> 3) + (SEGMENT.intensity >> 4);
for(uint16_t i=0; i < SEGMENT_LENGTH; i++) {
int s = (sin(i+SEGMENT_RUNTIME.counter_mode_call) * 127) + 128;
if (SEGMENT.palette == 0)
{
setPixelColor(SEGMENT.start + i, (((uint32_t)(r * s)) / 255), (((uint32_t)(g * s)) / 255), (((uint32_t)(b * s)) / 255), (((uint32_t)(w * s)) / 255));
} else {
setPixelColor(SEGMENT.start + i, color_from_palette(SEGMENT.start + i, true, PALETTE_SOLID_WRAP, 0, s));
}
uint8_t s = sin8(i*x_scale +(SEGMENT_RUNTIME.counter_mode_step >> 3));
setPixelColor(SEGMENT.start + i, color_blend(SEGMENT.colors[1], color_from_palette(SEGMENT.start + i, true, PALETTE_SOLID_WRAP, 0), s));
}
return 10 + (uint16_t)(255 - SEGMENT.speed);
SEGMENT_RUNTIME.counter_mode_step += SEGMENT.speed;
return 20;
}
@ -944,12 +937,10 @@ uint16_t WS2812FX::twinkle(uint32_t color) {
for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) {
setPixelColor(i, SEGMENT.colors[1]);
}
uint16_t min_leds = max(1, SEGMENT_LENGTH / 5); // make sure, at least one LED is on
uint16_t max_leds = max(1, SEGMENT_LENGTH / 2); // make sure, at least one LED is on
SEGMENT_RUNTIME.counter_mode_step = random(min_leds, max_leds);
SEGMENT_RUNTIME.counter_mode_step = map(SEGMENT.intensity, 0, 255, 1, SEGMENT_LENGTH); // make sure, at least one LED is on
}
uint16_t i = SEGMENT.start + random(SEGMENT_LENGTH);
uint16_t i = SEGMENT.start + random16(SEGMENT_LENGTH);
if (color == SEGMENT.colors[0])
{
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
@ -958,7 +949,7 @@ uint16_t WS2812FX::twinkle(uint32_t color) {
}
SEGMENT_RUNTIME.counter_mode_step--;
return 50 + (8 * (uint16_t)(255 - SEGMENT.speed));
return 20 + (5 * (uint16_t)(255 - SEGMENT.speed));
}
/*
@ -1021,38 +1012,55 @@ void WS2812FX::fade_out(uint8_t rate) {
/*
* twinkle_fade function
* Dissolve function
*/
uint16_t WS2812FX::twinkle_fade(uint32_t color) {
fade_out((255-SEGMENT.intensity) / 32);
if(random8(3) == 0) {
uint16_t i = SEGMENT.start + random(SEGMENT_LENGTH);
if (color == SEGMENT.colors[0])
{
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
} else {
setPixelColor(i, color);
uint16_t WS2812FX::dissolve(uint32_t color) {
bool wa = (SEGMENT.colors[1] != 0 && _brightness < 255); //workaround, can't compare getPixel to color if not full brightness
for (uint16_t j = 0; j <= SEGMENT_LENGTH / 15; j++)
{
if (random8() <= SEGMENT.intensity) {
for (uint8_t times = 0; times < 10; times++) //attempt to spawn a new pixel 5 times
{
uint16_t i = SEGMENT.start + random16(SEGMENT_LENGTH);
if (SEGMENT_RUNTIME.aux_param) { //dissolve to primary/palette
if (getPixelColor(i) == SEGMENT.colors[1] || wa) {
if (color == SEGMENT.colors[0])
{
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
} else { setPixelColor(i, color); }
break; //only spawn 1 new pixel per frame per 50 LEDs
}
} else { //dissolve to secondary
if (getPixelColor(i) != SEGMENT.colors[1]) { setPixelColor(i, SEGMENT.colors[1]); break; }
}
}
}
}
if (SEGMENT_RUNTIME.counter_mode_call > (255 - SEGMENT.speed) + 15)
{
SEGMENT_RUNTIME.aux_param = !SEGMENT_RUNTIME.aux_param;
SEGMENT_RUNTIME.counter_mode_call = 0;
}
return 100 + ((uint32_t)(255 - SEGMENT.speed)) / 3;
return 20;
}
/*
* Blink several LEDs on, fading out.
* Blink several LEDs on and then off
*/
uint16_t WS2812FX::mode_twinkle_fade(void) {
return twinkle_fade(SEGMENT.colors[0]);
uint16_t WS2812FX::mode_dissolve(void) {
return dissolve(SEGMENT.colors[0]);
}
/*
* Blink several LEDs in random colors on, fading out.
* Blink several LEDs on and then off in random colors
*/
uint16_t WS2812FX::mode_twinkle_fade_random(void) {
return twinkle_fade(color_wheel(random8()));
uint16_t WS2812FX::mode_dissolve_random(void) {
return dissolve(color_wheel(random8()));
}
@ -1064,7 +1072,7 @@ uint16_t WS2812FX::mode_sparkle(void) {
for(uint16_t i=SEGMENT.start; i <= SEGMENT.stop; i++) {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 1));
}
SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH); // aux_param stores the random led index
SEGMENT_RUNTIME.aux_param = random16(SEGMENT_LENGTH); // aux_param stores the random led index
setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[0]);
return 10 + (uint16_t)(255 - SEGMENT.speed);
}
@ -1085,7 +1093,7 @@ uint16_t WS2812FX::mode_flash_sparkle(void) {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
if(random8(5) == 0) {
SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH); // aux_param stores the random led index
SEGMENT_RUNTIME.aux_param = random16(SEGMENT_LENGTH); // aux_param stores the random led index
setPixelColor(SEGMENT.start + SEGMENT_RUNTIME.aux_param, SEGMENT.colors[1]);
return 20;
}
@ -1104,7 +1112,7 @@ uint16_t WS2812FX::mode_hyper_sparkle(void) {
if(random8(5) < 2) {
for(uint16_t i=0; i < max(1, SEGMENT_LENGTH/3); i++) {
setPixelColor(SEGMENT.start + random(SEGMENT_LENGTH), SEGMENT.colors[1]);
setPixelColor(SEGMENT.start + random16(SEGMENT_LENGTH), SEGMENT.colors[1]);
}
return 20;
}
@ -1515,7 +1523,7 @@ uint16_t WS2812FX::fireworks(uint32_t color) {
for(uint16_t i=0; i<max(1, SEGMENT_LENGTH/20); i++) {
if(random8((255 - SEGMENT.intensity)/8) == 0) {
uint16_t index = SEGMENT.start + random(SEGMENT_LENGTH);
uint16_t index = SEGMENT.start + random16(SEGMENT_LENGTH);
if (color == SEGMENT.colors[0])
{
setPixelColor(index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0));
@ -1887,8 +1895,8 @@ uint16_t WS2812FX::mode_icu(void) {
setPixelColor(SEGMENT.start + dest + SEGMENT_LENGTH/2, SEGMENT.colors[1]);
return 200;
}
SEGMENT_RUNTIME.aux_param = random(SEGMENT_LENGTH/2);
return 1000 + random(2000);
SEGMENT_RUNTIME.aux_param = random16(SEGMENT_LENGTH/2);
return 1000 + random16(2000);
}
if(SEGMENT_RUNTIME.aux_param > SEGMENT_RUNTIME.counter_mode_step) {
@ -2046,9 +2054,9 @@ uint16_t WS2812FX::mode_random_chase(void)
setPixelColor(i, getPixelColor(i-1));
}
uint32_t color = getPixelColor(SEGMENT.start + 1);
int r = random(6) != 0 ? (color >> 16 & 0xFF) : random(256);
int g = random(6) != 0 ? (color >> 8 & 0xFF) : random(256);
int b = random(6) != 0 ? (color & 0xFF) : random(256);
int r = random8(6) != 0 ? (color >> 16 & 0xFF) : random8();
int g = random8(6) != 0 ? (color >> 8 & 0xFF) : random8();
int b = random8(6) != 0 ? (color & 0xFF) : random8();
setPixelColor(SEGMENT.start, r, g, b);
return 10 + (uint16_t)(255 - SEGMENT.speed);
@ -2063,10 +2071,10 @@ typedef struct Oscillator {
uint16_t WS2812FX::mode_oscillate(void)
{
static oscillator oscillators[NUM_COLORS] = {
static oscillator oscillators[2] = {
{SEGMENT_LENGTH/4, SEGMENT_LENGTH/8, 1, 1},
{SEGMENT_LENGTH/4*2, SEGMENT_LENGTH/8, -1, 1},
{SEGMENT_LENGTH/4*3, SEGMENT_LENGTH/8, 1, 2}
{SEGMENT_LENGTH/4*2, SEGMENT_LENGTH/8, -1, 1}
//{SEGMENT_LENGTH/4*3, SEGMENT_LENGTH/8, 1, 2}
};
for(int8_t i=0; i < sizeof(oscillators)/sizeof(oscillators[0]); i++) {
@ -2074,12 +2082,12 @@ uint16_t WS2812FX::mode_oscillate(void)
if((oscillators[i].dir == -1) && (oscillators[i].pos <= 0)) {
oscillators[i].pos = 0;
oscillators[i].dir = 1;
oscillators[i].speed = random(1, 3);
oscillators[i].speed = random8(1, 3);
}
if((oscillators[i].dir == 1) && (oscillators[i].pos >= (SEGMENT_LENGTH - 1))) {
oscillators[i].pos = SEGMENT_LENGTH - 1;
oscillators[i].dir = -1;
oscillators[i].speed = random(1, 3);
oscillators[i].speed = random8(1, 3);
}
}
@ -2462,7 +2470,7 @@ uint16_t WS2812FX::mode_bpm(void)
uint16_t WS2812FX::mode_fillnoise8(void)
{
if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = random(12345);
if (SEGMENT_RUNTIME.counter_mode_call == 0) SEGMENT_RUNTIME.counter_mode_step = random16(12345);
CRGB fastled_col;
for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++) {
uint8_t index = inoise8(i * SEGMENT_LENGTH, SEGMENT_RUNTIME.counter_mode_step + i * SEGMENT_LENGTH) % 255;
@ -2670,14 +2678,6 @@ uint16_t WS2812FX::mode_meteor() {
}
//smooth
//front ramping (maybe from get color
//50fps
//fade each led by a certain range (even ramp possible for sparkling)
//maybe dim to color[1] at end?
//_locked 0-15 bg-last 15-240 last-first 240-255 first-bg
#define IS_PART_OF_METEOR 245
// smooth meteor effect
// send a meteor from begining to to the end of the strip with a trail that randomly decays.
// adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain
@ -2743,3 +2743,56 @@ uint16_t WS2812FX::mode_railway()
SEGMENT_RUNTIME.counter_mode_step += 20;
return 20;
}
//Water ripple
//fade duration is random 2-5sec
//propagation velocity from speed
//drop rate from intensity
uint16_t WS2812FX::mode_ripple()
{
uint16_t maxripples = SEGMENT_LENGTH / 5;
if (maxripples == 0) return mode_static();
//set background
for (uint16_t i = SEGMENT.start; i <= SEGMENT.stop; i++)
{
setPixelColor(i, SEGMENT.colors[1]);
}
//draw wave
for (uint16_t rippleI = 0; rippleI < maxripples; rippleI++)
{
uint16_t storeI = SEGMENT.start + 5*rippleI;
uint8_t ripplestate = _locked[storeI];
if (ripplestate)
{
uint16_t rippleorigin = ((_locked[storeI+2] << 8) & 0xFF00) + _locked[storeI+3];
uint8_t rippledur = _locked[storeI+1];
uint8_t ripplecolor = _locked[storeI+4];
int16_t progress = ripplestate - rippledur -1;
int16_t propagation = (progress * (SEGMENT.speed >> 1)) >> 8;
int16_t left = rippleorigin - propagation;
int16_t right = rippleorigin +1 + propagation;
uint8_t mix = (ripplestate > 127) ? (ripplestate-128)*2 : 0;
uint32_t col = color_blend(color_from_palette(ripplecolor, false, false, 255), SEGMENT.colors[1], mix);
if (left >= SEGMENT.start) setPixelColor(left, col);
if (right <= SEGMENT.stop) setPixelColor(right, col);
_locked[storeI]++;
} else //randomly create new ripple
{
if (random16(4096) <= SEGMENT.intensity)
{
_locked[storeI] = random8(120); //vary ripple strenght
_locked[storeI+1] = _locked[storeI];
uint16_t origin = SEGMENT.start + random16(SEGMENT_LENGTH);
_locked[storeI+2] = origin >> 8;
_locked[storeI+3] = origin & 0xFF;
_locked[storeI+4] = random8();
}
}
}
return 20;
}

View File

@ -85,7 +85,7 @@
#define REVERSE (uint8_t)0x80
#define IS_REVERSE ((SEGMENT.options & REVERSE) == REVERSE)
#define MODE_COUNT 79
#define MODE_COUNT 80
#define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1
@ -105,8 +105,8 @@
#define FX_MODE_RUNNING_LIGHTS 15
#define FX_MODE_TWINKLE 16
#define FX_MODE_TWINKLE_RANDOM 17
#define FX_MODE_TWINKLE_FADE 18
#define FX_MODE_TWINKLE_FADE_RANDOM 19
#define FX_MODE_DISSOLVE 18
#define FX_MODE_DISSOLVE_RANDOM 19
#define FX_MODE_SPARKLE 20
#define FX_MODE_FLASH_SPARKLE 21
#define FX_MODE_HYPER_SPARKLE 22
@ -167,6 +167,7 @@
#define FX_MODE_METEOR 76
#define FX_MODE_METEOR_SMOOTH 77
#define FX_MODE_RAILWAY 78
#define FX_MODE_RIPPLE 79
class WS2812FX {
@ -212,8 +213,8 @@ class WS2812FX {
_mode[FX_MODE_THEATER_CHASE_RAINBOW] = &WS2812FX::mode_theater_chase_rainbow;
_mode[FX_MODE_TWINKLE] = &WS2812FX::mode_twinkle;
_mode[FX_MODE_TWINKLE_RANDOM] = &WS2812FX::mode_twinkle_random;
_mode[FX_MODE_TWINKLE_FADE] = &WS2812FX::mode_twinkle_fade;
_mode[FX_MODE_TWINKLE_FADE_RANDOM] = &WS2812FX::mode_twinkle_fade_random;
_mode[FX_MODE_DISSOLVE] = &WS2812FX::mode_dissolve;
_mode[FX_MODE_DISSOLVE_RANDOM] = &WS2812FX::mode_dissolve_random;
_mode[FX_MODE_SPARKLE] = &WS2812FX::mode_sparkle;
_mode[FX_MODE_FLASH_SPARKLE] = &WS2812FX::mode_flash_sparkle;
_mode[FX_MODE_HYPER_SPARKLE] = &WS2812FX::mode_hyper_sparkle;
@ -275,7 +276,7 @@ class WS2812FX {
_mode[FX_MODE_METEOR] = &WS2812FX::mode_meteor;
_mode[FX_MODE_METEOR_SMOOTH] = &WS2812FX::mode_meteor_smooth;
_mode[FX_MODE_RAILWAY] = &WS2812FX::mode_railway;
_mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple;
_brightness = DEFAULT_BRIGHTNESS;
_running = false;
@ -372,7 +373,7 @@ class WS2812FX {
scan(bool),
theater_chase(uint32_t, uint32_t, bool),
twinkle(uint32_t),
twinkle_fade(uint32_t),
dissolve(uint32_t),
chase(uint32_t, uint32_t, uint32_t, uint8_t),
running(uint32_t, uint32_t),
fireworks(uint32_t),
@ -402,8 +403,8 @@ class WS2812FX {
mode_running_lights(void),
mode_twinkle(void),
mode_twinkle_random(void),
mode_twinkle_fade(void),
mode_twinkle_fade_random(void),
mode_dissolve(void),
mode_dissolve_random(void),
mode_sparkle(void),
mode_flash_sparkle(void),
mode_hyper_sparkle(void),
@ -438,6 +439,7 @@ class WS2812FX {
mode_tricolor_chase(void),
mode_tricolor_wipe(void),
mode_tricolor_fade(void),
mode_lightning(void),
mode_icu(void),
mode_multi_comet(void),
mode_dual_larson_scanner(void),
@ -459,7 +461,7 @@ class WS2812FX {
mode_meteor(void),
mode_meteor_smooth(void),
mode_railway(void),
mode_lightning(void);
mode_ripple(void);
private:
NeoPixelWrapper *bus;

View File

@ -2,7 +2,7 @@
<html>
<head><meta charset="utf-8"><meta name="theme-color" content="#fff">
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico'/>
<title>WLED 0.8.2</title>
<title>WLED 0.8.3</title>
<script>
var d=document;
var w=window.getComputedStyle(d.querySelector("html"));
@ -73,7 +73,7 @@
d.documentElement.style.setProperty("--bCol",this.responseXML.getElementsByTagName('cb')[0].childNodes[0].nodeValue);
d.documentElement.style.setProperty("--cCol",this.responseXML.getElementsByTagName('cc')[0].childNodes[0].nodeValue);
d.documentElement.style.setProperty("--dCol",this.responseXML.getElementsByTagName('cd')[0].childNodes[0].nodeValue);
d.documentElement.style.setProperty("--sCol",this.responseXML.getElementsByTagName('cs')[0].childNodes[0].nodeValue);
d.documentElement.style.setProperty("--sCol",this.responseXML.getElementsByTagName('cu')[0].childNodes[0].nodeValue);
d.documentElement.style.setProperty("--tCol",this.responseXML.getElementsByTagName('ct')[0].childNodes[0].nodeValue);
d.documentElement.style.setProperty("--cFn",this.responseXML.getElementsByTagName('cf')[0].childNodes[0].nodeValue);
UCol();

View File

@ -78,7 +78,7 @@
//version code in format yymmddb (b = daily build)
#define VERSION 1901291
#define VERSION 1901314
char versionString[] = "0.8.3-dev";

View File

@ -68,9 +68,9 @@ void XML_response(bool isHTTP, bool includeTheme)
oappend(cs[2]);
oappend("</cc><cd>#");
oappend(cs[3]);
oappend("</cd><cs>#");
oappend("</cd><cu>#");
oappend(cs[4]);
oappend("</cs><ct>#");
oappend("</cu><ct>#");
oappend(cs[5]);
oappend("</ct><cf>");
oappend(cssFont);

View File

@ -27,7 +27,7 @@ void wledInit()
DEBUG_PRINT(clientSSID);
userBeginPreConnection();
if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true;
WiFi.persistent(false);
initCon();
DEBUG_PRINTLN("");

View File

@ -177,7 +177,7 @@ void initServer()
server.sendHeader("Access-Control-Max-Age", "10000");
server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
server.sendHeader("Access-Control-Allow-Headers", "*");
server.send(204);
server.send(200);
return;
}