ACROBOTIC Industries ACROBOTIC Industries

Arduino Activity 3: Push Button

Overview

Time to complete: 2–10min; Level of difficulty: Beginner

In this activity, we’ll build an electronic circuit with an LED and a push button; we’ll program our Arduino board to turn the LED on or off depending on whether we press, hold, or release the push button!

List of Materials


Obtaining the Code

For this activity, we'll be loading 2 different programs to our Arduino Uno board, which are available in our Github repository:

We can open a new window in the Arduino environment and copy-paste the code.  We'll start out with the program Button Hold.


Wiring: Button Hold

In our LEDs tutorial, we learned how to recognize the proper polarity of an LED.  Recalling that the positive (longer) lead should match the lead with the little kink on the wiring diagram below, we proceed to wire up the circuit.

As for the push button, even for experienced users these 6mm x 6mm tactile switches can be tricky to connect properly.  The main challenge is recognizing their correct orientation prior to placing it on the breadboard; to do this, we need to use the pins of the button as reference.  As the pins protrude from the button's casing on opposite sides, we rotate the button so that the pins face sideways relative to the breadboard (towards the blue/red power rails!).

The resistor value used for limiting the current flow through the LED is 1KOhm (Brown-Black-Red).


Using Pull-up/Pull-down Resistors with Digital Inputs

Connecting one pin of the button to ground (GND) and the other directly to the pin on the Arduino board (pin 2) minimizes the wiring of the circuit, and allows us to send a digital LOW signal to the Arduino pin when the putton is pressed.  The question now is, what happens before the button is pressed?  Specifically, what value or signal does the Arduino pin receive?

Well, the datasheet of the ATmega328p microcontroller on our Arduino board tells us that the default state for a digital I/O pin is as an input.  In this state, the pin is 'floating' (i.e., in a high-impedance state) and it can switch between reading a digial HIGH or LOW erratically.  By connecting an input pin to either GND or VCC guarantees that it will always read one value OR the other.  Typically, we don't want this connection to be direct, but rather through a current-limiting resistor.  A resistor serving the function of tying an input pin to HIGH or LOW are commonly known as pull-up or pull-down, respectively.

In fact, pull-up resistors are so commonly used in microcontroller applications that these devices include internal ones that can be easily enabled and disabled.  They are convenient, and help reduce the number of components and wiring needed.  The value of this resistors in the case of the ATmega328p is between 20K–40KOhms.

MCU Internal Pull-Up Resistor Diagram


Code Walkthrough: Button Hold

Now that the wiring of the push button is understood, let's analyze the code in the Button Hold program.  After declaring the variables we'll be using in the rest of the code, we initialize the pins for their respective function.  This is where we configure the ATmega328p microcontroller to use its internal pull-up resistor on pin 2:

  // Initialize the pushbutton pin as an input that is internally pulled up
  // to 5V using the built-in 20~50K resistors (ATmega328p on the Arduino Uno)
  pinMode(button_pin, INPUT_PULLUP);  

Then we move to our loop() function.  The first thing we want to do is read the state of the button.  As we have the button connected to VCC through the internal pull-up resistor, we expect the state to be digital HIGH unless the push button is pressed (in which case it will be digital LOW).

  // Read the state of the push button value:
  button_state = digitalRead(button_pin); // pulled up to 5V by default 

We then implement the logic that will control the state of the LED (on/off) depending on the state of the push button.  That is, while the button is pressed we want the LED to stay on, otherwise we want it to be off.  For that:

  // Check if the push button is pressed. If it is, the button state is 
  // LOW because the button is connected to ground:
  if (button_state == LOW) 
  {
    // Turn LED on:    
    digitalWrite(led_pin, HIGH);  
  }
  // otherwise (i.e., if button_state is HIGH)
  else 
  {
    // Turn LED off:
    digitalWrite(led_pin, LOW);
  }

This works quite well, but at times you'll see that the LED will behave erratically.  In particular, it might switch between on and off states rapidly even when the push button had not been pressed or realeased.  This erractic on-off toggling usually occurs right after we've pressed or released the button, and it's typically due to a phenomenon known as bouncing.

Let's go ahead and test the program by uploading the code to the Arduino Uno board.


Fixing Switch Bouncing with Software

Bouncing in the context of electromechanical switches, is a phenomenon that occurs due to the kinetic energy that is generated when two (or more) contacts come together after a force is applied.  While the kinetic energy settles, there is some physical "ringing" of the contacts, which affects the electrical signal that is transmitted through the contacts.  Whereas the phenomenon tends to be more significant when switches are closed, it can also be present when they're opened.

Although bouncing occurs with all different types of switches (e.g., sliding, pushbutton), there are some better than others.  Typically, wetted contacts such as mercury-based ones are better.  In addition, depending on the quality of the switch we can see that some can take up a few tens of milliseconds to settle, whereas the better quality ones do so within a few (< 5ms) instants.

Whereas the rapid, transient bouncing of a digital signal doesn't typically have negative too many repercussions on the hardware, it can affect the behavior of a program running in a microcontroller.  We saw this when we pressed/released the button in the previous step, and the LED turned on/off erratically until the contact settled.  We can address this problem in two (non mutually-exclusive) ways: using additional hardware and/or modifying our software.

  if (button_state == LOW) 
  {
    // Turn LED on:    
    digitalWrite(led_pin, HIGH);
    delay(200); // quick and dirty debouncing
  }
  // otherwise (i.e., if button_state is HIGH)
  else 
  {
    // Turn LED off:
    digitalWrite(led_pin, LOW); 
    delay(200); // quick and dirty debouncing
  }

A very easy solution for the Button Hold program is to add a delay of ~200ms right after we change the state of the LED.  Whereas this would perhaps make the program not respond as quickly as we may desire, we wouldn't see the LED rapidly toggling on/off right after the button is pressed or released.  A more sophisticated strategy is implemented in the Button Toggle program below.


Code Walkthrough: Button Toggle

With a bit more insight into the Switch Bouncing phenomenon, we can go ahead and upload the Button Toggle program to our Arduino board.  As the name suggests, the idea is to have the LED change its on/off state when the button is pressed.  Different than in the Button Hold program, however, we want the LED to maintain its state until the button is pressed again.  For this, our loop() function now includes the following lines of code:

  if ( (button_state == HIGH) && 
       (button_state_old == LOW) && 
       ((millis() - time) > bounce_wait) ) 
  {
    // Check the previous state of the LED and toggle it
    if (led_state == HIGH)
      led_state = LOW;
    else
      led_state = HIGH;
    // Store the current time for comparison in the next loop iteration 
    time = millis();    
  }

We're using the built-in function millis() to get the number of milliseconds since the Arduino board began running the current program.  The code uses a variable, time, to store the last value of millis() when the button was pressed (initially set to zero).  Using this variable, we can compute how much time has passed since the last time the button was pressed through the operation millis()-time .  Then we compare the difference with a threshold (bounce_wait) and decide whether the button press is genuine, or perhaps caused by an spurious voltage change due to the Bouncing phenomenon.


Code Tinkering

As an exercise we invite you to try and add one more push button to Button Toggle code sample.  It'd be great to use one push button for turning the LED on, and a second one for turning it off.  The wiring would be similar for the second push button, but instead of connecting it to digital pin 2 we would connect it to any other digital pin.


Comments, questions, or concerns? Drop us a line!.