element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Arduino Forum Why does my Arduino switch Debounce routine bounce?
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 31 replies
  • Subscribers 385 subscribers
  • Views 4182 views
  • Users 0 members are here
  • arduino_code
  • arduino coding
  • arduino
Related

Why does my Arduino switch Debounce routine bounce?

colporteur
colporteur over 2 years ago

Why does the LED flash twice with one push and release of the button?

#include <Servo.h>

Servo Stop_servo;  // create servo object to control a servo

// Buttons with Pull-Ups are "backwards"
// Some DEFINEs to make reading code easier
#define PUSHED false
#define NOT_PUSHED true
#define WATCH_BUTTON true
#define IGNORE_BUTTON false

// Time to wait for bounce, in MICROsconds
const int buttonWaitInterval = 6000;
// Pins for LED and Button
const int LEDpin = 5;
const int BUTTONpin = 2;
float Minpos = 0;    // variable to store the servo position
float Maxpos = 255;  //greatest travel of servo

// Used to track how long between "bounces"
unsigned long previousMicros = 0;

// Used to track state of button (high or low)
boolean previousButtonState = NOT_PUSHED;

// Variable reporting de-bounced state.
boolean debouncedButtonState = NOT_PUSHED;

// Tracks if we are waiting for a "bounce" event
boolean bounceState = false;

// Nothing surprising here
void setup() {
  pinMode(LEDpin, OUTPUT);
  pinMode(BUTTONpin, INPUT_PULLUP);
  digitalWrite(LEDpin, LOW);
  Stop_servo.attach(3);  // attaches the servo on pin 3 to the servo object
  Stop_servo.write(0);

  Serial.begin(9600);
  Serial.println(F("Serial Initialized"));
}

void loop() {

  // This needs to be called periodically to
  // update the timers and button status
  updateButton();
  // This replaces: digitalRead(BUTTONpin);
  //digitalWrite(LEDpin, debouncedButtonState);
  if (debouncedButtonState == LOW) {
    digitalWrite(LEDpin, HIGH);
    delay(500);
    digitalWrite(LEDpin, LOW);
    delay(500);
    Stop_servo.write(255);
    delay(5000);
    Stop_servo.write(0);
    Serial.println(F("servo cycled"));
  }
}

// All of the magic happens here
void updateButton() {
  // We are waiting for any activity on the button
  if (bounceState == WATCH_BUTTON) {
    // Get and store current button state
    boolean currentButtonState = digitalRead(BUTTONpin);
    // Check to see if a transition has occured (and only one)
    if (previousButtonState != currentButtonState) {
      // A transition was detected, ignore the others for a while
      bounceState = IGNORE_BUTTON;
      // Store current time (start the clock)
      previousMicros = micros();
    }
    // Keep storing existing button state, if we're watching
    previousButtonState = currentButtonState;
  }
  // We are waiting for the buttonWaitInterval to elapse
  if (bounceState == IGNORE_BUTTON) {
    // Compare current value of micros to previously stored, enough time yet?
    unsigned long currentMicros = micros();
    if ((unsigned long)(currentMicros - previousMicros) >= buttonWaitInterval) {
      // Store the state of the button/pin to debouncedButtonState, which "reports"
      // the correct value. This allows for the code to handle active high or low inputs
      debouncedButtonState = digitalRead(BUTTONpin);
      // Go back to watching the button again.
      bounceState = WATCH_BUTTON;
    }
  }
}

I'm trying to use Baldengineer debounce code to read a button and take an action. Each press of the button causes the LED to flash twice. The serial output reflects the routine running twice. 

I have failed in my code changes to get the result I hope. I have looked at Internet and have found no hints to help.

  • Sign in to reply
  • Cancel

