[SOLVED] First sketch -- Push button Blinking LED -- Debouncing help!

Hello everyone,

I just got my first arduino on friday, and I've had a lot of fun blinking the LED in S.O.S. patterns and adding a switch.

I just successfully wrote my first sketch which blinks the LED on and off when you press a button, and turns it off when you press it again. My trouble is implementing a proper debounce to get an accurate read from the button. Below is my code. Any advice would be appreciated. Thanks!

int switchPin = 8;
int ledPin =  3;      
int ledState = LOW;             
long previousMillis = 0;                   
boolean lastButton = LOW;  // tracks button presses

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

void loop()
{
  if (digitalRead(switchPin) == HIGH && lastButton == LOW) // if the button is pressed change last button value 
  {
    lastButton = HIGH;
  }
  if (digitalRead(switchPin) == HIGH && lastButton == HIGH) // if the button is pressed change last button value 
  {
   lastButton = LOW;
  }
  if (lastButton == HIGH)  // if button is "on" blink the LED
  {
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > 250)  // defines a veriable that is going from true to false every quarter second
    {
      previousMillis = currentMillis;   
      if (ledState == LOW)  
      {
        ledState = HIGH;
      }
      else
      {
      ledState = LOW;
      }
    }
    digitalWrite(ledPin, ledState);
  }
  if (lastButton == LOW)  // if button is "off" turn the LED off
  {
    digitalWrite(ledPin, LOW);
  }
}

The cheap and cheerful 'debounce' algorithm commonly used is just to put a fixed delay after you notice the switch change, before you try reading it again.

A more sophisticated algorithm is to poll the switch until it has remained in the same state for a defined period so that you are sure it has settled before you act on any change. This takes more code and more testing, though, and is probably overkill for most applications.

If that is all your application does, add a delay(100); at the end of your main loop. Simple an does the job.

fm: If that is all your application does, add a delay(100); at the end of your main loop. Simple an does the job.

Im afraid a simple delay at the end of the loop will not help to debounce the button because it will interfere with the led Blinking. I had to use a blink without delay method, because such a delay would not allow me to read the button state.

Thank you for your help though, if you have any other suggestions Id be happy to try them out!

PeterH: The cheap and cheerful 'debounce' algorithm commonly used is just to put a fixed delay after you notice the switch change, before you try reading it again.

A more sophisticated algorithm is to poll the switch until it has remained in the same state for a defined period so that you are sure it has settled before you act on any change. This takes more code and more testing, though, and is probably overkill for most applications.

Thanks for your reply. Do you have any idea how I could implement such a debounce delay without breaking my blink function? Code would be of great use to me.

Thanks!

I figured it out! I had to add another variable, and as some suggested, add a delay if the pinRead was high, and read it again. Below is the working code with a debouncer. I hope this helps someone who has a similar problem.

int switchPin = 8;
int ledPin =  3;      
int ledState = LOW;             
long previousMillis = 0;                   
boolean lastButton = LOW;  // tracks button presses
boolean currentButton = LOW; // debouncer

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

void loop()
{
  if (digitalRead(switchPin) == HIGH) // debouncer
  {
    delay(75);
    currentButton = digitalRead(switchPin);
  }
  if (currentButton == HIGH && lastButton == LOW) // if the button is pressed change last button value 
  {
    lastButton = HIGH;
    currentButton = LOW;
  }
  if (currentButton == HIGH && lastButton == HIGH) // if the button is pressed change last button value 
  {
   lastButton = LOW;
   currentButton = LOW;
  }
  if (lastButton == HIGH)  // if button is "on" blink the LED
  {
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > 250)  // defines a veriable that is going from true to false every quarter second
    {
      previousMillis = currentMillis;   
      if (ledState == LOW)  
      {
        ledState = HIGH;
      }
      else
      {
      ledState = LOW;
      }
    }
    digitalWrite(ledPin, ledState);
  }
  if (lastButton == LOW)  // if button is "off" turn the LED off
  {
    digitalWrite(ledPin, LOW);
  }
}

A couple of suggestions.
boolean lastButton = LOW; // tracks button presses
boolean currentButton = LOW; // debouncer
I like name that are at least roughly the same name, like currXXX and prevXXX. I like names that reflect the purpose of the contents, too. You are not storing a button in the variables. Rather, you are storing the state of a switch. So, names like currState and prevState make more sense to me.

The type boolean is generally reserved for true and false values. HIGH and LOW are not true and false.

Finally, the digitalRead() function returns an int. The value that it returns should be stored in a variable of the same type. Yes, digitalRead() could, and probably should, return a uint8_t, since the values that it returns do not need an int to hold them. But, it is a good habit to develop to store function returned data in the proper type variable.

PaulS:
A couple of suggestions.
boolean lastButton = LOW; // tracks button presses
boolean currentButton = LOW; // debouncer
I like name that are at least roughly the same name, like currXXX and prevXXX. I like names that reflect the purpose of the contents, too. You are not storing a button in the variables. Rather, you are storing the state of a switch. So, names like currState and prevState make more sense to me.

The type boolean is generally reserved for true and false values. HIGH and LOW are not true and false.

Finally, the digitalRead() function returns an int. The value that it returns should be stored in a variable of the same type. Yes, digitalRead() could, and probably should, return a uint8_t, since the values that it returns do not need an int to hold them. But, it is a good habit to develop to store function returned data in the proper type variable.

Thanks a lot for your suggestions, I will certainly take them into consideration as I become more proficient in the arduino/BASIC language. I must admit though that I am a bonafide noob when it comes programing, and I am just happy that it works. But I am always open to sytax/form suggestions. Thanks again for the input!