diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce68319 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +examples/retrigger/Debug/Makefile +*.atsuo +examples/retrigger/retrigger.cppproj +*.xml +examples/retrigger/Visual Micro/.retrigger.vsarduino.h +*.a +*.eep +examples/held/Debug/held.elf +*.hex +examples/held/held.cppproj +examples/retrigger/Debug/retrigger.elf +*.atsln +examples/held/Visual Micro/.held.vsarduino.h \ No newline at end of file diff --git a/Bounce2.cpp b/Bounce2.cpp index c947815..0852523 100644 --- a/Bounce2.cpp +++ b/Bounce2.cpp @@ -10,27 +10,32 @@ #define DEBOUNCED_STATE 0 #define UNSTABLE_STATE 1 #define STATE_CHANGED 3 +#define STATE_HELD_ON 4 +#define FIRSTUPDATE 5 -Bounce::Bounce() - : previous_millis(0) - , interval_millis(10) - , state(0) - , pin(0) -{} +Bounce::Bounce(int pin, uint16_t interval_millis, uint16_t interval_retrigger, uint16_t interval_hold) +{ + this->pin = pin; + interval(interval_millis); + holdinterval(interval_hold); + retriggerinterval(interval_retrigger); + previous_millis_state_changed = 0; + state = _BV(FIRSTUPDATE); +} void Bounce::attach(int pin) { - this->pin = pin; - bool read = digitalRead(pin); - state = 0; - if (digitalRead(pin)) { - state = _BV(DEBOUNCED_STATE) | _BV(UNSTABLE_STATE); - } -#ifdef BOUNCE_LOCK_OUT - previous_millis = 0; -#else - previous_millis = millis(); -#endif + this->pin = pin; + bool read = digitalRead(pin); + state = 0; + if (digitalRead(pin)) { + state = _BV(DEBOUNCED_STATE) | _BV(UNSTABLE_STATE); + } + #ifdef BOUNCE_LOCK_OUT + previous_millis = 0; + #else + previous_millis = millis(); + #endif } void Bounce::attach(int pin, int mode){ @@ -41,58 +46,139 @@ void Bounce::attach(int pin, int mode){ void Bounce::interval(uint16_t interval_millis) { - this->interval_millis = interval_millis; + this->interval_millis = interval_millis; +} + +void Bounce::holdinterval(uint16_t interval_hold) +{ + this->interval_hold = interval_hold; +} + +void Bounce::retriggerinterval(uint16_t interval_retrigger) +{ + this->interval_retrigger = interval_retrigger; } bool Bounce::update() { -#ifdef BOUNCE_LOCK_OUT - state &= ~_BV(STATE_CHANGED); - // Ignore everything if we are locked out - if (millis() - previous_millis >= interval_millis) { - bool currentState = digitalRead(pin); - if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) { - previous_millis = millis(); - state ^= _BV(DEBOUNCED_STATE); - state |= _BV(STATE_CHANGED); - } - } - return state & _BV(STATE_CHANGED); -#else - // Read the state of the switch in a temporary variable. - bool currentState = digitalRead(pin); - state &= ~_BV(STATE_CHANGED); + // Attaches the pin the first time update is called + if(state & _BV(FIRSTUPDATE)) + { + attach(pin); + state &= ~_BV(FIRSTUPDATE); + } + else + { + #ifdef BOUNCE_LOCK_OUT + state &= ~_BV(STATE_CHANGED); + // Ignore everything if we are locked out + if (millis() - previous_millis >= interval_millis) { + bool currentState = digitalRead(pin); + if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) { + previous_millis = millis(); + state ^= _BV(DEBOUNCED_STATE); + state |= _BV(STATE_CHANGED); + } + } + return state & _BV(STATE_CHANGED); + #else + // Read the state of the switch in a temporary variable. + bool currentState = digitalRead(pin); + state &= ~_BV(STATE_CHANGED); - // If the reading is different from last reading, reset the debounce counter - if ( currentState != (bool)(state & _BV(UNSTABLE_STATE)) ) { - previous_millis = millis(); - state ^= _BV(UNSTABLE_STATE); - } else - if ( millis() - previous_millis >= interval_millis ) { - // We have passed the threshold time, so the input is now stable - // If it is different from last state, set the STATE_CHANGED flag - if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) { - previous_millis = millis(); - state ^= _BV(DEBOUNCED_STATE); - state |= _BV(STATE_CHANGED); - } - } + // If the reading is different from last reading, reset the debounce counter + if ( currentState != (bool)(state & _BV(UNSTABLE_STATE)) ) { + previous_millis = millis(); + state ^= _BV(UNSTABLE_STATE); + } else + if ( millis() - previous_millis >= interval_millis ) { + // We have passed the threshold time, so the input is now stable + // If it is different from last state, set the STATE_CHANGED flag + if ((bool)(state & _BV(DEBOUNCED_STATE)) != currentState) { + previous_millis = millis(); + state ^= _BV(DEBOUNCED_STATE); + state |= _BV(STATE_CHANGED); + } + } - return state & _BV(STATE_CHANGED); -#endif + + #endif + + //code for checking if state has been held on >= 500ms or interval_hold + + // If state has changed and has not been held on previously + if(state & _BV(STATE_CHANGED) && !(state & _BV(STATE_HELD_ON))) + { + //If state has been changed before 500ms since last change, reset state change timer + if(millis() - previous_millis_state_changed < interval_hold) + { + previous_millis_state_changed = 0; + } + else + { + previous_millis_state_changed = millis(); + } + } + // If state has changed and has been held on previously + else if(state & _BV(STATE_CHANGED) && (state & _BV(STATE_HELD_ON))) + { + // Immediately turn off held on state + state &= ~_BV(STATE_HELD_ON); + previous_millis_state_changed = 0; + } + else if(previous_millis_state_changed != 0) + { + //if button has been at a debounced state for >= 500ms + if(millis() - previous_millis_state_changed >= interval_hold) + { + state |= _BV(STATE_HELD_ON); + previous_millis_state_changed = 0; + } + } + return state & _BV(STATE_CHANGED); + } } +bool Bounce::retrigger() +{ + // if button is being held + if(this->held()) + { + if(previous_millis_state_changed != 0) + { + // Checks if it has been longer that retrigger time + if (millis() - previous_millis_state_changed >= interval_retrigger) + { + previous_millis_state_changed = millis(); + return true; + } + } + else + { + // sets the millis when first going into function + previous_millis_state_changed = millis(); + } + } + return false; +} + + bool Bounce::read() { - return state & _BV(DEBOUNCED_STATE); + return state & _BV(DEBOUNCED_STATE); } bool Bounce::rose() { - return ( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED)); + return ( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED)); } bool Bounce::fell() { - return !( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED)); + return !( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED)); +} + +bool Bounce::held() +{ + return (state & _BV(STATE_HELD_ON)); } diff --git a/Bounce2.h b/Bounce2.h index 77d384d..58c1fe0 100644 --- a/Bounce2.h +++ b/Bounce2.h @@ -23,7 +23,7 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * Main code by Thomas O Fredericks (tof@t-o-f.info) - Previous contributions by Eric Lowry, Jim Schimpf and Tom Harkaway + Previous contributions by Eric Lowry, Jim Schimpf and Tom Harkaway, Albert Phan * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifdef BOUNCE_LOCK @@ -43,7 +43,7 @@ class Bounce { public: // Create an instance of the bounce library - Bounce(); + Bounce(int pin, uint16_t interval_millis = 10, uint16_t interval_retrigger = 50, uint16_t interval_hold = 500); // Attach to a pin (and also sets initial state) void attach(int pin); @@ -54,7 +54,13 @@ class Bounce // Sets the debounce interval void interval(uint16_t interval_millis); - // Updates the pin + // Changes the interval for held() + void holdinterval(uint16_t interval_hold); + + // Changes the retrigger interval for retrigger() + void retriggerinterval(uint16_t interval_retrigger); + + // Updates the pin // Returns 1 if the state changed // Returns 0 if the state did not change bool update(); @@ -67,9 +73,19 @@ class Bounce // Returns the rising pin state bool rose(); + + // Returns 1 if state has been held for held interval (default is 500ms) + // Returns 0 if not + bool held(); + + // After the button has been held down, returns a 1 every interval_repeat(default is 50 ms) + bool retrigger(); protected: unsigned long previous_millis; + unsigned long previous_millis_state_changed; + uint16_t interval_hold; + uint16_t interval_retrigger; uint16_t interval_millis; uint8_t state; uint8_t pin; diff --git a/examples/bounce/bounce.ino b/examples/bounce/bounce.ino index 139620d..feef92e 100644 --- a/examples/bounce/bounce.ino +++ b/examples/bounce/bounce.ino @@ -11,18 +11,21 @@ #define BUTTON_PIN 2 #define LED_PIN 13 -// Instantiate a Bounce object -Bounce debouncer = Bounce(); +#define DEBOUNCE_TIME 5 +#define HOLD_TIME 1000 +#define RETRIGGER_TIME 100 + +// Instantiate a Bounce object with default values +Bounce debouncer(BUTTON_PIN); + +// Or set your own values when instantiating Bounce object +// Bounce debouncer(BUTTON_PIN,DEBOUNCE_TIME, RETRIGGER_TIME, HOLD_TIME); void setup() { // Setup the button with an internal pull-up : pinMode(BUTTON_PIN,INPUT_PULLUP); - // After setting up the button, setup the Bounce instance : - debouncer.attach(BUTTON_PIN); - debouncer.interval(5); // interval in ms - //Setup the LED : pinMode(LED_PIN,OUTPUT); diff --git a/examples/change/change.ino b/examples/change/change.ino index eb5fa26..9588696 100644 --- a/examples/change/change.ino +++ b/examples/change/change.ino @@ -9,20 +9,23 @@ #define BUTTON_PIN 2 #define LED_PIN 13 +#define DEBOUNCE_TIME 5 +#define HOLD_TIME 1000 +#define RETRIGGER_TIME 100 + int ledState = LOW; +// Instantiate a Bounce object with default values +Bounce debouncer(BUTTON_PIN); + +// Or set your own values when instantiating Bounce object +// Bounce debouncer(BUTTON_PIN,DEBOUNCE_TIME, RETRIGGER_TIME, HOLD_TIME); -// Instantiate a Bounce object : -Bounce debouncer = Bounce(); void setup() { // Setup the button with an internal pull-up : - pinMode(BUTTON_PIN,INPUT_PULLUP); - - // After setting up the button, setup the Bounce instance : - debouncer.attach(BUTTON_PIN); - debouncer.interval(500); + pinMode(BUTTON_PIN,INPUT); // Setup the LED : pinMode(LED_PIN,OUTPUT); diff --git a/examples/duration/duration.ino b/examples/duration/duration.ino index f0abcc5..10cf38d 100644 --- a/examples/duration/duration.ino +++ b/examples/duration/duration.ino @@ -14,8 +14,15 @@ a button press (transition from HIGH to LOW). #define BUTTON_PIN 2 #define LED_PIN 13 -// Instantiate a Bounce object : -Bounce debouncer = Bounce(); +#define DEBOUNCE_TIME 5 +#define HOLD_TIME 1000 +#define RETRIGGER_TIME 100 + +// Instantiate a Bounce object with default values +Bounce debouncer(BUTTON_PIN); + +// Or set your own values when instantiating Bounce object +// Bounce debouncer(BUTTON_PIN,DEBOUNCE_TIME, RETRIGGER_TIME, HOLD_TIME); unsigned long buttonPressTimeStamp; @@ -26,10 +33,6 @@ void setup() { // Setup the button with an internal pull-up : pinMode(BUTTON_PIN,INPUT_PULLUP); - // After setting up the button, setup the Bounce instance : - debouncer.attach(BUTTON_PIN); - debouncer.interval(5); - // Setup the LED : pinMode(LED_PIN,OUTPUT); diff --git a/examples/held/held.ino b/examples/held/held.ino new file mode 100644 index 0000000..ca57e0f --- /dev/null +++ b/examples/held/held.ino @@ -0,0 +1,57 @@ + +/* + DESCRIPTION + ==================== + Example of the held() function for the Bounce 2 library + The held() function returns a 1 when the button has been held for a minimum of the hold interval or 500ms which is the default + + An example of using this is in a menu where a user must hold a key down before he/she can edit something. + + */ +// Include the Bounce2 library found here : +// https://github.com/thomasfredericks/Bounce-Arduino-Wiring +#include + +#define BUTTON_PIN 2 +#define LED_PIN 13 + +#define DEBOUNCE_TIME 5 +#define HOLD_TIME 1000 +#define RETRIGGER_TIME 100 + +// Instantiate a Bounce object with default values +Bounce debouncer(BUTTON_PIN); + +// Or set your own values when instantiating Bounce object +// Bounce debouncer(BUTTON_PIN,DEBOUNCE_TIME, RETRIGGER_TIME, HOLD_TIME); + + +void setup() { + + // Setup the button with an internal pull-up : + //pinMode(BUTTON_PIN,INPUT_PULLUP); + pinMode(BUTTON_PIN, INPUT); + + //Setup the LED : + pinMode(LED_PIN,OUTPUT); + +} + +void loop() { + // Update the Bounce instance : + debouncer.update(); + + // Get the updated value : + int value = debouncer.held(); + + // Turn on or off the LED as determined by the state : + if (value) { + digitalWrite(LED_PIN, HIGH ); + } + else { + digitalWrite(LED_PIN, LOW ); + } + +} + + diff --git a/examples/retrigger/retrigger.ino b/examples/retrigger/retrigger.ino index b1143ee..527bd31 100644 --- a/examples/retrigger/retrigger.ino +++ b/examples/retrigger/retrigger.ino @@ -1,86 +1,81 @@ -/* +/* DESCRIPTION ==================== -Example of the bounce library that shows how to retrigger an event when a button is held down. -In this case, the debug LED will blink every 500 ms as long as the button is held down. +Example of the retrigger() function of the Bounce 2 library. This function will retrigger a HIGH value after +the button has been held on for at least the hold interval (default 500 ms) and then retrigger every retrigger_interval afterwards (default 50ms) +This function is great for editing values without repeatedly pressing the button. Open the Serial Monitor (57600 baud) for debug messages. */ // Include the Bounce2 library found here : // https://github.com/thomasfredericks/Bounce-Arduino-Wiring -#include +#include #define BUTTON_PIN 2 #define LED_PIN 13 -// Instantiate a Bounce object -Bounce debouncer = Bounce(); +#define DEBOUNCE_TIME 5 +#define HOLD_TIME 1000 +#define RETRIGGER_TIME 100 + +// Instantiate a Bounce object with default values +Bounce debouncer(BUTTON_PIN); + +// Or set your own values when instantiating Bounce object +// Bounce debouncer(BUTTON_PIN,DEBOUNCE_TIME, RETRIGGER_TIME, HOLD_TIME); -int buttonState; unsigned long buttonPressTimeStamp; - -int ledState; +unsigned char ledState = 0; void setup() { - - Serial.begin(57600); - - // Setup the button - pinMode(BUTTON_PIN,INPUT); - // Activate internal pull-up - digitalWrite(BUTTON_PIN,HIGH); - - // After setting up the button, setup debouncer - debouncer.attach(BUTTON_PIN); - debouncer.interval(5); - - //Setup the LED - pinMode(LED_PIN,OUTPUT); - digitalWrite(LED_PIN,ledState); - + Serial.begin(57600); + + // Setup the button + pinMode(BUTTON_PIN,INPUT); + + //Setup the LED + pinMode(LED_PIN,OUTPUT); + digitalWrite(LED_PIN,LOW); + } void loop() { - // Update the debouncer and get the changed state - boolean changed = debouncer.update(); + // Update the debouncer + debouncer.update(); + // If button had a rising transition, turn on led. + if(debouncer.rose()) + { + ledState = 1; + digitalWrite(LED_PIN, ledState); + buttonPressTimeStamp = millis(); + Serial.print(buttonPressTimeStamp); + Serial.println(" Button rose!"); + } + // After holding down the button, retrigger returns a 1 every interval_hold (default = 50 ms) + if (debouncer.retrigger()) + { + buttonPressTimeStamp = millis(); + Serial.print(buttonPressTimeStamp); + Serial.println(" Button retriggered!"); + + ledState = !ledState; + digitalWrite(LED_PIN, ledState); + } + // When button has a falling transition, turn off led. + if(debouncer.fell()) + { + ledState = 0; + digitalWrite(LED_PIN, ledState); + buttonPressTimeStamp = millis(); + Serial.print(buttonPressTimeStamp); + Serial.println(" Button fell!"); + } - - if ( changed ) { - // Get the update value - int value = debouncer.read(); - if ( value == HIGH) { - ledState = LOW; - digitalWrite(LED_PIN, ledState ); - - buttonState = 0; - Serial.println("Button released (state 0)"); - - } else { - ledState = HIGH; - digitalWrite(LED_PIN, ledState ); - - buttonState = 1; - Serial.println("Button pressed (state 1)"); - buttonPressTimeStamp = millis(); - - } - } - - if ( buttonState == 1 ) { - if ( millis() - buttonPressTimeStamp >= 500 ) { - buttonPressTimeStamp = millis(); - if ( ledState == HIGH ) ledState = LOW; - else if ( ledState == LOW ) ledState = HIGH; - digitalWrite(LED_PIN, ledState ); - Serial.println("Retriggering button"); - } - } - - + }