diff --git a/.travis.yml b/.travis.yml index c4408c4c..5d976261 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,4 +32,4 @@ install: - pip install -U platformio - platformio update script: - - platformio ci --project-conf=./platformio.ini -v + - platformio ci --project-conf=./platformio.ini diff --git a/platformio.ini b/platformio.ini index 45f2148f..f9c3575d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,9 +7,10 @@ data_dir = ./wled00/data ;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 = nodemcuv2 ; env_default = esp01 ; env_default = esp01_1m +; env_default = esp07 ; env_default = d1_mini ; env_default = esp32dev ; env_default = esp8285_4CH_MagicHome @@ -26,6 +27,18 @@ build_flags = -w ; supresses all C/C++ warnings ; -D VERSION=0.8.5 ; -D DEBUG + #build_flags for the IRremoteESP8266 library (enabled decoders have to appear here) + -D _IR_ENABLE_DEFAULT_=false + -D DECODE_HASH=true + -D DECODE_NEC=true + -D DECODE_SONY=true + -D DECODE_PANASONIC=true + -D DECODE_JVC=true + -D DECODE_SAMSUNG=true + -D DECODE_LG=true + -D DECODE_SANYO=true + -D DECODE_SHARP=true + -D DECODE_DENON=true # TODO replace libs in /lib with managed libs in here if possible. # If they are not changed it's just a matter of setting the correct version and change the import statement lib_deps_external = @@ -38,12 +51,16 @@ lib_deps_external = AsyncTCP@1.0.3 Esp Async WebServer@1.2.0 #ArduinoJson@5.13.5 - IRremoteESP8266@2.5.5 + #IRremoteESP8266@2.7.2 + #For saving 20k program space the brnach "compile_flags" will be used: + https://github.com/crankyoldgit/IRremoteESP8266.git#compile_flags #Time@1.5 #Timezone@1.2.1 #For use SSD1306 0.91" OLED display uncomment following #U8g2@~2.27.2 - + #For Dallas sensor uncomment following 2 lines + #DallasTemperature@~3.8.0 + #OneWire@~2.3.5 [common:esp8266] # ------------------------------------------------------------------------------ # PLATFORM: @@ -102,7 +119,6 @@ platform = espressif32@1.11.1 build_flags = -D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH -D ARDUINO_ARCH_ESP32 - -D WLED_DISABLE_INFRARED # see: http://docs.platformio.org/en/latest/platforms/espressif8266.html [env:nodemcuv2] @@ -156,6 +172,18 @@ build_flags = lib_deps = ${common.lib_deps_external} +[env:esp07] +board = esp07 +platform = ${common:esp8266.platform} +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +framework = ${common.framework} +build_flags = + ${common.build_flags} + ${common:esp8266.build_flags} +lib_deps = + ${common.lib_deps_external} + # see: http://docs.platformio.org/en/latest/platforms/espressif32.html [env:esp32dev] board = esp32dev @@ -169,7 +197,6 @@ build_flags = lib_deps = ${common.lib_deps_external} lib_ignore = - IRremoteESP8266 ESPAsyncUDP [env:esp8285_4CH_MagicHome] @@ -182,7 +209,7 @@ build_flags = ${common.build_flags} ${common:esp8266_1M.build_flags} -D WLED_DISABLE_HUESYNC - -D WLED_ENABLE_ANALOG_LEDS + -D WLED_USE_ANALOG_LEDS lib_deps = ${common.lib_deps_external} @@ -196,7 +223,7 @@ build_flags = ${common.build_flags} ${common:esp8266_1M.build_flags} -D WLED_DISABLE_HUESYNC - -D WLED_ENABLE_ANALOG_LEDS + -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801 lib_deps = ${common.lib_deps_external} @@ -211,7 +238,7 @@ build_flags = ${common.build_flags} ${common:esp8266_1M.build_flags} -D WLED_DISABLE_HUESYNC - -D WLED_ENABLE_ANALOG_LEDS + -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801 -D WLED_ENABLE_5CH_LEDS lib_deps = diff --git a/readme.md b/readme.md index c647b543..8a9d2ada 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs! ### Features: -- WS2812FX library integrated for almost 90 special effects +- WS2812FX library integrated for almost 100 special effects - FastLED noise effects and palettes - Modern UI with color, effect and segment controls - Segments to set different effects and colors to parts of the LEDs diff --git a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino index 593625b9..8c749603 100644 --- a/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino +++ b/usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino @@ -19,6 +19,7 @@ U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, void userSetup() { u8x8.begin(); u8x8.setPowerSave(0); + u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.drawString(0, 0, "Loading..."); } @@ -39,6 +40,8 @@ uint8_t knownMode = 0; uint8_t knownPalette = 0; long lastUpdate = 0; +long lastRedraw = 0; +bool displayTurnedOff = false; // How often we are redrawing screen #define USER_LOOP_REFRESH_RATE_MS 5000 @@ -49,9 +52,15 @@ void userLoop() { return; } lastUpdate = millis(); + + // Turn off display after 3 minutes with no change. + if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) { + u8x8.setPowerSave(1); + displayTurnedOff = true; + } - // Check if values which are shown on display changed from the last tiem. - if ((apActive == true ? String(apSSID) : WiFi.SSID()) != knownSsid) { + // Check if values which are shown on display changed from the last time. + if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) { needRedraw = true; } else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) { needRedraw = true; @@ -67,6 +76,13 @@ void userLoop() { return; } needRedraw = false; + + if (displayTurnedOff) + { + u8x8.setPowerSave(0); + displayTurnedOff = false; + } + lastRedraw = millis(); // Update last known values. #if defined(ESP8266) diff --git a/usermods/stairway_wipe_basic/readme.md b/usermods/stairway_wipe_basic/readme.md new file mode 100644 index 00000000..632b7d85 --- /dev/null +++ b/usermods/stairway_wipe_basic/readme.md @@ -0,0 +1,14 @@ +### Stairway lighting + +Quick usermod to accomplish something similar to [this video](https://www.youtube.com/watch?v=NHkju5ncC4A). + +This usermod allows you to add a lightstrip alongside or on the steps of a staircase. +When the `userVar0` variable is set, the LEDs will gradually turn on in a Wipe effect. +Both directions are supported by setting userVar0 to 1 and 2, respectively (HTTP API commands `U0=1` and `U0=2`). + +After the Wipe is complete, the light will either stay on (Solid effect) indefinitely or after `userVar1` seconds have elapsed. +If userVar0 is updated (e.g. by triggering a second sensor) the light will slowly fade off. +This could be extended to also run a Wipe effect in reverse order to turn the LEDs back off. + +This is just a basic version to accomplish this using HTTP API calls `U0` and `U1` and/or macros. +It should be easy to adapt this code however to interface with motion sensors or other input devices. \ No newline at end of file diff --git a/usermods/stairway_wipe_basic/wled06_usermod.ino b/usermods/stairway_wipe_basic/wled06_usermod.ino new file mode 100644 index 00000000..9fafb679 --- /dev/null +++ b/usermods/stairway_wipe_basic/wled06_usermod.ino @@ -0,0 +1,87 @@ +/* + * This file allows you to add own functionality to WLED more easily + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality + * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h) + * bytes 2400+ are currently ununsed, but might be used for future wled features + */ + +//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) + +byte wipeState = 0; //0: inactive 1: wiping 2: solid +unsigned long timeStaticStart = 0; +uint16_t previousUserVar0 = 0; + +//gets called once at boot. Do all initialization that doesn't depend on network here +void userSetup() +{ + //setup PIR sensor here, if needed +} + +//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() +{ + //userVar0 (U0 in HTTP API): + //has to be set to 1 if movement is detected on the PIR that is the same side of the staircase as the ESP8266 + //has to be set to 2 if movement is detected on the PIR that is the opposite side + //can be set to 0 if no movement is detected. Otherwise LEDs will turn off after a configurable timeout (userVar1 seconds) + + if (userVar0 > 0) + { + if ((previousUserVar0 == 1 && userVar0 == 2) || (previousUserVar0 == 2 && userVar0 == 1)) wipeState = 3; //turn off if other PIR triggered + previousUserVar0 = userVar0; + + if (wipeState == 0) { + startWipe(); + wipeState = 1; + } else if (wipeState == 1) { //wiping + uint32_t cycleTime = 360 + (255 - effectSpeed)*75; //this is how long one wipe takes (minus 25 ms to make sure we switch in time) + if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete + effectCurrent = FX_MODE_STATIC; + timeStaticStart = millis(); + colorUpdated(3); + wipeState = 2; + } + } else if (wipeState == 2) { //static + if (userVar1 > 0) //if U1 is not set, the light will stay on until second PIR or external command is triggered + { + if (millis() - timeStaticStart > userVar1*1000) wipeState = 3; + } + } else { //wipeState == 3, turn off slowly + turnOff(); + userVar0 = 0; + wipeState = 0; + } + } else { + if (previousUserVar0) turnOff(); + wipeState = 0; //reset for next time + previousUserVar0 = 0; + } +} + +void startWipe() +{ + bri = briLast; //turn on + transitionDelayTemp = 0; //no transition + effectCurrent = FX_MODE_COLOR_WIPE; + resetTimebase(); //make sure wipe starts from beginning + + //set wipe direction + WS2812FX::Segment& seg = strip.getSegment(0); + bool doReverse = (userVar0 == 2); + seg.setOption(1, doReverse); + + colorUpdated(3); +} + +void turnOff() +{ + transitionDelayTemp = 4000; + bri = 0; + colorUpdated(3); +} diff --git a/wled00/FX.cpp b/wled00/FX.cpp index d7100f96..b4defa74 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -349,7 +349,11 @@ uint16_t WS2812FX::mode_rainbow(void) { uint16_t counter = (now * ((SEGMENT.speed >> 3) +2)) & 0xFFFF; counter = counter >> 8; - fill(color_wheel(counter)); + if (SEGMENT.intensity < 128){ + fill(color_blend(color_wheel(counter),WHITE,128-SEGMENT.intensity)); + } else { + fill(color_wheel(counter)); + } return FRAMETIME; } @@ -2530,7 +2534,7 @@ uint16_t WS2812FX::mode_glitter() //each needs 12 bytes -//Spark type is used for popcorn and 1D fireworks +//Spark type is used for popcorn, 1D fireworks, and drip typedef struct Spark { float pos; float vel; @@ -2877,3 +2881,76 @@ uint16_t WS2812FX::mode_exploding_fireworks(void) return FRAMETIME; } + + +/* + * Drip Effect + * ported of: https://www.youtube.com/watch?v=sru2fXh4r7k + */ +uint16_t WS2812FX::mode_drip(void) +{ + //allocate segment data + uint16_t numDrops = 2; + uint16_t dataSize = sizeof(spark) * numDrops; + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + + fill(SEGCOLOR(1)); + + Spark* drops = reinterpret_cast(SEGENV.data); + + float gravity = -0.001 - (SEGMENT.speed/50000.0); + gravity *= SEGLEN; + int sourcedrop = 12; + + for (int j=0;j255) drops[j].col=255; + setPixelColor(SEGMENT.start + int(drops[j].pos),color_blend(BLACK,SEGCOLOR(0),drops[j].col)); + + drops[j].col += map(SEGMENT.intensity, 0, 255, 1, 6); // swelling + + if (random8() < drops[j].col/10) { // random drop + drops[j].colIndex=2; //fall + drops[j].col=255; + } + } + if (drops[j].colIndex > 1) { // falling + if (drops[j].pos > 0) { // fall until end of segment + drops[j].pos += drops[j].vel; + if (drops[j].pos < 0) drops[j].pos = 0; + drops[j].vel += gravity; + + for (int i=1;i<7-drops[j].colIndex;i++) { // some minor math so we don't expand bouncing droplets + setPixelColor(SEGMENT.start + int(drops[j].pos)+i,color_blend(BLACK,SEGCOLOR(0),drops[j].col/i)); //spread pixel with fade while falling + } + + if (drops[j].colIndex > 2) { // during bounce, some water is on the floor + setPixelColor(SEGMENT.start,color_blend(SEGCOLOR(0),BLACK,drops[j].col)); + } + } else { // we hit bottom + if (drops[j].colIndex > 2) { // already hit once, so back to forming + drops[j].colIndex = 0; + drops[j].col = sourcedrop; + + } else { + + if (drops[j].colIndex==2) { // init bounce + drops[j].vel = -drops[j].vel/4;// reverse velocity with damping + drops[j].pos += drops[j].vel; + } + drops[j].col = sourcedrop*2; + drops[j].colIndex = 5; // bouncing + } + } + } + } + return FRAMETIME; +} diff --git a/wled00/FX.h b/wled00/FX.h index 54ccd503..623f874b 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -91,7 +91,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 96 +#define MODE_COUNT 97 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -189,6 +189,7 @@ #define FX_MODE_SINELON_DUAL 93 #define FX_MODE_SINELON_RAINBOW 94 #define FX_MODE_POPCORN 95 +#define FX_MODE_DRIP 96 class WS2812FX { @@ -374,6 +375,7 @@ class WS2812FX { _mode[FX_MODE_SINELON_DUAL] = &WS2812FX::mode_sinelon_dual; _mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow; _mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn; + _mode[FX_MODE_DRIP] = &WS2812FX::mode_drip; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -554,7 +556,8 @@ class WS2812FX { mode_sinelon(void), mode_sinelon_dual(void), mode_sinelon_rainbow(void), - mode_popcorn(void); + mode_popcorn(void), + mode_drip(void); private: @@ -634,7 +637,7 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "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","Fireworks Starburst", -"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn" +"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip" ])====="; diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index 05d73868..7648350c 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -3,8 +3,10 @@ #define NpbWrapper_h //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 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 USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer) +//#define USE_LPD8806 // Uncomment for using LPD8806 //#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 @@ -18,7 +20,7 @@ //END CONFIGURATION -#ifdef USE_APA102 +#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) #define CLKPIN 0 #define DATAPIN 2 #if BTNPIN == CLKPIN || BTNPIN == DATAPIN @@ -52,6 +54,10 @@ #ifdef ARDUINO_ARCH_ESP32 #ifdef USE_APA102 #define PIXELMETHOD DotStarMethod + #elif defined(USE_WS2801) + #define PIXELMETHOD NeoWs2801Method + #elif defined(USE_LPD8806) + #define PIXELMETHOD Lpd8806Method #else #define PIXELMETHOD NeoEsp32Rmt0Ws2812xMethod #endif @@ -59,6 +65,10 @@ //autoselect the right method depending on strip pin #ifdef USE_APA102 #define PIXELMETHOD DotStarMethod + #elif defined(USE_WS2801) + #define PIXELMETHOD NeoWs2801Method + #elif defined(USE_LPD8806) + #define PIXELMETHOD Lpd8806Method #elif LEDPIN == 2 #define PIXELMETHOD NeoEsp8266Uart1Ws2813Method //if you get an error here, try to change to NeoEsp8266UartWs2813Method or update Neopixelbus #elif LEDPIN == 3 @@ -74,6 +84,9 @@ #ifdef USE_APA102 #define PIXELFEATURE3 DotStarBgrFeature #define PIXELFEATURE4 DotStarLbgrFeature +#elif defined(USE_LPD8806) + #define PIXELFEATURE3 Lpd8806GrbFeature + #define PIXELFEATURE4 Lpd8806GrbFeature #else #define PIXELFEATURE3 NeoGrbFeature #define PIXELFEATURE4 NeoGrbwFeature @@ -115,7 +128,7 @@ public: switch (_type) { case NeoPixelType_Grb: - #ifdef USE_APA102 + #if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) _pGrb = new NeoPixelBrightnessBus(countPixels, CLKPIN, DATAPIN); #else _pGrb = new NeoPixelBrightnessBus(countPixels, LEDPIN); @@ -124,47 +137,78 @@ public: break; case NeoPixelType_Grbw: - #ifdef USE_APA102 + #if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) _pGrbw = new NeoPixelBrightnessBus(countPixels, CLKPIN, DATAPIN); #else _pGrbw = new NeoPixelBrightnessBus(countPixels, LEDPIN); #endif _pGrbw->Begin(); - - #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 + #ifdef WLED_USE_ANALOG_LEDS + #ifdef ARDUINO_ARCH_ESP32 + ledcSetup(0, 5000, 8); + ledcAttachPin(RPIN, 0); + ledcSetup(1, 5000, 8); + ledcAttachPin(GPIN, 1); + ledcSetup(2, 5000, 8); + ledcAttachPin(BPIN, 2); + if(_type == NeoPixelType_Grbw) + { + ledcSetup(3, 5000, 8); + ledcAttachPin(WPIN, 3); + #ifdef WLED_USE_5CH_LEDS + ledcSetup(4, 5000, 8); + ledcAttachPin(W2PIN, 4); + #endif + } + #else // ESP8266 + //init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller + pinMode(RPIN, OUTPUT); + pinMode(GPIN, OUTPUT); + pinMode(BPIN, OUTPUT); + if(_type == NeoPixelType_Grbw) + { + pinMode(WPIN, OUTPUT); + #ifdef WLED_USE_5CH_LEDS + pinMode(W2PIN, OUTPUT); + #endif + } + analogWriteRange(255); //same range as one RGB channel + analogWriteFreq(880); //PWM frequency proven as good for LEDs + #endif #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 - } + #ifdef ARDUINO_ARCH_ESP32 + ledcWrite(0, r); //RPIN + ledcWrite(1, g); //GPIN + ledcWrite(2, b); //BPIN + switch (_type) { + case NeoPixelType_Grb: break; + #ifdef WLED_USE_5CH_LEDS + case NeoPixelType_Grbw: ledcWrite(3, w); ledcWrite(4, w2); break; + #else + case NeoPixelType_Grbw: ledcWrite(3, w); break; + #endif + } + #else + 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 } #endif @@ -191,7 +235,11 @@ public: } break; case NeoPixelType_Grbw: { + #ifdef USE_LPD8806 + _pGrbw->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); + #else _pGrbw->SetPixelColor(indexPixel, color); + #endif #ifdef WLED_USE_ANALOG_LEDS if (indexPixel != 0) return; //set analog LEDs from first pixel byte b = _pGrbw->GetBrightness(); diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 25bed845..cbda5877 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -187,7 +187,7 @@ const char PAGE_settings_sync[] PROGMEM = R"=====(

Sync setup

Button setup

On/Off button enabled:
-Infrared receiver enabled:
+Infrared receiver type (0 = disabled):
IR info

WLED Broadcast

UDP Port:
diff --git a/wled00/ir_codes.h b/wled00/ir_codes.h index e9043bd9..dda33e7b 100644 --- a/wled00/ir_codes.h +++ b/wled00/ir_codes.h @@ -30,52 +30,145 @@ #define IR24_FADE 0xF7C837 #define IR24_SMOOTH 0xF7E817 -/* 44-key defs, to be done later -#define IR44_BPlus 0xFF3AC5 // -#define IR44_BMinus 0xFFBA45 // -#define IR44_ON 0xFF827D // -#define IR44_OFF 0xFF02FD // -#define IR44_R 0xFF1AE5 // -#define IR44_G 0xFF9A65 // -#define IR44_B 0xFFA25D // -#define IR44_W 0xFF22DD // -#define IR44_B1 0xFF2AD5 // -#define IR44_B2 0xFFAA55 // -#define IR44_B3 0xFF926D // -#define IR44_B4 0xFF12ED // -#define IR44_B5 0xFF0AF5 // -#define IR44_B6 0xFF8A75 // -#define IR44_B7 0xFFB24D // -#define IR44_B8 0xFF32CD // -#define IR44_B9 0xFF38C7 // -#define IR44_B10 0xFFB847 // -#define IR44_B11 0xFF7887 // -#define IR44_B12 0xFFF807 // -#define IR44_B13 0xFF18E7 // -#define IR44_B14 0xFF9867 // -#define IR44_B15 0xFF58A7 // -#define IR44_B16 0xFFD827 // -#define IR44_UPR 0xFF28D7 // -#define IR44_UPG 0xFFA857 // -#define IR44_UPB 0xFF6897 // -#define IR44_QUICK 0xFFE817 // -#define IR44_DOWNR 0xFF08F7 // -#define IR44_DOWNG 0xFF8877 // -#define IR44_DOWNB 0xFF48B7 // -#define IR44_SLOW 0xFFC837 // -#define IR44_DIY1 0xFF30CF // -#define IR44_DIY2 0xFFB04F // -#define IR44_DIY3 0xFF708F // -#define IR44_AUTO 0xFFF00F // -#define IR44_DIY4 0xFF10EF // -#define IR44_DIY5 0xFF906F // -#define IR44_DIY6 0xFF50AF // -#define IR44_FLASH 0xFFD02F // -#define IR44_JUMP3 0xFF20DF // -#define IR44_JUMP7 0xFFA05F // -#define IR44_FADE3 0xFF609F // -#define IR44_FADE7 0xFFE01F // -*/ +// 24-key defs for white remote control with CW / WW / CT+ and CT- keys (from ALDI LED pillar lamp) +#define IR24_CT_BRIGHTER 0xF700FF // BRI + +#define IR24_CT_DARKER 0xF7807F // BRI - +#define IR24_CT_OFF 0xF740BF // OFF +#define IR24_CT_ON 0xF7C03F // ON +#define IR24_CT_RED 0xF720DF // RED +#define IR24_CT_REDDISH 0xF710EF // REDDISH +#define IR24_CT_ORANGE 0xF730CF // ORANGE +#define IR24_CT_YELLOWISH 0xF708F7 // YELLOWISH +#define IR24_CT_YELLOW 0xF728D7 // YELLOW +#define IR24_CT_GREEN 0xF7A05F // GREEN +#define IR24_CT_GREENISH 0xF7906F // GREENISH +#define IR24_CT_TURQUOISE 0xF7B04F // TURQUOISE +#define IR24_CT_CYAN 0xF78877 // CYAN +#define IR24_CT_AQUA 0xF7A857 // AQUA +#define IR24_CT_BLUE 0xF7609F // BLUE +#define IR24_CT_DEEPBLUE 0xF750AF // DEEPBLUE +#define IR24_CT_PURPLE 0xF7708F // PURPLE +#define IR24_CT_MAGENTA 0xF748B7 // MAGENTA +#define IR24_CT_PINK 0xF76897 // PINK +#define IR24_CT_COLDWHITE 0xF7E01F // CW +#define IR24_CT_WARMWHITE 0xF7D02F // WW +#define IR24_CT_CTPLUS 0xF7F00F // CT+ +#define IR24_CT_CTMINUS 0xF7C837 // CT- +#define IR24_CT_MEMORY 0xF7E817 // MEMORY + +// 24-key defs for old remote control +#define IR24_OLD_BRIGHTER 0xFF906F // Brightness Up +#define IR24_OLD_DARKER 0xFFB847 // Brightness Down +#define IR24_OLD_OFF 0xFFF807 // Power OFF +#define IR24_OLD_ON 0xFFB04F // Power On +#define IR24_OLD_RED 0xFF9867 // RED +#define IR24_OLD_REDDISH 0xFFE817 // Light RED +#define IR24_OLD_ORANGE 0xFF02FD // Orange +#define IR24_OLD_YELLOWISH 0xFF50AF // Light Orange +#define IR24_OLD_YELLOW 0xFF38C7 // YELLOW +#define IR24_OLD_GREEN 0xFFD827 // GREEN +#define IR24_OLD_GREENISH 0xFF48B7 // Light GREEN +#define IR24_OLD_TURQUOISE 0xFF32CD // TURQUOISE +#define IR24_OLD_CYAN 0xFF7887 // CYAN +#define IR24_OLD_AQUA 0xFF28D7 // AQUA +#define IR24_OLD_BLUE 0xFF8877 // BLUE +#define IR24_OLD_DEEPBLUE 0xFF6897 // Dark BLUE +#define IR24_OLD_PURPLE 0xFF20DF // PURPLE +#define IR24_OLD_MAGENTA 0xFF708F // MAGENTA +#define IR24_OLD_PINK 0xFFF00F // PINK +#define IR24_OLD_WHITE 0xFFA857 // WHITE +#define IR24_OLD_FLASH 0xFFB24D // FLASH Mode +#define IR24_OLD_STROBE 0xFF00FF // STROBE Mode +#define IR24_OLD_FADE 0xFF58A7 // FADE Mode +#define IR24_OLD_SMOOTH 0xFF30CF // SMOOTH Mode + +// 40-key defs for blue remote control +#define IR40_BPLUS 0xFF3AC5 // +#define IR40_BMINUS 0xFFBA45 // +#define IR40_OFF 0xFF827D // +#define IR40_ON 0xFF02FD // +#define IR40_RED 0xFF1AE5 // +#define IR40_GREEN 0xFF9A65 // +#define IR40_BLUE 0xFFA25D // +#define IR40_WHITE 0xFF22DD // natural white +#define IR40_REDDISH 0xFF2AD5 // +#define IR40_GREENISH 0xFFAA55 // +#define IR40_DEEPBLUE 0xFF926D // +#define IR40_WARMWHITE2 0xFF12ED // warmest white +#define IR40_ORANGE 0xFF0AF5 // +#define IR40_TURQUOISE 0xFF8A75 // +#define IR40_PURPLE 0xFFB24D // +#define IR40_WARMWHITE 0xFF32CD // warm white +#define IR40_YELLOWISH 0xFF38C7 // +#define IR40_CYAN 0xFFB847 // +#define IR40_MAGENTA 0xFF7887 // +#define IR40_COLDWHITE 0xFFF807 // cold white +#define IR40_YELLOW 0xFF18E7 // +#define IR40_AQUA 0xFF9867 // +#define IR40_PINK 0xFF58A7 // +#define IR40_COLDWHITE2 0xFFD827 // coldest white +#define IR40_WPLUS 0xFF28D7 // white chanel bright plus +#define IR40_WMINUS 0xFFA857 // white chanel bright minus +#define IR40_WOFF 0xFF6897 // white chanel on +#define IR40_WON 0xFFE817 // white chanel off +#define IR40_W25 0xFF08F7 // white chanel 25% +#define IR40_W50 0xFF8877 // white chanel 50% +#define IR40_W75 0xFF48B7 // white chanel 75% +#define IR40_W100 0xFFC837 // white chanel 100% +#define IR40_JUMP3 0xFF30CF // JUMP3 +#define IR40_FADE3 0xFFB04F // FADE3 +#define IR40_JUMP7 0xFF708F // JUMP7 +#define IR40_QUICK 0xFFF00F // QUICK +#define IR40_FADE7 0xFF10EF // FADE7 +#define IR40_FLASH 0xFF906F // FLASH +#define IR40_AUTO 0xFF50AF // AUTO +#define IR40_SLOW 0xFFD02F // SLOW + +// 44-key defs, to be done later +#define IR44_BPLUS 0xFF3AC5 // +#define IR44_BMINUS 0xFFBA45 // +#define IR44_OFF 0xFF827D // +#define IR44_ON 0xFF02FD // +#define IR44_RED 0xFF1AE5 // +#define IR44_GREEN 0xFF9A65 // +#define IR44_BLUE 0xFFA25D // +#define IR44_WHITE 0xFF22DD // natural white +#define IR44_REDDISH 0xFF2AD5 // +#define IR44_GREENISH 0xFFAA55 // +#define IR44_DEEPBLUE 0xFF926D // +#define IR44_WARMWHITE2 0xFF12ED // warmest white +#define IR44_ORANGE 0xFF0AF5 // +#define IR44_TURQUOISE 0xFF8A75 // +#define IR44_PURPLE 0xFFB24D // +#define IR44_WARMWHITE 0xFF32CD // warm white +#define IR44_YELLOWISH 0xFF38C7 // +#define IR44_CYAN 0xFFB847 // +#define IR44_MAGENTA 0xFF7887 // +#define IR44_COLDWHITE 0xFFF807 // cold white +#define IR44_YELLOW 0xFF18E7 // +#define IR44_AQUA 0xFF9867 // +#define IR44_PINK 0xFF58A7 // +#define IR44_COLDWHITE2 0xFFD827 // coldest white +#define IR44_REDPLUS 0xFF28D7 // +#define IR44_GREENPLUS 0xFFA857 // +#define IR44_BLUEPLUS 0xFF6897 // +#define IR44_QUICK 0xFFE817 // +#define IR44_REDMINUS 0xFF08F7 // +#define IR44_GREENMINUS 0xFF8877 // +#define IR44_BLUEMINUS 0xFF48B7 // +#define IR44_SLOW 0xFFC837 // +#define IR44_DIY1 0xFF30CF // +#define IR44_DIY2 0xFFB04F // +#define IR44_DIY3 0xFF708F // +#define IR44_AUTO 0xFFF00F // +#define IR44_DIY4 0xFF10EF // +#define IR44_DIY5 0xFF906F // +#define IR44_DIY6 0xFF50AF // +#define IR44_FLASH 0xFFD02F // +#define IR44_JUMP3 0xFF20DF // +#define IR44_JUMP7 0xFFA05F // +#define IR44_FADE3 0xFF609F // +#define IR44_FADE7 0xFFE01F // #define COLOR_RED 0xFF0000 #define COLOR_REDDISH 0xFF7800 @@ -93,3 +186,13 @@ #define COLOR_MAGENTA 0xFF00DC #define COLOR_PINK 0xFF00A0 #define COLOR_WHITE 0xFFFFDC +#define COLOR_WARMWHITE2 0xFFAA69 +#define COLOR_WARMWHITE 0xFFBF8E +#define COLOR_NEUTRALWHITE 0xFFD4B4 +#define COLOR_COLDWHITE 0xFFE9D9 +#define COLOR_COLDWHITE2 0xFFFFFF +#define COLOR2_WARMWHITE2 0xFFFF9900 +#define COLOR2_WARMWHITE 0xFF825A00 +#define COLOR2_NEUTRALWHITE 0xFF000000 +#define COLOR2_COLDWHITE 0xFF7F7F7F +#define COLOR2_COLDWHITE2 0xFFFFFFFF diff --git a/wled00/src/dependencies/espalexa/Espalexa.h b/wled00/src/dependencies/espalexa/Espalexa.h index 0c817dcf..49c9b6a9 100644 --- a/wled00/src/dependencies/espalexa/Espalexa.h +++ b/wled00/src/dependencies/espalexa/Espalexa.h @@ -10,7 +10,7 @@ */ /* * @title Espalexa library - * @version 2.4.3 + * @version 2.4.4 * @author Christian Schwinne * @license MIT * @contributors d-999 @@ -49,7 +49,7 @@ #include #ifdef ESPALEXA_DEBUG - #pragma message "Espalexa 2.4.3 debug mode" + #pragma message "Espalexa 2.4.4 debug mode" #define EA_DEBUG(x) Serial.print (x) #define EA_DEBUGLN(x) Serial.println (x) #else @@ -164,7 +164,7 @@ private: json += "\",\"modelid\":\"" + modelidString(dev->getType()); json += "\",\"manufacturername\":\"Philips\",\"productname\":\"E" + String(static_cast(dev->getType())); json += "\",\"uniqueid\":\"" + String(encodeLightId(deviceId+1)); - json += "\",\"swversion\":\"espalexa-2.4.3\"}"; + json += "\",\"swversion\":\"espalexa-2.4.4\"}"; return json; } @@ -188,7 +188,7 @@ private: } res += "\r\nFree Heap: " + (String)ESP.getFreeHeap(); res += "\r\nUptime: " + (String)millis(); - res += "\r\n\r\nEspalexa library v2.4.3 by Christian Schwinne 2019"; + res += "\r\n\r\nEspalexa library v2.4.4 by Christian Schwinne 2020"; server->send(200, "text/plain", res); } #endif @@ -298,7 +298,7 @@ private: "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber "hue-bridgeid: "+ escapedMac +"\r\n" "ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType - "USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::upnp:rootdevice\r\n" // _uuid::_deviceType + "USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::ssdp:all\r\n" // _uuid::_deviceType "\r\n"; espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort()); @@ -372,7 +372,7 @@ public: String request = packetBuffer; if(request.indexOf("M-SEARCH") >= 0) { EA_DEBUGLN(request); - if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0) { + if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("ssdp:all") > 0) { EA_DEBUGLN("Responding search req..."); respondToSearch(); } @@ -584,4 +584,4 @@ public: ~Espalexa(){delete devices;} //note: Espalexa is NOT meant to be destructed }; -#endif \ No newline at end of file +#endif diff --git a/wled00/src/dependencies/espalexa/EspalexaDevice.cpp b/wled00/src/dependencies/espalexa/EspalexaDevice.cpp index df859c1d..25d70bb0 100644 --- a/wled00/src/dependencies/espalexa/EspalexaDevice.cpp +++ b/wled00/src/dependencies/espalexa/EspalexaDevice.cpp @@ -130,30 +130,28 @@ uint32_t EspalexaDevice::getRGB() case 350: rgb[0]=130,rgb[1]=90,rgb[2]=0;rgb[3]=255;break; case 383: rgb[0]=255,rgb[1]=153,rgb[2]=0;rgb[3]=255;break; default: { - - if( temp <= 66 ){ - r = 255; - g = temp; - g = 99.470802 * log(g) - 161.119568; - if( temp <= 19){ - b = 0; - } else { - b = temp-10; - b = 138.517731 * log(b) - 305.044793; - } - } else { - r = temp - 60; - r = 329.698727 * pow(r, -0.13320476); - g = temp - 60; - g = 288.12217 * pow(g, -0.07551485 ); - b = 255; - } + if( temp <= 66 ){ + r = 255; + g = temp; + g = 99.470802 * log(g) - 161.119568; + if( temp <= 19){ + b = 0; + } else { + b = temp-10; + b = 138.517731 * log(b) - 305.044793; + } + } else { + r = temp - 60; + r = 329.698727 * pow(r, -0.13320476); + g = temp - 60; + g = 288.12217 * pow(g, -0.07551485 ); + b = 255; + } - rgb[0] = (byte)constrain(r,0.1,255.1); - rgb[1] = (byte)constrain(g,0.1,255.1); - rgb[2] = (byte)constrain(b,0.1,255.1); - - } + rgb[0] = (byte)constrain(r,0.1,255.1); + rgb[1] = (byte)constrain(g,0.1,255.1); + rgb[2] = (byte)constrain(b,0.1,255.1); + } } } else if (_mode == EspalexaColorMode::hs) { @@ -232,6 +230,12 @@ uint32_t EspalexaDevice::getRGB() return _rgb; } +//white channel for RGBW lights. Always 0 unless colormode is ct +uint8_t EspalexaDevice::getW() +{ + return (getRGB() >> 24) & 0xFF; +} + uint8_t EspalexaDevice::getR() { return (getRGB() >> 16) & 0xFF; diff --git a/wled00/src/dependencies/espalexa/EspalexaDevice.h b/wled00/src/dependencies/espalexa/EspalexaDevice.h index 8d7be873..a6644916 100644 --- a/wled00/src/dependencies/espalexa/EspalexaDevice.h +++ b/wled00/src/dependencies/espalexa/EspalexaDevice.h @@ -51,6 +51,7 @@ public: uint8_t getR(); uint8_t getG(); uint8_t getB(); + uint8_t getW(); EspalexaColorMode getColorMode(); EspalexaDeviceType getType(); diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 111304e5..3a05ed17 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -83,22 +83,15 @@ #endif #endif -#ifdef ARDUINO_ARCH_ESP32 - #undef WLED_USE_ANALOG_LEDS // Solid RGBW not implemented for ESP32 yet - /*#ifndef WLED_DISABLE_INFRARED - #include - #endif*/ //there are issues with ESP32 infrared, so it is disabled for now -#else #ifndef WLED_DISABLE_INFRARED #include #include #include #endif -#endif - //version code in format yymmddb (b = daily build) -#define VERSION 2001071 +#define VERSION 2001141 + char versionString[] = "0.9.0-b2"; @@ -144,6 +137,7 @@ byte briS = 128; //default brightness byte nightlightTargetBri = 0; //brightness after nightlight is over byte nightlightDelayMins = 60; bool nightlightFade = true; //if enabled, light will gradually dim towards the target bri. Otherwise, it will instantly set after delay over +bool nightlightColorFade = false; //if enabled, light will gradually fade color from primary to secondary color. bool fadeTransition = true; //enable crossfading color transition bool enableSecTransition = true; //also enable transition for secondary color uint16_t transitionDelay = 750; //default crossfade duration in ms @@ -159,7 +153,7 @@ bool syncToggleReceive = false; //UIs which only have a single but //Sync CONFIG bool buttonEnabled = true; -bool irEnabled = false; //Infrared receiver +byte irEnabled = 0; //Infrared receiver uint16_t udpPort = 21324; //WLED notifier default port uint16_t udpRgbPort = 19446; //Hyperion port @@ -278,6 +272,7 @@ uint32_t nightlightDelayMs = 10; uint8_t nightlightDelayMinsDefault = nightlightDelayMins; unsigned long nightlightStartTime; byte briNlT = 0; //current nightlight brightness +byte colNlT[]{0, 0, 0, 0}; //current nightlight color //brightness unsigned long lastOnTime = 0; @@ -287,6 +282,7 @@ byte briOld = 0; byte briT = 0; byte briIT = 0; byte briLast = 128; //brightness before turned off. Used for toggle function +byte whiteLast = 128; //white channel before turned off. Used for toggle function //button bool buttonPressedBefore = false; @@ -506,6 +502,7 @@ void setup() { //main program loop void loop() { + handleIR(); //2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too handleConnection(); handleSerial(); handleNotifications(); diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index b7110dcb..441712e0 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -248,7 +248,7 @@ void getSettingsJS(byte subPage, char* dest) if (subPage == 4) { sappend('c',"BT",buttonEnabled); - sappend('c',"IR",irEnabled); + sappend('v',"IR",irEnabled); sappend('v',"UP",udpPort); sappend('c',"RB",receiveNotificationBrightness); sappend('c',"RC",receiveNotificationColor); diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 3db10425..3ebec49b 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -119,7 +119,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (subPage == 4) { buttonEnabled = request->hasArg("BT"); - irEnabled = request->hasArg("IR"); + irEnabled = request->arg("IR").toInt(); int t = request->arg("UP").toInt(); if (t > 0) udpPort = t; receiveNotificationBrightness = request->hasArg("RB"); @@ -510,6 +510,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) if (pos > 0) { nightlightFade = (req.charAt(pos+3) != '0'); + nightlightColorFade = (req.charAt(pos+3) == '2'); //NighLightColorFade can only be enabled via API or Macro with "NF=2" nightlightActiveOld = false; //re-init } diff --git a/wled00/wled08_led.ino b/wled00/wled08_led.ino index 2bbee9c3..786049a0 100644 --- a/wled00/wled08_led.ino +++ b/wled00/wled08_led.ino @@ -217,11 +217,16 @@ void handleNightlight() nightlightDelayMs = (int)(nightlightDelayMins*60000); nightlightActiveOld = true; briNlT = bri; + for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color } float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs); if (nightlightFade) { bri = briNlT + ((nightlightTargetBri - briNlT)*nper); + if (nightlightColorFade) // color fading only is enabled with "NF=2" + { + for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color + } colorUpdated(5); } if (nper >= 1) diff --git a/wled00/wled14_colors.ino b/wled00/wled14_colors.ino index aaa92cad..8b041462 100644 --- a/wled00/wled14_colors.ino +++ b/wled00/wled14_colors.ino @@ -17,6 +17,29 @@ void colorFromUint32(uint32_t in, bool secondary) } } +//load a color without affecting the white channel +void colorFromUint24(uint32_t in, bool secondary = false) +{ + if (secondary) { + colSec[0] = in >> 16 & 0xFF; + colSec[1] = in >> 8 & 0xFF; + colSec[2] = in & 0xFF; + } else { + col[0] = in >> 16 & 0xFF; + col[1] = in >> 8 & 0xFF; + col[2] = in & 0xFF; + } +} + +//relatively change white brightness, minumum A=5 +void relativeChangeWhite(int8_t amount, byte lowerBoundary =0) +{ + int16_t new_val = (int16_t) col[3] + amount; + if (new_val > 0xFF) new_val = 0xFF; + else if (new_val < lowerBoundary) new_val = lowerBoundary; + col[3] = new_val; +} + void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb { float h = ((float)hue)/65535.0; diff --git a/wled00/wled20_ir.ino b/wled00/wled20_ir.ino index 88d1bdff..d602e4e1 100644 --- a/wled00/wled20_ir.ino +++ b/wled00/wled20_ir.ino @@ -1,8 +1,8 @@ /* - * Infrared sensor support for generic 24 key RGB remote + * Infrared sensor support for generic 24/40/44 key RGB remotes */ -#if defined(WLED_DISABLE_INFRARED) || defined(ARDUINO_ARCH_ESP32) +#if defined(WLED_DISABLE_INFRARED) void handleIR(){} #else @@ -48,15 +48,23 @@ void decodeIR(uint32_t code) if (code == 0xFFFFFFFF) //repeated code, continue brightness up/down { irTimesRepeated++; - if (lastValidCode == IR24_BRIGHTER) + if (lastValidCode == IR24_BRIGHTER || lastValidCode == IR40_BPLUS ) { relativeChange(&bri, 10); colorUpdated(2); } - else if (lastValidCode == IR24_DARKER) + else if (lastValidCode == IR24_DARKER || lastValidCode == IR40_BMINUS ) { relativeChange(&bri, -10, 5); colorUpdated(2); } - else if (lastValidCode == IR24_ON && irTimesRepeated > 7) + if (lastValidCode == IR40_WPLUS) + { + relativeChangeWhite(10); colorUpdated(2); + } + else if (lastValidCode == IR40_WMINUS) + { + relativeChangeWhite(-10, 5); colorUpdated(2); + } + else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 ) { nightlightActive = true; nightlightStartTime = millis(); @@ -68,8 +76,16 @@ void decodeIR(uint32_t code) if (decodeIRCustom(code)) return; if (code > 0xFFFFFF) return; //invalid code - else if (code > 0xFF0000) decodeIR44(code); //is in 44-key remote range else if (code > 0xF70000 && code < 0xF80000) decodeIR24(code); //is in 24-key remote range + else if (code > 0xFF0000) { + switch (irEnabled) { + case 1: decodeIR24OLD(code); break; // white 24-key remote (old) - it sends 0xFF0000 values + case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys + case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys + case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys + default: return; + } + } //code <= 0xF70000 also invalid } @@ -107,16 +123,202 @@ void decodeIR24(uint32_t code) colorUpdated(2); //for notifier, IR is considered a button input } +void decodeIR24OLD(uint32_t code) +{ + switch (code) { + case IR24_OLD_BRIGHTER : relativeChange(&bri, 10); break; + case IR24_OLD_DARKER : relativeChange(&bri, -10, 5); break; + case IR24_OLD_OFF : briLast = bri; bri = 0; break; + case IR24_OLD_ON : bri = briLast; break; + case IR24_OLD_RED : colorFromUint32(COLOR_RED); break; + case IR24_OLD_REDDISH : colorFromUint32(COLOR_REDDISH); break; + case IR24_OLD_ORANGE : colorFromUint32(COLOR_ORANGE); break; + case IR24_OLD_YELLOWISH : colorFromUint32(COLOR_YELLOWISH); break; + case IR24_OLD_YELLOW : colorFromUint32(COLOR_YELLOW); break; + case IR24_OLD_GREEN : colorFromUint32(COLOR_GREEN); break; + case IR24_OLD_GREENISH : colorFromUint32(COLOR_GREENISH); break; + case IR24_OLD_TURQUOISE : colorFromUint32(COLOR_TURQUOISE); break; + case IR24_OLD_CYAN : colorFromUint32(COLOR_CYAN); break; + case IR24_OLD_AQUA : colorFromUint32(COLOR_AQUA); break; + case IR24_OLD_BLUE : colorFromUint32(COLOR_BLUE); break; + case IR24_OLD_DEEPBLUE : colorFromUint32(COLOR_DEEPBLUE); break; + case IR24_OLD_PURPLE : colorFromUint32(COLOR_PURPLE); break; + case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break; + case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break; + case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break; + case IR24_OLD_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; break; + case IR24_OLD_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; break; + case IR24_OLD_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; + case IR24_OLD_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; + default: return; + } + lastValidCode = code; + colorUpdated(2); //for notifier, IR is considered a button input +} + + +void decodeIR24CT(uint32_t code) +{ + switch (code) { + case IR24_CT_BRIGHTER : relativeChange(&bri, 10); break; + case IR24_CT_DARKER : relativeChange(&bri, -10, 5); break; + case IR24_CT_OFF : briLast = bri; bri = 0; break; + case IR24_CT_ON : bri = briLast; break; + case IR24_CT_RED : colorFromUint32(COLOR_RED); break; + case IR24_CT_REDDISH : colorFromUint32(COLOR_REDDISH); break; + case IR24_CT_ORANGE : colorFromUint32(COLOR_ORANGE); break; + case IR24_CT_YELLOWISH : colorFromUint32(COLOR_YELLOWISH); break; + case IR24_CT_YELLOW : colorFromUint32(COLOR_YELLOW); break; + case IR24_CT_GREEN : colorFromUint32(COLOR_GREEN); break; + case IR24_CT_GREENISH : colorFromUint32(COLOR_GREENISH); break; + case IR24_CT_TURQUOISE : colorFromUint32(COLOR_TURQUOISE); break; + case IR24_CT_CYAN : colorFromUint32(COLOR_CYAN); break; + case IR24_CT_AQUA : colorFromUint32(COLOR_AQUA); break; + case IR24_CT_BLUE : colorFromUint32(COLOR_BLUE); break; + case IR24_CT_DEEPBLUE : colorFromUint32(COLOR_DEEPBLUE); break; + case IR24_CT_PURPLE : colorFromUint32(COLOR_PURPLE); break; + case IR24_CT_MAGENTA : colorFromUint32(COLOR_MAGENTA); break; + case IR24_CT_PINK : colorFromUint32(COLOR_PINK); break; + case IR24_CT_COLDWHITE : colorFromUint32(COLOR_COLDWHITE); effectCurrent = 0; break; + case IR24_CT_WARMWHITE : colorFromUint32(COLOR_WARMWHITE); effectCurrent = 0; break; + case IR24_CT_CTPLUS : colorFromUint32(COLOR_COLDWHITE2); effectCurrent = 0; break; + case IR24_CT_CTMINUS : colorFromUint32(COLOR_WARMWHITE2); effectCurrent = 0; break; + case IR24_CT_MEMORY : { + if (col[3] > 0) col[3] = 0; + else colorFromUint32(COLOR_NEUTRALWHITE); effectCurrent = 0; } break; + default: return; + } + lastValidCode = code; + colorUpdated(2); //for notifier, IR is considered a button input +} + + +void decodeIR40(uint32_t code) +{ + switch (code) { + case IR40_BPLUS : relativeChange(&bri, 10); break; + case IR40_BMINUS : relativeChange(&bri, -10, 5); break; + case IR40_OFF : briLast = bri; bri = 0; break; + case IR40_ON : bri = briLast; break; + case IR40_RED : colorFromUint24(COLOR_RED); break; + case IR40_REDDISH : colorFromUint24(COLOR_REDDISH); break; + case IR40_ORANGE : colorFromUint24(COLOR_ORANGE); break; + case IR40_YELLOWISH : colorFromUint24(COLOR_YELLOWISH); break; + case IR40_YELLOW : colorFromUint24(COLOR_YELLOW); break; + case IR40_GREEN : colorFromUint24(COLOR_GREEN); break; + case IR40_GREENISH : colorFromUint24(COLOR_GREENISH); break; + case IR40_TURQUOISE : colorFromUint24(COLOR_TURQUOISE); break; + case IR40_CYAN : colorFromUint24(COLOR_CYAN); break; + case IR40_AQUA : colorFromUint24(COLOR_AQUA); break; + case IR40_BLUE : colorFromUint24(COLOR_BLUE); break; + case IR40_DEEPBLUE : colorFromUint24(COLOR_DEEPBLUE); break; + case IR40_PURPLE : colorFromUint24(COLOR_PURPLE); break; + case IR40_MAGENTA : colorFromUint24(COLOR_MAGENTA); break; + case IR40_PINK : colorFromUint24(COLOR_PINK); break; + case IR40_WARMWHITE2 : { + if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; } + else colorFromUint24(COLOR_WARMWHITE2); } break; + case IR40_WARMWHITE : { + if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; } + else colorFromUint24(COLOR_WARMWHITE); } break; + case IR40_WHITE : { + if (useRGBW) { colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; } + else colorFromUint24(COLOR_NEUTRALWHITE); } break; + case IR40_COLDWHITE : { + if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; } + else colorFromUint24(COLOR_COLDWHITE); } break; + case IR40_COLDWHITE2 : { + if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; } + else colorFromUint24(COLOR_COLDWHITE2); } break; + case IR40_WPLUS : relativeChangeWhite(10); break; + case IR40_WMINUS : relativeChangeWhite(-10, 5); break; + case IR40_WOFF : whiteLast = col[3]; col[3] = 0; break; + case IR40_WON : col[3] = whiteLast; break; + case IR40_W25 : bri = 63; break; + case IR40_W50 : bri = 127; break; + case IR40_W75 : bri = 191; break; + case IR40_W100 : bri = 255; break; + case IR40_QUICK : relativeChange(&effectSpeed, 10); break; + case IR40_SLOW : relativeChange(&effectSpeed, -10, 5); break; + case IR40_JUMP7 : relativeChange(&effectIntensity, 10); break; + case IR40_AUTO : relativeChange(&effectIntensity, -10, 5); break; + case IR40_JUMP3 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break; + case IR40_FADE3 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; + case IR40_FADE7 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break; + case IR40_FLASH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; + } + lastValidCode = code; + colorUpdated(2); //for notifier, IR is considered a button input +} void decodeIR44(uint32_t code) { - //not implemented for now + switch (code) { + case IR44_BPLUS : relativeChange(&bri, 10); break; + case IR44_BMINUS : relativeChange(&bri, -10, 5); break; + case IR44_OFF : briLast = bri; bri = 0; break; + case IR44_ON : bri = briLast; break; + case IR44_RED : colorFromUint24(COLOR_RED); break; + case IR44_REDDISH : colorFromUint24(COLOR_REDDISH); break; + case IR44_ORANGE : colorFromUint24(COLOR_ORANGE); break; + case IR44_YELLOWISH : colorFromUint24(COLOR_YELLOWISH); break; + case IR44_YELLOW : colorFromUint24(COLOR_YELLOW); break; + case IR44_GREEN : colorFromUint24(COLOR_GREEN); break; + case IR44_GREENISH : colorFromUint24(COLOR_GREENISH); break; + case IR44_TURQUOISE : colorFromUint24(COLOR_TURQUOISE); break; + case IR44_CYAN : colorFromUint24(COLOR_CYAN); break; + case IR44_AQUA : colorFromUint24(COLOR_AQUA); break; + case IR44_BLUE : colorFromUint24(COLOR_BLUE); break; + case IR44_DEEPBLUE : colorFromUint24(COLOR_DEEPBLUE); break; + case IR44_PURPLE : colorFromUint24(COLOR_PURPLE); break; + case IR44_MAGENTA : colorFromUint24(COLOR_MAGENTA); break; + case IR44_PINK : colorFromUint24(COLOR_PINK); break; + case IR44_WHITE : { + if (useRGBW) { + if (col[3] > 0) col[3] = 0; + else { colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; } + } else colorFromUint24(COLOR_NEUTRALWHITE); } break; + case IR44_WARMWHITE2 : { + if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; } + else colorFromUint24(COLOR_WARMWHITE2); } break; + case IR44_WARMWHITE : { + if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; } + else colorFromUint24(COLOR_WARMWHITE); } break; + case IR44_COLDWHITE : { + if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; } + else colorFromUint24(COLOR_COLDWHITE); } break; + case IR44_COLDWHITE2 : { + if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; } + else colorFromUint24(COLOR_COLDWHITE2); } break; + case IR44_REDPLUS : relativeChange(&effectCurrent, 1); break; + case IR44_REDMINUS : relativeChange(&effectCurrent, -1, 0); break; + case IR44_GREENPLUS : relativeChange(&effectPalette, 1); break; + case IR44_GREENMINUS : relativeChange(&effectPalette, -1, 0); break; + case IR44_BLUEPLUS : relativeChange(&effectIntensity, 10); break; + case IR44_BLUEMINUS : relativeChange(&effectIntensity, -10, 5); break; + case IR44_QUICK : relativeChange(&effectSpeed, 10); break; + case IR44_SLOW : relativeChange(&effectSpeed, -10, 5); break; + case IR44_DIY1 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break; + case IR44_DIY2 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break; + case IR44_DIY3 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break; + case IR44_DIY4 : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break; + case IR44_DIY5 : if (!applyPreset(5)) effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; break; + case IR44_DIY6 : if (!applyPreset(6)) effectCurrent = FX_MODE_RAIN; effectPalette = 0; break; + case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break; + case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break; + case IR44_JUMP3 : bri = 63; break; + case IR44_JUMP7 : bri = 127; break; + case IR44_FADE3 : bri = 191; break; + case IR44_FADE7 : bri = 255; break; + } + lastValidCode = code; + colorUpdated(2); //for notifier, IR is considered a button input } void initIR() { - if (irEnabled) + if (irEnabled > 0) { irrecv = new IRrecv(IR_PIN); irrecv->enableIRIn(); @@ -126,10 +328,10 @@ void initIR() void handleIR() { - if (irEnabled && millis() - irCheckedTime > 120) + if (irEnabled > 0 && millis() - irCheckedTime > 120) { irCheckedTime = millis(); - if (irEnabled) + if (irEnabled > 0) { if (irrecv == NULL) { @@ -138,9 +340,12 @@ void handleIR() if (irrecv->decode(&results)) { - Serial.print("IR recv\r\n0x"); - Serial.println((uint32_t)results.value, HEX); - Serial.println(); + if (results.value != 0) // only print results if anything is received ( != 0 ) + { + Serial.print("IR recv\r\n0x"); + Serial.println((uint32_t)results.value, HEX); + Serial.println(); + } decodeIR(results.value); irrecv->resume(); }