Debouncing multiple inputs

Hi all, I have built a circuit, and it's working fine, except that when I press a button to perform an action, sometimes the button doesn't do anything, and i have to toggle it a few times before it registers. I believe this is a problem with debouncing, however, I have multiple buttons which have the same issue, so my question is, how do I debounce multiple inputs?

Here is my code:

//sensors and outputs
int sensorPin = A0;    // select the input pin for the LDR
int ledPin1 = 12;      // select the pin for one relay coil
int ledPin2 = 13;      // select the pin for the other relay coil
//
//buttons
int testpin = 11;      // select the pin for the test enable switch
int testpinstate = 0;   
int manualclosepin = 10;   // select the pin for the manual close button
int closestate = 0;
int manualopenpin = 9;   // select the pin for the manual open button
int openstate = 0;
//
//variables
int sensorValue = 0;  // variable to store the value coming from the sensor
boolean relayshouldbe = HIGH;   // what value the relay should be (will be compared against the relaycurrent variable to determine if any change needs to happen.
boolean relaycurrent = HIGH;   // what state the relay is currently in
int relaystate = 0;
int delayclose = 4;   // variable for the closing delay
int counterclose = 0;
int delayopen = 4;   // variable for the opening delay
int counteropen = 0;
int limit = 100; //sets the sensor value limit
//



void setup() {

  pinMode(ledPin1, OUTPUT); 
  pinMode(ledPin2, OUTPUT);
  pinMode(testpin, INPUT);
  pinMode(sensorPin, INPUT);
  pinMode (manualclosepin, INPUT);
  pinMode (manualopenpin, INPUT);
  Serial.begin(9600);
}


void loop(){  
    sensorValue = analogRead(sensorPin);
    testpinstate = digitalRead(testpin);
    openstate = digitalRead(manualopenpin);
    closestate = digitalRead(manualclosepin);
  
  // sets the delay based on the test switch input
  // if the test switch is high, the delay is reduced
  if (testpinstate == HIGH){
    delayclose = 4;
    delayopen = 4;}
  else{delayclose = 1200;
    delayopen = 400;}
  
// Manual open/close settings, only enabled when test mode is enabled
if (testpinstate == HIGH){
  if ((closestate == HIGH) && (openstate == LOW)){
   relayshouldbe = LOW;}

  if ((openstate == HIGH) && (closestate == LOW)){
   relayshouldbe = HIGH;}
   // I didn't want both buttons being high to confuse things
   // so i made it do this instead.
   if ((openstate == HIGH) && (closestate == HIGH)){
   Serial.print("You're doing it wrong.");}
//
}

if ((closestate == LOW) && (openstate == LOW)){

  // This is for delay and as a jitter elimination method.
  if(sensorValue > limit){
  counteropen = counteropen + 1;
  }
  else{ counteropen = 0; }
  
  if(sensorValue < limit){
  counterclose = counterclose + 1;
  }
  else{ counterclose = 0;  }
  //
  
if ((counteropen > delayopen) && (relaycurrent == LOW)){

  relayshouldbe = HIGH;}
  
  
if ((counterclose > delayclose) && (relaycurrent == HIGH)){
 
  relayshouldbe = LOW;
  } 
}
  
if ((relayshouldbe == HIGH) && (relaycurrent == LOW)){
digitalWrite(ledPin1, HIGH);
delay(1000);
digitalWrite(ledPin1, LOW);
relaycurrent = HIGH;
relaystate = 1;}

if ((relayshouldbe == LOW) && (relaycurrent == HIGH)){
digitalWrite(ledPin2, HIGH);
delay(1000);
digitalWrite(ledPin2, LOW);
relaycurrent = LOW;
relaystate = 0;}

// These are mainly to see what's going on and to check everything's working ok
Serial.println(" ");
Serial.println(sensorValue); 
Serial.println(delayopen);
Serial.println(delayclose);
Serial.println(relaystate);
Serial.println(counteropen);
Serial.println(counterclose);
delay(1000);
}
delay(1000);

Unless you have a defective switch, nothing bounces for this long. Therefore, your problem is NOT switch bouncing.

I have multiple buttons which have the same issue, so my question is, how do I debounce multiple inputs?

The consensus at avrfreaks is to use the 'vertical counter' code by Peter Dannegger aka danni. You can find a copy buried in this thread http://8515.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=33821&postdays=0&postorder=asc. Scroll down until you find the post by danni.

Don

The danni code is cool. Personally, I use the Bounce library which I find has a quite nice interface. Then I wrote a small library, ButtonSpace, to collect a set of 'Bounce' objects into one. Simple example at sixbuttons.pde.

Paul could be correct, I have changed some code to hopefully tell me when the manual close and the manual open button is pressed, however, the value seems to remain constant.

Here is the updated code:

