Skip to content

State change detection

A pushbutton lets the user send a signal to the system, but when the button is released the signal is lost. Usually we need to remember that the button was pressed. We save the information in a state variable. This is described in a little more detail in the original tutorial on the Arduino web site.

The code for this example is shown in the box below. You can load it into your Arduino IDE from the File menu: File → Examples → 02.Digital → StateChangeDetection

The aim is to count how many times the button has been pressed, and to turn on the LED if the number is divisible by four (0, 4, 8, ...).

This example also demonstrates the use of the serial monitor to get output from your sketch.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// constants
const int  buttonPin  = 2;   // the pin that the pushbutton is attached to
const int ledPin      = 13;  // the pin that the LED is attached to

// Variables
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState       = 0;   // current state of the button
int lastButtonState   = 0;   // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
    } else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by
  // checking the modulo of the button push counter.
  // the modulo function gives you the remainder of
  // the division of two numbers:
  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
}

You can use the same hardware configuration as for the button examples if you still have it made up. The layout shown below includes an external LED.

If you upload and run the sketch, the LED should light up because the button has not yet been pressed and zero is divisible by four (0 / 4 = 0). If you press the button, the LED will go out, and if you press it three more times it will come back on. That way you can see that the sketch is working correctly. Sometimes, however, you need to get more information about how your sketch is working. The serial monitor is a good way to do that.

What does bouncing mean?

The loop() function repeats so quickly that it may read the same button press more than once before you remove your finger. This is known as bouncing. A small delay is usually enough to prevent this from happening.

The serial monitor

The Arduino board can send and receive data using a serial communications connection. The serial monitor lets you see data that is being sent by the Arduino, and you can also use it to send data to the Arduino. In this example, we will just look at message generated from the sketch.

You can open the serial monitor using the button in the top right-hand side of the IDE window:

Serial monitor button

The example sketch contains three commands that allow it to send serial data. They are summarised below:

Line Command Description
16 Serial.begin(9600); Start serial communication at 9600 bits per second (bps or baud)
31 Serial.println( message ); Prints message in the monitor window and moves to the next line
32 Serial.print( message ); Prints message in the monitor window but does not move to the next line

A baud rate of 9600 bps is the default speed; you should not need to change this.

You can use the two forms of output command to construct a wide range of useful messages.

All of the serial communication commands are containing in a library called Serial. The commands used here are prefixed with the name of the library.

Run the example again with the serial monitor open and watch what happens when you press the button.

Binary

You can use the state variable concept to represent a number in binary format. The layout below uses two LEDS to represent the binary numbers 0 - 3.

Copy and upload the code below, and see what happens when you press the button.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// constants
const int button = 2;       // the number of the first pushbutton pin
const int led0   = 13;      // the number of the first LED pin
const int led1   = 12;      // the number of the second LED pin

// variables
int buttonState       = 0;  // current state of the button
int lastButtonState   = 0;  // previous state of the button
int buttonPushCounter = 0;  // Counter
int binaryDigit1      = 0;  // First binary digit
int binaryDigit2      = 0;  // Second binary digit

void setup() {
  // initialize the LED pins as outputs:
  pinMode(led0, OUTPUT);
  pinMode(led1, OUTPUT);
  // initialize the pushbutton pin as input:
  pinMode(button, INPUT);
  Serial.begin(9600);
}

void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(button);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, update the binary digits
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);

      if (binaryDigit1 == 0) {
        binaryDigit1 = 1;
      }
      else {
        binaryDigit1 = 0;
        if (binaryDigit2 == 0) {
          binaryDigit2 = 1;
        }
        else {
          binaryDigit2 = 0;
        }
      }
    } else {
      // if the current state is LOW then the button
      // went from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;


  // turns on the LEDs if the corresponding variable is HIGH
  if (binaryDigit1 == 1) {
    digitalWrite(led0, HIGH);
  } else {
    digitalWrite(led0, LOW);
  }
  if (binaryDigit2 == 1) {
    digitalWrite(led1, HIGH);
  } else {
    digitalWrite(led1, LOW);
  }
}

Further reading

Original tutorials

Debounce