diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index d22c9a4c9..93e94a6c9 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -14,6 +14,7 @@ - Add command ``SetOption91 1`` to enable fading at startup / power on - Add command ``SetOption41 `` to force sending gratuitous ARP every seconds - Add quick wifi reconnect using saved AP parameters when ``SetOption56 0`` (#3189) +- Fix PWM flickering during wifi connection (#8046) ### 8.2.0.2 20200328 diff --git a/tasmota/core_esp8266_waveform.cpp b/tasmota/core_esp8266_waveform.cpp index 0e4beeef2..a35bb7c84 100644 --- a/tasmota/core_esp8266_waveform.cpp +++ b/tasmota/core_esp8266_waveform.cpp @@ -274,7 +274,11 @@ static ICACHE_RAM_ATTR void timer1Interrupt() { // cyclesToGo = -((-cyclesToGo) % (wave->nextTimeHighCycles + wave->nextTimeLowCycles)); // // Alternative version with lower CPU impact: - // while (-cyclesToGo > wave->nextTimeHighCycles + wave->nextTimeLowCycles) { cyclesToGo += wave->nextTimeHighCycles + wave->nextTimeLowCycles)}; + // while (-cyclesToGo > wave->nextTimeHighCycles + wave->nextTimeLowCycles) { cyclesToGo += wave->nextTimeHighCycles + wave->nextTimeLowCycles); } + // + // detect interrupt storm, for example during wifi connection. + // if we overshoot the cycle by more than 25%, we forget phase and keep PWM duration + int32_t overshoot = (-cyclesToGo) > ((wave->nextTimeHighCycles + wave->nextTimeLowCycles) >> 2); waveformState ^= mask; if (waveformState & mask) { if (i == 16) { @@ -282,16 +286,26 @@ static ICACHE_RAM_ATTR void timer1Interrupt() { } else { SetGPIO(mask); } - wave->nextServiceCycle += wave->nextTimeHighCycles; - nextEventCycles = min_u32(nextEventCycles, max_32(wave->nextTimeHighCycles + cyclesToGo, microsecondsToClockCycles(1))); + if (overshoot) { + wave->nextServiceCycle = now + wave->nextTimeHighCycles; + nextEventCycles = min_u32(nextEventCycles, wave->nextTimeHighCycles); + } else { + wave->nextServiceCycle += wave->nextTimeHighCycles; + nextEventCycles = min_u32(nextEventCycles, max_32(wave->nextTimeHighCycles + cyclesToGo, microsecondsToClockCycles(1))); + } } else { if (i == 16) { GP16O &= ~1; // GPIO16 write slow as it's RMW } else { ClearGPIO(mask); } - wave->nextServiceCycle += wave->nextTimeLowCycles; - nextEventCycles = min_u32(nextEventCycles, max_32(wave->nextTimeLowCycles + cyclesToGo, microsecondsToClockCycles(1))); + if (overshoot) { + wave->nextServiceCycle = now + wave->nextTimeLowCycles; + nextEventCycles = min_u32(nextEventCycles, wave->nextTimeLowCycles); + } else { + wave->nextServiceCycle += wave->nextTimeLowCycles; + nextEventCycles = min_u32(nextEventCycles, max_32(wave->nextTimeLowCycles + cyclesToGo, microsecondsToClockCycles(1))); + } } } else { uint32_t deltaCycles = wave->nextServiceCycle - now;