//sensors and outputs
int sensorPin = A0;    // select the input pin for the LDR
int ledPin1 = 12;      // select the pin for one relay coil
int ledPin2 = 13;      // select the pin for the other relay coil
//
//buttons
int testpin = 11;      // select the pin for the test enable switch
int testpinstate = 0;   
int manualclosepin = 10;   // select the pin for the manual close button
int closestate = 0;
int closestateprint = 0;
int manualopenpin = 9;   // select the pin for the manual open button
int openstate = 0;
int openstateprint = 0;
//
//variables
int sensorValue = 0;  // variable to store the value coming from the sensor
boolean relayshouldbe = HIGH;   // what value the relay should be (will be compared against the relaycurrent variable to determine if any change needs to happen.
boolean relaycurrent = HIGH;   // what state the relay is currently in
int relaystate = 0;
int delayclose = 4;   // variable for the closing delay
int counterclose = 0;
int delayopen = 4;   // variable for the opening delay
int counteropen = 0;
int limit = 100; //sets the sensor value limit
//



void setup() {

  pinMode(ledPin1, OUTPUT); 
  pinMode(ledPin2, OUTPUT);
  pinMode(testpin, INPUT);
  pinMode(sensorPin, INPUT);
  pinMode (manualclosepin, INPUT);
  pinMode (manualopenpin, INPUT);
  Serial.begin(9600);
}


void loop(){  
    sensorValue = analogRead(sensorPin);
    testpinstate = digitalRead(testpin);
    openstate = digitalRead(manualopenpin);
    closestate = digitalRead(manualclosepin);
  
  // sets the delay based on the test switch input
  // if the test switch is high, the delay is reduced
if (testpinstate == HIGH){
    delayclose = 4;
    delayopen = 4;}
else{delayclose = 1200;
    delayopen = 400;}
        // Manual open/close settings, only enabled when test mode is enabled

        if ((closestate == HIGH) && (openstate == LOW)){
        relayshouldbe = LOW;
        closestateprint = 1;
        openstateprint = 0;}

        if ((openstate == HIGH) && (closestate == LOW)){
        openstateprint = 1;
        closestateprint = 0;
        relayshouldbe = HIGH;}
        // I didn't want both buttons being high to confuse things
        // so i made it do this instead.
        if ((openstate == HIGH) && (closestate == HIGH)){
        openstateprint = 0;
        closestateprint = 0;
        Serial.print("You're doing it wrong.");}


//


if ((closestate == LOW) && (openstate == LOW)){
openstateprint = 0;
closestateprint = 0;
  // This is for delay and as a jitter elimination method.
  if(sensorValue > limit){
  counteropen = counteropen + 1;
  }
  else{ counteropen = 0; }
  
  if(sensorValue < limit){
  counterclose = counterclose + 1;
  }
  else{ counterclose = 0;  }
  //
  
if ((counteropen > delayopen) && (relaycurrent == LOW)){

  relayshouldbe = HIGH;}
  
  
if ((counterclose > delayclose) && (relaycurrent == HIGH)){
 
  relayshouldbe = LOW;
  } 
  
if (counteropen > delayopen + 2){
  counteropen = counteropen -1;
}
if (counterclose > delayclose +2){
  counterclose = counterclose - 1;
}

if ((relayshouldbe == HIGH) && (relaycurrent == LOW)){
digitalWrite(ledPin1, HIGH);
delay(50);
digitalWrite(ledPin1, LOW);
relaycurrent = HIGH;
relaystate = 1;}

if ((relayshouldbe == LOW) && (relaycurrent == HIGH)){
digitalWrite(ledPin2, HIGH);
delay(50);
digitalWrite(ledPin2, LOW);
relaycurrent = LOW;
relaystate = 0;}

// These are mainly to see what's going on and to check everything's working ok
Serial.println(" ");
Serial.print("Sensor Value: "); 
Serial.print(sensorValue);
Serial.println(" ");
Serial.print("Open Delay: ");
Serial.print(delayopen);
Serial.println(" ");
Serial.print("Close Delay: ");
Serial.print(delayclose);
Serial.println(" ");
Serial.print("relay state: ");
Serial.print(relaystate);
Serial.println(" ");
Serial.print("Open counter: ");
Serial.print(counteropen);
Serial.println(" ");
Serial.print("Close counter: ");
Serial.print(counterclose);
Serial.println(" ");
Serial.print("Manual Close state: ");
Serial.print(closestateprint);
Serial.println(" ");
Serial.print("Manual Open state: ");
Serial.print(openstateprint);
Serial.println(" ");
delay(1000);

}
}

Also, the delay(1000); is there to cause each loop to be 1 second, this allows the delay for the opening and closing to be set in seconds, just to make it a little easier to get the delays correct.

This project is for a chicken coop door opener, using a latching dpdt relay, hence the need for 2 outputs, one for each coil.