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.
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.
void loop(){
val = digitalRead(switchPin); // read input value and store it in val
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 purse
OpenUmbrella(); // 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 pressed
Serial.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?