Trouble with Debounce tutorial

I'm working through the Debounce tutorial at http://arduino.cc/en/Tutorial/Debounce. The code is also included in the Examples in the Arduino 0018 environment.

My understanding of the sketch is that it should toggle the LED (switch it from on to off, or vice versa) when the button is pushed.

The description says, "This example demonstrates the use of a pushbutton as a switch: each time you press the button, the LED (or whatever) is turned on (if it's off) or off (if on)."

I traced through the code line by line and tried to understand exactly how it would increment (is that the right term?) the LED's state, but it looked to me like the code would only turn the LED on when the button was pushed and turn it off when the button was released, not toggle the output state of the LED pin.

Here's the

/* 
 Debounce

 Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 a minimum delay between toggles to debounce the circuit (i.e. to ignore
 noise).  

 The circuit:
 * LED attached from pin 13 to ground
 * pushbutton attached from pin 2 to +5V
 * 10K resistor attached from pin 2 to ground

 * Note: On most Arduino boards, there is already an LED on the board
 connected to pin 13, so you don't need any extra components for this example.


 created 21 November 2006
 by David A. Mellis
 modified 3 Jul 2009
 by Limor Fried


 http://www.arduino.cc/en/Tutorial/Debounce
 */

// constants won't change. They're used here to 
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

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

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button 
  // (i.e. the input went from LOW to HIGH),  and you've waited 
  // long enough since the last press to ignore any noise:  

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  } 
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    buttonState = reading;
  }
  
  // set the LED using the state of the button:
  digitalWrite(ledPin, buttonState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

When I run the code, that's exactly what happens. I am completely new to programming and electronics, but it seems to me that beginning with the line buttonState = reading, there should be a routine that switches button state from HIGH to LOW or vice versa.

Am I correct that the code description doesn't match the code?

I do believe that your description of the code is correct. The comments in the code do appear to be wrong.

It wouldn't take much - a boolean to hold the LED state, toggled each time the button is pressed, to make the code match the comments.

Thank you Paul,

I am confused by the line

buttonState = reading

Isn't the value of "reading" going to be a long number instead of a "HIGH" or a "LOW"

Seems like I need something like "if buttonState != to lastButtonState, ledState ++"

Am I on the right track?

The return type for the digitalRead function is an int. The values are 0 or 1. There are typedefs that define HIGH as 1 and LOW as 0, so, even though the return value is 0 or 1, they can be compared to HIGH and LOW.

The buttonState variable is an int, do assigning it the value returned by digitalRead is a perfectly valid thing to do.

If you add a boolean, ledState, it should be set to false initially.

Then, every time the buttonState value is HIGH:

ledState = !ledState;

When ledState is false, !ledState == true, and when ledState = true, !ledState == false.

Paul, I understand what YOU are saying. But I don't understand how to work the boolean operation into the existing sketch. I think I need to start from scratch, and I am only just barely beginning to understand how to do that.

I guess the starting place is to try to outline exactly what I want the sketch to do and then write some sort of quasi program to lay out the logical structure of the sketch before I start trying to write code.

So the purpose of the sketch is to toggle the LED on or off in response to a push button, but ignore intermittent vibrations of the mechanical contacts in the switch ("bouncing") for a moment...maybe 50ms...so that noise as the switch opens or closes is ignored. Ultimately, the switch could be any kind of sensor, and the LED could be any kind of output.

I'm planning to implement this by starting a timer the moment a switch contact is detected, respond to that contact by toggling the LED, and ignore any further switch activity until the timer has run for at least a specified interval.

I know that Arduino can keep track of how long it has been running. millis() returns the time in milliseconds since the program began.

When the program starts, the button will be off and the led will be off (buttonState = LOW, ledState = LOW)

The program will look for a button push, (digitalRead(buttonState)) and when it sees one, it will: 1) a) note the time of the button push (reading = millis()) b) ignore it unless more than n milliseconds (reading - previousreading > n) have passed since the last time it responded to a button push. 2) toggle the led (ledState = 1 - ledState) if the time is greater than n.

Then it has to clean up somehow, recording the times when it does these things, logging the state of the button and led at the end of the loop and going back to the beginning without flashing the led incessantly, which I wouldn't notice because of POV.

I have to go make breakfast for my kids, but feel free to poke holes at what I'm trying to do in the meanwhile.

Just reading other people's code, and using it without understanding it, is not a good way to become a programmer.

Reading it, understanding it, and then attempting to re-write it is a much better approach. That's what you are doing.

Typically, debouncing is done with a call to delay(). That's normally fine when the Arduino. However, there are times when it isn't, and debouncing is done using millis() to answer the question "Are we there, yet?". It's a bit more complicated to do it this way, but, once you understand what debouncing is (you do), how it is done (you do), and how it can be done without resorting to delay() (you seem to have a good handle on this), you will be free of the need to ever use delay().

Thanks again for your help Paul,

Delay would seem to be a huge waste. The whole works has to sit and wait until the delay has passed. I'm fussing with this because I want to know how to make the machine set the table and make a martini while waiting for the steaks to broil as it were.

I think my "ledState = 1 - ledState" does the same thing as your "ledState = !ledState". While I guess that the typedef (thanks, that's a new term for me) makes it perfectly logical, I'm bothered by the lack of specificity in the latter statement.

Presumably the typedef makes it impossible for !ledState to be == "truth" or "blueberry pie". I like the certainty of (1-0 = 1(HIGH)) and (1-1 = 0(LOW)). Still, I will keep the not operator ! in mind.

Where I'm stuck right now is in trying to figure out how to write "If A and If B" then do something... I know there is something with &&, but I haven't quite got it figured. I'm about at the point of backing up and attacking the C++ language directly rather than trying to learn all this programming stuff through the back door via Arduino. Don't know if that's a good idea, but I ordered a copy of Programming: Principles and Practice Using C++ by Bjarne Stroustrup, which was already on my short list...I decided that K&R would be just a bit faster than I can go.

Meanwhile I'm just going to sit out on the porch and read through the Arduino Programming Notebook...probably too early for the martini...

Where I’m stuck right now is in trying to figure out how to write “If A and If B” then do something… I know there is something with &&, but I haven’t quite got it figured.

It does, indeed, use &&.

int a = 4;
int b = 7;
if(a == 4 && b == 7)
{
   // Do something
}

The if clause (the part in the ()) is evaluated, left to right. The first false terminates evaluation. In this test:

if(a == 6 && b == 7)

the b == 7 part will not be evaluated, since a is not 6.

It’s never to early for a martini. A vodka martini, anyway.