Saturday, May 31, 2014

eRCaGuy_ButtonReader Library for Arduino - Debounce and read the current button state, & most recent action ("just pressed" or "just released") easily!


Subscribe by Email!
By Gabriel Staples
Written: 31 May 2014
Last Updated: 25 July 2015
Article History (newest on top)
-added button image & updated download links - 25 July 2015

Other Articles to Check Out:
This Article:

Library History (newest on top):

20141031: major bug fix; added multi-button support with a new 5-button-reader example!
20140531: first release.
Misc. push buttons which can greatly
benefit from digital debouncing. 
(Image source here).

Summary:

I wanted a simple and universal, yet very powerful & reliable library to read a button or switch in such a way that I can easily implement toggled actions and momentary actions, know the true, debounced state of a button or switch at any given time, and specify whether I want an action to take place when the button is *pressed* or *released.* This library makes implementing all of these things easy for me, and I now use it on all of my projects that require reading a button or switch, so I wanted to share it with others. Hopefully you find it useful too. Check out the included examples.  

This code is an elaboration of, and library form of, the main Arduino-sponsored "Debounce" example found here.  Thanks to David A. Mellis, Limor Fried (LadyAda), and Mike Walters for writing that excellent and well-thought-out example code.

Download:

(Optionally) donate, & download via the link just above, or by clicking here then choosing the appropriate download.  Install the library into the Arduino IDE (using Sketch --> Include Library --> Add .ZIP Library), then run the examples to see how to use the library.

List of Functions (see .h and .cpp files in the library for details):

  • eRCaGuy_ButtonReader(uint8_t buttonPin,unsigned int debounceDelay,boolean pinStateWhenButtonPressed) //class constructor
  • setDebounceDelay(unsigned int debounceDelay)
  • setButtonPin(uint8_t buttonPin)
  • setPinStateWhenButtonPressed(boolean pinStateWhenButtonPressed)
  • getDebounceDelay()
  • readButton(int8_t* button_action, boolean* button_state)

Example code (may be outdated; refer to example files for latest code):

/*
readButtonVerbose.ino
-This code differs from readButton.ino ONLY in that it also outputs the button status every 0.5 seconds; rather than just outputting the button status when a 
 button *press* or *release* is detected.
eRCaGuy_ButtonReader example
By Gabriel Staples
http://electricrcaircraftguy.blogspot.com/
30 May 2014

Library webpage: http://electricrcaircraftguy.blogspot.com/2014/05/ercaguybuttonreader-library-for-arduino.html
-I wanted a simple and universal, yet very powerful & reliable library to read a button or switch in such a way that I can
 easily implement toggled actions and momentary actions, know the true, debounced state of a button or switch at any given time, 
 and specify whether I want an action to take place when the button is *pressed* or *released.*  This library makes implementing all of
 these things easy for me, and I now use it on all of my projects that require reading a button or switch, so I wanted to share it with others.  
 Hopefully you find it useful too.
 
License for Library and Examples: GNU Lesser General Public License Version 3 (LGPLv3) - https://www.gnu.org/licenses/lgpl.html
-See library .h and .cpp files for details

Description:
-This example will print out data to the Serial Monitor either: 
 1) every time the button is pressed, or released, OR
 2) every 1/2 second that the button remains in its current state
 --it will also toggle LED 13 every time a button press is detected

Circuit:
-Connect a button from digital pin 5 to GND
--the internal pull-up resistor is enabled on pin 5 to protect the pin from over-current

Instructions:
Upload the code, open the serial monitor, and play around pressing, releasing, and holding down the button, to see what happens!
*/

//include the library
#include <eRCaGuy_ButtonReader.h>

//Global Constants:
//Pins:
const byte buttonPin = 5; //the number of the pushbutton pin
const byte ledPin = 13; // the number of the LED pin
//Define Button States:
const boolean BUTTON_PRESSED = LOW; //if using a pull-up resistor (ex: INPUT_PULLUP) on your button, the buttonPin will be LOW when the button is pressed; 
const boolean BUTTON_NOT_PRESSED = HIGH; //if using a pull-up resistor (ex: INPUT_PULLUP) on your button, the buttonPin will be HIGH when the button is NOT pressed

//instantiate an object of this library class; call it "button1"
//if not explicitly stated, debounceDelay defaults to 50ms, and the _BUTTON_PRESSED value in the library defaults to LOW; see .h file for details
eRCaGuy_ButtonReader button1 = eRCaGuy_ButtonReader(buttonPin); 
//alternatively, the object instantiation could be explicit, as follows:
//eRCaGuy_ButtonReader button1 = eRCaGuy_ButtonReader(buttonPin,50,BUTTON_PRESSED);

