Skip to content

Commit

Permalink
Merge pull request #9 from Mokolea/support-released-duration-time
Browse files Browse the repository at this point in the history
Support pressed-on time duration on release
  • Loading branch information
Mokolea authored Apr 17, 2018
2 parents 08cb883 + bc2fb2e commit 43a6e6f
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 47 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Simple polling input debounce [Arduino](https://www.arduino.cc/) library. Also u
- used for push-button like switches
- delivers input value (state) after it has been stable (not flickering) for longer than the debounce period
- delivers continuous or single-shot pressed-on time duration [ms]
- delivers pressed-on time duration on release [ms]
- handles input pin with:
- external pull-down resistor
- external pull-up resistor
Expand Down
2 changes: 1 addition & 1 deletion examples/Test_InputDebounce/Test_InputDebounce.ino
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void loop()
// save current on-time (button pressed), to be used when released
buttonTest_OnTimeLast = buttonTest_OnTime;
// check for state change
unsigned int count = buttonTest.getStateOnCount();
unsigned int count = buttonTest.getStatePressedCount();
if(buttonTest_StateOnCount != count) {
buttonTest_StateOnCount = count;
// handle pressed state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,19 @@ void buttonTest_pressedDurationCallback(uint8_t pinIn, unsigned long duration)
// handle still pressed state
Serial.print("HIGH (pin: ");
Serial.print(pinIn);
Serial.print(") still pressed (");
Serial.print(") still pressed, duration ");
Serial.print(duration);
Serial.println("ms)");
Serial.println("ms");
}

void buttonTest_releasedDurationCallback(uint8_t pinIn, unsigned long duration)
{
// handle released state
Serial.print("LOW (pin: ");
Serial.print(pinIn);
Serial.print("), duration ");
Serial.print(duration);
Serial.println("ms");
}

void setup()
Expand All @@ -70,15 +80,15 @@ void setup()
Serial.println("Test InputDebounce library, using callback functions");

// register callback functions (shared, used by all buttons)
buttonTestA.registerCallbacks(buttonTest_pressedCallback, buttonTest_releasedCallback, buttonTest_pressedDurationCallback);
buttonTestB.registerCallbacks(buttonTest_pressedCallback, buttonTest_releasedCallback, buttonTest_pressedDurationCallback);
buttonTestA.registerCallbacks(buttonTest_pressedCallback, buttonTest_releasedCallback, buttonTest_pressedDurationCallback, buttonTest_releasedDurationCallback);
buttonTestB.registerCallbacks(buttonTest_pressedCallback, buttonTest_releasedCallback, buttonTest_pressedDurationCallback, buttonTest_releasedDurationCallback);

// setup input buttons (debounced)
buttonTestA.setup(pinSwitchA, BUTTON_DEBOUNCE_DELAY, InputDebounce::PIM_INT_PULL_UP_RES);
buttonTestB.setup(pinSwitchB, BUTTON_DEBOUNCE_DELAY, InputDebounce::PIM_INT_PULL_UP_RES, 300); // single-shot pressed-on time duration callback

// examples
// buttonTestA.registerCallbacks(buttonTest_pressedCallback, buttonTest_releasedCallback, NULL); // no continuous pressed-on time duration
// buttonTestA.registerCallbacks(buttonTest_pressedCallback, NULL, NULL, buttonTest_releasedDurationCallback); // no continuous pressed-on time duration, ...
// buttonTestA.setup(pinSwitchA);
// buttonTestA.setup(pinSwitchA, BUTTON_DEBOUNCE_DELAY);
// buttonTestA.setup(pinSwitchA, DEFAULT_INPUT_DEBOUNCE_DELAY, InputDebounce::PIM_EXT_PULL_UP_RES);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,18 @@ protected:
// handle still pressed state
Serial.print("HIGH (pin: ");
Serial.print(getPinIn());
Serial.print(") still pressed (");
Serial.print(") still pressed, duration ");
Serial.print(duration);
Serial.println("ms)");
Serial.println("ms");
}
virtual void releasedDuration(unsigned long duration)
{
// handle released state
Serial.print("LOW (pin: ");
Serial.print(getPinIn());
Serial.print("), duration ");
Serial.print(duration);
Serial.println("ms");
}
private:
int8_t _pinLED;
Expand Down
12 changes: 11 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@ InputDebounce KEYWORD1

setup KEYWORD2
process KEYWORD2
getStateOnCount KEYWORD2
getPinIn KEYWORD2
getDebounceDelay KEYWORD2
getPinInMode KEYWORD2
getPressedDurationMode KEYWORD2
getSwitchType KEYWORD2
isEnabled KEYWORD2
isPressed KEYWORD2
isReleased KEYWORD2
getStatePressedCount KEYWORD2
getCurrentPressedDuration KEYWORD2
getLastPressedDuration KEYWORD2
registerCallbacks KEYWORD2

