I can't do hardware debouncing (i.e. for a button push) using a capacitor

Hello.
Some days ago i started messing around with my Arduino again. However i can't do hardware debouncing of a pushbutton with the use of a capacitor across the button:
I make the well known topology (the pin set to digital input, 10K pulldown resistor etc.) but even if i try 10?F, 10nF or 100pF capacitors it doesn't work.
One year ago I had made 10s of projects using hardware debouncing using 10?F capacitor and had no problem. Is there a common mistake i may make and haven't noticed? Is there any chance that the capacitors are broken after a year?

Circuit?

saavedra29:
Hello.
Some days ago i started messing around with my Arduino again. However i can't do hardware debouncing of a pushbutton with the use of a capacitor across the button:
I make the well known topology (the pin set to digital input, 10K pulldown resistor etc.) but even if i try 10?F, 10nF or 100pF capacitors it doesn't work.
One year ago I had made 10s of projects using hardware debouncing using 10?F capacitor and had no problem. Is there a common mistake i may make and haven't noticed? Is there any chance that the capacitors are broken after a year?

Don't use a capacitor to debounce a switch... do it in software.

uint8_t get_switch (uint8_t pin)
{
#define debtime 100 // switch must be stable for 100 msec, change as desired

        uint16_t debounce; // debounce timer

        if (digitalRead (pin) == 1) {
                return 0; // return 0 == "button not pushed"
        }

        debounce = debtime; // init debounce timer

        while (debounce--) { // keep checking until debounce counts to 0
                if (digitalRead (pin) == 1) {
                        debounce = debtime; // switch bounced, reset timer
                }
                _delay_ms (1); // wait 1 msec, then check again
        }

        return 1; // return 1 == "button push detected"
}

This code assumes you have a digital input set as "input_pullup" or have a pullup resistor, and a button or switch that pulls the pin to ground when pushed.

Assume you have the switch connected to pin 7:

uint8_t status = get_switch (7);

"status" is 0 if switch not pushed, 1 if it is, and bounces are removed.

Hope this helps.

Or do it like this

//macro for detection of raising edge and debouncing
#define DRE(signal, state) (state=(state<<1)|(signal&1)&15)==7

const int ledPin = 13;
const int buttonPin = 2;
int buttonState;

void setup(){
  pinMode(ledPin, OUTPUT);
}//setup

void loop(){
  if(DRE(digitalRead(buttonPin), buttonState)) digitalWrite(ledpin, !digitalRead(ledPin));
}//loop()

nilton61:
Or do it like this

//macro for detection of raising edge and debouncing

#define DRE(signal, state) (state=(state<<1)|(signal&1)&15)==7

const int ledPin = 13;
const int buttonPin = 2;
int buttonState;

void setup(){
  pinMode(ledPin, OUTPUT);
}//setup

void loop(){
  if(DRE(digitalRead(buttonPin), buttonState)) digitalWrite(ledpin, !digitalRead(ledPin));
}//loop()

How does that debounce?

It signals a raising edge on a zero followed by three consecutive ones, Works fine even on very bouncing switches with minimun delay

saavedra29:
Is there a common mistake i may make and haven't noticed?

One common mistake is asking about common mistakes in hardware, but not providing a schematic.

I'm slowly converting to the "do it in software" camp -- especially with the bitshifted debounce code above, which is a darn clever way of doing it, IMO. Another way is to build a timer interrupt that polls for UI events every (e.g.) 10-20ms and sets a (volatile!) state variable that you read in your loop, rather than reading the pin itself.

However, if you decide to stick to hardware debounce, I would avoid caps >1uF. That's quite a bit of energy to fill and release through an I/O pin and low-current switch contacts. Remember, empty caps are a short to ground for a brief moment -- and likewise grounding a charged cap. If that's a button that gets pressed frequently, you don't want the involved components to have to dissipate much energy.

If you still want to debounce in hardware use a proper circuit with a schmitt trigger, a sr latch or a 555. To my knowing a input pin on a avr does not have smitt trigger action.

Thank you for the responses.
The schematic i try is the first picture attached. The OUT goes to the pin 8. And i use the led on pin 13 to test. The code is this:

 int switchPin = 8;
int ledPin = 13;
boolean lastButton = LOW;
boolean ledOn = false;

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

void loop()
{
  if (digitalRead(switchPin) == HIGH && lastButton == LOW)
  {
    ledOn = !ledOn;
    lastButton = HIGH;
  }
  else
  {
    //lastButton = LOW;
    lastButton = digitalRead(switchPin);
  }
  
  digitalWrite(ledPin, ledOn);

}

I also use the same code with the second schematic attached (schmitt triger) but no luck..
I don't want to use the Debounce.h library (software debounce) or software debounce generally. One reason is because i want to use the debounced button on an interrupt pin (i.e. pin2), and i don't want it to trigger the interrupt many times, but just once.

cap button.PNG

capButton2.png

saavedra29:
I don't want to use the Debounce.h library (software debounce). One reason is because i want to use the debounced button on an interrupt pin (i.e. pin2), and i don't want it to trigger the interrupt many times, but just once.

Hardware debouncing is almost never necessary when you have a microcontroller.

Just reject pulses that happen a short time after the initial one (eg. reject all pulses that happen within 2ms of the first one).

fungus:
Hardware debouncing is almost never necessary when you have a microcontroller.

Just reject pulses that happen a short time after the initial one (eg. reject all pulses that happen within 2ms of the first one).

Yes, but on the other hand it's not necessary to make the code complicated when there is plenty of capacitors :slight_smile:

saavedra29:
Yes, but on the other hand it's not necessary to make the code complicated when there is plenty of capacitors :slight_smile:

Using a capacitor isn't turning out to be more complicated than a couple of lines of code?

fungus:
Using a capacitor isn't turning out to be more complicated than a couple of lines of code?

Well it depends. Personally i find it much simpler to use a capacitor.

Hah... I'm lazyer than all of you, with exception I use a pulldown/up resistor ..

DigitalRead.. if it's high, I use a 300ms delay (to make sure your finger is off) unless it's time critical to hell with how it works XD

Even with a cap, it won't be bounce-free. Which means your interrupt will get called multiple times. I spent a lot of effort trying to get hardware denouncing to work right on a rotary knob so I could use interrupts. Even at its best, performance was pretty poor.

Why do you need an interrupt? Can't you use a timer interrupt and poll the pin?

SirNickity, that's a good idea.
However when i try it writing the code in C it works perfectly with a 10nF capacitor :slight_smile:
So i will stick with C. Arduino language is the 'easy' road, but if something is wrong it's difficult to figure out what happens.
Thank you everyone for helping!

I have to say... 10uF is a -very- large debounce capacitor.

saavedra29:
So i will stick with C. Arduino language is the 'easy' road, but if something is wrong it's difficult to figure out what happens.

You do know that Arduino is C, right? (Technically C++.) Not "almost C", but actual real C. Compiled with GCC and everything.

Both Americans and English And Australians and the Canadians speak English...

So why do so many translations between these countries go wrong? we all speak English yet there's words that don't even exist in other countries..

I think this is all boils down to really, it's all still the same language when it boils down...