void setup() 
{
  Serial.begin(115200);
  
  //configure pins
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state to OFF
  toggleLED();
  
  //configure button1
  //button1.setDebounceDelay(50); //(optional); set debounceDelay to 50ms; uncomment this and increase the debounceDelay if the button_state jitters unexpectedly
  //button1.setButtonPin(buttonPin); //(optional), since this was established during the object instantiation above
  //button1.setPinStateWhenButtonPressed(HIGH); //uncomment this line if using a pull-down resistor on the button or switch instead of the internal pull-up resistor
}

void loop() 
{
  //local variables
  int8_t button_action; //see details below
  boolean button_state; //see details below
  
  //read button; use the ampersands (&) to pass the address to (pointers to) the variables as input parameters, so that the variables can be updated by the function
  //Details:
    //read the button action, and store it into the button_action variable; and read the button state, & store it into the button_state variable
    //The button state can be 0 or 1, for LOW or HIGH, respectively
    // button action indicates what just happened to the button: 
    // 0 = no-change in true, debounced button state since last time reading the button, or debounceDelay time not yet elapsed
    // 1 = button was just pressed by a human operator (debounceDelay had elapsed)
    // -1 = button was just released by a human operator (debounceDelay had elapsed)
  button1.readButton(&button_action,&button_state);
  
  //output data, & toggle LED
  if (button_action != 0) //if an action has occured on the button
  {
    Serial.print("button_action = "); Serial.print(button_action); Serial.print(", "); 
    if (button_action==1)
    {
      Serial.print("Button PRESS detected");
    }
    else //button_action==-1
    {
      Serial.print("Button RELEASE detected");
    }
    Serial.print("; button_state = "); Serial.print(button_state); 
    Serial.print(", "); 
    if (button_state==BUTTON_PRESSED)
    {
      Serial.println("BUTTON_PRESSED");
    }
    else //button_state==BUTTON_NOT_PRESSED
    {
      Serial.println("BUTTON_NOT_PRESSED");
    }
    
    //toggle the led on every button press
    if (button_action==1) //if button just pressed
    {
      toggleLED(); //turn the LED on if off, and off if on
    }
    //alternately, you could comment out the above if statement, and use this one below instead, if you desire to do an action on the *release* of the button
    //instead of on the *press* of the button
//    if (button_action==-1) //if button just released 
//    {
//      toggleLED(); //turn the LED on if off, and off if on
//    }
  }
  //THE BELOW SEGMENT OF CODE (else statement) IS COMMENTED OUT FOR readButton.ino, but NOT for readButtonVerbose.ino
  else //button_action==0
  {
    //if there is no new action on the button, let's print out the button_state every 0.5 seconds, to see whether the button is currently NOT being pressed, 
    //or whether it is being held down continuously
    static unsigned long t_start = millis(); //ms; a time stamp to ensure printouts only happen every 0.5 seconds
    if (millis() - t_start >= 500) //if 500ms (0.5 sec) has elapsed
    {
      t_start = millis(); //ms; update
      if (button_state==BUTTON_PRESSED)
      {
        Serial.println("button is being held down");
      }
      else //button_state==BUTTON_NOT_PRESSED
      {
        Serial.println("button is just sitting there, NOT pressed");
      }
    }
  }
} //end of loop()

//Here you will do something useful, determined by the press or release of the button; I am simply toggling led 13 on and off in order 
//to demonstrate one use of a button as a toggle switch
void toggleLED()
{ 
  static boolean ledState = HIGH;
  ledState = !ledState; //invert led state
  digitalWrite(ledPin, ledState); //write to led
}





***Subscribe by Email!***

5 comments:

  1. Could you add this library to Arduino's Library Manager? This would give more visibility to your work. Thanks

    ReplyDelete
    Replies
    1. Hi thanks for the suggestion. I'll have to look into it. At the moment, I don't know how to add it to the library manager as an option.

      Delete
    2. Hope this helps you... https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Your comment that you deleted said: "I would like some advice in using your button library. I like this library a lot but i think i may have an issue for my application. I have 3 buttons that will trigger low, but i have one that triggers high. in looking at the code for your library it seems as though this will be in conflict, is this correct? if not, how can i implement this library using both a high button pressed and a low button pressed option in a single sketch? "

      My answer is: yes, my library works fine for this. Simply call:

      myButton.setPinStateWhenButtonPressed(LOW)
      OR
      myButton.setPinStateWhenButtonPressed(HIGH)

      to set whether you want the button to be considered to be pressed when the pin state is LOW or HIGH.

      Delete

Thanks for your comment or question! If it is a question, I will try to get back to you quickly. Notice to spammers: I personally remove all spam promptly and report spammers to Google, so please don't do it.

Note: some HTML tags are allowed in your comments. To learn how to add bold (<b>...</b>), italics (<i>...</i>), or hyperlinks (<a href="URL">NAME</a>) to your comments, read here.

~Sincerely, Gabriel Staples.

P.S. Yo hablo español también. Je parle français aussi. (I speak Spanish & French too).