################################################################################
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/Mokolea/InputDebounce.git"
},
"version": "1.5.0",
"version": "1.6.0",
"license": "Apache-2.0",
"frameworks": "arduino",
"platforms": "*"
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=InputDebounce
version=1.5.0
version=1.6.0
author=Mario Ban <[email protected]>
maintainer=Mario Ban <[email protected]>
sentence=Simple polling input debounce Arduino library.
Expand Down
102 changes: 80 additions & 22 deletions src/InputDebounce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,37 @@
//namespace inputdebounce
//{

InputDebounce::InputDebounce(int8_t pinIn, unsigned long debDelay, PinInMode pinInMode, unsigned long pressedDuration, SwitchType switchType)
InputDebounce::InputDebounce(int8_t pinIn, unsigned long debounceDelay, PinInMode pinInMode, unsigned long pressedDurationMode, SwitchType switchType)
: _pinIn(0)
, _debDelay(0)
, _debounceDelay(0)
, _pinInMode(PIM_INT_PULL_UP_RES)
, _pressedDuration(0)
, _pressedDurationMode(0)
, _switchType(ST_NORMALLY_OPEN)
, _enabled(false)
, _valueLast(false)
, _stateOn(false)
, _statePressed(false)
, _timeStamp(0)
, _stateOnCount(0)
, _stateOnCountSingleShot(0)
, _statePressedCount(0)
, _statePressedCountSingleShot(0)
, _currentPressedDuration(0)
, _pressedCallback(NULL)
, _releasedCallback(NULL)
, _pressedDurationCallback(NULL)
, _releasedDurationCallback(NULL)
{
setup(pinIn, debDelay, pinInMode, pressedDuration, switchType);
setup(pinIn, debounceDelay, pinInMode, pressedDurationMode, switchType);
}

InputDebounce::~InputDebounce()
{}

