Skip to content

Commit dac787c

Browse files
committed
Fix bug where isPressed returns True a second time
As currently implemented, if the button is pressed and immediately released before the next `loop` call, e.g., due to a blocking action like a `delay` call, the subsequent `loop` call will still consider the button as pressed. The same behavior occurs with unpressed when holding the button, and only momentarily releasing it. To fix this issue, we need to do away with the `previousSteadyState` variable so that it does not require two calls to `loop` in order to change the state.
1 parent 192d9c3 commit dac787c

File tree

2 files changed

+22
-26
lines changed

2 files changed

+22
-26
lines changed

src/ezButton.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ ezButton::ezButton(int pin, int mode) {
3838
debounceTime = 0;
3939
count = 0;
4040
countMode = COUNT_FALLING;
41+
transition = NEITHER;
4142

4243
if (mode == INTERNAL_PULLUP || mode == INTERNAL_PULLDOWN) {
4344
pinMode(btnPin, mode);
@@ -54,9 +55,8 @@ ezButton::ezButton(int pin, int mode) {
5455
unpressedState = HIGH;
5556
}
5657

57-
previousSteadyState = digitalRead(btnPin);
58-
lastSteadyState = previousSteadyState;
59-
lastFlickerableState = previousSteadyState;
58+
lastSteadyState = digitalRead(btnPin);
59+
lastFlickerableState = lastSteadyState;
6060

6161
lastDebounceTime = 0;
6262
}
@@ -74,17 +74,11 @@ int ezButton::getStateRaw(void) {
7474
}
7575

7676
bool ezButton::isPressed(void) {
77-
if(previousSteadyState == unpressedState && lastSteadyState == pressedState)
78-
return true;
79-
else
80-
return false;
77+
return transition == PRESSED;
8178
}
8279

8380
bool ezButton::isReleased(void) {
84-
if(previousSteadyState == pressedState && lastSteadyState == unpressedState)
85-
return true;
86-
else
87-
return false;
81+
return transition == UNPRESSED;
8882
}
8983

9084
void ezButton::setCountMode(int mode) {
@@ -116,25 +110,21 @@ void ezButton::loop(void) {
116110
lastFlickerableState = currentState;
117111
}
118112

119-
if ((currentTime - lastDebounceTime) >= debounceTime) {
113+
if ((currentTime - lastDebounceTime) >= debounceTime && currentState != lastSteadyState) {
120114
// whatever the reading is at, it's been there for longer than the debounce
121115
// delay, so take it as the actual current state:
122116

123-
// save the the steady state
124-
previousSteadyState = lastSteadyState;
117+
// save the the steady state and set the transition
125118
lastSteadyState = currentState;
126-
}
119+
transition = currentState == pressedState ? PRESSED : UNPRESSED;
127120

128-
if(previousSteadyState != lastSteadyState){
129121
if(countMode == COUNT_BOTH)
130122
count++;
131-
else if(countMode == COUNT_FALLING){
132-
if(previousSteadyState == HIGH && lastSteadyState == LOW)
133-
count++;
134-
}
135-
else if(countMode == COUNT_RISING){
136-
if(previousSteadyState == LOW && lastSteadyState == HIGH)
137-
count++;
138-
}
123+
else if(countMode == COUNT_FALLING && currentState == LOW)
124+
count++;
125+
else if(countMode == COUNT_RISING && currentState == HIGH)
126+
count++;
127+
} else {
128+
transition = NEITHER;
139129
}
140130
}

src/ezButton.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@
4949
#define EXTERNAL_PULLUP 0xFE
5050
#define EXTERNAL_PULLDOWN 0xFF
5151

52+
enum Transition : byte {
53+
NEITHER,
54+
PRESSED,
55+
UNPRESSED
56+
};
57+
5258
class ezButton
5359
{
5460
private:
@@ -59,9 +65,9 @@ class ezButton
5965
int pressedState; // the state when the button is considered pressed
6066
int unpressedState; // the state when the button is considered unpressed
6167

62-
int previousSteadyState; // the previous steady state from the input pin, used to detect pressed and released event
63-
int lastSteadyState; // the last steady state from the input pin
68+
int lastSteadyState; // the last steady state from the input pin, used to detect pressed and released event
6469
int lastFlickerableState; // the last flickerable state from the input pin
70+
Transition transition;
6571

6672
unsigned long lastDebounceTime; // the last time the output pin was toggled
6773

0 commit comments

Comments
 (0)