Top Replies

  • scottiebabe
    scottiebabe over 2 years ago in reply to scottiebabe +4
    Technical forums are great, so many great tidbits of knowledge shared in this thread! One more demonstration showing why a schmitt trigger is an important part of the solution. I wrote a simple PIO…
  • dougw
    dougw over 2 years ago +3
    Debouncing may be good practice, but it would seem you don't need it here. If you start your LED and servo cycle as soon as a button push is first detected, all button bouncing will be long over before…
  • shabaz
    shabaz over 2 years ago +3
    Hi Sean, I've not looked in detail, but it seems that you wish to move a servo just once, if a button is pressed. Your delay() functions are actually already performing a button-pushed-down debounce…
  • dougw
    dougw over 2 years ago

    Debouncing may be good practice, but it would seem you don't need it here. If you start your LED and servo cycle as soon as a button push is first detected, all button bouncing will be long over before the LED and servo delays are completed. The MCU is not reading the switch during all this cycling time, so no extra activity will be triggered.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 2 years ago

    Hi Sean,


    I've not looked in detail, but it seems that you wish to move a servo just once, if a button is pressed. Your delay() functions are actually already performing a button-pushed-down debounce.
    That's because no mechanical switch will have bouncing output for longer than (say) 50 msec (this is an arbitrary value), and your delay() functions are clearly longer than that. So the debounce is effectively redundant, it's already achieved by your delay being longer.

    However there could be a scenario where the user simply holds down the button for many seconds. I think you wish to hold off until the button is released, before performing any more servo movements?

    If so, what you could do is simply check if the button is being held down after the servo has completed its motion, and you can just hold off there until the button is released, and have a little delay at the end too. It will be pretty rock-solid.

    Here's what it would look like approximately in pseudocode:


    IF the button is pressed:
        LED on
        MOVE servo
        WAIT 5 seconds
        LED off
        IF the button is still pressed: // User is holding it down for longer than 5 seconds!
            WAIT until button is released
            WAIT 100 msec // i.e. wait longer than 50 msec to be sure the button is not bouncing
    LOOP again

    Here is what it could look like in code:


    void loop() {
        // check if the button is pressed
        if (digitalRead(BUTTONpin) == LOW) {
            // turn LED on
            digitalWrite(LEDpin, HIGH);
            // move the servo and then wait 5 seconds
            Stop_servo.write(255);
            delay(5000);
            // move the servo back
            Stop_servo.write(0);
            // turn LED off
            digitalWrite(LEDpin, LOW);
            // if the user is holding down the button, wait for it to be released
            wait_for_button_release();
        }
    }

    That function wait_for_button_release() would be something like:

    void wait_for_button_release(void) {
        // Is the user holding down the button?
        if (digitalRead(BUTTONpin) == LOW) {
            // wait for the button to be released, by just repeatedly checking if the button is still pressed:
            while (digitalRead(BUTTONpin) == LOW) {
                delay(10); // tiny delay
            }
            // ok the user has released the button. Perform the debounce by waiting 100 msec which is greater than our arbitrary 50 msec assumption
            delay(100);
        }
    }

    The editor toolbar seems broken, so I had to just put the code in bold, instead of with proper formatting.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Cancel
  • BigG
    BigG over 2 years ago

    I found this Arduino library to be pretty good at handling debounce nuances pretty well: reference.arduino.cc/.../

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • Cancel
  • feiticeir0
    feiticeir0 over 2 years ago

    When creating a project with Arduino (a Geocache)  that needed button presses, i was able to solve that problem by using a delay function (with a specified debounce time) inside the function that reads (or waits for the user to press the button) the user input.

    Instead of using if to compare if the button was pressed and now it is in another state, when the user presses the button, just wait a few milliseconds before doing anything else.

    Here's an example:

    if (button != NO_BUTTON) {
         //play music
         tonner (button);
         if (DEBUG) Serial.println("Button pressed inside: " + String(button));
         delay (debounceDelay); //debounce to prevent multiple presses
         //check if button pressed is the same as in the array
         if (button == flashArray[numPressButtons]) {
           if (DEBUG) Serial.println ("corret button");
           //next button
           numPressButtons++;
           if (DEBUG) Serial.println("numPress: " + String(numPressButtons));
           setLedsPressed (NO_BUTTON);
           continue; //advance next
         }


    After pressing the button (if button != NO_BUTTON) - I have the delay (debouncedelay) to prevent registering new inputs..  It works very well.

    You can also see this code from Sparkfun for the Simon Says game that has a similar solutions (that's were my code is based from).

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • colporteur
    colporteur over 2 years ago

    Really appreciate the responses folks. I've been struggling with this concept for sometime. I estimate I am on about my forth debounce implementation. For some reason or another I go back to the well to revisit a "better" solution.

    Why my search didn't come up with BigG results is beyond me. My coding knowledge is limited so a canned library solution is appealing. I have one nasty animation controlled by a button that has been causing me problems. 

    The  Fireworks Simulation with Optical Fiber Cable (OFC)  animation project is controlled by a button some distance away from the Arduino Mega. The 26 gauge copper pair acts like an antenna for picking up noise. Adding sound to the animation now makes spurious noise triggering the fireworks more noticeable. 

    I like the supported library solution. With my limited coding skills canned solution like this have a greater appeal. I'm going to use the Fireworks as a test case to see how it works. 

    Thanks again for all the prompt responses.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • baldengineer
    baldengineer over 2 years ago

    As the creator of this code... I also second using a button library.

    I think I wrote this example before those libraries started popping up. Also, I remember having fun figuring out the logic. However, those libraries essentially do the same thing but were written by people much better at coding than me.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • phoenixcomm
    phoenixcomm over 2 years ago

     colporteur Hi, personally   I do not like soft debounce. I much prefer to get it over with a Schmitt Trigger (IC) you can use CD40106 (CMOS) or my favorite SN7414N, it is ubiquitous, and has many families.  you can look here for how it's done.  there is more info on this page:  if you wish to see the full article there is linked under one of the photos. This works ALL THE TIME, rain, snow whatever.. LOL

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Cancel
  • mayermakes
    mayermakes over 2 years ago

    in some cases a simple RC-network on the button does sufficient debounce, would be cheap and quick to try out.
    i usually use a 0,1uF cap and 10k resistor.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 2 years ago in reply to phoenixcomm

    Agree..

    The software debounce is now just moving the problem, especially because of the comment "controlled by a button some distance away from the Arduino Mega. The 26 gauge copper pair acts like an antenna for picking up noise".

    Now if a software debounce library is used, the question becomes, what sort of debounce to do in software? The debounce library can be configured with about 3 options, and not all will work if the issue is noise pickup (which is unrelated to button debounce).

    At some point, the issue needs to be understood, for the best configuration of code, regardless of whether a library is used or not. I too would have gone with hardware fix, although to augment the software debounce, i.e. an approach that uses both software and hardware.

    Also, one really needs to look at the code, and learn how the debounce works, and where and why it is needed, otherwise one will never move forward at learning how to marry up code to the underlying problem or task at hand,

    I sketched this, just as a discrete version. It can tolerate a lot of noise. The resistors could be about 2.2k ohm, for the collector one, and the base-to-emitter one could've 2.2k ohm too. Maybe 10 k ohm for the resistor connected to the switch. And a capacitor will help, maybe 100nF. This would all cost just $0.20 perhaps.

    image

    And for the logic IC version, I'd do the same as phoenixcomm recommends. A resistor can be added to prevent the input floating. This circuit expects the switch to be connected between positive supply and the Schmitt trigger input, but it could be rearranged if it's preferred to have the switch to ground.

    image

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
  • colporteur
    colporteur over 2 years ago in reply to baldengineer

    My apologies B. NO reflection on your code. I got stuck looking for a solution. If someone suggests a library to solve a problem, I'm there. I have a bad coding back so any heavy lifting done for me is a bonus:)

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube