From 126acbddf87c3b45eeaa707ba79645c1c234c726 Mon Sep 17 00:00:00 2001 From: Matthew Richardson Date: Fri, 24 May 2024 08:50:40 -0400 Subject: [PATCH 1/5] Debounce State Debounce the button state, not just the pin state. This way debounce() will know if it's pressed or not pressed. Also, enable a negative ms value so it will only debounce the state on inactive. This way a button press will be recognized instantly. Deactivating the button press will still be subject to the debounce time, preventing switch "noise" from propagating through to the _fsm. --- src/OneButton.cpp | 22 ++++++++++++++-------- src/OneButton.h | 10 +++++----- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/OneButton.cpp b/src/OneButton.cpp index 3e09768..1836294 100644 --- a/src/OneButton.cpp +++ b/src/OneButton.cpp @@ -59,7 +59,7 @@ OneButton::OneButton(const int pin, const bool activeLow, const bool pullupActiv // explicitly set the number of millisec that have to pass by before a click is assumed stable. -void OneButton::setDebounceMs(const unsigned int ms) +void OneButton::setDebounceMs(const int ms) { _debounce_ms = ms; } // setDebounceMs @@ -206,26 +206,32 @@ int OneButton::getNumberClicks(void) */ int OneButton::debounce(const int value) { now = millis(); // current (relative) time in msecs. - if (_lastDebouncePinLevel == value) { - if (now - _lastDebounceTime >= _debounce_ms) - debouncedPinLevel = value; + + // Don't debounce going into active state, if _debounce_ms is negative + if(value && _debounce_ms < 0){ + debouncedLevel = value; + } + + if (_lastDebounceLevel == value) { + if (now - _lastDebounceTime >= abs(_debounce_ms)) + debouncedLevel = value; } else { _lastDebounceTime = now; - _lastDebouncePinLevel = value; + _lastDebounceLevel = value; } - return debouncedPinLevel; + return debouncedLevel; }; /** * @brief Check input of the configured pin, - * debounce input pin level and then + * debounce button state and then * advance the finite state machine (FSM). */ void OneButton::tick(void) { if (_pin >= 0) { - _fsm(debounce(digitalRead(_pin)) == _buttonPressed); + _fsm(debounce(digitalRead(_pin) == _buttonPressed)); } } // tick() diff --git a/src/OneButton.h b/src/OneButton.h index 77a8476..f5ae9fd 100644 --- a/src/OneButton.h +++ b/src/OneButton.h @@ -56,7 +56,7 @@ class OneButton */ [[deprecated("Use setDebounceMs() instead.")]] void setDebounceTicks(const unsigned int ms) { setDebounceMs(ms); }; // deprecated - void setDebounceMs(const unsigned int ms); + void setDebounceMs(const int ms); /** * set # millisec after single click is assumed. @@ -177,7 +177,7 @@ class OneButton private: int _pin = -1; // hardware pin number. - unsigned int _debounce_ms = 50; // number of msecs for debounce times. + int _debounce_ms = 50; // number of msecs for debounce times. unsigned int _click_ms = 400; // number of msecs before a click is detected. unsigned int _press_ms = 800; // number of msecs before a long button press is detected unsigned int _idle_ms = 1000; // number of msecs before idle is detected @@ -241,8 +241,8 @@ class OneButton bool _idleState = false; - int debouncedPinLevel = -1; - int _lastDebouncePinLevel = -1; // used for pin debouncing + int debouncedLevel = -1; + int _lastDebounceLevel = -1; // used for pin debouncing unsigned long _lastDebounceTime = 0; // millis() unsigned long now = 0; // millis() @@ -257,7 +257,7 @@ class OneButton int pin() const { return _pin; }; stateMachine_t state() const { return _state; }; int debounce(const int value); - int debouncedValue() const { return debouncedPinLevel; }; + int debouncedValue() const { return debouncedLevel; }; /** * @brief Use this function in the DuringLongPress and LongPressStop events to get the time since the button was pressed. From ed5a7c81c3bb232832db3756f9f65f809acad544 Mon Sep 17 00:00:00 2001 From: Matthew Richardson Date: Fri, 24 May 2024 15:07:47 -0400 Subject: [PATCH 2/5] Fix bool variables These should be boolean values, since they are passed into _fsm() which expects bool. Otherwise the (previous) default value of -1 will be interpreted by the _fsm() as being 'true' (not 0). --- src/OneButton.cpp | 2 +- src/OneButton.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OneButton.cpp b/src/OneButton.cpp index 1836294..0ab28c8 100644 --- a/src/OneButton.cpp +++ b/src/OneButton.cpp @@ -204,7 +204,7 @@ int OneButton::getNumberClicks(void) /** * @brief Debounce input pin level for use in SpesialInput. */ -int OneButton::debounce(const int value) { +bool OneButton::debounce(const bool value) { now = millis(); // current (relative) time in msecs. // Don't debounce going into active state, if _debounce_ms is negative diff --git a/src/OneButton.h b/src/OneButton.h index f5ae9fd..0ad65b0 100644 --- a/src/OneButton.h +++ b/src/OneButton.h @@ -241,8 +241,8 @@ class OneButton bool _idleState = false; - int debouncedLevel = -1; - int _lastDebounceLevel = -1; // used for pin debouncing + bool debouncedLevel = false; + bool _lastDebounceLevel = false; // used for pin debouncing unsigned long _lastDebounceTime = 0; // millis() unsigned long now = 0; // millis() @@ -256,7 +256,7 @@ class OneButton public: int pin() const { return _pin; }; stateMachine_t state() const { return _state; }; - int debounce(const int value); + bool debounce(const bool value); int debouncedValue() const { return debouncedLevel; }; /** From abf3b8ad18b741f070d99a9eef1b775061a81321 Mon Sep 17 00:00:00 2001 From: Matthew Richardson Date: Fri, 24 May 2024 15:09:39 -0400 Subject: [PATCH 3/5] Add support for press event Add support for a callback immediately when detecting a press, rather than the alternatives of waiting for a release or a long press. --- src/OneButton.cpp | 17 +++++++++++++++++ src/OneButton.h | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/OneButton.cpp b/src/OneButton.cpp index 0ab28c8..74a52c6 100644 --- a/src/OneButton.cpp +++ b/src/OneButton.cpp @@ -84,6 +84,20 @@ void OneButton::setIdleMs(const unsigned int ms) _idle_ms = ms; } // setIdleMs +// save function for click event +void OneButton::attachPress(callbackFunction newFunction) +{ + _pressFunc = newFunction; +} // attachPress + + +// save function for parameterized click event +void OneButton::attachPress(parameterizedCallbackFunction newFunction, void *parameter) +{ + _paramPressFunc = newFunction; + _pressFuncParam = parameter; +} // attachPress + // save function for click event void OneButton::attachClick(callbackFunction newFunction) { @@ -273,6 +287,9 @@ void OneButton::_fsm(bool activeLevel) _newState(OneButton::OCS_DOWN); _startTime = now; // remember starting time _nClicks = 0; + + if (_pressFunc) _pressFunc(); + if (_paramPressFunc) _paramPressFunc(_pressFuncParam); } // if break; diff --git a/src/OneButton.h b/src/OneButton.h index 0ad65b0..a706c10 100644 --- a/src/OneButton.h +++ b/src/OneButton.h @@ -85,6 +85,13 @@ class OneButton // ----- Attach events functions ----- + /** + * Attach an event to be called immediately when a depress is detected. + * @param newFunction This function will be called when the event has been detected. + */ + void attachPress(callbackFunction newFunction); + void attachPress(parameterizedCallbackFunction newFunction, void *parameter); + /** * Attach an event to be called when a single click is detected. * @param newFunction This function will be called when the event has been detected. @@ -187,6 +194,10 @@ class OneButton // HIGH if the button connects the input pin to VCC when pressed. // These variables will hold functions acting as event source. + callbackFunction _pressFunc = NULL; + parameterizedCallbackFunction _paramPressFunc = NULL; + void *_pressFuncParam = NULL; + callbackFunction _clickFunc = NULL; parameterizedCallbackFunction _paramClickFunc = NULL; void *_clickFuncParam = NULL; From 55148174cc4b84af3190a6d2441c2ea6575bbf9c Mon Sep 17 00:00:00 2001 From: Matthew Richardson Date: Fri, 24 May 2024 15:10:11 -0400 Subject: [PATCH 4/5] Tidy up 'if' Tidy up a single-line if-statement. --- src/OneButton.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/OneButton.cpp b/src/OneButton.cpp index 74a52c6..0a83bb3 100644 --- a/src/OneButton.cpp +++ b/src/OneButton.cpp @@ -222,9 +222,8 @@ bool OneButton::debounce(const bool value) { now = millis(); // current (relative) time in msecs. // Don't debounce going into active state, if _debounce_ms is negative - if(value && _debounce_ms < 0){ + if(value && _debounce_ms < 0) debouncedLevel = value; - } if (_lastDebounceLevel == value) { if (now - _lastDebounceTime >= abs(_debounce_ms)) From 2251f1a82333a935d74ee049f5e6d25e85af41b8 Mon Sep 17 00:00:00 2001 From: Matthew Richardson Date: Mon, 27 May 2024 09:30:17 -0400 Subject: [PATCH 5/5] Update Readme Update readme to reflect the changes. --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0ed76d8..aafdfa4 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,8 @@ Here's a full list of events handled by this library: | Attach Function | Description | | ----------------------- | ------------------------------------------------------------- | -| `attachClick` | Fires as soon as a single click is detected. | +| `attachPress` | Fires as soon as a press is detected. | +| `attachClick` | Fires as soon as a single click press and release is detected.| | `attachDoubleClick` | Fires as soon as a double click is detected. | | `attachMultiClick` | Fires as soon as multiple clicks have been detected. | | `attachLongPressStart` | Fires as soon as the button is held down for 800 milliseconds.| @@ -175,12 +176,16 @@ This is because a single click callback must not to be triggered in case of a do | `setPressMs(int)` | `800 msec` | Duration to hold a button to trigger a long press. | You may change these default values but be aware that when you specify too short times -it is hard to click twice or you will create a press instead of a click. +it is hard to click twice or you will create a long press instead of a click. The former functions `setDebounceTicks`, `setClickTicks` and `setPressTicks` are marked deprecated. The term `Ticks` in these functions where confusing. Replace them with the ...Ms function calls. There is no functional change on them. +Set debounce ms to a negative value to only debounce on release. `setDebounceMs(-25);` will immediately +update to a pressed state, and will debounce for 25ms going into the released state. This will expidite +the `attachPress` callback function to run instantly. + ### Additional Functions