Skip to content

Commit 6d97f26

Browse files
committed
Bugfix, Refactoring
1 parent aac24e7 commit 6d97f26

4 files changed

Lines changed: 79 additions & 44 deletions

File tree

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Button_SL",
3-
"version": "1.1.6",
3+
"version": "1.1.7",
44
"keywords": "button, debounce, signal, input, ouput",
55
"description": "Button_SL enables the query of buttons. The query is debounced. A query can be made as to whether the button was pressed for a short or long time.",
66
"repository": {

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Button_SL
2-
version=1.1.6
2+
version=1.1.7
33
author=Kai R.
44
maintainer=Kai R.
55
sentence=Button query

src/Button_SL.cpp

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,18 @@
2525
/// @version 1.1.4 Repeated debounce in the button class removed.
2626
///
2727
/// @date 2024-07-06
28-
/// @version 1.1.5 The autorelease is only executed once as long as the button has not been released.
29-
/// Previously, if the button was held down continuously, the autorelease was executed
30-
/// every time the time for a long button press expired.
28+
/// @version 1.1.5 The autorelease is only executed once as long as the button has not been released.
29+
/// Previously, if the button was held down continuously, the autorelease was executed
30+
/// every time the time for a long button press expired.
31+
///
32+
/// @date 2025-05-10
33+
/// @version 1.1.6 The ButtonState::pressed status has been added.
34+
/// For a long button press with automatic release enabled, the ButtonState::longPressed status
35+
/// is returned once when the defined time for a long button press is reached. Then
36+
/// the ButtonState::pressed status is returned as long as the button is held down.
37+
///
38+
/// @date 2025-05-26
39+
/// @version 1.1.7 tick() Method code rework. Bug fix.
3140
///
3241
/// @copyright Copyright (c) 2022
3342
/// MIT license, check license.md for more information
@@ -58,10 +67,10 @@ bool Button::tick() {
5867
switch (compareState) {
5968
case LOW:
6069
compareState = HIGH; // set to HIGH when Button was pressed
61-
timeStamp = millis();
70+
timestamp = millis();
6271
[[fallthrough]];
6372
case HIGH:
64-
if (millis() - timeStamp > dbTime_ms) {
73+
if (millis() - timestamp > dbTime_ms) {
6574
// If the button press is equal to the specified debounce time, confirm the button press with true.
6675
flag = true;
6776
}
@@ -84,30 +93,50 @@ void Button::setDebounceTime_ms(uint16_t dbT_ms) { dbTime_ms = dbT_ms; }
8493
/// @brief The ButtonSL query. The tick() method should be called in an endless loop.
8594
///
8695
/// @param time_ms time (in ms) from which a key press is recognized as long
87-
/// @return ButtonState The states are "Not pressed", "short pressed" and "long pressed"
96+
/// @return ButtonState The states are "not pressed", "pressed", "short pressed" and "long pressed"
8897
//////////////////////////////////////////////////////////////////////////////
98+
8999
ButtonState ButtonSL::tick() {
90-
uint_least32_t now = millis();
91100
compareState = state;
92101
state = digitalRead(pin);
93-
if (state == activeState && compareState != activeState) {
94-
timeStamp = now;
95-
hasReleased = false;
96-
} else if (state != activeState && compareState == activeState) {
97-
timeStamp = now - timeStamp;
98-
if (timeStamp >= dbTime_ms && !hasReleased) { // released after debounce time?
99-
return (timeStamp >= time_ms) ? ButtonState::longPressed : ButtonState::shortPressed;
100-
}
101-
// hasReleased = false;
102-
} else if (autoRelease && not hasReleased && (compareState == activeState)) {
103-
if (now - timeStamp >= time_ms) {
104-
// state = !compareState;
105-
hasReleased = true;
106-
timeStamp = time_ms;
107-
return ButtonState::longPressed;
108-
}
102+
103+
MillisType now = millis();
104+
if (state != activeState && compareState != activeState) { // not pressed
105+
return ButtonState::notPressed;
106+
} else if (state == activeState && compareState != activeState) { // Not pressed to pressed
107+
timestamp = now;
108+
autoReleaseFired = false;
109+
pin_state = Condition::notPressedToPressed;
110+
} else if (state == activeState && compareState == activeState) { // pressed
111+
pin_state = Condition::pressed;
112+
} else if (state != activeState && compareState == activeState) { // Pressed to not pressed
113+
pin_state = Condition::pressedToNotpressed;
114+
}
115+
116+
switch (pin_state) {
117+
case Condition::notPressedToPressed:
118+
case Condition::pressed:
119+
if (autoRelease) {
120+
switch (autoReleaseFired) {
121+
case true: return ButtonState::pressed; break;
122+
case false:
123+
if (now - timestamp >= time_ms) {
124+
autoReleaseFired = true;
125+
timestamp = time_ms;
126+
return ButtonState::longPressed;
127+
}
128+
}
129+
}
130+
break;
131+
case Condition::pressedToNotpressed:
132+
timestamp = now - timestamp;
133+
// Push duration longer than the debounce time?
134+
if (timestamp >= dbTime_ms && !autoReleaseFired) {
135+
return (timestamp >= time_ms) ? ButtonState::longPressed : ButtonState::shortPressed;
136+
}
137+
break;
109138
}
110-
return hasReleased ? ButtonState::pressed : ButtonState::notPressed;
139+
return ButtonState::notPressed;
111140
}
112141

113142
//////////////////////////////////////////////////////////////////////////////
@@ -122,5 +151,5 @@ void ButtonSL::setTimeThreshold_ms(uint16_t th_ms) { time_ms = th_ms; }
122151
///
123152
/// @return uint32_t Time in milliseconds
124153
//////////////////////////////////////////////////////////////////////////////
125-
uint32_t ButtonSL::getDuration_ms(void) const { return timeStamp; }
154+
uint32_t ButtonSL::getDuration_ms(void) const { return timestamp; }
126155
} // namespace Btn

src/Button_SL.hpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,21 @@
1717
/// All text above must be included in any redistribution
1818
//////////////////////////////////////////////////////////////////////////////
1919

20-
#ifndef _BUTTON_SL_HPP_
21-
#define _BUTTON_SL_HPP_
20+
#pragma once
21+
2222
#include <Arduino.h>
2323

2424
namespace Btn {
25+
26+
//////////////////////////////////////////////////
27+
// Type alias(es)
28+
//////////////////////////////////////////////////
29+
using MillisType = decltype(millis());
30+
2531
//////////////////////////////////////////////////
2632
// Constants
2733
//////////////////////////////////////////////////
28-
constexpr uint8_t DEBOUNCE_TIME{30}; // The value can be reduced for buttons that bounce little. Time in ms.
34+
constexpr uint8_t DEBOUNCE_TIME {30}; // The value can be reduced for buttons that bounce little. Time in ms.
2935

3036
//////////////////////////////////////////////////
3137
// Variables and Classdefinitions
@@ -40,20 +46,20 @@ enum class ButtonState : uint8_t { notPressed = false, pressed = true, shortPres
4046
//////////////////////////////////////////////////////////////////////////////
4147
class Button {
4248
public:
43-
Button(uint8_t pinNr = 0, bool as = LOW) : pin{pinNr}, activeState{as} {}
44-
Button(const Button &) = delete; // No copy constructor
45-
Button &operator=(const Button &) = delete; // No assignment
46-
Button(Button &&) = default; // Move it
49+
Button(uint8_t pinNr = 0, bool as = LOW) : pin {pinNr}, activeState {as} {}
50+
Button(const Button&) = delete; // No copy constructor
51+
Button& operator=(const Button&) = delete; // No assignment
52+
Button(Button&&) = default; // Move it
4753
void begin();
4854
bool tick();
4955
void setDebounceTime_ms(uint16_t);
5056

5157
protected:
5258
uint8_t pin; // Button PIN number
5359
uint8_t activeState; // Saves whether the buttons active state is HIGH or LOW.
54-
uint8_t compareState{LOW};
55-
uint16_t dbTime_ms{DEBOUNCE_TIME};
56-
uint_least32_t timeStamp;
60+
uint8_t compareState {LOW};
61+
uint16_t dbTime_ms {DEBOUNCE_TIME};
62+
MillisType timestamp;
5763
};
5864

5965
//////////////////////////////////////////////////////////////////////////////
@@ -63,19 +69,19 @@ class Button {
6369
//////////////////////////////////////////////////////////////////////////////
6470
class ButtonSL : public Button {
6571
public:
66-
ButtonSL(uint8_t pinNr = 0, uint16_t t_ms = 1000, bool as = LOW) : Button{pinNr, as} { time_ms = t_ms; }
72+
ButtonSL(uint8_t pinNr = 0, uint16_t t_ms = 1000, bool as = LOW) : Button {pinNr, as} { time_ms = t_ms; }
6773
ButtonState tick();
6874
void setTimeThreshold_ms(uint16_t);
6975
void releaseOn() { autoRelease = true; }
7076
void releaseOff() { autoRelease = false; }
7177
uint32_t getDuration_ms() const;
7278

7379
private:
74-
uint16_t time_ms; // Saves the time (in ms) from which a key press is recognized as long.
75-
uint8_t state{!activeState};
76-
uint16_t pressingTime; // Saves the length of time that the button was pressed (ms).
77-
bool autoRelease{false};
78-
bool hasReleased{false};
80+
uint16_t time_ms; // Saves the time (in ms) from which a key press is recognized as long.
81+
uint8_t state {!activeState};
82+
bool autoRelease {false};
83+
bool autoReleaseFired {false};
84+
enum class Condition : byte { notPressedToPressed, pressed, pressedToNotpressed };
85+
Condition pin_state {Condition::pressedToNotpressed};
7986
};
8087
} // namespace Btn
81-
#endif

0 commit comments

Comments
 (0)