diff --git a/usermods/deep_sleep/deep_sleep.cpp b/usermods/deep_sleep/deep_sleep.cpp index 65cebc5e..cff40f86 100644 --- a/usermods/deep_sleep/deep_sleep.cpp +++ b/usermods/deep_sleep/deep_sleep.cpp @@ -156,7 +156,7 @@ class DeepSleepUsermod : public Usermod { delay(1000); // just in case: give user a short ~10s window to turn LEDs on in UI (delaycounter is 10 by default) return; } - if (powerup == false && delaycounter) { // delay sleep in case a preset is being loaded and turnOnAtBoot is disabled (handleIO() does enable offMode temporarily in this case) + if (powerup == false && delaycounter) { // delay sleep in case a preset is being loaded and turnOnAtBoot is disabled (beginStrip() / handleIO() does enable offMode temporarily in this case) delaycounter--; if (delaycounter == 1 && offMode) { // force turn on, no matter the settings (device is bricked if user set sleepDelay=0, no bootup preset and turnOnAtBoot=false) if (briS == 0) bri = 10; // turn on and set low brightness to avoid automatic turn off diff --git a/wled00/button.cpp b/wled00/button.cpp index f6a07f51..d544dd73 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -367,24 +367,29 @@ void handleIO() // if we want to control on-board LED (ESP8266) or relay we have to do it here as the final show() may not happen until // next loop() cycle - if (strip.getBrightness()) { + handleOnOff(); +} + +void handleOnOff(bool forceOff) +{ + if (strip.getBrightness() && !forceOff) { lastOnTime = millis(); if (offMode) { BusManager::on(); if (rlyPin>=0) { - pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT); - digitalWrite(rlyPin, rlyMde); - delay(50); // wait for relay to switch and power to stabilize + // note: pinMode is set in first call to handleOnOff(true) in beginStrip() + digitalWrite(rlyPin, rlyMde); // set to on state + delay(RELAY_DELAY); // let power stabilize before sending LED data (#346 #812 #3581 #3955) } offMode = false; } - } else if (millis() - lastOnTime > 600 && !strip.needsUpdate()) { + } else if ((millis() - lastOnTime > 600 && !strip.needsUpdate()) || forceOff) { // for turning LED or relay off we need to wait until strip no longer needs updates (strip.trigger()) if (!offMode) { BusManager::off(); if (rlyPin>=0) { + digitalWrite(rlyPin, !rlyMde); // set output before disabling high-z state to avoid output glitches pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT); - digitalWrite(rlyPin, !rlyMde); } offMode = true; } diff --git a/wled00/const.h b/wled00/const.h index 9fa85dda..50eefe18 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -114,6 +114,8 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit"); #endif #endif +#define RELAY_DELAY 50 // delay in ms between switching on relay and sending data to LEDs + #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32S2) #define WLED_MAX_COLOR_ORDER_MAPPINGS 5 #else diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 24c13aae..3081a493 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -20,6 +20,7 @@ void longPressAction(uint8_t b=0); void doublePressAction(uint8_t b=0); bool isButtonPressed(uint8_t b=0); void handleButton(); +void handleOnOff(bool forceOff = false); void handleIO(); void IRAM_ATTR touchButtonISR(); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index bb1befcd..df9a5833 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -591,6 +591,10 @@ void WLED::beginStrip() strip.setShowCallback(handleOverlayDraw); doInitBusses = false; + // init offMode and relay + offMode = false; // init to on state to allow proper relay init + handleOnOff(true); // init relay and force off + if (turnOnAtBoot) { if (briS > 0) bri = briS; else if (bri == 0) bri = 128; @@ -606,7 +610,8 @@ void WLED::beginStrip() } briLast = briS; bri = 0; strip.fill(BLACK); - strip.show(); + if (rlyPin < 0) + strip.show(); // ensure LEDs are off if no relay is used } colorUpdated(CALL_MODE_INIT); // will not send notification but will initiate transition if (bootPreset > 0) { @@ -614,12 +619,6 @@ void WLED::beginStrip() } strip.setTransition(transitionDelayDefault); // restore transitions - - // init relay pin - if (rlyPin >= 0) { - pinMode(rlyPin, rlyOpenDrain ? OUTPUT_OPEN_DRAIN : OUTPUT); - digitalWrite(rlyPin, (rlyMde ? bri : !bri)); - } } void WLED::initAP(bool resetAP)