Edit 2 I made a function that works, but I'm still confused about just one thing...

I'm very confused about how variables work in C++.

In this program...

  boolean debounce(void)
  static boolean buttonState=LOW;
  static boolean lastButtonState;
  boolean currentState = digitalRead(4);
  static unsigned long lastDebounceTime;
  if (currentState != lastButtonState){ //if the button state has changed
    lastDebounceTime=millis();  //reset timer

  if ((millis()-lastDebounceTime) > 50)  //if 50 milliseconds has passed since last bounce
    buttonState = currentState;  //read value again now that bouncing is over

  lastButtonState = currentState;
  return buttonState;

Why does changing this

lastButtonState = currentState;

To this

lastButtonState = buttonState;

Make any difference in the program?

When I try the latter line of code, the whole function stops working and I don't understand why.

  • What happens if 50ms haven't passed? Jan 13, 2016 at 22:19
  • 4
    Using the same name for globals, locals & function parameters is just begging for confusion.
    – brhans
    Jan 13, 2016 at 22:21
  • 1
    Your debounce() function is only being called every 500ms. That is probably not what you intended.
    – uint128_t
    Jan 13, 2016 at 22:29
  • @uint128_t - Why do you say: "debounce() function is only being called every 500ms" ? I don't see that, what have I missed?
    – gbulmer
    Jan 13, 2016 at 22:53
  • @gbulmer he edited his question
    – Marco
    Jan 13, 2016 at 22:53

4 Answers 4


This probably won't answer your question completely, but here are some notes from me:

buttonState = current ;  //read value again now that bouncing is over

This won't read the value again, it just copies current into buttonValue.

What you wanted is:

buttonState = digitalRead(BUTTON); // read value again now that bouncing is over

You have multiple issues with your debounce call:

  • lastTimeDebounce is never used by your code, so it is always zero.
  • lastButtonState will be always buttonVal making the debounce function useless.

Some other tips:

  • Don't use the same names for parameters as for global variables:

    boolean debounce(boolean lastButton, long lastDebounce, int BUTTON)

    The global variable BUTTON will be shadowed by int BUTTON, essentially overriding it.

  • Don't use global variables (unless you have a very good reason)


I would strongly recommend writing a function that debounces only one pin.

Because if you want a function which can debounce any pin you would need a state variable for each pin (which needs arrays hence a lot of space).


Here is a debounce function that should work:

const uint8_t PIN = 13;

 * Returns debounced value for `PIN`
boolean debounce(void)
    // Current state of the pin
    boolean currentState;
    // Last state of the pin, initial value is zero
    static boolean lastCurrentState = 0;
    // Timer
    static unsigned long debounceTimer = millis();
    // Debounced value, initial value is zero
    static boolean debouncedValue = 0;

    // We first read the current state of the pin
    currentState = digitalRead(PIN);

    // Then we look if the state has changed
    if (currentState != lastCurrentState) {
        // If it has, we need to reset the debounce timer
        debounceTimer = millis();

    // Then we check if the timer has expired
    if ((millis() - 50) > debounceTimer) {
        // The timer expired so we update the value
        debouncedValue = currentState;

    // Save the latest state
    lastCurrentState = currentState;

    // We always return a debounced value:
    return debouncedValue;

But always test such things with an oscilloscope, no guarantee. FYI: this is not an ideal debounce function, but it should make the idea clear.

  • "buttonState = current ; This won't read the value again, it just copies current into buttonValue." I'm not questioning that your right, but I actually copied the official arduino website when I did this. arduino.cc/en/Tutorial/Debounce
    – Dallin
    Jan 14, 2016 at 2:23
  • The Arduino site does not make the statement that it is actually reading the pin again.
    – Marco
    Jan 15, 2016 at 20:43
  • Ok I understand now. I made my code look like yours, and my function works now. Thanks for the help. Quick question though, why does "lastCurrentState = currentState" have to go outside of the if statement?
    – Dallin
    Jan 15, 2016 at 22:19
  • You could add an else and add it there and it won't affect the debouncing. I just put it there for convience.
    – Marco
    Jan 16, 2016 at 0:18
  • Sorry maybe I'm still a little confused... The second if statement will be executed no matter what right? ( because the program can't exit the function unless 50 millis have passed). If this is true, why can't I put "lastCurrentState = currentState" within the second if statement?
    – Dallin
    Jan 16, 2016 at 6:49

"It worked perfectly" is probably an overstatement. Yes, you saw the LED change when you pressed the button, but that doesn't mean it was getting debounced.

The problem is that you are trying to use global variables to remember the internal state of the debouncer function, and you're passing those variables into the function as parameters. In C (or C++, which is the underlying language that you're using), an assignment to a function parameter does NOT update the corresponding variable in the caller's environment. Therefore, lastDebounceTime never gets updated, and your debounce() function always just returns the current state of the button.

  • Beat me to it! +1 for "It worked perfectly" is probably an overstatement. Yes, you saw the LED change when you pressed the button, but that doesn't mean it was getting debounced.. A quick (possible) fix is to remove the parameters to debounce() and keep the state in global variables. A bit messy, but more useful than broken.
    – gbulmer
    Jan 13, 2016 at 23:06
  • Thank you for your answer @Dave, I think I'm starting to understand. But quick question, what do you mean by "an assignment to a function parameter does NOT update the corresponding variable in the callers environment"? Does this mean assigning a variable to a function parameter is pointless?
    – Dallin
    Jan 14, 2016 at 2:18
  • No, it isn't entirely pointless, because you can use it as an additional local variable inside the function. You can think of it as the caller initializing that variable for you, but then you can update it as needed while the function executes.
    – Dave Tweed
    Jan 14, 2016 at 2:34
  • @gbulmer or use static variables private to debounce()
    – Jasen
    Jan 14, 2016 at 9:27
  • @Jasen - Yes, that would be better. C++ classes are a bit verbose (I like to write Go) but a simple class would do, or a struct if there were several buttons to handle.
    – gbulmer
    Jan 14, 2016 at 16:51

Im not an expert of C programming, but I can see lot of troubles in your programming, because you do call a function debounce(), but it is not a function that does a complete task, so you set additional variables outside of it. This is a bad practice, because you can't call the same function to compute multiple keys, that's what functons are for - make one function and call multiple times with different parameters. You should switch to pointer orented parameters for lastButtonState.

    boolean LastButton_1; // global or static variable
    long LastDebounce_1;
    int BUTTON_1;
        ... and so on

    boolean debounce(boolean *LastButton, long *LastDebounce, int BUTTON)
          //your code here, where you read and write to variables located at pointer
           boolean something, new_value;
           something = *LastButton; //read value at pointer address
           *LastButton = new_value; //store the value at pointer address
//now you call this
debounce(&LastButton_1, &LastDebounce_1, BUTTON_1)

Perhaps it is not correct, since I know only very basic C, but the way is the right one


If you only have one button to debounce, you can store it's state as static variables in the debounce() function itself, like:

bool debounce()
    const int pin = 4;
    static bool last_state;
    static unsigned long last_change;
    unsigned long now = millis();

    if (now - last_change > 50) {
        bool state = digitalRead(pin);
        if (state != last_state) {
            last_change = now;
            last_state = state;
    return last_state;

If you may have to debounce more than one button, the cleaner way would be to store the state inside an object, and have the debounce function be one of its methods. That's what the Bounce library does.

  • Strictly speaking, digitalRead() returns an int not a bool.
    – Nick Gammon
    Jan 15, 2016 at 3:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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