Wednesday, March 14, 2012

Arduino Software and Hardware Based Button Debouncing

This, button debouncing, is vital for using any type of button with the Arduino. A bounce is referring to when the switch is pressed, and since its mechanical, its not a clean one time press. There are a whole bunch of tiny connections between the two sides of the switch before the button is actually pressed fully, and so the Arduino incorrectly counts those tiny connections as presses. So, to fix this we need to debounce the switch and make those tiny connections not count as button presses. There are two ways to do this; through software, and with hardware.

Software Debouncing:
Software based debouncing is by far the most common and easier to implement depending on where your skills are(HW vs SW). Basically, the Arduino runs in a loop(like it normally does) and when it detects the switch as "HIGH" it records the time. then it checks again, and if its still "HIGH" and its been high for long enough to be considered a full press of the switch, it sets a value or something saying that a button was completely pressed. Here is a ton of different ways to do software debouncing. This is some code from the Arduino website that works perfectly:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }
  
  // set the LED using the state of the button:
  digitalWrite(ledPin, buttonState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
} 

Hardware Debouncing: 


This, on the other hand is used much less. The big point here is that it uses a 100nf cap. This cap is charged as soon as the circuit gets power and since the cap is fully charged there is no current flowing and the pin will read LOW. As soon as the button is pressed, the cap is discharged and the pin will read HIGH. Using this method, all that is needed for code is a simple digitalRead to check the status of the button.

#define buttonPin  2    // the number of the pushbutton pin
#define ledPin  13      // the number of the LED pin

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
   digitalWrite(ledPin, digitalRead(buttonPin));  //sets the LED to current state of button
} 

13 comments:

  1. Clear and concise.
    Picking nits to be sure I understand.
    "the capacitor has to charge first"
    Might you mean discharge?

    ReplyDelete
  2. no. the cap has to charge and the button has to be fully pressed for this. the micro connections don't have enough "juice" flowing through them to charge teh cap + trigger the pin.
    that is how i understand it

    ReplyDelete
    Replies
    1. maybe it is me but if you ask me, no cap can charge when it is shortcircuited

      Delete
    2. Thank you for your response. I will reverse and rewire my circuit to match yours. 10k from ground point to input pin and ,,, sw & cap in parallel from input pin to + 5 volts. Don't know why i used a low value resistor, I guess I thought a strong current draw, when switched was pressed, would be a more stable read. I used those cheap radio shack momentary button switches. Won't do that again..
      Thanks again

      Delete
  3. Hi,

    I'm wondering... is there a reason for using a polarized capacitor? Would a regular one do just as well?

    ReplyDelete
    Replies
    1. just what i had on hand. non-polarized will do too.

      Delete
  4. As long as the button is not pressed, the cap is charged and it is charged fully, so the pin will be set LOW. If one presses the button, the capacitor is quickly discharged and the pin pulled HIGH.
    If there is a momentary release of the button (the 'bouncing'), the capacitor will not re-charge quick enough to set the pin LOW. There will be in fact a 0 to very small voltage over the cap, so the pin will still be pulled HIGH (5V -0V=5 V)

    ReplyDelete
    Replies
    1. Thanks for your input ed. i went back to look at the diagrams, and sure enough you're right haha. i definitely wasnt that great with electronics back then

      Delete
    2. we have all been there :-)

      Delete
  5. Just wondering? Does using a momentary switch (NO contacts) change anything with the CAP or Program. I am already wired with SW to ground then resistor to +5v. Do i need to rewire for best results? Does using a membrane momentary SW eliminate most of the bounce. My sketch using interrupts with mega 2560 controller. Have noticed that the worst bounce coming from when pressing SW in an not from releasing. I am using a 220 ohm resistor should i replace this with a 10K.
    Thanks

    ReplyDelete
    Replies
    1. yes i would reqire and use a 10k. not exactly sure what youre saying, so see if that works.

      Delete
  6. Thank you very much for sharing. I have used it with success in my project.

    ReplyDelete
  7. Hello, I can attest it works... I expanded it to three buttons that control menu, up and down functions.

    Great contribution. Thank you.

    ReplyDelete