Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions wled00/button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
* Physical IO
*/

#define WLED_DEBOUNCE_THRESHOLD 50 // only consider button input of at least 50ms as valid (debouncing)
#define WLED_LONG_PRESS 600 // long press if button is released after held for at least 600ms
#define WLED_DOUBLE_PRESS 350 // double press if another press within 350ms after a short press
#define WLED_LONG_REPEATED_ACTION 400 // how often a repeated action (e.g. dimming) is fired on long press on button IDs >0
#define WLED_LONG_AP 5000 // how long button 0 needs to be held to activate WLED-AP
#define WLED_LONG_FACTORY_RESET 10000 // how long button 0 needs to be held to trigger a factory reset
Expand Down Expand Up @@ -136,7 +133,7 @@ void handleSwitch(uint8_t b)

if (buttons[b].longPressed == buttons[b].pressedBefore) return;

if (millis() - buttons[b].pressedTime > WLED_DEBOUNCE_THRESHOLD) { //fire edge event only after 50ms without change (debounce)
if (millis() - buttons[b].pressedTime > buttonDebounceMs) { //fire edge event only after debounce threshold without change
DEBUG_PRINTF_P(PSTR("Switch: Activating %u\n"), b);
if (!buttons[b].pressedBefore) { // on -> off
DEBUG_PRINTF_P(PSTR("Switch: On -> Off (%u)\n"), b);
Expand Down Expand Up @@ -304,7 +301,7 @@ void handleButton()
if (!buttons[b].pressedBefore) buttons[b].pressedTime = now;
buttons[b].pressedBefore = true;

if (now - buttons[b].pressedTime > WLED_LONG_PRESS) { //long press
if (now - buttons[b].pressedTime > buttonLongPressMs) { //long press
if (!buttons[b].longPressed) {
buttonBriDirection = !buttonBriDirection; //toggle brightness direction on long press
longPressAction(b);
Expand All @@ -320,11 +317,11 @@ void handleButton()

// released after rising-edge short press action
if (buttons[b].macroButton && buttons[b].macroButton == buttons[b].macroLongPress && buttons[b].macroButton == buttons[b].macroDoublePress) {
if (dur > WLED_DEBOUNCE_THRESHOLD) buttons[b].pressedBefore = false; // debounce, blocks button for 50 ms once it has been released
if (dur > buttonDebounceMs) buttons[b].pressedBefore = false; // debounce, blocks button once it has been released
continue;
}

if (dur < WLED_DEBOUNCE_THRESHOLD) {buttons[b].pressedBefore = false; continue;} // too short "press", debounce
if (dur < buttonDebounceMs) {buttons[b].pressedBefore = false; continue;} // too short "press", debounce
Comment thread
coderabbitai[bot] marked this conversation as resolved.
bool doublePress = buttons[b].waitTime; //did we have a short press before?
buttons[b].waitTime = 0;

Expand All @@ -339,7 +336,7 @@ void handleButton()
//NOTE: this interferes with double click handling in usermods so usermod needs to implement full button handling
if (b != 1 && !buttons[b].macroDoublePress) { //don't wait for double press on buttons without a default action if no double press macro set
shortPressAction(b);
} else { //double press if less than 350 ms between current press and previous short press release (buttonWaitTime!=0)
} else { //double press if within double press window of current press and previous short press release (buttonWaitTime!=0)
if (doublePress) {
doublePressAction(b);
} else {
Expand All @@ -351,8 +348,8 @@ void handleButton()
buttons[b].longPressed = false;
}

//if 350ms elapsed since last short press release it is a short press
if (buttons[b].waitTime && now - buttons[b].waitTime > WLED_DOUBLE_PRESS && !buttons[b].pressedBefore) {
//if double press window elapsed since last short press release it is a short press
if (buttons[b].waitTime && now - buttons[b].waitTime > buttonDoublePressMs && !buttons[b].pressedBefore) {
buttons[b].waitTime = 0;
shortPressAction(b);
}
Expand Down
9 changes: 9 additions & 0 deletions wled00/cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,12 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
}

CJSON(buttonPublishMqtt, btn_obj["mqtt"]);
CJSON(buttonDebounceMs, btn_obj[F("dbnc")]);
CJSON(buttonLongPressMs, btn_obj[F("lp")]);
CJSON(buttonDoublePressMs, btn_obj[F("dp")]);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
buttonDebounceMs = constrain(buttonDebounceMs, 0, 100);
buttonLongPressMs = constrain(buttonLongPressMs, 200, 4000); // floor kept above the debounce max (100) so long press can never be shorter than debounce
buttonDoublePressMs = constrain(buttonDoublePressMs, 100, 1000);

#ifndef WLED_DISABLE_INFRARED
int hw_ir_pin = hw["ir"]["pin"] | -2; // 4
Expand Down Expand Up @@ -1048,6 +1054,9 @@ void serializeConfig(JsonObject root) {

hw_btn[F("tt")] = touchThreshold;
hw_btn["mqtt"] = buttonPublishMqtt;
hw_btn[F("dbnc")] = buttonDebounceMs;
hw_btn[F("lp")] = buttonLongPressMs;
hw_btn[F("dp")] = buttonDoublePressMs;

JsonObject hw_ir = hw.createNestedObject("ir");
#ifndef WLED_DISABLE_INFRARED
Expand Down
4 changes: 4 additions & 0 deletions wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,10 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit");

#define TOUCH_THRESHOLD 32 // limit to recognize a touch, higher value means more sensitive

#define WLED_DEBOUNCE_THRESHOLD 50 // default: only consider button input of at least 50ms as valid (debouncing)
#define WLED_LONG_PRESS 600 // default: trigger long press after the button remains pressed for 600ms
#define WLED_DOUBLE_PRESS 350 // default: double press if another press within 350ms after a short press

// Size of buffer for API JSON object (increase for more segments)
#ifdef ESP8266
#define JSON_BUFFER_SIZE 10240
Expand Down
11 changes: 10 additions & 1 deletion wled00/data/settings_leds.htm
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,9 @@
addBtn(i,v.pin[0],v.type);
});
d.getElementsByName("TT")[0].value = b.tt;
if (b.dbnc !== undefined) d.getElementsByName("DB")[0].value = b.dbnc;
if (b.lp !== undefined) d.getElementsByName("LP")[0].value = b.lp;
if (b.dp !== undefined) d.getElementsByName("DP")[0].value = b.dp;
Comment thread
adamsthws marked this conversation as resolved.
}
let ir = c.hw.ir;
if (ir) {
Expand Down Expand Up @@ -1093,7 +1096,13 @@ <h3>Buttons</h3>
<button type="button" id="btn_rem" onclick="remBtn()">-</button>
</div>
Disable internal pull-up/down: <input type="checkbox" name="IP"><br>
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br><br>
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>
Debounce time: <input type="number" class="s" min="0" max="100" name="DB" required> ms (0-100)<br>
<small>Ignores presses shorter than this (filters switch/contact noise)<br></small>
Long press time: <input type="number" class="s" min="200" max="4000" name="LP" required> ms (200-4000)<br>
<small>How long to hold before a long press triggers<br></small>
Double press time: <input type="number" class="s" min="100" max="1000" name="DP" required> ms (100-1000)<br>
<small>Max gap between two clicks to count as a double press<br></small><br>
</div>
<div class="sec">
<h3>IR Remote</h3>
Expand Down
6 changes: 6 additions & 0 deletions wled00/set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)

disablePullUp = (bool)request->hasArg(F("IP"));
touchThreshold = request->arg(F("TT")).toInt();
t = request->arg(F("DB")).toInt();
if (t >= 0 && t <= 100) buttonDebounceMs = t;
t = request->arg(F("LP")).toInt();
if (t >= 200 && t <= 4000) buttonLongPressMs = t; // stay below WLED_LONG_AP so button 0's AP-mode/factory-reset thresholds are unaffected; floor kept above the debounce max (100) so long press can never be shorter than debounce
t = request->arg(F("DP")).toInt();
if (t >= 100 && t <= 1000) buttonDoublePressMs = t;
for (int i = 0; i < WLED_MAX_BUTTONS; i++) {
int offset = i < 10 ? '0' : 'A' - 10;
char bt[4] = "BT"; bt[2] = offset+i; bt[3] = 0; // button pin (use A,B,C,... if WLED_MAX_BUTTONS>10)
Expand Down
3 changes: 3 additions & 0 deletions wled00/wled.h
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,9 @@ WLED_GLOBAL std::vector<Button> buttons; // vector of button structs
WLED_GLOBAL bool buttonPublishMqtt _INIT(false);
WLED_GLOBAL bool disablePullUp _INIT(false);
WLED_GLOBAL byte touchThreshold _INIT(TOUCH_THRESHOLD);
WLED_GLOBAL uint16_t buttonDebounceMs _INIT(WLED_DEBOUNCE_THRESHOLD);
WLED_GLOBAL uint16_t buttonLongPressMs _INIT(WLED_LONG_PRESS);
WLED_GLOBAL uint16_t buttonDoublePressMs _INIT(WLED_DOUBLE_PRESS);

// notifications
WLED_GLOBAL bool sendNotifications _INIT(false); // master notification switch
Expand Down
3 changes: 3 additions & 0 deletions wled00/xml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,9 @@ void getSettingsJS(byte subPage, Print& settingsScript)
}
printSetFormCheckbox(settingsScript,PSTR("IP"),disablePullUp);
printSetFormValue(settingsScript,PSTR("TT"),touchThreshold);
printSetFormValue(settingsScript,PSTR("DB"),buttonDebounceMs);
printSetFormValue(settingsScript,PSTR("LP"),buttonLongPressMs);
printSetFormValue(settingsScript,PSTR("DP"),buttonDoublePressMs);
#ifndef WLED_DISABLE_INFRARED
printSetFormValue(settingsScript,PSTR("IR"),irPin);
printSetFormValue(settingsScript,PSTR("IT"),irEnabled);
Expand Down
Loading