1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Dual State Pushbutton, Debounced, using Interrupts for Arduino

Discussion in 'Code Repository' started by djsfantasi, Feb 1, 2016.

  1. djsfantasi

    djsfantasi Member

    Mar 15, 2011
    Metro Boston
    This routine is interrupt driven, and will detect either a short or long button press. It's return value is bit encoded and as such it is possible that both a long and short press can be detected. They are valid, since the press is debounced.

    The code is not optimized, but written for instructional use. The majority of variables are Boolean, to keep track of the state of the button. The listing is of an entire sketch, to show the global definitions, setup and use of the function.

    Code (C):

    #define HALT while(true);
    #define STATE_NORMAL 0
    #define STATE_SHORT 1
    #define STATE_LONG 2

    const int LED = 13;

    // Button input related values
    static const byte BUTTON_PIN = 2;
    //static const int  STATE_NORMAL = 0; // no button activity
    //static const int  STATE_SHORT  = 1; // short button press
    //static const int  STATE_LONG  = 2; // long button press
    volatile int  resultButton = 0; // global value set by checkButton()

    void setup() {
      digitalWrite(LED, LOW);
      Serial.println(F("Initializing Button pin"));
      attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), checkButton, CHANGE);
      Serial.println(F("Button pin initialized"));

    void loop() {
      int longButton=0;
      int count=0;
      while (true) {
      switch (resultButton) {

      case STATE_NORMAL: {
    /*  Serial.print(".");
      count = count % 10;
      if (count==0) Serial.println(""); */


      case STATE_SHORT: {
      Serial.println("Short press has been detected");

      case STATE_LONG: {
      Serial.println("Button was pressed for long time");
      if (longButton==5) {

    void checkButton() {
      * This function implements software debouncing for a two-state button.
      * It responds to a short press and a long press and identifies between
      * the two states. Your sketch can continue processing while the button
      * function is driven by pin changes.

      const unsigned long LONG_DELTA = 1000ul;               // hold seconds for a long press
      const unsigned long DEBOUNCE_DELTA = 30ul;        // debounce time
      static int lastButtonStatus = HIGH;                                   // HIGH indicates the button is NOT pressed
      int buttonStatus;                                                                    // button atate Pressed/LOW; Open/HIGH
      static unsigned long longTime = 0ul, shortTime = 0ul; // future times to determine is button has been poressed a short or long time
      boolean Released = true, Transition = false;                  // various button states
      boolean timeoutShort = false, timeoutLong = false;    // flags for the state of the presses

      buttonStatus = digitalRead(BUTTON_PIN);                // read the button state on the pin "BUTTON_PIN"
      timeoutShort = (millis() > shortTime);                          // calculate the current time states for the button presses
      timeoutLong = (millis() > longTime);

      if (buttonStatus != lastButtonStatus) {                          // reset the timeouts if the button state changed
          shortTime = millis() + DEBOUNCE_DELTA;
          longTime = millis() + LONG_DELTA;

      Transition = (buttonStatus != lastButtonStatus);        // has the button changed state
      Released = (Transition && (buttonStatus == HIGH)); // for input pullup circuit

      lastButtonStatus = buttonStatus;                                     // save the button status

      if ( ! Transition) {                                                                //without a transition, there's no change in input
      // if there has not been a transition, don't change the previous result
           resultButton =  STATE_NORMAL | resultButton;

      if (timeoutLong && Released) {                                      // long timeout has occurred and the button was just released
           resultButton = STATE_LONG | resultButton;       // ensure the button result reflects a long press
      } else if (timeoutShort && Released) {                          // short timeout has occurred (and not long timeout) and button was just released
          resultButton = STATE_SHORT | resultButton;     // ensure the button result reflects a short press
      } else {                                                                                  // else there is no change in status, return the normal state
          resultButton = STATE_NORMAL | resultButton; // with no change in status, ensure no change in button status
    • Thanks Thanks x 1
  2. Rich D.

    Rich D. Active Member

    Feb 3, 2014
    West Chester, PA
    Thanks! I'm going to read this through and make sure I know learn this stuff. Although I am a pretty good programmer, sometimes Arduino stuff seems to stump me because of it's simplicity (I guess I'm used to complicated). The best way for me to learn it is seeing some actual code.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice