5

I've been using a button to interact with a sketch (on my Uno), and it's mostly working fine. However, sometimes it seems to be detecting multiple presses when it's only pressed once.

It's a small circuit-mounted momentary button, which is normally open. It's connected from +5V directly to an input pin. I've also added a 10K pull-down resistor on the pin to make sure the input isn't left floating.

Here's a test sketch I've been using, which reports the number of presses to the serial monitor:

int oldState = LOW;
int numPresses = 0;

void setup()
{
    pinMode(5, INPUT);
    Serial.begin(9600);
}

void loop()
{
    const int newState = digitalRead(5);

    if (newState != oldState) {
        if (newState == HIGH) Serial.println(++numPresses);
        oldState = newState;
    }
}

Sometimes when I press the button once, the serial monitor shows two presses in a row. It sometimes even reports a press when I release the button.

Is it possible to fix this? Or do I just have a faulty button or pin or something?

  • So it would seem as if the voltage is going weird when pressing the button... would you mind checking the voltage with a meter to see what happens? It could just be that the button creates a weird contact, and thus contacts when it shouldn't... – hichris123 Feb 23 '14 at 21:53
  • The meter holds steady if it's connected between +5V and Ground (although it doesn't usually show any brief spikes). – Peter Bloomfield Feb 23 '14 at 22:02
  • 2
    @hichris123 Multimeters only update the display a few times a second. What we're looking for only lasts a couple hundredths of a second at the longest. You really need an oscilloscope to see it. See my answer for a picture. – sachleen Feb 23 '14 at 22:45
  • @sachleen Yeah, wasn't sure about that. I need an oscilloscope now (I only have a multimeter and some other stuff). – hichris123 Feb 23 '14 at 22:47
  • Hehe, maybe you should have rephrased your question title to something like "what are good justifications to afford an oscilloscope?" :-) – jfpoilpret Feb 24 '14 at 13:16
10

Contact Bounce

This is known as contact bounce and happens when the metal contacts in the button or switch bounce against each other when you push it. The microcontroller is fast enough to pick up these bounces and, as far as it's concerned, you're toggling the switch many times in as much as 10 milliseconds of time.

Different switches and buttons will have a different amount of contact bounce, and even one switch will behave differently between two presses.

Here's a button press captured on a scope (image from Maxim):

enter image description here

At 2ms/div we don't see a stable signal until 6ms after initial contact!

Solutions

Add a delay

The absolute simplest solution is to introduce a short delay after you read the button input. This will prevent the code from picking up any bounces and when it resumes, the signal should be stable.

if (digitalRead(A3) == 0) {
    // do something here
    delay(500);
}

In the example above, I delay 500ms after reading the state of the pin. The button is normally high so when I press it down, the state of the pin goes to logic 0. I pick that up in the code and do something and then wait at least 500ms before continuing.

Obviously, this code will just halt for half a second every time you push a button, which may or may not be acceptable in your application. You can decrease the amount of delay depending on the contact bounce time of your switch, too, but I play it safe here.

Ignore button presses too close to each other

Similar to the solution above but instead of adding a hard delay, you use the millis() function to keep track of when the last time the switch was triggered. Every time you see a switch trigger, you compare against the time and, if not enough time has elapsed (say like 500ms in my previous example), you ignore it.

This solves the problem of having to use delay() in your code.

Switch debouncer IC

There are things like the MAX6816 which is an IC that you put in between your switch and microcontroller input. It will denounce the signal for you. At a price of $1.62 @1k you'll probably never use this.

Other

There are many solutions to this problem... I always do it in software, but some others include using a latch or capacitor.

Debounce Code – one post to rule them all

  • thanks, I'm learning and this was driving me nuts! – Gothburz Jul 9 at 20:27
3

The button contacts themselves are probably bouncing in and out of contact, which is causing the circuit to open and close multiple times, even though the button position isn't changing.

It's a common problem with buttons and would be the first thing I would check. In order to fix this, you need to de-bounce the button. There are various ways in which to accomplish this, some of which can be done in the sketch itself.

A good solution is code that measures the duration of each button state and only registers a change in state if the current duration is greater than the desired duration. That option should be used for more complex projects. The code for it will be project specific and likely use sketch defined variables, but an example of what needs to be done can be found here.

If the sketch is very basic or you just want to make sure that bounce is the problem, you can add a short delay after the button state changes. For example:

void loop()
{
    const int newState = digitalRead(5);

    if (newState != oldState) {
        if (newState == HIGH) Serial.println(++numPresses);
        oldState = newState;
        delay(10) //Adjust the delay length to be as short as possible without triggering errors
    }
}    
2

This is your button bouncing which is quite usual behavior; it has nothing to do with button quality.

There are 2 ways to "debounce" a button: by hardware or by software.

Personally, I prefer by hardware; just google for button debouncing circuit and you should find many examples.

If you don't have the necessary components available, you can use software debouncing.

By software, you have an example here on Arduino web site.

  • Some buttons bounce much more than others, so it does have something to do with button quality. – sachleen Feb 23 '14 at 22:36
  • @sachleen I am not sure I would say so; it essentially depends on the metal used for the contacts in the button. I don't think one could find a non-bouncing button under all situations. Switch bouncing is to be expected, and will bite you in particular if your sketch runs quickly between 2 digitalRead() calls. – jfpoilpret Feb 23 '14 at 23:32
  • Also bouncing will depend on how the button is pushed (e.g. what force is applied to it and how). – jfpoilpret Feb 23 '14 at 23:33
  • 2
    Though the phenomenon is called contact-bounce, "looks" electrically like "bouncing" (and may in fact involve some actual "bouncing"), in a mechanical switch, the contacts never approach/depart each other totally squarely; there is unavoidably some degree of sliding, one over the other. The sliding of rough surfaces is what gives rise to the make-break-make... phenomenon, even when if contacts don't actually "bounce". (Think of one sort-of-smooth rock sliding against another). Note that this also means contact break will involve break-make-break..., as well. – JRobert Feb 26 '14 at 21:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.