diff --git a/platformio.ini b/platformio.ini index a0ee6a6f2..c4cac76d1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -4,14 +4,17 @@ [platformio] src_dir = ./wled00 data_dir = ./wled00/data -lib_extra_dirs = ./wled00/src +;lib_extra_dirs = ./wled00/src +lib_dir = ./wled00/src ; Please uncomment one of the 5 lines below to select your board ; env_default = nodemcuv2 ; env_default = esp01 ; env_default = esp01_1m ; env_default = d1_mini ; env_default = esp32dev - +; env_default = esp8285_4CH_MagicHome +; env_default = esp8285_4CH_H801 +; env_default = esp8285_5CH_H801 [common] framework = arduino @@ -77,7 +80,7 @@ build_flags = -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE ; -D WLED_DISABLE_HUESYNC - -D WLED_DISABLE_INFRARED + ; -D WLED_DISABLE_INFRARED [common:esp8266_512k] platform = espressif8266@1.8.0 @@ -89,15 +92,15 @@ build_flags = ; -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE - ; -D WLED_DISABLE_HUESYNC - -D WLED_DISABLE_INFRARED + -D WLED_DISABLE_HUESYNC + ; -D WLED_DISABLE_INFRARED [common:esp32] platform = espressif32@1.11.1 build_flags = -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -D ARDUINO_ARCH_ESP32 - -D WLED_DISABLE_INFRARED + -D WLED_DISABLE_INFRARED # see: http://docs.platformio.org/en/latest/platforms/espressif8266.html [env:nodemcuv2] @@ -147,6 +150,7 @@ framework = ${common.framework} build_flags = ${common.build_flags} ${common:esp8266_512k.build_flags} + -D WLED_DISABLE_INFRARED lib_deps = ${common.lib_deps_external} @@ -165,3 +169,49 @@ lib_deps = lib_ignore = IRremoteESP8266 ESPAsyncUDP + +[env:esp8285_4CH_MagicHome] +board = esp8285 +platform = ${common:esp8266_1M.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266_1M.build_flags} + -D WLED_DISABLE_HUESYNC + -D WLED_ENABLE_ANALOG_LEDS +lib_deps = + ${common.lib_deps_external} + +[env:esp8285_4CH_H801] +board = esp8285 +platform = ${common:esp8266_1M.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266_1M.build_flags} + -D WLED_DISABLE_HUESYNC + -D WLED_ENABLE_ANALOG_LEDS + -D WLED_USE_H801 +lib_deps = + ${common.lib_deps_external} + +[env:esp8285_5CH_H801] +board = esp8285 +platform = ${common:esp8266_1M.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266_1M.build_flags} + -D WLED_DISABLE_HUESYNC + -D WLED_ENABLE_ANALOG_LEDS + -D WLED_USE_H801 + -D WLED_ENABLE_5CH_LEDS +lib_deps = + ${common.lib_deps_external} + \ No newline at end of file diff --git a/readme.md b/readme.md index 6a4b41e2d..c647b543a 100644 --- a/readme.md +++ b/readme.md @@ -10,13 +10,14 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs! ### Features: -- WS2812FX library integrated for 80 special effects +- WS2812FX library integrated for almost 90 special effects - FastLED noise effects and palettes -- Customizable Mobile and desktop UI with color and effect controls +- Modern UI with color, effect and segment controls +- Segments to set different effects and colors to parts of the LEDs - Settings page - configuration over network - Access Point and station mode - automatic failsafe AP - Support for RGBW strips -- 25 user presets to save and load colors/effects easily, supports cycling through them. +- 16 user presets to save and load colors/effects easily, supports cycling through them. - Macro functions to automatically execute API calls - Nightlight function (gradually dims down) - Full OTA software updatability (HTTP + ArduinoOTA), password protectable 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 5ec1385a5..9ca9561c4 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -151,7 +151,7 @@ uint16_t WS2812FX::color_wipe(bool rev, bool useRandomColors) { uint32_t col1 = useRandomColors? color_wheel(SEGENV.aux1) : SEGCOLOR(1); for (uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++) { - uint16_t index = (rev && back)? SEGMENT.stop -1 -i : i; + uint16_t index = (rev && back)? SEGMENT.stop -1 -i +SEGMENT.start : i; uint32_t col0 = useRandomColors? color_wheel(SEGENV.aux0) : color_from_palette(index, true, PALETTE_SOLID_WRAP, 0); if (i - SEGMENT.start < ledIndex) @@ -729,33 +729,40 @@ uint16_t WS2812FX::mode_colorful(void) { cols[3] = 0x0077F0F0; for (uint8_t i = 4; i < 7; i++) cols[i] = cols[i-4]; } - int i = SEGMENT.start; - for (i; i < SEGMENT.stop ; i+=4) + + uint32_t cycleTime = 50 + (15 * (uint32_t)(255 - SEGMENT.speed)); + uint32_t it = now / cycleTime; + if (it != SEGENV.step) { - setPixelColor(i, cols[SEGENV.step]); - setPixelColor(i+1, cols[SEGENV.step+1]); - setPixelColor(i+2, cols[SEGENV.step+2]); - setPixelColor(i+3, cols[SEGENV.step+3]); + if (SEGMENT.speed > 0) SEGENV.aux0++; + if (SEGENV.aux0 > 3) SEGENV.aux0 = 0; + SEGENV.step = it; + } + + uint16_t i = SEGMENT.start; + for (i; i < SEGMENT.stop -3; i+=4) + { + setPixelColor(i, cols[SEGENV.aux0]); + setPixelColor(i+1, cols[SEGENV.aux0+1]); + setPixelColor(i+2, cols[SEGENV.aux0+2]); + setPixelColor(i+3, cols[SEGENV.aux0+3]); } - i+=4; if(i < SEGMENT.stop) { - setPixelColor(i, cols[SEGENV.step]); + setPixelColor(i, cols[SEGENV.aux0]); if(i+1 < SEGMENT.stop) { - setPixelColor(i+1, cols[SEGENV.step+1]); + setPixelColor(i+1, cols[SEGENV.aux0+1]); if(i+2 < SEGMENT.stop) { - setPixelColor(i+2, cols[SEGENV.step+2]); + setPixelColor(i+2, cols[SEGENV.aux0+2]); } } } - if (SEGMENT.speed > 0) SEGENV.step++; //static if lowest speed - if (SEGENV.step >3) SEGENV.step = 0; - return 50 + (15 * (uint32_t)(255 - SEGMENT.speed)); + return FRAMETIME; } @@ -768,7 +775,7 @@ uint16_t WS2812FX::mode_traffic_light(void) { uint32_t mdelay = 500; for (int i = SEGMENT.start; i < SEGMENT.stop-2 ; i+=3) { - switch (SEGENV.step) + switch (SEGENV.aux0) { case 0: setPixelColor(i, 0x00FF0000); mdelay = 150 + (100 * (uint32_t)(255 - SEGMENT.speed));break; case 1: setPixelColor(i, 0x00FF0000); mdelay = 150 + (20 * (uint32_t)(255 - SEGMENT.speed)); setPixelColor(i+1, 0x00EECC00); break; @@ -777,9 +784,14 @@ uint16_t WS2812FX::mode_traffic_light(void) { } } - SEGENV.step++; - if (SEGENV.step >3) SEGENV.step = 0; - return mdelay; + if (now - SEGENV.step > mdelay) + { + SEGENV.aux0++; + if (SEGENV.aux0 > 3) SEGENV.aux0 = 0; + SEGENV.step = now; + } + + return FRAMETIME; } @@ -2306,6 +2318,10 @@ uint16_t WS2812FX::mode_glitter() } +//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) { @@ -2333,17 +2349,14 @@ uint16_t WS2812FX::mode_candle() uint8_t valrange = SEGMENT.intensity; uint8_t rndval = valrange >> 1; target = random8(rndval) + random8(rndval); - if (target < (rndval >> 1)) target += random8(rndval >> 1); + 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; - uint16_t fadeSpeed = 50 + ((255-SEGMENT.speed) >> 1); //how much to move closer to target per frame - fadeStep = dif; - uint8_t frames = 1; - if (fadeSpeed > FRAMETIME) fadeStep = dif / (fadeSpeed / FRAMETIME); + 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; diff --git a/wled00/FX.h b/wled00/FX.h index 9ba70357d..e877a055e 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -571,12 +571,12 @@ 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", +"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" ])====="; @@ -586,7 +586,8 @@ const char JSON_palette_names[] PROGMEM = R"=====([ "Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash", "Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64", "Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn", -"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura" +"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura", +"Aurora" ])====="; #endif diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index ab204d69a..2b7d6ec1d 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -481,6 +481,10 @@ void WS2812FX::resetSegments() { _segments[0].speed = DEFAULT_SPEED; _segments[0].stop = _length; _segments[0].setOption(0, 1); //select + for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++) + { + _segments[i].colors[0] = color_wheel(i*51); + } } void WS2812FX::setIndividual(uint16_t i, uint32_t col) diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index fb8ae1b53..a704e4269 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -5,12 +5,18 @@ //PIN CONFIGURATION #define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos) //#define USE_APA102 // Uncomment for using APA102 LEDs. -#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) -#define IR_PIN 4 //infrared pin (-1 to disable) -#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,... -#define AUXPIN -1 //debug auxiliary output pin (-1 to disable) +//#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13) +//#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well +//#define WLED_USE_5CH //5 Channel H801 for cold and warm white -#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on +#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) +#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0 +#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,... +#define AUXPIN -1 //debug auxiliary output pin (-1 to disable) + +#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on + +//END CONFIGURATION #ifdef USE_APA102 #define CLKPIN 0 @@ -20,6 +26,27 @@ #endif #endif +#ifdef WLED_USE_ANALOG_LEDS + //PWM pins - PINs 15,13,12,14 (W2 = 04)are used with H801 Wifi LED Controller + #ifdef WLED_USE_H801 + #define RPIN 15 //R pin for analog LED strip + #define GPIN 13 //G pin for analog LED strip + #define BPIN 12 //B pin for analog LED strip + #define WPIN 14 //W pin for analog LED strip (W1: 14, W2: 04) + #define W2PIN 04 //W2 pin for analog LED strip + #undef BTNPIN + #undef IR_PIN + #define IR_PIN 0 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0 + #else + //PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller + #define RPIN 5 //R pin for analog LED strip + #define GPIN 12 //G pin for analog LED strip + #define BPIN 15 //B pin for analog LED strip + #define WPIN 13 //W pin for analog LED strip (W1: 14, W2: 04) + #endif + #undef RLYPIN + #define RLYPIN -1 //disable as pin 12 is used by analog LEDs +#endif //automatically uses the right driver method for each platform #ifdef ARDUINO_ARCH_ESP32 @@ -104,40 +131,94 @@ public: #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 + #endif + } } +#ifdef WLED_USE_ANALOG_LEDS + void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0) + { + analogWrite(RPIN, r); + analogWrite(GPIN, g); + analogWrite(BPIN, b); + switch (_type) { + case NeoPixelType_Grb: break; + #ifdef WLED_USE_5CH_LEDS + case NeoPixelType_Grbw: analogWrite(WPIN, w); analogWrite(W2PIN, w2); break; + #else + case NeoPixelType_Grbw: analogWrite(WPIN, w); break; + #endif + } + } +#endif + void Show() { + byte b; switch (_type) { - case NeoPixelType_Grb: _pGrb->Show(); break; - case NeoPixelType_Grbw: _pGrbw->Show(); break; - } - } - - bool CanShow() const - { - switch (_type) { - case NeoPixelType_Grb: _pGrb->CanShow(); break; - case NeoPixelType_Grbw: _pGrbw->CanShow(); break; - } - } - - void SetPixelColor(uint16_t indexPixel, RgbColor color) - { - switch (_type) { - case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color); break; - case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color); break; + case NeoPixelType_Grb: _pGrb->Show(); break; + case NeoPixelType_Grbw: _pGrbw->Show(); break; } } void SetPixelColor(uint16_t indexPixel, RgbwColor color) { switch (_type) { - case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); break; - case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break; + case NeoPixelType_Grb: { + _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); + #ifdef WLED_USE_ANALOG_LEDS + if (indexPixel != 0) return; //set analog LEDs from first pixel + byte b = _pGrb->GetBrightness(); + SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, 0); + #endif + } + break; + case NeoPixelType_Grbw: { + _pGrbw->SetPixelColor(indexPixel, color); + #ifdef WLED_USE_ANALOG_LEDS + if (indexPixel != 0) return; //set analog LEDs from first pixel + byte b = _pGrbw->GetBrightness(); + // check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp + #ifdef WLED_USE_5CH_LEDS + if (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) { + SetRgbwPwm(0, 0, 0, 0, color.W * b / 255); + } else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) { + SetRgbwPwm(0, 0, 0, color.W * b / 512, colorW.W * b / 255); + } else if (color.R == 0 & color.G == 0 && color.B == 0 && color.W == 255) { + SetRgbwPwm(0, 0, 0, color.W * b / 255, 0); + } else if (color.R == 130 & color.G == 90 && color.B == 0 && color.W == 255) { + SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512); + } else if (color.R == 255 & color.G == 153 && color.B == 0 && color.W == 255) { + SetRgbwPwm(0, 0, 0, color.W * b / 255, 0); + } else { // not only white colors + SetRgbwPwm(color.R * b / 255, colorW.G * b / 255, colorW.B * b / 255, color.W * b / 255); + } + #else + SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255); + #endif + #endif + } + break; } + } void SetBrightness(byte b) @@ -148,15 +229,6 @@ public: } } - RgbColor GetPixelColor(uint16_t indexPixel) const - { - switch (_type) { - case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break; - case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break; - } - return 0; - } - // NOTE: Due to feature differences, some support RGBW but the method name // here needs to be unique, thus GetPixeColorRgbw RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const @@ -168,21 +240,6 @@ public: return 0; } - void ClearTo(RgbColor color) - { - switch (_type) { - case NeoPixelType_Grb: _pGrb->ClearTo(color); break; - case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break; - } - } - - void ClearTo(RgbwColor color) - { - switch (_type) { - case NeoPixelType_Grb: break; - case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break; - } - } private: NeoPixelType _type; diff --git a/wled00/data/index.htm b/wled00/data/index.htm index 460bcadfd..e7ea5e75b 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -10,7 +10,7 @@ -