void InputDebounce::setup(int8_t pinIn, unsigned long debDelay, PinInMode pinInMode, unsigned long pressedDuration, SwitchType switchType)
void InputDebounce::setup(int8_t pinIn, unsigned long debounceDelay, PinInMode pinInMode, unsigned long pressedDurationMode, SwitchType switchType)
{
if(pinIn >= 0) {
_pinIn = pinIn;
_debDelay = debDelay;
_debounceDelay = debounceDelay;
_pinInMode = pinInMode;
_pressedDuration = pressedDuration;
_pressedDurationMode = pressedDurationMode;
_switchType = switchType;
// initialize digital pin as an input
if(_pinInMode == PIM_INT_PULL_UP_RES) {
Expand Down Expand Up @@ -90,25 +92,27 @@ unsigned long InputDebounce::process(unsigned long now)
return 0;
}
// wait debouncing time
if(now - _timeStamp > _debDelay) {
if(now - _timeStamp > _debounceDelay) {
// input value (state) has been stable longer than the debounce period
if(_stateOn != _valueLast) {
_stateOn = _valueLast;
if(_stateOn) {
_stateOnCount++;
if(_statePressed != _valueLast) {
_statePressed = _valueLast;
if(_statePressed) {
_statePressedCount++;
pressed();
}
else {
released();
releasedDuration(_currentPressedDuration);
}
}
unsigned long duration = _stateOn ? now - _timeStamp : 0;
unsigned long duration = _statePressed ? now - _timeStamp : 0;
if(duration) {
if(!_pressedDuration) {
_currentPressedDuration = duration;
if(!_pressedDurationMode) {
pressedDuration(duration); // continuous
}
else if(duration >= _pressedDuration && _stateOnCountSingleShot != _stateOnCount) {
_stateOnCountSingleShot = _stateOnCount;
else if(duration >= _pressedDurationMode && _statePressedCountSingleShot != _statePressedCount) {
_statePressedCountSingleShot = _statePressedCount;
pressedDuration(duration); // single-shot
}
}
Expand All @@ -122,16 +126,63 @@ uint8_t InputDebounce::getPinIn() const
return _pinIn;
}

unsigned long InputDebounce::getStateOnCount() const
unsigned long InputDebounce::getDebounceDelay() const
{
return _stateOnCount;
return _debounceDelay;
}

void InputDebounce::registerCallbacks(inputdebounce_state_cb pressedCallback, inputdebounce_state_cb releasedCallback, inputdebounce_duration_cb pressedDurationCallback)
InputDebounce::PinInMode InputDebounce::getPinInMode() const
{
return _pinInMode;
}

unsigned long InputDebounce::getPressedDurationMode() const
{
return _pressedDurationMode;
}

InputDebounce::SwitchType InputDebounce::getSwitchType() const
{
return _switchType;
}

bool InputDebounce::isEnabled() const
{
return _enabled;
}

bool InputDebounce::isPressed() const
{
return _statePressed;
}

bool InputDebounce::isReleased() const
{
return !_statePressed;
}

unsigned long InputDebounce::getStatePressedCount() const
{
return _statePressedCount;
}

unsigned long InputDebounce::getCurrentPressedDuration() const
{
return _statePressed ? _currentPressedDuration : 0;
}

unsigned long InputDebounce::getLastPressedDuration() const
{
return !_statePressed ? _currentPressedDuration : 0;
}

void InputDebounce::registerCallbacks(inputdebounce_state_cb pressedCallback, inputdebounce_state_cb releasedCallback,
inputdebounce_duration_cb pressedDurationCallback, inputdebounce_duration_cb releasedDurationCallback)
{
_pressedCallback = pressedCallback;
_releasedCallback = releasedCallback;
_pressedDurationCallback = pressedDurationCallback;
_releasedDurationCallback = releasedDurationCallback;
}

void InputDebounce::pressed()
Expand All @@ -155,4 +206,11 @@ void InputDebounce::pressedDuration(unsigned long duration)
}
}

void InputDebounce::releasedDuration(unsigned long duration)
{
if(_releasedDurationCallback) {
_releasedDurationCallback(_pinIn, duration);
}
}

//} // namespace
45 changes: 31 additions & 14 deletions src/InputDebounce.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,51 +46,68 @@ class InputDebounce
ST_NORMALLY_CLOSED
};

InputDebounce(int8_t pinIn = -1, // set input pin >= 0 to enable --> calls setup
unsigned long debDelay = DEFAULT_INPUT_DEBOUNCE_DELAY,
explicit InputDebounce(int8_t pinIn = -1, // set input pin >= 0 to enable --> calls setup
unsigned long debounceDelay = DEFAULT_INPUT_DEBOUNCE_DELAY,
PinInMode pinInMode = PIM_INT_PULL_UP_RES,
unsigned long pressedDuration = 0, // pressed-on time duration: 0 continuous; >0 single-shot [ms]
unsigned long pressedDurationMode = 0, // pressed-on time duration mode: 0 continuous; >0 single-shot threshold [ms]
SwitchType switchType = ST_NORMALLY_OPEN);
virtual ~InputDebounce();

void setup(int8_t pinIn,
unsigned long debDelay = DEFAULT_INPUT_DEBOUNCE_DELAY,
unsigned long debounceDelay = DEFAULT_INPUT_DEBOUNCE_DELAY,
PinInMode pinInMode = PIM_INT_PULL_UP_RES,
unsigned long pressedDuration = 0,
unsigned long pressedDurationMode = 0,
SwitchType switchType = ST_NORMALLY_OPEN);
unsigned long process(unsigned long now); // poll button state, returns continuous pressed-on time duration if on (> debounce delay)

unsigned long process(unsigned long now); // poll button state, returns continuous pressed-on time duration if pressed state (> debounce delay)

uint8_t getPinIn() const;
unsigned long getStateOnCount() const;
unsigned long getDebounceDelay() const;
InputDebounce::PinInMode getPinInMode() const;
unsigned long getPressedDurationMode() const;
InputDebounce::SwitchType getSwitchType() const;

bool isEnabled() const;
bool isPressed() const;
bool isReleased() const;
unsigned long getStatePressedCount() const;
unsigned long getCurrentPressedDuration() const; // if currently in pressed state
unsigned long getLastPressedDuration() const; // if currently in released state

void registerCallbacks(inputdebounce_state_cb pressedCallback, inputdebounce_state_cb releasedCallback, inputdebounce_duration_cb pressedDurationCallback);
void registerCallbacks(inputdebounce_state_cb pressedCallback,
inputdebounce_state_cb releasedCallback,
inputdebounce_duration_cb pressedDurationCallback = NULL, // still pressed state: continuous or single-shot pressed-on time duration [ms]
inputdebounce_duration_cb releasedDurationCallback = NULL); // pressed-on time duration on release [ms]

protected:
virtual void pressed(); // called once for state change
virtual void released(); // called once for state change
virtual void pressedDuration(unsigned long duration); // still pressed state: continuous pressed-on time duration
virtual void pressedDuration(unsigned long duration); // still pressed state: continuous or single-shot pressed-on time duration [ms]
virtual void releasedDuration(unsigned long duration); // pressed-on time duration on release [ms]

private:
// implicitly implemented, not to be used
InputDebounce(const InputDebounce&);
InputDebounce& operator=(const InputDebounce&);

uint8_t _pinIn;
unsigned long _debDelay;
unsigned long _debounceDelay;
PinInMode _pinInMode;
unsigned long _pressedDuration;
unsigned long _pressedDurationMode;
SwitchType _switchType;

bool _enabled;
bool _valueLast; // last input value
bool _stateOn; // current on state (debounced)
bool _statePressed; // current pressed/released state (debounced)
unsigned long _timeStamp; // last input value (state) change, start debounce time
unsigned long _stateOnCount;
unsigned long _stateOnCountSingleShot;
unsigned long _statePressedCount;
unsigned long _statePressedCountSingleShot;
unsigned long _currentPressedDuration;

inputdebounce_state_cb _pressedCallback;
inputdebounce_state_cb _releasedCallback;
inputdebounce_duration_cb _pressedDurationCallback;
inputdebounce_duration_cb _releasedDurationCallback;
};

//} // namespace
Expand Down

0 comments on commit 43a6e6f

Please sign in to comment.