diff --git a/usermods/rotary_encoder_change_effect/wled06_usermod.ino b/usermods/rotary_encoder_change_effect/wled06_usermod.ino new file mode 100644 index 000000000..dbde9560a --- /dev/null +++ b/usermods/rotary_encoder_change_effect/wled06_usermod.ino @@ -0,0 +1,45 @@ +//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) + +long lastTime = 0; +int delayMs = 10; +const int pinA = D6; //data +const int pinB = D7; //clk +int oldA = LOW; + +//gets called once at boot. Do all initialization that doesn't depend on network here +void userSetup() { + pinMode(pinA, INPUT_PULLUP); + pinMode(pinB, INPUT_PULLUP); +} + +//gets called every time WiFi is (re-)connected. Initialize own network interfaces here +void userConnected() { +} + +//loop. You can use "if (WLED_CONNECTED)" to check for successful connection +void userLoop() { + if (millis()-lastTime > delayMs) { + int A = digitalRead(pinA); + int B = digitalRead(pinB); + + if (oldA == LOW && A == HIGH) { + if (oldB == HIGH) { + // bri += 10; + // if (bri > 250) bri = 10; + effectCurrent += 1; + if (effectCurrent >= MODE_COUNT) effectCurrent = 0; + } + else { + // bri -= 10; + // if (bri < 10) bri = 250; + effectCurrent -= 1; + if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1); + } + oldA = A; + + //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) + // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa + colorUpdated(6); + lastTime = millis(); + } +} diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 9a2da2043..5fbde07f8 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -533,11 +533,18 @@ uint16_t WS2812FX::mode_dissolve_random(void) { */ 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)); + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 1)); } - SEGENV.aux0 = random16(SEGLEN); // aux0 stores the random led index + uint32_t cycleTime = 10 + (255 - SEGMENT.speed)*2; + uint32_t it = now / cycleTime; + if (it != SEGENV.step) + { + SEGENV.aux0 = random16(SEGLEN); // aux0 stores the random led index + SEGENV.step = it; + } + setPixelColor(SEGMENT.start + SEGENV.aux0, SEGCOLOR(0)); - return 10 + (uint16_t)(255 - SEGMENT.speed); + return FRAMETIME; } @@ -546,15 +553,10 @@ uint16_t WS2812FX::mode_sparkle(void) { * Inspired by www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/ */ uint16_t WS2812FX::mode_flash_sparkle(void) { - if(SEGENV.call == 0) { - for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { - setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); - } + for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) { + setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); } - uint16_t i = SEGMENT.start + SEGENV.aux0; - setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0)); - if(random8(5) == 0) { SEGENV.aux0 = random16(SEGLEN); // aux0 stores the random led index setPixelColor(SEGMENT.start + SEGENV.aux0, SEGCOLOR(1)); @@ -613,7 +615,6 @@ uint16_t WS2812FX::mode_multi_strobe(void) { uint16_t WS2812FX::mode_android(void) { if (SEGENV.call == 0) { - SEGENV.aux0 = 0; SEGENV.step = SEGMENT.start; } @@ -1530,13 +1531,13 @@ uint16_t WS2812FX::mode_palette() } bool noWrap = (paletteBlend == 2 || (paletteBlend == 0 && SEGMENT.speed == 0)); - for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) + for (uint16_t i = 0; i < SEGLEN; i++) { uint8_t colorIndex = (i * 255 / SEGLEN) - counter; if (noWrap) colorIndex = map(colorIndex, 0, 255, 0, 240); //cut off blend at palette "end" - setPixelColor(i, color_from_palette(colorIndex, false, true, 255)); + setPixelColor(SEGMENT.start + i, color_from_palette(colorIndex, false, true, 255)); } return FRAMETIME; } @@ -2376,6 +2377,20 @@ uint16_t WS2812FX::mode_sinelon(void) { } +//Rainbow with glitter, inspired by https://gist.github.com/kriegsman/062e10f7f07ba8518af6 +uint16_t WS2812FX::mode_glitter() +{ + mode_palette(); + + if (SEGMENT.intensity > random8()) + { + setPixelColor(SEGMENT.start + random16(SEGLEN), ULTRAWHITE); + } + + return FRAMETIME; +} + + /* * POPCORN */ @@ -2422,4 +2437,53 @@ uint16_t WS2812FX::mode_popcorn(void) { } return SPEED_FORMULA_L; -} \ No newline at end of file +} + + +//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/ + +uint16_t WS2812FX::mode_candle() +{ + if (SEGENV.call == 0) { + SEGENV.aux0 = 128; SEGENV.aux1 = 132; SEGENV.step = 1; + } + bool newTarget = false; + + uint8_t s = SEGENV.aux0, target = SEGENV.aux1, fadeStep = SEGENV.step; + + if (target > s) { //fade up + s = qadd8(s, fadeStep); + if (s >= target) newTarget = true; + } else { + s = qsub8(s, fadeStep); + if (s <= target) newTarget = true; + } + SEGENV.aux0 = s; + + for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { + setPixelColor(i, color_blend(color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), SEGCOLOR(1), 255-s)); + } + + if (newTarget) + { + uint8_t valrange = SEGMENT.intensity; + uint8_t rndval = valrange >> 1; + target = random8(rndval) + random8(rndval); + if (target < (rndval >> 1)) target = (rndval >> 1) + random8(rndval); + uint8_t offset = (255 - valrange) >> 1; + target += offset; + + uint8_t dif = (target > s) ? target - s : s - target; + + //how much to move closer to target per frame + fadeStep = dif >> 2; //mode called every ~25 ms, so 4 frames to have a new target every 100ms + if (fadeStep == 0) fadeStep = 1; + + SEGENV.step = fadeStep; + SEGENV.aux1 = target; + } + + return FRAMETIME; +} diff --git a/wled00/FX.h b/wled00/FX.h index 57b256be4..985766532 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -42,7 +42,7 @@ /* Not used in all effects yet */ #define WLED_FPS 42 -#define FRAMETIME 1000/WLED_FPS +#define FRAMETIME (1000/WLED_FPS) /* each segment uses 37 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ @@ -84,7 +84,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 90 +#define MODE_COUNT 92 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -173,9 +173,11 @@ #define FX_MODE_TRI_STATIC_PATTERN 84 #define FX_MODE_SPOTS 85 #define FX_MODE_SPOTS_FADE 86 -#define FX_MODE_BOUNCINGBALLS 87 -#define FX_MODE_SINELON 88 -#define FX_MODE_POPCORN 89 +#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 { @@ -323,6 +325,8 @@ class WS2812FX { _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; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -506,7 +510,10 @@ class WS2812FX { mode_spots_fade(void), mode_BouncingBalls(void), mode_sinelon(void), - mode_popcorn(void); + mode_popcorn(void), + mode_glitter(void), + mode_candle(void); + private: NeoPixelWrapper *bus; @@ -573,13 +580,14 @@ class WS2812FX { const char JSON_mode_names[] PROGMEM = R"=====([ "Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow", "Scan","Dual Scan","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd", -"Sparkle","Dark Sparkle","Sparkle+","Strobe","Strobe Rainbow","Mega Strobe","Blink Rainbow","Android","Chase","Chase Random", +"Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random", "Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", "Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All", "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","Popcorn" +"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" ])====="; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index b887332f4..ab204d69a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -711,7 +711,8 @@ void WS2812FX::handle_palette(void) _segment_index_palette_last = _segment_index; byte paletteIndex = SEGMENT.palette; - if ((SEGMENT.mode >= FX_MODE_METEOR) && SEGMENT.palette == 0) paletteIndex = 4; + if (SEGMENT.mode == FX_MODE_GLITTER && paletteIndex == 0) paletteIndex = 11; + if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4; switch (paletteIndex) { @@ -725,6 +726,7 @@ void WS2812FX::handle_palette(void) case FX_MODE_NOISE16_2 : targetPalette = gGradientPalettes[30]; break;//Blue cyan yellow case FX_MODE_NOISE16_3 : targetPalette = gGradientPalettes[22]; break;//heat palette case FX_MODE_NOISE16_4 : targetPalette = gGradientPalettes[13]; break;//landscape 33 + //case FX_MODE_GLITTER : targetPalette = RainbowColors_p; break; default: targetPalette = PartyColors_p; break;//palette, bpm } @@ -763,7 +765,8 @@ void WS2812FX::handle_palette(void) case 5: {//based on primary + secondary CRGB prim = col_to_crgb(SEGCOLOR(0)); CRGB sec = col_to_crgb(SEGCOLOR(1)); - targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;} + CRGB ter = col_to_crgb(SEGCOLOR(2)); + targetPalette = CRGBPalette16(ter,sec,prim); break;} case 6: //Party colors targetPalette = PartyColors_p; break; case 7: //Cloud colors diff --git a/wled00/data/index.htm b/wled00/data/index.htm index 439081b44..c3f1cb779 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -10,7 +10,7 @@ -