multiple "debounce" Buttons

Hi guys,

I'm a newbie to Arduino and programming in general but I have this project which is basically controlling a house via phone (Home automation) yet I want to add push buttons also to control my outputs which are relays in my case.

I wanna know if this is actually possible to do,I mean to control the outputs using a Web server and external buttons at the same time.

Or else would you guys have any ideas how to use the Arduino Debounce example code with multiple buttons.

I would really appreciate any help

thanks.

Without knowing much about he application, my initial answer is yes. As long as you have free input pins on your controller you can add as many inputs as you want and have them all control the same output using code logic.

As far as using debounce, just consider it a process which has two states. Either something is debounced, or it isn't. A function can be created that returns true or false (or any pair of digital values) that indicate that a button input isn't bouncing. You then have boolean global variables that you can use at whim in your program to control whichever states you want.

Hi,

Debouncing many buttons is easy, provided they will be operated one at a time. Things get more complex when multiple switches can be activated together, such as a musical or qwerty keyboard, or game controller.

Paul

thanks guys
Apex, thank you for the informations.
Paul, I would really love it if you could give me an example code for it, or just hints if it's not a burden for you :frowning:

thanks again

Or just use a libray like Bounce2 to do all the work for you. Easy and quick :wink:

How many buttons, and will they all be located together?

septillion:
Or just use a libray like Bounce2 to do all the work for you. Easy and quick :wink:

Thanks for your answer, I didn't know that such a library exist, I searched for it and found the code which control a single LED using two bounce buttons and since my program is to control each output using one single button I guess it would be a bit different, so i'll try to make it work somehow.

Hmm.

Check out this code:

// Radio Buttons!
const int led1Pin =  3;    // LED pin number
const int button1 =  2;
const int led2Pin =  5; 
const int button2 =  4;
const int led3Pin =  6;
const int button3 =  7;
const int led4Pin =  9;
const int button4 =  8;
char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
char bstate4 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.
unsigned long bcount2 = 0;
unsigned long bcount3 = 0;
unsigned long bcount4 = 0;


// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
// Routines by Paul__B of Arduino Forum
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

void setup() {
  pinMode(led1Pin, OUTPUT);      
  pinMode(button1, INPUT); 
  pinMode(led2Pin, OUTPUT);      
  pinMode(button2, INPUT);      
  pinMode(led3Pin, OUTPUT);      
  pinMode(button3, INPUT);      
  pinMode(led4Pin, OUTPUT);      
  pinMode(button4, INPUT);        
  digitalWrite (led1Pin, LOW);
  digitalWrite (led2Pin, LOW);
  digitalWrite (led3Pin, LOW);
  digitalWrite (led4Pin, LOW);
}

void loop() {
  // Select LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    digitalWrite (led1Pin, HIGH);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
  } 
  // Select LED if button debounced
  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, HIGH);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
  } 
  // Select LED if button debounced
  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, HIGH);
    digitalWrite (led4Pin, LOW);
  } 
  if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL )) {
    // Select LED if button debounced
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, HIGH);
  } 
}

Sam, so you want to emulate 12 toggle switches using 12 pushbuttons attached to pins 22 to 34?

int toggleSwitch[12];
int pushButton[12];
unsigned long debounceTime = millis();

...

void loop() {

...

  unsigned long timeNow = millis();
  for (int i=1; i<12; i++) {
    int pb = digitalRead(22+i);
    if (pb != pushButton[i] && timeNow - debounceTime > 50) {
      debounceTime = timeNow;
      pushButton[i] = pb;
      if (pb == LOW) toggleButton[i] = ~toggleButton[i];
    }
  }

...

}

I have not tested or even compiled the above, but that was my general idea.

Paul__B:
Hmm.

Check out this code:

// Radio Buttons!

const int led1Pin =  3;    // LED pin number
const int button1 =  2;
const int led2Pin =  5;
const int button2 =  4;
const int led3Pin =  6;
const int button3 =  7;
const int led4Pin =  9;
const int button4 =  8;
char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
char bstate4 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.
unsigned long bcount2 = 0;
unsigned long bcount3 = 0;
unsigned long bcount4 = 0;

// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
// Routines by Paul__B of Arduino Forum
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) {
    *marker += interval;    // move on ready for next interval
    return true;     
  }
  else return false;
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {              // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far,
    if (button == HIGH) return false; // Nothing happening!
    else {
      *butnstate = 2;                // record that is now pressed
      *marker = millis();            // note when was pressed
      return false;                  // and move on
    }

case 1: // Button down so far,
    if (button == LOW) return false; // Nothing happening!
    else {
      *butnstate = 3;                // record that is now released
      *marker = millis();            // note when was released
      return false;                  // and move on
    }

case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                // no, not debounced; revert the state
      return false;                  // False alarm!
    }
    else {
      if (millis() - *marker >= interval) {
        *butnstate = 1;              // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else
        return false;                // not done yet; just move on
    }

case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                // no, not debounced; revert the state
      return false;                  // False alarm!
    }
    else {
      if (millis() - *marker >= interval) {
        *butnstate = 0;              // Debounced; update the state
        return false;                // but it is not the event we want
      }
      else
        return false;                // not done yet; just move on
    }
  default:                            // Error; recover anyway
    { 
      *butnstate = 0;
      return false;                  // Definitely false!
    }
  }
}

void setup() {
  pinMode(led1Pin, OUTPUT);     
  pinMode(button1, INPUT);
  pinMode(led2Pin, OUTPUT);     
  pinMode(button2, INPUT);     
  pinMode(led3Pin, OUTPUT);     
  pinMode(button3, INPUT);     
  pinMode(led4Pin, OUTPUT);     
  pinMode(button4, INPUT);       
  digitalWrite (led1Pin, LOW);
  digitalWrite (led2Pin, LOW);
  digitalWrite (led3Pin, LOW);
  digitalWrite (led4Pin, LOW);
}

void loop() {
  // Select LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    digitalWrite (led1Pin, HIGH);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
  }
  // Select LED if button debounced
  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, HIGH);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
  }
  // Select LED if button debounced
  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, HIGH);
    digitalWrite (led4Pin, LOW);
  }
  if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL )) {
    // Select LED if button debounced
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, HIGH);
  }
}

I complied this code it works but when I press the button(1) the LED (1) turns On however it doesn't turn off when I press that same button again, this code is not responding to my needs since the buttons only change the activated output but can't turn off the outputs they're connected to.

Victarionz:
I complied this code it works but when I press the button(1) the LED (1) turns On however it doesn't turn off when I press that same button again, this code is not responding to my needs since the buttons only change the activated output but can't turn off the outputs they're connected to.

Well, the code does what it is intended to do, it implements "radio buttons".

I gave it to you as an example of debouncing and timing.

The idea is that you take it as a concept and modify it do do what you want.

What, do you want us to do everything for you? :roll_eyes:

Ah well ...

// Multiple toggles!
const int led1Pin =  3;    // LED pin number
const int button1 =  2;
const int led2Pin =  5; 
const int button2 =  4;
const int led3Pin =  6;
const int button3 =  7;
const int led4Pin =  9;
const int button4 =  8;
char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
char bstate4 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.
unsigned long bcount2 = 0;
unsigned long bcount3 = 0;
unsigned long bcount4 = 0;

char led1State = LOW;        // initialise the LED
char led2State = LOW;
char led3State = LOW;
char led4State = LOW;

// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
// Routines by Paul__B of Arduino Forum
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

// ----------------------------- toggle ------------------------------------------
char toggle(char *flip) {   // Yes, it toggles the variable pointed to
  if (*flip == LOW) {
    *flip = HIGH;
  }
  else {
    *flip = LOW; 
  } 
  return *flip;
}

void setup() {
  pinMode(led1Pin, OUTPUT);      
  pinMode(button1, INPUT); 
  pinMode(led2Pin, OUTPUT);      
  pinMode(button2, INPUT);      
  pinMode(led3Pin, OUTPUT);      
  pinMode(button3, INPUT);      
  pinMode(led4Pin, OUTPUT);      
  pinMode(button4, INPUT);        
  digitalWrite (led1Pin, LOW);
  digitalWrite (led2Pin, LOW);
  digitalWrite (led3Pin, LOW);
  digitalWrite (led4Pin, LOW);
}

void loop() {
  // Toggle LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    toggle(&led1State);
    digitalWrite(led1Pin, led1State);
  } 

  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    toggle(&led2State);
    digitalWrite(led2Pin, led2State);
  } 

  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    toggle(&led3State);
    digitalWrite(led3Pin, led3State);
  } 

  if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL )) {
    toggle(&led4State);
    digitalWrite(led4Pin, led4State);
  } 
}