• 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.

Dual State Pushbutton, Debounced, using Interrupts for Arduino

Not open for further replies.


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.

#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

Rich D.

Active Member
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.
Not open for further replies.

EE World Online Articles