From 7ca1970fff2080929b8a89e77202d5b660403ce6 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 10 Dec 2019 20:06:00 +0100 Subject: [PATCH 01/26] add bouncing balls effect --- wled00/FX.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 9 +++++--- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 2bdb75ba9..495c0397a 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2285,3 +2285,67 @@ uint16_t WS2812FX::mode_spots_fade() uint16_t tr = (t >> 1) + (t >> 2); return spots_base(tr); } + + +/* +* Bouncing Balls Effect +* Adapted from: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ +*/ +uint16_t WS2812FX::mode_BouncingBalls(void) { + // number of balls based on intensity setting, + // only has 4 for a few of the higher settings as there is no colour selection + // fourth ball is a random colour + int balls = int(((SEGMENT.intensity * 6.2) / 255) + 1); + + // ideally use speed for gravity effect on the bounce + float Gravity = -9.81; + + const int maxBallCount = 7; + static float Height[maxBallCount]; + static float ImpactVelocity[maxBallCount]; + static int Position[maxBallCount]; + static float TimeSinceLastBounce[maxBallCount]; + static long ClockTimeSinceLastBounce[maxBallCount]; + static int StartHeight = 1; // height in metres (strip length) + static float Dampening[maxBallCount] = {0}; // Coefficient of Restitution (bounce damping) + static float ImpactVelocityStart=sqrt( -2 * Gravity * StartHeight); + + // Different from the examples, to allow for initialisation of the first bounce + if (Dampening[0] == 0) { + for (int i = 0 ; i < maxBallCount ; i++) { + ClockTimeSinceLastBounce[i] = millis(); + ImpactVelocity[i] = ImpactVelocityStart; + TimeSinceLastBounce[i] = 0; + Dampening[i] = 0.90 - float(i)/pow(maxBallCount,2); + } + } + + for (int i = 0 ; i < balls ; i++) { + TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i]; + Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000; + + if ( Height[i] < 0 ) { + Height[i] = 0; + ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i]; + ClockTimeSinceLastBounce[i] = millis(); + + if ( ImpactVelocity[i] < 0.01 ) { + ImpactVelocity[i] = ImpactVelocityStart; + } + } + Position[i] = round( Height[i] * (SEGLEN - 1) / StartHeight); + } + + fill(BLACK); + + for (int i = 0 ; i < balls ; i++) { + uint32_t color = SEGCOLOR(i % NUM_COLORS); + if (!color) { + color = color_wheel(random8()); + } + + setPixelColor(Position[i],color); + } + + return 20; +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 5a3865ae0..5642850a3 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 87 +#define MODE_COUNT 88 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -173,6 +173,7 @@ #define FX_MODE_TRI_STATIC_PATTERN 84 #define FX_MODE_SPOTS 85 #define FX_MODE_SPOTS_FADE 86 +#define FX_MODE_BOUNCINGBALLS 87 class WS2812FX { @@ -317,6 +318,7 @@ class WS2812FX { _mode[FX_MODE_TRI_STATIC_PATTERN] = &WS2812FX::mode_tri_static_pattern; _mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots; _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; + _mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_BouncingBalls; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -497,7 +499,8 @@ class WS2812FX { mode_static_pattern(void), mode_tri_static_pattern(void), mode_spots(void), - mode_spots_fade(void); + mode_spots_fade(void), + mode_BouncingBalls(void); private: NeoPixelWrapper *bus; @@ -570,7 +573,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Bouncing Balls" ])====="; From 86ae11f4c44fe1b37a325af5040b9438a6d5ed9d Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 10 Dec 2019 20:26:02 +0100 Subject: [PATCH 02/26] add sinelon effect --- wled00/FX.cpp | 25 +++++++++++++++++++++++++ wled00/FX.h | 9 ++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 495c0397a..d0a34a28d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2348,4 +2348,29 @@ uint16_t WS2812FX::mode_BouncingBalls(void) { } return 20; +} + +/* +* Sinelon stolen from FASTLED examples +*/ +uint16_t WS2812FX::mode_sinelon(void) { + + fade_out(SEGMENT.intensity); + int pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); + static int prevpos = 0; + + // setRange seems great to use, but doesn't work here for some reason + if( pos < prevpos ) { + for (uint16_t i = pos; i < prevpos; i++) + { + setPixelColor(i, color_from_palette(pos, false, false, 0)); + } + } else { + for (uint16_t i = prevpos; i < pos; i++) + { + setPixelColor(i, color_from_palette(pos, false, false, 0)); + } + } + prevpos = pos; + return FRAMETIME; } \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 5642850a3..aabf70790 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 88 +#define MODE_COUNT 89 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -174,6 +174,7 @@ #define FX_MODE_SPOTS 85 #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_BOUNCINGBALLS 87 +#define FX_MODE_SINELON 88 class WS2812FX { @@ -319,6 +320,7 @@ class WS2812FX { _mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots; _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_BouncingBalls; + _mode[FX_MODE_SINELON] = &WS2812FX::mode_sinelon; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -500,7 +502,8 @@ class WS2812FX { mode_tri_static_pattern(void), mode_spots(void), mode_spots_fade(void), - mode_BouncingBalls(void); + mode_BouncingBalls(void), + mode_sinelon(void); private: NeoPixelWrapper *bus; @@ -573,7 +576,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Bouncing Balls" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Bouncing Balls", "Sinelon" ])====="; From c1dec16c500d1fe5adfcedb3c54163e9a1f597bd Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 10 Dec 2019 20:34:59 +0100 Subject: [PATCH 03/26] add popcorn effect --- wled00/FX.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 9 ++++++--- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index d0a34a28d..9a2da2043 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2373,4 +2373,53 @@ uint16_t WS2812FX::mode_sinelon(void) { } prevpos = pos; return FRAMETIME; +} + + +/* +* POPCORN +*/ +typedef struct Kernel { + float position; + float velocity; + int32_t color; +} kernel; + +#define MAX_NUM_POPCORN 12 +#define GRAVITY 0.06 + +uint16_t WS2812FX::mode_popcorn(void) { + uint32_t popcornColor = SEGCOLOR(0); + uint32_t bgColor = SEGCOLOR(1); + if(popcornColor == bgColor) popcornColor = color_wheel(random8()); + + static kernel popcorn[MAX_NUM_POPCORN]; + static float coeff = 0.0f; + if(coeff == 0.0f) { // calculate the velocity coeff once (the secret sauce) + coeff = pow((float)SEGLEN, 0.5223324f) * 0.3944296f; + } + + fill(SEGCOLOR(1)); + + uint16_t ledIndex; + for(int8_t i=0; i < MAX_NUM_POPCORN; i++) { + bool isActive = popcorn[i].position >= 0.0f; + + if(isActive) { // if kernel is active, update its position + popcorn[i].position += popcorn[i].velocity; + popcorn[i].velocity -= (GRAVITY * SEGMENT.intensity/25); + ledIndex = SEGMENT.start + popcorn[i].position; + if(ledIndex >= SEGMENT.start && ledIndex <= SEGMENT.stop) setPixelColor(ledIndex, popcorn[i].color); + } else { // if kernel is inactive, randomly pop it + if(random8() < 2) { // POP!!! + popcorn[i].position = 0.0f; + popcorn[i].velocity = coeff * (random(66, 100) / 100.0f); + popcorn[i].color = popcornColor; + ledIndex = SEGMENT.start; + setPixelColor(ledIndex, popcorn[i].color); + } + } + } + + return SPEED_FORMULA_L; } \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index aabf70790..57b256be4 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 89 +#define MODE_COUNT 90 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,6 +175,7 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_BOUNCINGBALLS 87 #define FX_MODE_SINELON 88 +#define FX_MODE_POPCORN 89 class WS2812FX { @@ -321,6 +322,7 @@ class WS2812FX { _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_BouncingBalls; _mode[FX_MODE_SINELON] = &WS2812FX::mode_sinelon; + _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -503,7 +505,8 @@ class WS2812FX { mode_spots(void), mode_spots_fade(void), mode_BouncingBalls(void), - mode_sinelon(void); + mode_sinelon(void), + mode_popcorn(void); private: NeoPixelWrapper *bus; @@ -576,7 +579,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Bouncing Balls", "Sinelon" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Bouncing Balls", "Sinelon","Popcorn" ])====="; From f3371c443e16599dff26610e311d627ac4ce7875 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 14:46:07 +0100 Subject: [PATCH 04/26] more effects to FRAMETIME --- wled00/FX.cpp | 178 +++++++++----------------------------------------- 1 file changed, 32 insertions(+), 146 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b1e348849..1791b710c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -961,6 +961,10 @@ uint16_t WS2812FX::mode_halloween(void) { * Random colored pixels running. */ uint16_t WS2812FX::mode_running_random(void) { + uint32_t cycleTime = 25 + (3 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.aux1 == it) return FRAMETIME; + for(uint16_t i=SEGLEN-1; i > 0; i--) { setPixelColor(SEGMENT.start + i, getPixelColor(SEGMENT.start + i - 1)); } @@ -975,7 +979,9 @@ uint16_t WS2812FX::mode_running_random(void) { { SEGENV.step = 0; } - return SPEED_FORMULA_L; + + SEGENV.aux1 = it; + return FRAMETIME; } @@ -1091,6 +1097,10 @@ uint16_t WS2812FX::mode_rain() * Fire flicker function */ uint16_t WS2812FX::mode_fire_flicker(void) { + uint32_t cycleTime = 40 + (255 - SEGMENT.speed); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + byte w = (SEGCOLOR(0) >> 24) & 0xFF; byte r = (SEGCOLOR(0) >> 16) & 0xFF; byte g = (SEGCOLOR(0) >> 8) & 0xFF; @@ -1105,7 +1115,9 @@ uint16_t WS2812FX::mode_fire_flicker(void) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0, 255 - flicker)); } } - return 20 + random((255 - SEGMENT.speed),(2 * (uint16_t)(255 - SEGMENT.speed))); + + SEGENV.step = it; + return FRAMETIME; } @@ -1285,6 +1297,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); + if (SEGMENT.intensity > 127) return FRAMETIME; return SPEED_FORMULA_L; } @@ -1294,6 +1307,11 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { + uint32_t cycleTime = 40 + (3 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + uint8_t incr = it-SEGENV.step; + if(SEGENV.step < SEGLEN) { uint32_t led_offset = SEGENV.step; setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(0)); @@ -1307,7 +1325,7 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) } SEGENV.step = (SEGENV.step + 1) % (SEGLEN * 3); - return SPEED_FORMULA_L; + return FRAMETIME; } @@ -1318,6 +1336,9 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) */ uint16_t WS2812FX::mode_tricolor_fade(void) { + uint16_t counter = now * ((SEGMENT.speed >> 3) +1); + SEGENV.step = (counter * 768) >> 16; + uint32_t color1 = 0, color2 = 0; byte stage = 0; @@ -1348,10 +1369,7 @@ uint16_t WS2812FX::mode_tricolor_fade(void) setPixelColor(i, color); } - SEGENV.step += 4; - if(SEGENV.step >= 768) SEGENV.step = 0; - - return 5 + ((uint32_t)(255 - SEGMENT.speed) / 10); + return FRAMETIME; } @@ -1361,6 +1379,10 @@ uint16_t WS2812FX::mode_tricolor_fade(void) */ uint16_t WS2812FX::mode_multi_comet(void) { + uint32_t cycleTime = 20 + (2 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + fade_out(SEGMENT.intensity); static uint16_t comets[] = {UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX}; @@ -1382,7 +1404,9 @@ uint16_t WS2812FX::mode_multi_comet(void) } } } - return SPEED_FORMULA_L; + + SEGENV.step = it; + return FRAMETIME; } @@ -2341,95 +2365,6 @@ uint16_t WS2812FX::mode_spots_fade() } -/* -* Bouncing Balls Effect -* Adapted from: https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ -*/ -uint16_t WS2812FX::mode_BouncingBalls(void) { - // number of balls based on intensity setting, - // only has 4 for a few of the higher settings as there is no colour selection - // fourth ball is a random colour - int balls = int(((SEGMENT.intensity * 6.2) / 255) + 1); - - // ideally use speed for gravity effect on the bounce - float Gravity = -9.81; - - const int maxBallCount = 7; - static float Height[maxBallCount]; - static float ImpactVelocity[maxBallCount]; - static int Position[maxBallCount]; - static float TimeSinceLastBounce[maxBallCount]; - static long ClockTimeSinceLastBounce[maxBallCount]; - static int StartHeight = 1; // height in metres (strip length) - static float Dampening[maxBallCount] = {0}; // Coefficient of Restitution (bounce damping) - static float ImpactVelocityStart=sqrt( -2 * Gravity * StartHeight); - - // Different from the examples, to allow for initialisation of the first bounce - if (Dampening[0] == 0) { - for (int i = 0 ; i < maxBallCount ; i++) { - ClockTimeSinceLastBounce[i] = millis(); - ImpactVelocity[i] = ImpactVelocityStart; - TimeSinceLastBounce[i] = 0; - Dampening[i] = 0.90 - float(i)/pow(maxBallCount,2); - } - } - - for (int i = 0 ; i < balls ; i++) { - TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i]; - Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000; - - if ( Height[i] < 0 ) { - Height[i] = 0; - ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i]; - ClockTimeSinceLastBounce[i] = millis(); - - if ( ImpactVelocity[i] < 0.01 ) { - ImpactVelocity[i] = ImpactVelocityStart; - } - } - Position[i] = round( Height[i] * (SEGLEN - 1) / StartHeight); - } - - fill(BLACK); - - for (int i = 0 ; i < balls ; i++) { - uint32_t color = SEGCOLOR(i % NUM_COLORS); - if (!color) { - color = color_wheel(random8()); - } - - setPixelColor(Position[i],color); - } - - return 20; -} - -/* -* Sinelon stolen from FASTLED examples -*/ -uint16_t WS2812FX::mode_sinelon(void) { - - fade_out(SEGMENT.intensity); - int pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); - static int prevpos = 0; - - // setRange seems great to use, but doesn't work here for some reason - if( pos < prevpos ) { - for (uint16_t i = pos; i < prevpos; i++) - { - setPixelColor(i, color_from_palette(pos, false, false, 0)); - } - } else { - for (uint16_t i = prevpos; i < pos; i++) - { - setPixelColor(i, color_from_palette(pos, false, false, 0)); - } - } - prevpos = pos; - return FRAMETIME; -} - - //Rainbow with glitter, inspired by https://gist.github.com/kriegsman/062e10f7f07ba8518af6 uint16_t WS2812FX::mode_glitter() { @@ -2444,55 +2379,6 @@ uint16_t WS2812FX::mode_glitter() } -/* -* POPCORN -*/ -typedef struct Kernel { - float position; - float velocity; - int32_t color; -} kernel; - -#define MAX_NUM_POPCORN 12 -#define GRAVITY 0.06 - -uint16_t WS2812FX::mode_popcorn(void) { - uint32_t popcornColor = SEGCOLOR(0); - uint32_t bgColor = SEGCOLOR(1); - if(popcornColor == bgColor) popcornColor = color_wheel(random8()); - - static kernel popcorn[MAX_NUM_POPCORN]; - static float coeff = 0.0f; - if(coeff == 0.0f) { // calculate the velocity coeff once (the secret sauce) - coeff = pow((float)SEGLEN, 0.5223324f) * 0.3944296f; - } - - fill(SEGCOLOR(1)); - - uint16_t ledIndex; - for(int8_t i=0; i < MAX_NUM_POPCORN; i++) { - bool isActive = popcorn[i].position >= 0.0f; - - if(isActive) { // if kernel is active, update its position - popcorn[i].position += popcorn[i].velocity; - popcorn[i].velocity -= (GRAVITY * SEGMENT.intensity/25); - ledIndex = SEGMENT.start + popcorn[i].position; - if(ledIndex >= SEGMENT.start && ledIndex <= SEGMENT.stop) setPixelColor(ledIndex, popcorn[i].color); - } else { // if kernel is inactive, randomly pop it - if(random8() < 2) { // POP!!! - popcorn[i].position = 0.0f; - popcorn[i].velocity = coeff * (random(66, 100) / 100.0f); - popcorn[i].color = popcornColor; - ledIndex = SEGMENT.start; - setPixelColor(ledIndex, popcorn[i].color); - } - } - } - - return SPEED_FORMULA_L; -} - - //values close to 100 produce 5Hz flicker, which looks very candle-y //Inspired by https://github.com/avanhanegem/ArduinoCandleEffectNeoPixel //and https://cpldcpu.wordpress.com/2016/01/05/reverse-engineering-a-real-candle/ From 8600360173083d379f1437a32af580d498c1ccbf Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 14:46:07 +0100 Subject: [PATCH 05/26] more effects to FRAMETIME --- wled00/FX.cpp | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 8349f0f69..4410a43b7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -961,6 +961,10 @@ uint16_t WS2812FX::mode_halloween(void) { * Random colored pixels running. */ uint16_t WS2812FX::mode_running_random(void) { + uint32_t cycleTime = 25 + (3 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.aux1 == it) return FRAMETIME; + for(uint16_t i=SEGLEN-1; i > 0; i--) { setPixelColor(SEGMENT.start + i, getPixelColor(SEGMENT.start + i - 1)); } @@ -975,7 +979,9 @@ uint16_t WS2812FX::mode_running_random(void) { { SEGENV.step = 0; } - return SPEED_FORMULA_L; + + SEGENV.aux1 = it; + return FRAMETIME; } @@ -1091,6 +1097,10 @@ uint16_t WS2812FX::mode_rain() * Fire flicker function */ uint16_t WS2812FX::mode_fire_flicker(void) { + uint32_t cycleTime = 40 + (255 - SEGMENT.speed); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + byte w = (SEGCOLOR(0) >> 24) & 0xFF; byte r = (SEGCOLOR(0) >> 16) & 0xFF; byte g = (SEGCOLOR(0) >> 8) & 0xFF; @@ -1105,7 +1115,9 @@ uint16_t WS2812FX::mode_fire_flicker(void) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0, 255 - flicker)); } } - return 20 + random((255 - SEGMENT.speed),(2 * (uint16_t)(255 - SEGMENT.speed))); + + SEGENV.step = it; + return FRAMETIME; } @@ -1285,6 +1297,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); + if (SEGMENT.intensity > 127) return FRAMETIME; return SPEED_FORMULA_L; } @@ -1294,6 +1307,11 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { + uint32_t cycleTime = 40 + (3 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + uint8_t incr = it-SEGENV.step; + if(SEGENV.step < SEGLEN) { uint32_t led_offset = SEGENV.step; setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(0)); @@ -1307,7 +1325,7 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) } SEGENV.step = (SEGENV.step + 1) % (SEGLEN * 3); - return SPEED_FORMULA_L; + return FRAMETIME; } @@ -1318,6 +1336,9 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) */ uint16_t WS2812FX::mode_tricolor_fade(void) { + uint16_t counter = now * ((SEGMENT.speed >> 3) +1); + SEGENV.step = (counter * 768) >> 16; + uint32_t color1 = 0, color2 = 0; byte stage = 0; @@ -1348,10 +1369,7 @@ uint16_t WS2812FX::mode_tricolor_fade(void) setPixelColor(i, color); } - SEGENV.step += 4; - if(SEGENV.step >= 768) SEGENV.step = 0; - - return 5 + ((uint32_t)(255 - SEGMENT.speed) / 10); + return FRAMETIME; } @@ -1361,6 +1379,10 @@ uint16_t WS2812FX::mode_tricolor_fade(void) */ uint16_t WS2812FX::mode_multi_comet(void) { + uint32_t cycleTime = 20 + (2 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (SEGENV.step == it) return FRAMETIME; + fade_out(SEGMENT.intensity); static uint16_t comets[] = {UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX}; @@ -1382,7 +1404,9 @@ uint16_t WS2812FX::mode_multi_comet(void) } } } - return SPEED_FORMULA_L; + + SEGENV.step = it; + return FRAMETIME; } From 0d4d1eff94ccbf43a8f047968fd8cd9611139070 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 14:58:22 +0100 Subject: [PATCH 06/26] Revert "Merge branch 'master' into framerate" This reverts commit 38cc4603580249cf317353b97941a8b0a1b0080f, reversing changes made to 8600360173083d379f1437a32af580d498c1ccbf. --- wled00/FX.cpp | 28 ++++++++++++++-------------- wled00/FX.h | 14 ++------------ wled00/wled00.ino | 2 +- wled00/wled01_eeprom.ino | 7 ------- 4 files changed, 17 insertions(+), 34 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 1791b710c..4410a43b7 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -301,24 +301,24 @@ uint16_t WS2812FX::scan(bool dual) uint32_t cycleTime = 750 + (255 - SEGMENT.speed)*150; uint32_t perc = now % cycleTime; uint16_t prog = (perc * 65535) / cycleTime; - uint16_t size = 1 + ((SEGMENT.intensity * SEGLEN) >>9); - uint16_t ledIndex = (prog * ((SEGLEN *2) - size *2)) >> 16; + uint16_t ledIndex = (prog * ((SEGLEN * 2) - 2)) >> 16; + uint16_t size = 1 + SEGMENT.intensity >> 3; fill(SEGCOLOR(1)); - int led_offset = ledIndex - (SEGLEN - size); + int led_offset = ledIndex - (SEGLEN - 1); led_offset = abs(led_offset); - if (dual) { - for (uint16_t j = led_offset; j < led_offset + size; j++) { - uint16_t i2 = SEGMENT.stop -1 -j; - setPixelColor(i2, color_from_palette(i2, true, PALETTE_SOLID_WRAP, (SEGCOLOR(2))? 2:0)); - } + uint16_t i = SEGMENT.start + led_offset; + for (int16_t j=i-size/2; j<=i+size/2; j++) { + if (j>=0) setPixelColor(j, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); } - for (uint16_t j = led_offset; j < led_offset + size; j++) { - uint16_t i = SEGMENT.start + j; - setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + if (dual) { + uint16_t i2 = SEGMENT.start + SEGLEN - led_offset - 1; + for (int16_t j=i2-size/2; j<=i2+size/2; j++) { + if (j>=0) setPixelColor(j, color_from_palette(i2, true, PALETTE_SOLID_WRAP, 0)); + } } return FRAMETIME; @@ -1004,7 +1004,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?i:SEGLEN-1-i; - setPixelColor(SEGMENT.start + j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); } if (dual) { uint32_t c; @@ -1016,7 +1016,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?SEGLEN-1-i:i; - setPixelColor(SEGMENT.start + j, c); + setPixelColor(j, c); } } @@ -1034,7 +1034,7 @@ uint16_t WS2812FX::mode_comet(void) { fade_out(SEGMENT.intensity); - setPixelColor(SEGMENT.start + index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); return FRAMETIME; } diff --git a/wled00/FX.h b/wled00/FX.h index 92f3cf78d..53096b7e0 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 92 +#define MODE_COUNT 89 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,9 +175,6 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 -#define FX_MODE_BOUNCINGBALLS 89 -#define FX_MODE_SINELON 90 -#define FX_MODE_POPCORN 91 class WS2812FX { @@ -322,9 +319,6 @@ class WS2812FX { _mode[FX_MODE_TRI_STATIC_PATTERN] = &WS2812FX::mode_tri_static_pattern; _mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots; _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; - _mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_BouncingBalls; - _mode[FX_MODE_SINELON] = &WS2812FX::mode_sinelon; - _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; @@ -508,9 +502,6 @@ class WS2812FX { mode_tri_static_pattern(void), mode_spots(void), mode_spots_fade(void), - mode_BouncingBalls(void), - mode_sinelon(void), - mode_popcorn(void), mode_glitter(void), mode_candle(void); @@ -587,8 +578,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Scanner Dual ","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle", -"Bouncing Balls", "Sinelon","Popcorn" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" ])====="; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index a577c95d4..90bf0ac8e 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912232 +#define VERSION 1912231 char versionString[] = "0.9.0-b2"; diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 8a43a79db..2f68703ea 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -561,7 +561,6 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load col[j] = EEPROM.read(i+j+2); colSec[j] = EEPROM.read(i+j+6); } - strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color } if (loadFX) { @@ -599,12 +598,6 @@ void savePreset(byte index) } EEPROM.write(i+10, effectCurrent); EEPROM.write(i+11, effectSpeed); - - uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; - EEPROM.write(i+12, (colTer >> 16) & 0xFF); - EEPROM.write(i+13, (colTer >> 8) & 0xFF); - EEPROM.write(i+14, (colTer >> 0) & 0xFF); - EEPROM.write(i+15, (colTer >> 24) & 0xFF); EEPROM.write(i+16, effectIntensity); EEPROM.write(i+17, effectPalette); From 7712faca0a2bad60ba40ee49056349e392c85619 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:11:04 +0100 Subject: [PATCH 07/26] manual merge --- wled00/wled00.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 90bf0ac8e..a577c95d4 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912231 +#define VERSION 1912232 char versionString[] = "0.9.0-b2"; From 58f41a1f9b7946489cc5a4d50c3198d5c239e3f7 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:12:54 +0100 Subject: [PATCH 08/26] manual merge #2 --- wled00/FX.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 4410a43b7..1791b710c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -301,24 +301,24 @@ uint16_t WS2812FX::scan(bool dual) uint32_t cycleTime = 750 + (255 - SEGMENT.speed)*150; uint32_t perc = now % cycleTime; uint16_t prog = (perc * 65535) / cycleTime; - uint16_t ledIndex = (prog * ((SEGLEN * 2) - 2)) >> 16; - uint16_t size = 1 + SEGMENT.intensity >> 3; + uint16_t size = 1 + ((SEGMENT.intensity * SEGLEN) >>9); + uint16_t ledIndex = (prog * ((SEGLEN *2) - size *2)) >> 16; fill(SEGCOLOR(1)); - int led_offset = ledIndex - (SEGLEN - 1); + int led_offset = ledIndex - (SEGLEN - size); led_offset = abs(led_offset); - uint16_t i = SEGMENT.start + led_offset; - for (int16_t j=i-size/2; j<=i+size/2; j++) { - if (j>=0) setPixelColor(j, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); + if (dual) { + for (uint16_t j = led_offset; j < led_offset + size; j++) { + uint16_t i2 = SEGMENT.stop -1 -j; + setPixelColor(i2, color_from_palette(i2, true, PALETTE_SOLID_WRAP, (SEGCOLOR(2))? 2:0)); + } } - if (dual) { - uint16_t i2 = SEGMENT.start + SEGLEN - led_offset - 1; - for (int16_t j=i2-size/2; j<=i2+size/2; j++) { - if (j>=0) setPixelColor(j, color_from_palette(i2, true, PALETTE_SOLID_WRAP, 0)); - } + for (uint16_t j = led_offset; j < led_offset + size; j++) { + uint16_t i = SEGMENT.start + j; + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); } return FRAMETIME; @@ -1004,7 +1004,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?i:SEGLEN-1-i; - setPixelColor(j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(SEGMENT.start + j, color_from_palette(j, true, PALETTE_SOLID_WRAP, 0)); } if (dual) { uint32_t c; @@ -1016,7 +1016,7 @@ uint16_t WS2812FX::larson_scanner(bool dual) { for (uint16_t i = SEGENV.step; i < index; i++) { uint16_t j = (SEGENV.aux0)?SEGLEN-1-i:i; - setPixelColor(j, c); + setPixelColor(SEGMENT.start + j, c); } } @@ -1034,7 +1034,7 @@ uint16_t WS2812FX::mode_comet(void) { fade_out(SEGMENT.intensity); - setPixelColor(index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); + setPixelColor(SEGMENT.start + index, color_from_palette(index, true, PALETTE_SOLID_WRAP, 0)); return FRAMETIME; } From 37827cdd6c95f83659c2f69f288580e822277d4e Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:20:38 +0100 Subject: [PATCH 09/26] another manual merge --- wled00/wled01_eeprom.ino | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 2f68703ea..8a43a79db 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -561,6 +561,7 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load col[j] = EEPROM.read(i+j+2); colSec[j] = EEPROM.read(i+j+6); } + strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color } if (loadFX) { @@ -598,6 +599,12 @@ void savePreset(byte index) } EEPROM.write(i+10, effectCurrent); EEPROM.write(i+11, effectSpeed); + + uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2]; + EEPROM.write(i+12, (colTer >> 16) & 0xFF); + EEPROM.write(i+13, (colTer >> 8) & 0xFF); + EEPROM.write(i+14, (colTer >> 0) & 0xFF); + EEPROM.write(i+15, (colTer >> 24) & 0xFF); EEPROM.write(i+16, effectIntensity); EEPROM.write(i+17, effectPalette); From f39b9041a032beb5c81c289b51d6c7bc4a5c9189 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 15:22:40 +0100 Subject: [PATCH 10/26] remove test --- wled00/FX.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 1791b710c..cfd204ef2 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1297,8 +1297,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); - if (SEGMENT.intensity > 127) return FRAMETIME; - return SPEED_FORMULA_L; + return FRAMETIME; } From 012045878d68a6e22c3c9b97b5e1dc2ada741926 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 24 Dec 2019 21:05:20 +0100 Subject: [PATCH 11/26] theatre rainbow too fast with a double-step --- wled00/FX.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index cfd204ef2..7ea1fe79c 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -414,7 +414,6 @@ uint16_t WS2812FX::mode_theater_chase(void) { * Inspired by the Adafruit examples. */ uint16_t WS2812FX::mode_theater_chase_rainbow(void) { - SEGENV.step = (SEGENV.step + 1) & 0xFF; return theater_chase(color_wheel(SEGENV.step), SEGCOLOR(1), false); } From e3def22b07f7bd0547ded1c00d2026bdd4d7bbaf Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Sat, 28 Dec 2019 15:43:55 +0100 Subject: [PATCH 12/26] add multi fireworks starburst effect --- wled00/FX.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ wled00/FX.h | 9 ++-- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c862a0854..a9fc1f039 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2348,3 +2348,119 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + +typedef struct Particle { + CRGB color; + uint32_t birth =0; + uint32_t last =0; + double vel =0; + uint16_t pos =0; + float fragment[40]; +} star; + +uint16_t WS2812FX::mode_starburst(void) { + uint32_t it = millis(); + + boolean Blend = true; + const uint8_t numStars = 10; + const uint8_t maxFrag = 15; + static star stars[numStars]; + float MaxSpeed = 375.0f; // Max velocity + int NewParticleProbability = 2; // Odds of new particle (out of 255) + float ParticlePreignitonTime = 0.0f; // How long to "wink" + float ParticleIgnition = 0.15f; // How long to "flash" + float ParticleHoldTime = 0.0f; // Main lifecycle time + float ParticleFadeTime = 1.4f; // Fade out time + float ParticleSize = 0.00f; // Size of the particle + + for (int j = 0; j < numStars; j++) + { + if (random8((265-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) + { + // Pick a random color and location. + uint16_t startPos = random8(SEGLEN-1); + CRGB color = col_to_crgb(color_wheel(random8())); + double multiplier = (double)(random8())/255.0 * 0.5; + + stars[j].color = color; + stars[j].pos = startPos; + stars[j].vel = MaxSpeed * (double)(random16())/65535.0 * multiplier; + stars[j].birth = it; + stars[j].last = it; + int num = 10+SEGMENT.intensity * random8(5,maxFrag)/255; + + for (int i=0; i<=maxFrag; i++) { + if (i < num) stars[j].fragment[i] = startPos; + else stars[j].fragment[i] = -1; + } + } + } + + fill(BLACK); + + for (int j=0; j 0) { + float dt = (it-stars[j].last)/1000.0; + + for (int i=0; i<=maxFrag; i++) { + int var = i/2; + if (stars[j].fragment[i] > 0) { + if (i % 2) { + stars[j].fragment[i] -= stars[j].vel * dt * (float)var/6.0; + } else { + stars[j].fragment[i] += stars[j].vel * dt * (float)var/6.0; + } + } + } + stars[j].last = it; + stars[j].vel -= 2*stars[j].vel*dt; + stars[j].color = stars[j].color.nscale8_video(235); + } + + CRGB c = stars[j].color; + + // If the star is brand new, it flashes white briefly. + // Otherwise it just fades over time. + float fade = 0.0f; + float age = (it-stars[j].birth)/1000.0; + + if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { + c = CRGB(WHITE); + } else { + // Figure out how much to fade and shrink the star based on + // its age relative to its lifetime + if (age < ParticlePreignitonTime) { + fade = 1.0 - (age / ParticlePreignitonTime); + } else { + age -= ParticlePreignitonTime; + if (age < ParticleHoldTime + ParticleIgnition) { + fade = 0.0f; // Just born + } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + } else { + age -= (ParticleHoldTime + ParticleIgnition); + fade = (age / ParticleFadeTime); // Fading star + } + } + c = c.nscale8_video(255-int(255.0*fade)); + } + ParticleSize = (1 - fade) * 5; + + for (int i=0; i<=maxFrag; i++) { + if (stars[j].fragment[i] > 0) { + int start = stars[j].fragment[i] - int(ParticleSize/2); + if (start<0) start = 0; + int end = stars[j].fragment[i] + int(ParticleSize/2); + if (end>SEGLEN-1) end = SEGLEN-1; + for (int p=start; p<=end; p++) { + setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); + } + } + } + + } + + return FRAMETIME; +} \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index 9ba70357d..f61cb4005 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 89 +#define MODE_COUNT 90 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -175,6 +175,7 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 +#define FX_MODE_STARBURST 89 class WS2812FX { @@ -321,6 +322,7 @@ class WS2812FX { _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; + _mode[FX_MODE_STARBURST] = &WS2812FX::mode_starburst; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -503,7 +505,8 @@ class WS2812FX { mode_spots(void), mode_spots_fade(void), mode_glitter(void), - mode_candle(void); + mode_candle(void), + mode_starburst(void); private: @@ -577,7 +580,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", "Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst" ])====="; From 5efd1f3a918d1e90678ada1eb826fba268727ee9 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 30 Dec 2019 00:04:56 +0100 Subject: [PATCH 13/26] add comment for source and description --- wled00/FX.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a9fc1f039..48048339d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2349,6 +2349,12 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + +/* +/ Fireworks in starburst effect +/ based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ +/ Speed sets frequency of new starbursts, intensity is the intensity of the burst +*/ typedef struct Particle { CRGB color; uint32_t birth =0; From f187d7258b73013ae8605b7379eabe80c4c7114b Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Mon, 30 Dec 2019 00:08:49 +0100 Subject: [PATCH 14/26] rework for slightly better visuals --- wled00/FX.cpp | 63 +++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 48048339d..501995ffb 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2360,7 +2360,7 @@ typedef struct Particle { uint32_t birth =0; uint32_t last =0; double vel =0; - uint16_t pos =0; + uint16_t pos =-1; float fragment[40]; } star; @@ -2368,34 +2368,36 @@ uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); boolean Blend = true; - const uint8_t numStars = 10; - const uint8_t maxFrag = 15; + const uint8_t numStars = 12; + const uint8_t maxFrag = 20; static star stars[numStars]; float MaxSpeed = 375.0f; // Max velocity int NewParticleProbability = 2; // Odds of new particle (out of 255) float ParticlePreignitonTime = 0.0f; // How long to "wink" - float ParticleIgnition = 0.15f; // How long to "flash" + float ParticleIgnition = 0.06f; // How long to "flash" float ParticleHoldTime = 0.0f; // Main lifecycle time - float ParticleFadeTime = 1.4f; // Fade out time + float ParticleFadeTime = 2.6f; // Fade out time float ParticleSize = 0.00f; // Size of the particle for (int j = 0; j < numStars; j++) { - if (random8((265-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) + // speed to adjust chance of a burst, max is nearly always. + if (random8((263-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) { // Pick a random color and location. uint16_t startPos = random8(SEGLEN-1); CRGB color = col_to_crgb(color_wheel(random8())); - double multiplier = (double)(random8())/255.0 * 0.5; + double multiplier = (float)(random8())/255.0 * 1.0; stars[j].color = color; stars[j].pos = startPos; - stars[j].vel = MaxSpeed * (double)(random16())/65535.0 * multiplier; + stars[j].vel = MaxSpeed * (float)(random8())/255.0 * multiplier; stars[j].birth = it; stars[j].last = it; - int num = 10+SEGMENT.intensity * random8(5,maxFrag)/255; + // more fragments means larger burst effect + int num = random8(5,10 + (SEGMENT.intensity * maxFrag/255)); - for (int i=0; i<=maxFrag; i++) { + for (int i=0; i<40; i++) { if (i < num) stars[j].fragment[i] = startPos; else stars[j].fragment[i] = -1; } @@ -2406,12 +2408,14 @@ uint16_t WS2812FX::mode_starburst(void) { for (int j=0; j 0) { + if (stars[j].birth != 0) { float dt = (it-stars[j].last)/1000.0; for (int i=0; i<=maxFrag; i++) { int var = i/2; + if (stars[j].fragment[i] > 0) { + // spplit fragments half to each side with some travelling further if (i % 2) { stars[j].fragment[i] -= stars[j].vel * dt * (float)var/6.0; } else { @@ -2420,8 +2424,8 @@ uint16_t WS2812FX::mode_starburst(void) { } } stars[j].last = it; - stars[j].vel -= 2*stars[j].vel*dt; - stars[j].color = stars[j].color.nscale8_video(235); + stars[j].vel -= 3*stars[j].vel*dt; + stars[j].color = stars[j].color.nscale8(235); } CRGB c = stars[j].color; @@ -2430,7 +2434,7 @@ uint16_t WS2812FX::mode_starburst(void) { // Otherwise it just fades over time. float fade = 0.0f; float age = (it-stars[j].birth)/1000.0; - + if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { c = CRGB(WHITE); } else { @@ -2439,34 +2443,33 @@ uint16_t WS2812FX::mode_starburst(void) { if (age < ParticlePreignitonTime) { fade = 1.0 - (age / ParticlePreignitonTime); } else { - age -= ParticlePreignitonTime; - if (age < ParticleHoldTime + ParticleIgnition) { - fade = 0.0f; // Just born - } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { - fade = 1.0f; // Black hole, all faded out - stars[j].birth = 0; - } else { - age -= (ParticleHoldTime + ParticleIgnition); - fade = (age / ParticleFadeTime); // Fading star - } + age -= ParticlePreignitonTime; + if (age < ParticleHoldTime + ParticleIgnition) { + fade = 0.0f; // Just born + } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + } else { + age -= (ParticleHoldTime + ParticleIgnition); + fade = (age / ParticleFadeTime); // Fading star + } } - c = c.nscale8_video(255-int(255.0*fade)); + + c = c.nscale8(255-int(255.0*fade)/2); } - ParticleSize = (1 - fade) * 5; + ParticleSize = (1 - fade) * 4; for (int i=0; i<=maxFrag; i++) { if (stars[j].fragment[i] > 0) { - int start = stars[j].fragment[i] - int(ParticleSize/2); + int start = int(stars[j].fragment[i]) - int(ParticleSize/2); if (start<0) start = 0; - int end = stars[j].fragment[i] + int(ParticleSize/2); + int end = int(stars[j].fragment[i]) + int(ParticleSize/2); if (end>SEGLEN-1) end = SEGLEN-1; for (int p=start; p<=end; p++) { setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); } } } - } - return FRAMETIME; } \ No newline at end of file From 508804d0d5548a47ba2f39ec5b81bd7bb6ae2739 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 30 Dec 2019 01:18:19 +0100 Subject: [PATCH 15/26] Few fixes for tricolor wipe --- wled00/FX.cpp | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 7ea1fe79c..6eab3195b 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1296,7 +1296,7 @@ uint16_t WS2812FX::mode_icu(void) { setPixelColor(SEGMENT.start + dest, col); setPixelColor(SEGMENT.start + dest + SEGLEN/2, col); - return FRAMETIME; + return SPEED_FORMULA_L; } @@ -1305,24 +1305,35 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { - uint32_t cycleTime = 40 + (3 * (uint32_t)(255 - SEGMENT.speed)); - uint32_t it = now / cycleTime; - if (SEGENV.step == it) return FRAMETIME; - uint8_t incr = it-SEGENV.step; + uint32_t counter = now / (40 + (3 * (uint32_t)(255 - SEGMENT.speed))); + uint32_t prog = counter % (SEGLEN * 3); + uint16_t led_offset = prog; - if(SEGENV.step < SEGLEN) { - uint32_t led_offset = SEGENV.step; - setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(0)); - } else if (SEGENV.step < SEGLEN*2) { - uint32_t led_offset = SEGENV.step - SEGLEN; - setPixelColor(SEGMENT.start + led_offset, SEGCOLOR(1)); - } else + for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { - uint32_t led_offset = SEGENV.step - SEGLEN*2; - setPixelColor(SEGMENT.start + led_offset, color_from_palette(SEGMENT.start + led_offset, true, PALETTE_SOLID_WRAP, 2)); + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 2)); + } + + if(prog < SEGLEN) { //wipe from 0 to 1 + for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) + { + setPixelColor(i, (i - SEGMENT.start > led_offset)? SEGCOLOR(0) : SEGCOLOR(1)); + } + } else if (prog < SEGLEN*2) { //wipe from 1 to 2 + led_offset = prog - SEGLEN; + for (uint16_t i = SEGMENT.start +led_offset +1; i < SEGMENT.stop; i++) + { + setPixelColor(i, SEGCOLOR(1)); + } + } else //wipe from 2 to 0 + { + led_offset = prog - SEGLEN*2; + for (uint16_t i = SEGMENT.start; i <= SEGMENT.start +led_offset; i++) + { + setPixelColor(i, SEGCOLOR(0)); + } } - SEGENV.step = (SEGENV.step + 1) % (SEGLEN * 3); return FRAMETIME; } @@ -1335,16 +1346,16 @@ uint16_t WS2812FX::mode_tricolor_wipe(void) uint16_t WS2812FX::mode_tricolor_fade(void) { uint16_t counter = now * ((SEGMENT.speed >> 3) +1); - SEGENV.step = (counter * 768) >> 16; + uint32_t prog = (counter * 768) >> 16; uint32_t color1 = 0, color2 = 0; byte stage = 0; - if(SEGENV.step < 256) { + if(prog < 256) { color1 = SEGCOLOR(0); color2 = SEGCOLOR(1); stage = 0; - } else if(SEGENV.step < 512) { + } else if(prog < 512) { color1 = SEGCOLOR(1); color2 = SEGCOLOR(2); stage = 1; @@ -1354,7 +1365,7 @@ uint16_t WS2812FX::mode_tricolor_fade(void) stage = 2; } - byte stp = SEGENV.step % 256; + byte stp = prog; // % 256 uint32_t color = 0; for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { if (stage == 2) { From 8ca6ca2c88e02b934444122c1423053b983604b0 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 30 Dec 2019 01:40:38 +0100 Subject: [PATCH 16/26] TriWipe synced --- wled00/FX.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 6eab3195b..76aee7bf6 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -1305,30 +1305,32 @@ uint16_t WS2812FX::mode_icu(void) { */ uint16_t WS2812FX::mode_tricolor_wipe(void) { - uint32_t counter = now / (40 + (3 * (uint32_t)(255 - SEGMENT.speed))); - uint32_t prog = counter % (SEGLEN * 3); - uint16_t led_offset = prog; + uint32_t cycleTime = 1000 + (255 - SEGMENT.speed)*200; + uint32_t perc = now % cycleTime; + uint16_t prog = (perc * 65535) / cycleTime; + uint16_t ledIndex = (prog * SEGLEN * 3) >> 16; + uint16_t ledOffset = ledIndex; for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 2)); } - if(prog < SEGLEN) { //wipe from 0 to 1 + if(ledIndex < SEGLEN) { //wipe from 0 to 1 for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { - setPixelColor(i, (i - SEGMENT.start > led_offset)? SEGCOLOR(0) : SEGCOLOR(1)); + setPixelColor(i, (i - SEGMENT.start > ledOffset)? SEGCOLOR(0) : SEGCOLOR(1)); } - } else if (prog < SEGLEN*2) { //wipe from 1 to 2 - led_offset = prog - SEGLEN; - for (uint16_t i = SEGMENT.start +led_offset +1; i < SEGMENT.stop; i++) + } else if (ledIndex < SEGLEN*2) { //wipe from 1 to 2 + ledOffset = ledIndex - SEGLEN; + for (uint16_t i = SEGMENT.start +ledOffset +1; i < SEGMENT.stop; i++) { setPixelColor(i, SEGCOLOR(1)); } } else //wipe from 2 to 0 { - led_offset = prog - SEGLEN*2; - for (uint16_t i = SEGMENT.start; i <= SEGMENT.start +led_offset; i++) + ledOffset = ledIndex - SEGLEN*2; + for (uint16_t i = SEGMENT.start; i <= SEGMENT.start +ledOffset; i++) { setPixelColor(i, SEGCOLOR(0)); } From 6e35b5ba8b6a39658836d761a3acfb688df6d1b0 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 30 Dec 2019 17:34:15 +0100 Subject: [PATCH 17/26] Fix analog write range --- wled00/FX.cpp | 2 +- wled00/NpbWrapper.h | 35 +++++++++++++++++------------------ wled00/wled00.ino | 2 +- wled00/wled19_json.ino | 2 +- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index aeba14854..552b0f55f 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -242,7 +242,7 @@ uint16_t WS2812FX::mode_dynamic(void) { uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*15; uint32_t it = now / cycleTime; - if (it != SEGENV.step) //new color + if (it != SEGENV.step && SEGMENT.speed != 0) //new color { for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { if (random8() <= SEGMENT.intensity) _locked[i] = random8(); diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index a704e4269..05d738680 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -130,26 +130,25 @@ public: _pGrbw = new NeoPixelBrightnessBus(countPixels, LEDPIN); #endif _pGrbw->Begin(); - break; - - #ifdef WLED_USE_ANALOG_LEDS - //init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller - pinMode(RPIN, OUTPUT); - pinMode(GPIN, OUTPUT); - pinMode(BPIN, OUTPUT); - switch (_type) { - case NeoPixelType_Grb: break; - #ifdef WLED_USE_5CH_LEDS - case NeoPixelType_Grbw: pinMode(WPIN, OUTPUT); pinMode(W2PIN, OUTPUT); break; - #else - case NeoPixelType_Grbw: pinMode(WPIN, OUTPUT); break; - #endif - } - analogWriteRange(255); //same range as one RGB channel - analogWriteFreq(880); //PWM frequency proven as good for LEDs + + #ifdef WLED_USE_ANALOG_LEDS + pinMode(WPIN, OUTPUT); + #ifdef WLED_USE_5CH_LEDS + pinMode(W2PIN, OUTPUT); #endif - + #endif + + break; } + + #ifdef WLED_USE_ANALOG_LEDS + //init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller + pinMode(RPIN, OUTPUT); + pinMode(GPIN, OUTPUT); + pinMode(BPIN, OUTPUT); + analogWriteRange(255); //same range as one RGB channel + analogWriteFreq(880); //PWM frequency proven as good for LEDs + #endif } #ifdef WLED_USE_ANALOG_LEDS diff --git a/wled00/wled00.ino b/wled00/wled00.ino index a577c95d4..0d120292f 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912232 +#define VERSION 1912291 char versionString[] = "0.9.0-b2"; diff --git a/wled00/wled19_json.ino b/wled00/wled19_json.ino index 3e135d406..802941a62 100644 --- a/wled00/wled19_json.ino +++ b/wled00/wled19_json.ino @@ -243,7 +243,7 @@ void serializeInfo(JsonObject root) leds_pin.add(LEDPIN); leds["pwr"] = strip.currentMilliamps; - leds["maxpwr"] = strip.ablMilliampsMax; + leds["maxpwr"] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0; leds["maxseg"] = strip.getMaxSegments(); leds["seglock"] = false; //will be used in the future to prevent modifications to segment config From 51fb981d24e75300ad0833688c513a9041ab5c9e Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 11:11:05 +0100 Subject: [PATCH 18/26] Add possiblilty for segments to dynamically allocate memory --- wled00/FX.h | 39 +++++++++++++++++++++++++++++++++++---- wled00/FX_fcn.cpp | 6 +++++- wled00/wled00.ino | 2 +- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/wled00/FX.h b/wled00/FX.h index 53096b7e0..8f2ba95ba 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -44,10 +44,17 @@ #define WLED_FPS 42 #define FRAMETIME (1000/WLED_FPS) -/* each segment uses 37 bytes of SRAM memory, so if you're application fails because of +/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ #define MAX_NUM_SEGMENTS 10 +/* How much data bytes all segments combined may allocate */ +#ifdef ESP8266 +#define MAX_SEGMENT_DATA 2048 +#else +#define MAX_SEGMENT_DATA 8192 +#endif + #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] #define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x]) @@ -221,13 +228,35 @@ class WS2812FX { } segment; // segment runtime parameters - typedef struct Segment_runtime { // 16 bytes + typedef struct Segment_runtime { // 28 bytes unsigned long next_time; uint32_t step; uint32_t call; uint16_t aux0; uint16_t aux1; - void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;}; + byte* data = nullptr; + bool allocateData(uint16_t len){ + if (data && _dataLen == len) return true; //already allocated + deallocateData(); + if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory + data = new (std::nothrow) byte[len]; + if (!data) return false; //allocation failed + WS2812FX::_usedSegmentData += len; + _dataLen = len; + memset(data, 0, len); + return true; + } + void deallocateData(){ + if (data) { + delete[] data; + } + data = nullptr; + WS2812FX::_usedSegmentData -= _dataLen; + _dataLen = 0; + } + void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();} + private: + uint16_t _dataLen = 0; } segment_runtime; WS2812FX() { @@ -518,6 +547,7 @@ class WS2812FX { uint16_t _length, _lengthRaw, _usableCount; uint16_t _rand16seed; uint8_t _brightness; + static uint16_t _usedSegmentData; void handle_palette(void); void fill(uint32_t); @@ -564,7 +594,8 @@ class WS2812FX { // start, stop, speed, intensity, palette, mode, options, 3 unused bytes (group, spacing, opacity), color[] { 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}} }; - segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element + segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element + friend class Segment_runtime; }; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 2b7d6ec1d..7fa6eae89 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -473,7 +473,7 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) { void WS2812FX::resetSegments() { memset(_segments, 0, sizeof(_segments)); - memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); + //memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); _segment_index = 0; _segments[0].mode = DEFAULT_MODE; _segments[0].colors[0] = DEFAULT_COLOR; @@ -484,7 +484,9 @@ void WS2812FX::resetSegments() { for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) { _segments[i].colors[0] = color_wheel(i*51); + _segment_runtimes[i].reset(); } + _segment_runtimes[0].reset(); } void WS2812FX::setIndividual(uint16_t i, uint32_t col) @@ -862,3 +864,5 @@ uint32_t WS2812FX::gamma32(uint32_t color) b = gammaT[b]; return ((w << 24) | (r << 16) | (g << 8) | (b)); } + +uint16_t WS2812FX::_usedSegmentData = 0; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 0d120292f..6a1a7b072 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912291 +#define VERSION 1912311 char versionString[] = "0.9.0-b2"; From 1671c782609257ef9c84b630913c3c1010577ab3 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 12:35:18 +0100 Subject: [PATCH 19/26] First working state --- wled00/FX.cpp | 29 ++++++++++++++--------------- wled00/wled00.ino | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 193adfacc..a5a207336 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2444,21 +2444,21 @@ uint16_t WS2812FX::mode_candle() / based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ / Speed sets frequency of new starbursts, intensity is the intensity of the burst */ +#define STARBURST_MAX_FRAG 20 + typedef struct Particle { CRGB color; uint32_t birth =0; uint32_t last =0; double vel =0; uint16_t pos =-1; - float fragment[40]; + float fragment[STARBURST_MAX_FRAG]; } star; uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - boolean Blend = true; const uint8_t numStars = 12; - const uint8_t maxFrag = 20; static star stars[numStars]; float MaxSpeed = 375.0f; // Max velocity int NewParticleProbability = 2; // Odds of new particle (out of 255) @@ -2466,15 +2466,14 @@ uint16_t WS2812FX::mode_starburst(void) { float ParticleIgnition = 0.06f; // How long to "flash" float ParticleHoldTime = 0.0f; // Main lifecycle time float ParticleFadeTime = 2.6f; // Fade out time - float ParticleSize = 0.00f; // Size of the particle for (int j = 0; j < numStars; j++) { // speed to adjust chance of a burst, max is nearly always. - if (random8((263-SEGMENT.speed)/2) < NewParticleProbability && stars[j].birth==0) + if (random8((263-SEGMENT.speed)>>1) < NewParticleProbability && stars[j].birth==0) { // Pick a random color and location. - uint16_t startPos = random8(SEGLEN-1); + uint16_t startPos = random16(SEGLEN-1); CRGB color = col_to_crgb(color_wheel(random8())); double multiplier = (float)(random8())/255.0 * 1.0; @@ -2484,9 +2483,9 @@ uint16_t WS2812FX::mode_starburst(void) { stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect - int num = random8(5,10 + (SEGMENT.intensity * maxFrag/255)); + int num = random8(5,10 + (SEGMENT.intensity * STARBURST_MAX_FRAG/255)); - for (int i=0; i<40; i++) { + for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (i < num) stars[j].fragment[i] = startPos; else stars[j].fragment[i] = -1; } @@ -2500,7 +2499,7 @@ uint16_t WS2812FX::mode_starburst(void) { if (stars[j].birth != 0) { float dt = (it-stars[j].last)/1000.0; - for (int i=0; i<=maxFrag; i++) { + for (int i=0; i < STARBURST_MAX_FRAG; i++) { int var = i/2; if (stars[j].fragment[i] > 0) { @@ -2525,7 +2524,7 @@ uint16_t WS2812FX::mode_starburst(void) { float age = (it-stars[j].birth)/1000.0; if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { - c = CRGB(WHITE); + c = CRGB(ULTRAWHITE); } else { // Figure out how much to fade and shrink the star based on // its age relative to its lifetime @@ -2546,19 +2545,19 @@ uint16_t WS2812FX::mode_starburst(void) { c = c.nscale8(255-int(255.0*fade)/2); } - ParticleSize = (1 - fade) * 4; + float ParticleSize = (1 - fade) * 4; - for (int i=0; i<=maxFrag; i++) { + for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (stars[j].fragment[i] > 0) { int start = int(stars[j].fragment[i]) - int(ParticleSize/2); if (start<0) start = 0; int end = int(stars[j].fragment[i]) + int(ParticleSize/2); - if (end>SEGLEN-1) end = SEGLEN-1; - for (int p=start; p<=end; p++) { + if (end > SEGLEN) end = SEGLEN; + for (int p = start; p < end; p++) { setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); } } } } return FRAMETIME; -} \ No newline at end of file +} diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 6a1a7b072..c77eae7ac 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912311 +#define VERSION 1912312 char versionString[] = "0.9.0-b2"; From 8b6366688a37151b9e7ba1b75dd359eb50f2d180 Mon Sep 17 00:00:00 2001 From: fishbone-git Date: Tue, 31 Dec 2019 13:47:17 +0100 Subject: [PATCH 20/26] minor updates for cleanup --- wled00/FX.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 501995ffb..fa4bbef09 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2359,25 +2359,23 @@ typedef struct Particle { CRGB color; uint32_t birth =0; uint32_t last =0; - double vel =0; + float vel =0; uint16_t pos =-1; - float fragment[40]; + float fragment[30]; } star; uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - boolean Blend = true; - const uint8_t numStars = 12; - const uint8_t maxFrag = 20; + const uint8_t numStars = 12; // max starburtsts at one time + const uint8_t maxFrag = 20; // max fragments from each burst static star stars[numStars]; - float MaxSpeed = 375.0f; // Max velocity + int MaxSpeed = 375; // Max velocity int NewParticleProbability = 2; // Odds of new particle (out of 255) float ParticlePreignitonTime = 0.0f; // How long to "wink" - float ParticleIgnition = 0.06f; // How long to "flash" + float ParticleIgnition = 0.06f; // How long to "flash" float ParticleHoldTime = 0.0f; // Main lifecycle time float ParticleFadeTime = 2.6f; // Fade out time - float ParticleSize = 0.00f; // Size of the particle for (int j = 0; j < numStars; j++) { @@ -2387,7 +2385,7 @@ uint16_t WS2812FX::mode_starburst(void) { // Pick a random color and location. uint16_t startPos = random8(SEGLEN-1); CRGB color = col_to_crgb(color_wheel(random8())); - double multiplier = (float)(random8())/255.0 * 1.0; + float multiplier = (float)(random8())/255.0 * 1.0; stars[j].color = color; stars[j].pos = startPos; @@ -2397,7 +2395,7 @@ uint16_t WS2812FX::mode_starburst(void) { // more fragments means larger burst effect int num = random8(5,10 + (SEGMENT.intensity * maxFrag/255)); - for (int i=0; i<40; i++) { + for (int i=0; i<30; i++) { if (i < num) stars[j].fragment[i] = startPos; else stars[j].fragment[i] = -1; } @@ -2457,7 +2455,7 @@ uint16_t WS2812FX::mode_starburst(void) { c = c.nscale8(255-int(255.0*fade)/2); } - ParticleSize = (1 - fade) * 4; + float ParticleSize = (1 - fade) * 4; for (int i=0; i<=maxFrag; i++) { if (stars[j].fragment[i] > 0) { From 446e2c123f9ad0235ad37974bc12feb414467d5f Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 16:37:44 +0100 Subject: [PATCH 21/26] More improvements --- wled00/FX.cpp | 61 ++++++++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index a5a207336..ebd22f679 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2458,28 +2458,24 @@ typedef struct Particle { uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - const uint8_t numStars = 12; + const uint8_t numStars = 4; static star stars[numStars]; - float MaxSpeed = 375.0f; // Max velocity - int NewParticleProbability = 2; // Odds of new particle (out of 255) - float ParticlePreignitonTime = 0.0f; // How long to "wink" - float ParticleIgnition = 0.06f; // How long to "flash" - float ParticleHoldTime = 0.0f; // Main lifecycle time - float ParticleFadeTime = 2.6f; // Fade out time + float maxSpeed = 375.0f; // Max velocity + float ParticleIgnition = 250.0f; // How long to "flash" + float ParticleFadeTime = 1500.0f; // Fade out time for (int j = 0; j < numStars; j++) { // speed to adjust chance of a burst, max is nearly always. - if (random8((263-SEGMENT.speed)>>1) < NewParticleProbability && stars[j].birth==0) + if (random8((144-(SEGMENT.speed >> 1))) == 0 && stars[j].birth == 0) { // Pick a random color and location. uint16_t startPos = random16(SEGLEN-1); - CRGB color = col_to_crgb(color_wheel(random8())); double multiplier = (float)(random8())/255.0 * 1.0; - stars[j].color = color; + stars[j].color = col_to_crgb(color_wheel(random8())); stars[j].pos = startPos; - stars[j].vel = MaxSpeed * (float)(random8())/255.0 * multiplier; + stars[j].vel = maxSpeed * (float)(random8())/255.0 * multiplier; stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect @@ -2492,7 +2488,7 @@ uint16_t WS2812FX::mode_starburst(void) { } } - fill(BLACK); + fill(SEGCOLOR(1)); for (int j=0; j> 1; if (stars[j].fragment[i] > 0) { // spplit fragments half to each side with some travelling further @@ -2513,7 +2509,6 @@ uint16_t WS2812FX::mode_starburst(void) { } stars[j].last = it; stars[j].vel -= 3*stars[j].vel*dt; - stars[j].color = stars[j].color.nscale8(235); } CRGB c = stars[j].color; @@ -2521,37 +2516,33 @@ uint16_t WS2812FX::mode_starburst(void) { // If the star is brand new, it flashes white briefly. // Otherwise it just fades over time. float fade = 0.0f; - float age = (it-stars[j].birth)/1000.0; + float age = it-stars[j].birth; - if (age > ParticlePreignitonTime && age < ParticleIgnition + ParticlePreignitonTime) { - c = CRGB(ULTRAWHITE); + if (age < ParticleIgnition) { + c = col_to_crgb(color_blend(ULTRAWHITE, crgb_to_col(c), 254.5f*((age / ParticleIgnition)))); } else { // Figure out how much to fade and shrink the star based on // its age relative to its lifetime - if (age < ParticlePreignitonTime) { - fade = 1.0 - (age / ParticlePreignitonTime); + if (age > ParticleIgnition + ParticleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + c = col_to_crgb(SEGCOLOR(1)); } else { - age -= ParticlePreignitonTime; - if (age < ParticleHoldTime + ParticleIgnition) { - fade = 0.0f; // Just born - } else if (age > ParticleHoldTime + ParticleIgnition + ParticleFadeTime) { - fade = 1.0f; // Black hole, all faded out - stars[j].birth = 0; - } else { - age -= (ParticleHoldTime + ParticleIgnition); - fade = (age / ParticleFadeTime); // Fading star - } + age -= ParticleIgnition; + fade = (age / ParticleFadeTime); // Fading star + byte f = 254.5f*fade; + c = col_to_crgb(color_blend(crgb_to_col(c), SEGCOLOR(1), f)); } - - c = c.nscale8(255-int(255.0*fade)/2); } - float ParticleSize = (1 - fade) * 4; + + float ParticleSize = (1.0 - fade) * 2; for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (stars[j].fragment[i] > 0) { - int start = int(stars[j].fragment[i]) - int(ParticleSize/2); - if (start<0) start = 0; - int end = int(stars[j].fragment[i]) + int(ParticleSize/2); + int start = int(stars[j].fragment[i]) - int(ParticleSize); + if (start < 0) start = 0; + int end = int(stars[j].fragment[i]) + int(ParticleSize); + if (start == end) end++; if (end > SEGLEN) end = SEGLEN; for (int p = start; p < end; p++) { setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); From 21b498fecec35a7fc5389a84f78106c3881b1629 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Tue, 31 Dec 2019 19:01:37 +0100 Subject: [PATCH 22/26] Memory optimizations --- wled00/FX.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ebd22f679..3d8399954 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2444,9 +2444,9 @@ uint16_t WS2812FX::mode_candle() / based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ / Speed sets frequency of new starbursts, intensity is the intensity of the burst */ -#define STARBURST_MAX_FRAG 20 +#define STARBURST_MAX_FRAG 12 -typedef struct Particle { +typedef struct particle { CRGB color; uint32_t birth =0; uint32_t last =0; @@ -2458,11 +2458,11 @@ typedef struct Particle { uint16_t WS2812FX::mode_starburst(void) { uint32_t it = millis(); - const uint8_t numStars = 4; + const uint8_t numStars = 15; static star stars[numStars]; float maxSpeed = 375.0f; // Max velocity - float ParticleIgnition = 250.0f; // How long to "flash" - float ParticleFadeTime = 1500.0f; // Fade out time + float particleIgnition = 250.0f; // How long to "flash" + float particleFadeTime = 1500.0f; // Fade out time for (int j = 0; j < numStars; j++) { @@ -2471,7 +2471,7 @@ uint16_t WS2812FX::mode_starburst(void) { { // Pick a random color and location. uint16_t startPos = random16(SEGLEN-1); - double multiplier = (float)(random8())/255.0 * 1.0; + float multiplier = (float)(random8())/255.0 * 1.0; stars[j].color = col_to_crgb(color_wheel(random8())); stars[j].pos = startPos; @@ -2479,7 +2479,7 @@ uint16_t WS2812FX::mode_starburst(void) { stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect - int num = random8(5,10 + (SEGMENT.intensity * STARBURST_MAX_FRAG/255)); + int num = random8(3,6 + (SEGMENT.intensity >> 5)); for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (i < num) stars[j].fragment[i] = startPos; @@ -2499,12 +2499,8 @@ uint16_t WS2812FX::mode_starburst(void) { int var = i >> 1; if (stars[j].fragment[i] > 0) { - // spplit fragments half to each side with some travelling further - if (i % 2) { - stars[j].fragment[i] -= stars[j].vel * dt * (float)var/6.0; - } else { - stars[j].fragment[i] += stars[j].vel * dt * (float)var/6.0; - } + //all fragments travel right, will be mirrored on other side + stars[j].fragment[i] += stars[j].vel * dt * (float)var/3.0; } } stars[j].last = it; @@ -2518,30 +2514,34 @@ uint16_t WS2812FX::mode_starburst(void) { float fade = 0.0f; float age = it-stars[j].birth; - if (age < ParticleIgnition) { - c = col_to_crgb(color_blend(ULTRAWHITE, crgb_to_col(c), 254.5f*((age / ParticleIgnition)))); + if (age < particleIgnition) { + c = col_to_crgb(color_blend(WHITE, crgb_to_col(c), 254.5f*((age / particleIgnition)))); } else { // Figure out how much to fade and shrink the star based on // its age relative to its lifetime - if (age > ParticleIgnition + ParticleFadeTime) { + if (age > particleIgnition + particleFadeTime) { fade = 1.0f; // Black hole, all faded out stars[j].birth = 0; c = col_to_crgb(SEGCOLOR(1)); } else { - age -= ParticleIgnition; - fade = (age / ParticleFadeTime); // Fading star + age -= particleIgnition; + fade = (age / particleFadeTime); // Fading star byte f = 254.5f*fade; c = col_to_crgb(color_blend(crgb_to_col(c), SEGCOLOR(1), f)); } } - float ParticleSize = (1.0 - fade) * 2; + float particleSize = (1.0 - fade) * 2; - for (int i=0; i < STARBURST_MAX_FRAG; i++) { + for (uint8_t index=0; index < STARBURST_MAX_FRAG*2; index++) { + bool mirrored = index & 0x1; + uint8_t i = index >> 1; if (stars[j].fragment[i] > 0) { - int start = int(stars[j].fragment[i]) - int(ParticleSize); + float loc = stars[j].fragment[i]; + if (mirrored) loc -= (loc-stars[j].pos)*2; + int start = loc - particleSize; + int end = loc + particleSize; if (start < 0) start = 0; - int end = int(stars[j].fragment[i]) + int(ParticleSize); if (start == end) end++; if (end > SEGLEN) end = SEGLEN; for (int p = start; p < end; p++) { From 1c6b1c530f1c97c882398ed073d3501e77c6d766 Mon Sep 17 00:00:00 2001 From: srg74 <28492985+srg74@users.noreply.github.com> Date: Tue, 31 Dec 2019 17:52:59 -0500 Subject: [PATCH 23/26] Update wled06_usermod.ino Corrected pin numbering --- usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino index c73170645..593625b91 100644 --- a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino +++ b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino @@ -1,7 +1,7 @@ #include // from https://github.com/olikraus/u8g2/ //The SCL and SDA pins are defined here. -//Lolin32 boards use SCL=4 SDA=5 +//Lolin32 boards use SCL=5 SDA=4 #define U8X8_PIN_SCL 5 #define U8X8_PIN_SDA 4 From 58861fa524e38c46a93ef964662719f1dd0a6d42 Mon Sep 17 00:00:00 2001 From: srg74 <28492985+srg74@users.noreply.github.com> Date: Tue, 31 Dec 2019 17:57:15 -0500 Subject: [PATCH 24/26] Update platformio.ini Added commented library reference for OLED display --- platformio.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index c4cac76d1..45f2148fe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -41,6 +41,8 @@ lib_deps_external = IRremoteESP8266@2.5.5 #Time@1.5 #Timezone@1.2.1 + #For use SSD1306 0.91" OLED display uncomment following + #U8g2@~2.27.2 [common:esp8266] # ------------------------------------------------------------------------------ @@ -214,4 +216,4 @@ build_flags = -D WLED_ENABLE_5CH_LEDS lib_deps = ${common.lib_deps_external} - \ No newline at end of file + From 4dfc1631af08bc26b6c4ff92b31a15cb57a20019 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Wed, 1 Jan 2020 01:04:54 +0100 Subject: [PATCH 25/26] Few Cronixie fixes --- wled00/wled03_set.ino | 7 ++++--- wled00/wled10_ntp.ino | 17 ++++++++++------- wled00/wled13_cronixie.ino | 1 - 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 3f08d2807..9c753fec2 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -622,6 +622,10 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) //cronixie #ifndef WLED_DISABLE_CRONIXIE + //mode, 1 countdown + pos = req.indexOf("NM="); + if (pos > 0) countdownMode = (req.charAt(pos+3) != '0'); + pos = req.indexOf("NX="); //sets digits to code if (pos > 0) { strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 6); @@ -636,9 +640,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) overlayRefreshedTime = 0; } #endif - //mode, 1 countdown - pos = req.indexOf("NM="); - if (pos > 0) countdownMode = (req.charAt(pos+3) != '0'); pos = req.indexOf("U0="); //user var 0 if (pos > 0) { diff --git a/wled00/wled10_ntp.ino b/wled00/wled10_ntp.ino index 57a810f14..bf8df064d 100644 --- a/wled00/wled10_ntp.ino +++ b/wled00/wled10_ntp.ino @@ -163,13 +163,16 @@ void setCountdown() //returns true if countdown just over bool checkCountdown() { - long diff = countdownTime - now(); - local = abs(diff); - if (diff <0 && !countdownOverTriggered) - { - if (macroCountdown != 0) applyMacro(macroCountdown); - countdownOverTriggered = true; - return true; + unsigned long n = now(); + local = countdownTime - n; + if (n > countdownTime) { + local = n - countdownTime; + if (!countdownOverTriggered) + { + if (macroCountdown != 0) applyMacro(macroCountdown); + countdownOverTriggered = true; + return true; + } } return false; } diff --git a/wled00/wled13_cronixie.ino b/wled00/wled13_cronixie.ino index dac324751..4c5a74961 100644 --- a/wled00/wled13_cronixie.ino +++ b/wled00/wled13_cronixie.ino @@ -147,7 +147,6 @@ void _overlayCronixie() { if (countdownMode) checkCountdown(); #ifndef WLED_DISABLE_CRONIXIE - byte h = hour(local); byte h0 = h; byte m = minute(local); From 22c1f4bb4e3aa6d963547489fcf5bc236226e28d Mon Sep 17 00:00:00 2001 From: srg74 <28492985+srg74@users.noreply.github.com> Date: Tue, 31 Dec 2019 19:53:25 -0500 Subject: [PATCH 26/26] Update readme.txt Minor editing --- usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt b/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt index 62401f8ee..612873360 100644 --- a/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt +++ b/usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.txt @@ -4,5 +4,5 @@ This code uses Aircookie's WLED software. It has a premade file for user modific To install: -Add the enties in the WLED00 file to the top of the same file from Aircoookies WLED. +Add the entries in the WLED00 file to the top of the same file from Aircoookies WLED. Replace the WLED06_usermod.ino file in Aircoookies WLED folder.