Having an LED turn on or off when a button is pressed is quite impressive, but it would be pretty odd if you had to press a button constantly to keep the TV on. What we want is an alternating action switch, where the press-and-release of a button does something, not just press-and-hold. Basically we want to test whether the button was just released, or just pressed.

To do this, we need to keep track of the button input value, to see if its changed. This is called the state of a button. When the state changes (an action occurs), that's when we want to perform an action.

Upload it to your Arduino and try it out, watching the serial monitor as you press and release the button. Lets go through the new lines of code:

int buttonState; // variable to hold the button state

This line isn't too unusual, its just a variable that is going to hold the state of the button. Since we don't know the state of the button when the Arduino is first turned on, we will leave it as unknown (uninitialized).

buttonState = digitalRead(switchPin); // read the initial state

In the setup() procedure, we initialize (set the initial/starting value) of the button state variable by reading the button value once we've started up and set the pin to an input.

OK now to the interesting part. In the loop procedure, we begin by first checking the button pin state and storing it an temporary variable val.

if (val != buttonState) { // the button state has changed! if (val == LOW) { // check if the button is pressed

Now we see 2 if statements that are nested, this means that we perform one test and if that test comes out true we go on to perform another test. This is more complex than a simple if statement but not much more different than the kinds of decisions we make all the time.

For example:

if ( it is raining ) { // look up, is there water falling on me? if ( I have an umbrella ) { // check my purseOpenUmbrella(); // Perform the umbrella opening procedure
}
}

Of course, we can't open the umbrella if we don't have one. And there's no point in checking if we have one if its not raining!

In the first if statement, we check if the current button state (HIGH or LOW) is different than the last time we looked at the button. If it is different (tested by the != inequality operator ) then we execute the next group of statements, enclosed by the {} braces.

Lets move on and examine the new statement we see, which is the if-else statment.

if (val == LOW) { // check if the button is pressedSerial.println("Button just pressed");
} else { // the button is -not- pressed...Serial.println("Button just released");
}

This statement is easy to understand: before, we would run a test and if that test passed, we would perform the statements in the {} braces. Now we also have an alternative, which is what we should do if the test fails! Now we used to perform two tests, one for (val == LOW) and one for (val == HIGH). This code is equivalent but its a little more straightforward. If its not LOW it must be HIGH.

if

(test statement)

{ statements to perform if test is True}

else

{ statements to perform if test is not True}

if

( val == LOW )

{ ... }

else

{ ... }

In the if-else statement, we simply examine val to deterimine if the last digitalRead() procedure informed us that the button is currently pressed or not pressed.

buttonState = val; // save the new state in our variable

Finally, we make sure that we've updated the button state variable with the current state.

Additional Tasks:

Add in an LED and modify the program to turn it on and off.

Remove or comment out the "buttonState = val;" line. What happens? Why?