fix relay not turning on at boot (#5315)

These changes eliminate an elaborate race condition
* add dedicated function to handle on/off and relay
* add clarifying comment on output set order
* add define for relay delay, honor forceOff in all cases
This commit is contained in:
Damian Schneider
2026-01-31 17:40:53 +01:00
committed by GitHub
parent 2c4ed4249d
commit 1ca55e42af
5 changed files with 21 additions and 14 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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)