From a9cdd21da90bca5f364e2694acde1f59143a65de Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 12 Jun 2023 23:27:09 +0200 Subject: [PATCH] prevent strip flickering * it seems that NPB is very sensitive when being interrupted during LEDs driving. This change tries to avoid flash (file) writes when the strip is active. * minor optimization: yield is completely unnecessary on ESP32 (we have a real OS). --- wled00/fcn_declare.h | 2 ++ wled00/presets.cpp | 14 ++++++++++++++ wled00/wled.cpp | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index ad6fe6ea..98f95caa 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -199,6 +199,8 @@ void handlePlaylist(); void serializePlaylist(JsonObject obj); //presets.cpp +bool presetsSavePending(void); // WLEDMM true if presetToSave, playlistSave or saveLedmap +bool presetsActionPending(void); // WLEDMM true if presetToApply, presetToSave, playlistSave or saveLedmap void initPresetsFile(); void handlePresets(); bool applyPreset(byte index, byte callMode = CALL_MODE_DIRECT_CHANGE); diff --git a/wled00/presets.cpp b/wled00/presets.cpp index abcc4e79..b293bb2e 100644 --- a/wled00/presets.cpp +++ b/wled00/presets.cpp @@ -20,6 +20,20 @@ static const char *getFileName(bool persist = true) { return persist ? "/presets.json" : "/tmp.json"; } +bool presetsSavePending(void) { // WLEDMM true if presetToSave, playlistSave or saveLedmap + if (presetToSave > 0) return(true); + if (playlistSave == true) return(true); + if (saveLedmap >= 0) return(true); + return(false); +} +bool presetsActionPending(void) { // WLEDMM true if presetToApply, presetToSave, playlistSave or saveLedmap + if (presetToApply > 0) return(true); + if (presetToSave > 0) return(true); + if (playlistSave == true) return(true); + if (saveLedmap >= 0) return(true); + return(false); +} + static void doSaveState() { bool persist = (presetToSave < 251); const char *filename = getFileName(persist); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 6521e3f5..c61b12b0 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -87,6 +87,10 @@ void WLED::reset() ESP.restart(); } +#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH) +#define yield() {} // WLEDMM yield() is completely unnecessary on esp32. See https://github.com/espressif/arduino-esp32/issues/1385 +#endif + void WLED::loop() { #ifdef WLED_DEBUG @@ -141,6 +145,18 @@ void WLED::loop() yield(); + // https://github.com/Makuna/NeoPixelBus/wiki/ESP32-and-RTOS-Tasks + // On ESP32, when the CPU is loaded, asynchronous WiFi libraries (like ESPAsyncWebServer or async-mqtt-client) may interfere with interrupts used to control the LEDs (I2S mode is less affected by this), + // which causes flickering of LEDs. + #if defined(ARDUINO_ARCH_ESP32) && (defined(WLEDMM_FASTPATH) || defined(WLEDMM_PROTECT_SERVICE)) // WLEDMM experimental: avoid strip flickering + #define FILEWRITE_MAX_WAIT_MS 30 // max time for waiting - aligned with 33 fps + //if (doReboot || doSerializeConfig || doCloseFile || loadLedmap || presetsActionPending()) { // WLEDMM trx this to also wait before reading from files + if (doReboot || doSerializeConfig || doCloseFile || presetsSavePending()) { // WLEDMM wait until strip gets idle before writing to files + unsigned long waitStripStart = millis(); + while (strip.isUpdating() && (millis() - waitStripStart < FILEWRITE_MAX_WAIT_MS)) {delay(3);} + } + #endif + if (doSerializeConfig) serializeConfig(); if (doReboot && !doInitBusses) // if busses have to be inited & saved, wait until next iteration @@ -340,6 +356,10 @@ void WLED::loop() #endif } +#if defined(ARDUINO_ARCH_ESP32) && defined(WLEDMM_FASTPATH) +#undef yield // WLEDMM restore yield() +#endif + void WLED::enableWatchdog() { #if WLED_WATCHDOG_TIMEOUT > 0 #ifdef ARDUINO_ARCH_ESP32