Button debounce

Ok so let me start by saying I have very little experience writing any kind of code, but I’ve been figuring stuff out. so I’ve got this code working. But I wanna add debounce to the buttons to one press doesn’t send it through the whole scope of numbers. I tried following the example and changed the parameters to work with my code. Was getting an error on the lastbuttonstste. I’m sure it’s simple but I can’t figure it out. Maybe got the order of operations wrong. I’ve seen some code use other void. Parameters. Do I need to do something along those lines? I’d also like to it keep the same value after being turned off and then turned back on if possible… as well as being able press the button to increase one unit and also be able to hold the button to cycle thru the entire scope of numbers. Thanks in advance everyone! Sorry if it’s a simple stupid question.
#include <LiquidCrystal.h>

LiquidCrystal lcd(2,3,4,5,6,7);

const int buttonup = 8; // the pin that the Up pushbutton is attached to

const int buttondn = 9; // the pin that the Down pushbutton is attached to

// Variables will change:

int settemp = 0; // counter for the number of button presses
int buttonStateup = 0; // current state of the button
int buttonStatedn = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
int upperlimit = 800;
int lowerlimit = 0;

void setup() {

// initialize the button pin as a input:

pinMode(buttonup, INPUT);

pinMode(buttondn, INPUT);

// LCD Setup
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(“xxxx”);
lcd.setCursor(0,1);
lcd.print(“Version 1.0”);
delay(4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(“xxxx”);
lcd.setCursor(0,1);
lcd.print(“xxxx!”);
delay (4000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(“xxx”);
lcd.setCursor(0, 1);
lcd.print(“xxxx”);
delay(500);

}

void loop() {

// read the pushbutton up input pin:

buttonStateup = digitalRead(buttonup);

// compare the buttonState to its previous state

if (buttonStateup != lastButtonState) {

// if the state has changed, increment the counter

if (buttonStateup == HIGH)

{

settemp++;
if (settemp > upperlimit) settemp = lowerlimit;
lcd.setCursor(8,1);

lcd.print(settemp);
}

}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonStateup;

// read the pushbutton down input pin:

buttonStatedn = digitalRead(buttondn);

// compare the buttonState to its previous state

if (buttonStatedn != lastButtonState) {

// if the state has changed, decrement the counter

if (buttonStatedn == HIGH)

{

settemp–;
if (settemp < lowerlimit) settemp = upperlimit;

lcd.setCursor(8,1);

lcd.print(settemp);
}

}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonStatedn;

}

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom.. :slight_smile:

Hi,
How have you got your buttons wired.

I noticed you do not use PULL_UP in the software.

So if you are switching the digital inputs to 5V, have you got a 10K resisitor from that input to gnd, to pull the input to gnd when the switch is open?

Thanks.. Tom... :slight_smile:

I have written debounce code. And I will occasionally write debounce code. But more often than not, I take whatever capacitor I've got handy in the low uF or high nF range and throw it across my button to take the bounce out in hardware. It's all too often that is even easier than writing the few simple lines of code it would take to do in software.

I have a button library that treats the button(s) as independent routines in loop().
Other code in the sketch gets the button status and works from that.
My buttons use pin mode INPUT_PULLUP so that grounding the pin is button press, LOW not HIGH.

Below is the button run routine. It is not beginner code. It uses bit logic and 8-bit timing values to save RAM and return a comprehensive status that can still tell “button just pressed” == 2.

However note the comments:
** // understand that stable state means no change for debounceMs. When time**
** // is over the state bits are manipulated to show a state change.**
** buttonState &= CURRENT_1; // clear all but the current state bit**
** if ( buttonState == 0 ) buttonState = PREVIOUS_2; // HIGH->LOW**
** else buttonState = CURRENT_1; // LOW->HIGH**
** // buttonState now appears as a debounced state change in bits 0 and 1**

The button is considered debounced when the pin state is stable over time means that current and previous states will be the same. So my routine cheats and sets the previous to before the change.
Some of the code prevents false presses from being seen as a press, it does not simply make the previous opposite to current, it can’t get that wrong with every other bounce clearing the bounce bit.

byte button::runButton( void )
{
//  static byte msNow;

  buttonState &= BOUNCE_4 | CURRENT_1; // clears previous state bit
  buttonState |= ( buttonState & CURRENT_1 ) << 1; // copy current state to previous
  buttonState &= BOUNCE_4 | PREVIOUS_2; // clears current state bit
  buttonState += digitalRead( arduPin ); // current state loaded into bit 0

//  msNow = (byte) millis(); // gets the low byte of millis

  if ( buttonState & 3 == CURRENT_1 || buttonState & 3 == PREVIOUS_2 )  // state change detected
  {
    buttonState ^= BOUNCE_4;      // toggles debounce bit
    // on 1st and odd # changes since last stable state, debounce is on
    // on bounces back to original state, debounce is off 
    if ( buttonState & BOUNCE_4 )
    {
      startMs = (byte) millis();    // starts/restarts the bounce clock on any change.
    }
  }
  else if ( buttonState & BOUNCE_4 ) // then wait to clear debounce bit
  {
    if ( (byte)((byte)millis()) - startMs >= debounceMs ) // then stable button state achieved
    {
      //   understand that stable state means no change for debounceMs. When time
      //   is over the state bits are manipulated to show a state change.
      buttonState &= CURRENT_1; // clear all but the current state bit
      if ( buttonState == 0 )  buttonState = PREVIOUS_2;  // HIGH->LOW
      else                     buttonState = CURRENT_1;  // LOW->HIGH
      //   buttonState now appears as a debounced state change in bits 0 and 1
    }
  }

  return buttonState;
};

I’ve got it down to 4 bytes per button and debouncing jumpers touched to ground (my dirty buttons) with 2ms stable time (after the last bounce) working dependably.

There's a library in the playground.

There’s 100’s of them. Some are iffy and some are rock solid.

I’ve got it down to 4 bytes RAM per independent button with button arrays allowed. The code is small too.