From e16d3bf040a20d104c29fe870639d04e018a7b8d Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Fri, 13 Dec 2024 07:40:04 +0100 Subject: [PATCH 1/3] Fix: output-glitching on ESPNow remote command reception Processing of received button command is no longer processed in the callback, instead the value is saved to a variable and processed in the main loop. The actual fix is to not access the file system while data is being sent out: even just trying to open a non-existing file causes glitches on the C3. Waiting for the bus to finish fixes this BUT it causes a frame-delay which is the lesser evil than random color flashes. --- wled00/fcn_declare.h | 1 + wled00/remote.cpp | 19 ++++++++++++++++--- wled00/wled.cpp | 3 +++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 3d8c27aca..e883c5fbd 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -231,6 +231,7 @@ bool getPresetName(byte index, String& name); //remote.cpp void handleRemote(uint8_t *data, size_t len); +void processESPNowButton(); //set.cpp bool isAsterisksOnly(const char* str, byte maxLen); diff --git a/wled00/remote.cpp b/wled00/remote.cpp index 9bc5430c0..de386932a 100644 --- a/wled00/remote.cpp +++ b/wled00/remote.cpp @@ -1,6 +1,8 @@ #include "wled.h" #ifndef WLED_DISABLE_ESPNOW +#define ESPNOW_BUSWAIT_TIMEOUT 30 // timeout in ms to wait for bus to finish updating + #define NIGHT_MODE_DEACTIVATED -1 #define NIGHT_MODE_BRIGHTNESS 5 @@ -38,6 +40,7 @@ typedef struct WizMoteMessageStructure { static uint32_t last_seq = UINT32_MAX; static int brightnessBeforeNightMode = NIGHT_MODE_DEACTIVATED; +static uint8_t ESPNowButton = 0; // set in callback if new button value is received // Pulled from the IR Remote logic but reduced to 10 steps with a constant of 3 static const byte brightnessSteps[] = { @@ -121,6 +124,9 @@ static bool remoteJson(int button) sprintf_P(objKey, PSTR("\"%d\":"), button); + unsigned long start = millis(); + while (strip.isUpdating() && millis()-start < ESPNOW_BUSWAIT_TIMEOUT) yield(); // wait for strip to finish updating, accessing FS during sendout causes glitches + // attempt to read command from remote.json readObjectFromFile(PSTR("/remote.json"), objKey, pDoc); JsonObject fdo = pDoc->as(); @@ -202,8 +208,14 @@ void handleRemote(uint8_t *incomingData, size_t len) { DEBUG_PRINT(F("] button: ")); DEBUG_PRINTLN(incoming->button); - if (!remoteJson(incoming->button)) - switch (incoming->button) { + ESPNowButton = incoming->button; // save state, do not process in callback (can cause glitches) + last_seq = cur_seq; +} + +void processESPNowButton() { + if(ESPNowButton > 0) { + if (!remoteJson(ESPNowButton)) + switch (ESPNowButton) { case WIZMOTE_BUTTON_ON : setOn(); break; case WIZMOTE_BUTTON_OFF : setOff(); break; case WIZMOTE_BUTTON_ONE : presetWithFallback(1, FX_MODE_STATIC, 0); break; @@ -219,7 +231,8 @@ void handleRemote(uint8_t *incomingData, size_t len) { case WIZ_SMART_BUTTON_BRIGHT_DOWN : brightnessDown(); break; default: break; } - last_seq = cur_seq; + } + ESPNowButton = 0; } #else diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 394da6783..229d363b3 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -84,6 +84,9 @@ void WLED::loop() #ifndef WLED_DISABLE_INFRARED handleIR(); #endif + #ifndef WLED_DISABLE_ESPNOW + processESPNowButton(); + #endif #ifndef WLED_DISABLE_ALEXA handleAlexa(); #endif From fd3b47908b8eab700391a759a99d3987f536586f Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 19 Dec 2024 17:41:44 +0100 Subject: [PATCH 2/3] renamed functions, changed timeout to 24ms --- wled00/fcn_declare.h | 4 ++-- wled00/remote.cpp | 9 +++++---- wled00/udp.cpp | 2 +- wled00/wled.cpp | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index e883c5fbd..2e965a9af 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -230,8 +230,8 @@ void deletePreset(byte index); bool getPresetName(byte index, String& name); //remote.cpp -void handleRemote(uint8_t *data, size_t len); -void processESPNowButton(); +void handleWiZdata(uint8_t *incomingData, size_t len); +void handleRemote(); //set.cpp bool isAsterisksOnly(const char* str, byte maxLen); diff --git a/wled00/remote.cpp b/wled00/remote.cpp index de386932a..8787369c0 100644 --- a/wled00/remote.cpp +++ b/wled00/remote.cpp @@ -1,7 +1,7 @@ #include "wled.h" #ifndef WLED_DISABLE_ESPNOW -#define ESPNOW_BUSWAIT_TIMEOUT 30 // timeout in ms to wait for bus to finish updating +#define ESPNOW_BUSWAIT_TIMEOUT 24 // one frame timeout to wait for bus to finish updating #define NIGHT_MODE_DEACTIVATED -1 #define NIGHT_MODE_BRIGHTNESS 5 @@ -182,7 +182,7 @@ static bool remoteJson(int button) } // Callback function that will be executed when data is received -void handleRemote(uint8_t *incomingData, size_t len) { +void handleWiZdata(uint8_t *incomingData, size_t len) { message_structure_t *incoming = reinterpret_cast(incomingData); if (strcmp(last_signal_src, linked_remote) != 0) { @@ -212,7 +212,8 @@ void handleRemote(uint8_t *incomingData, size_t len) { last_seq = cur_seq; } -void processESPNowButton() { +// process ESPNow button data (acesses FS, should not be called while update to avoid glitches) +void handleRemote() { if(ESPNowButton > 0) { if (!remoteJson(ESPNowButton)) switch (ESPNowButton) { @@ -236,5 +237,5 @@ void processESPNowButton() { } #else -void handleRemote(uint8_t *incomingData, size_t len) {} +void handleRemote() {} #endif diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 60774d701..5173842a6 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -979,7 +979,7 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs // handle WiZ Mote data if (data[0] == 0x91 || data[0] == 0x81 || data[0] == 0x80) { - handleRemote(data, len); + handleWiZdata(data, len); return; } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 229d363b3..b7f4ad7d6 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -85,7 +85,7 @@ void WLED::loop() handleIR(); #endif #ifndef WLED_DISABLE_ESPNOW - processESPNowButton(); + handleRemote(); #endif #ifndef WLED_DISABLE_ALEXA handleAlexa(); From dcfebcb9732e3ffae63d8e2b8566f70397b6c745 Mon Sep 17 00:00:00 2001 From: Damian Schneider Date: Thu, 19 Dec 2024 17:46:39 +0100 Subject: [PATCH 3/3] allow for 0 value button code --- wled00/remote.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wled00/remote.cpp b/wled00/remote.cpp index 8787369c0..c3325ab98 100644 --- a/wled00/remote.cpp +++ b/wled00/remote.cpp @@ -40,7 +40,7 @@ typedef struct WizMoteMessageStructure { static uint32_t last_seq = UINT32_MAX; static int brightnessBeforeNightMode = NIGHT_MODE_DEACTIVATED; -static uint8_t ESPNowButton = 0; // set in callback if new button value is received +static int16_t ESPNowButton = -1; // set in callback if new button value is received // Pulled from the IR Remote logic but reduced to 10 steps with a constant of 3 static const byte brightnessSteps[] = { @@ -214,7 +214,7 @@ void handleWiZdata(uint8_t *incomingData, size_t len) { // process ESPNow button data (acesses FS, should not be called while update to avoid glitches) void handleRemote() { - if(ESPNowButton > 0) { + if(ESPNowButton >= 0) { if (!remoteJson(ESPNowButton)) switch (ESPNowButton) { case WIZMOTE_BUTTON_ON : setOn(); break; @@ -233,7 +233,7 @@ void handleRemote() { default: break; } } - ESPNowButton = 0; + ESPNowButton = -1; } #else