Switches

Project 7: A Simple Switch

What you will need:

  • Raspberry Pi
  • Breadboard
  • 4 Pushbutton Switches
  • 2 10kΩ Resistors —[III I]—
  • 4 1kΩ Resistors —[III I]—
  • 4 .1μF Ceramic Disk Capacitors
  • 6 Female to Male Jumper Wires
  • 4 Male to Male Jumper Wires

Instructions:

Up until now, all our projects have used Python scripts to manipulate LEDs. My son and I wanted to begin to introduce push-button switches into our future experiments. Before that could happen, however, we wanted to ensure we knew how switches worked with the Raspberry Pi’s GPIO.

Interestingly, we discovered that we couldn’t simply hook a switch between a controlling GPIO pin and ground to read its state. When a switch is connected to a GPIO input pin, its state is actually floating between high and low and is unreliable to read.

To anchor the GPIO pin’s state, we discovered we could connect either a Pull-Up or Pull-Down resistor to our switch. A Pull-Down resistor connects the pin to ground through a large resistance so when the switch is open there is a path to ground and the GPIO pin will read low. With the other side connected to 3.3v and the switch pressed, there is a lower resistance path to high and so the GPIO pin will read high. A large 10kΩ Pull-Down resistor in the circuit ensures that only a small amount of current is drawn when the switch is pressed.

Pull-Up Pull-Down Schematic

Building a circuit like this ensures we will be able to take reliable readings from our switch. However, it is still possible to damage the GPIO pins if they are accidentally set to output mode in our Python script. Pushing the button could easily create a short circuit between 3.3V and ground. To make this less possible, we can insert a 1kΩ limiting resistor into the circuit to ensure the Pi can handle the current drawn.

Interestingly, each GPIO pin of the Raspberry Pi also has a software configurable pull-up or pull-down resistor built into its hardware. When using a GPIO pin as an input, you can configure these resistors so they are enabled by using the optional PUD_UP or PUD_DOWN parameter of GPIO.setup. If this parameter is omitted, then neither resistor will be enabled.

As can be seen from our breadboard layout, we have set up four switches. The first is an example of using a Pull-Up resistor. The second is an example of using a Pull-Down resistor. The last two examples are identical to the first two except  they no longer use a physical resistor but instead use our Python script to incorporate the software configurable resistors built into the Raspberry Pi.

You might have noticed that we have inserted a .1μF capacitor across the pins of our switches. This can help if you experience a state fluctuation (bouncing) occurring during the time you are reading a switch connected to a GPIO pin. By connecting a capacitor, the result is a smoothing of the voltage curve. Before the button is pressed, the capacitor is fully charged. When the button is pressed, the capacitor starts draining. The voltage on the GPIO pin will smoothly ramp down from 3.3v to 0v and the GPIO will sense a single state change.

After carefully populating your breadboard and connecting the circuit to the Raspberry Pi’s GPIO, use your favorite editor to create the following Python script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  switch_test.py
#
# A short program to test implementing 4 switches.
# Each switch is attached to the Raspberry Pi in a
# different manner. One uses a physical Pull-Up resistor.
# The second uses a physical Pull-Down resistor.
# The third uses an internal Pull-Up resistor and the fourth
# uses an internal Pull-Down resistor. The switches are
# attached to GPIO 17, 23, 24, and 25.
#
# Each switch is connected to a 1K resistor to protect the
# GPIO in case a pin is accidentally set to an Output
# instead of an Input mode which could short things out
# and damage the Raspberry Pi.
#
#  Copyright 2015  Ken Powers
# 

# Import the modules used in the script
import RPi.GPIO as GPIO
import time

# Set constants
RUNNING = True
button_one = 17
button_two = 23
button_three = 24
button_four = 25

# Select GPIO numbering method and set switch pin
# as an input
GPIO.setmode(GPIO.BCM)
GPIO.setup(button_one, GPIO.IN)
GPIO.setup(button_two, GPIO.IN)
GPIO.setup(button_three, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(button_four, GPIO.IN, GPIO.PUD_DOWN)

# Main loop
try:
    while RUNNING:
		# Print a notification if a button is pressed
		while True:
			input_one = GPIO.input(button_one)
			input_two = GPIO.input(button_two)
			input_three = GPIO.input(button_three)
			input_four = GPIO.input(button_four)
			if input_one == False:
				print('Button One Pressed!')
			if input_two == True:
				print('Button Two Pressed!')
			if input_three == False:
				print('Button Three Pressed!')
			if input_four == True:
				print('Button Four Pressed!')
			# Wait until the button is released to move on
			while input_one == False or input_two == True or input_three == False or input_four == True:
				input_one = GPIO.input(button_one)
				input_two = GPIO.input(button_two)
				input_three = GPIO.input(button_three)
				input_four = GPIO.input(button_four)
				# Let the system have a brief break
				time.sleep(0.01)

# If CTRL+C is pressed the main loop is broken
except KeyboardInterrupt:
    RUNNING = False
    print "\Quitting"

# Actions under 'finally' will always be called
finally:
    # Stop and finish cleanly so the pins
    # are available to be used again
    GPIO.cleanup()

Code Analysis:

As with our previous projects, we begin by making sure the interpreter knows we are using the Python language. We also make a few comments so code analysts know what our Python script is going to accomplish.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  switch_test.py
#
# A short program to test implementing 4 switches.
# Each switch is attached to the Raspberry Pi in a
# different manner. One uses a physical Pull-Up resistor.
# The second uses a physical Pull-Down resistor.
# The third uses an internal Pull-Up resistor and the fourth
# uses an internal Pull-Down resistor. The switches are
# attached to GPIO 17, 23, 24, and 25.
#
# Each switch is connected to a 1K resistor to protect the
# GPIO in case a pin is accidentally set to an Output
# instead of an Input mode which could short things out
# and damage the Raspberry Pi.
#
#  Copyright 2015  Ken Powers
#

Next, we import the Python modules that are required for our script and define some constants. The first you may recognize from all our previous projects and is used in determining when our main program loop should end. The next four define which GPIO pins we are using to read the states of our switches.

# Import the modules used in the script
import RPi.GPIO as GPIO
import time

# Set constants
RUNNING = True
button_one = 17
button_two = 23
button_three = 24
button_four = 25

The next section of our Python script sets our GPIO mode to the Broadcom system. We then set our pre-defined GPIO pins to be inputs. Notice that the first two coincide with our two left-most breadboard buttons. They are using external Pull-Up and Pull-Down resistors. The next two coincide with the second set of switches on our breadboard which are using the Raspberry Pi’s internal Pull-Up and Pull-Down resistors so we need to mention that in our GPIO setup code. This is done through the use of the GPIO.PUD_UP and GPIO.PUD_DOWN parameters of GPIO.setup.

# Select GPIO numbering method and set switch pin
# as an input
GPIO.setmode(GPIO.BCM)
GPIO.setup(button_one, GPIO.IN)
GPIO.setup(button_two, GPIO.IN)
GPIO.setup(button_three, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(button_four, GPIO.IN, GPIO.PUD_DOWN)

Our main program loop checks to see if a button has been pressed and then prints out an appropriate message. Notice that the switches using Pull-Up resistors are checked to see if their state is 0 or False which indicates they have been depressed. The switches using Pull-Down resistors are checked to see if their state is 1 or True to determine if they have been pressed.

Because the Raspberry Pi can check the state of the switches very rapidly, we have included another short loop that waits until a switch is released before the program proceeds. If we didn’t do this, the main loop would repeatedly print a new “Button Pressed” message until the switch was released.

The main Python script loop continues until Ctrl + C is pressed.

# Main loop
try:
    while RUNNING:
		# Print a notification if a button is pressed
		while True:
			input_one = GPIO.input(button_one)
			input_two = GPIO.input(button_two)
			input_three = GPIO.input(button_three)
			input_four = GPIO.input(button_four)
			if input_one == False:
				print('Button One Pressed!')
			if input_two == True:
				print('Button Two Pressed!')
			if input_three == False:
				print('Button Three Pressed!')
			if input_four == True:
				print('Button Four Pressed!')
			# Wait until the button is released to move on
			while input_one == False or input_two == True or input_three == False or input_four == True:
				input_one = GPIO.input(button_one)
				input_two = GPIO.input(button_two)
				input_three = GPIO.input(button_three)
				input_four = GPIO.input(button_four)
				# Let the system have a brief break
				time.sleep(0.01)

# If CTRL+C is pressed the main loop is broken
except KeyboardInterrupt:
    RUNNING = False
    print "\Quitting"

# Actions under 'finally' will always be called
finally:
    # Stop and finish cleanly so the pins
    # are available to be used again
    GPIO.cleanup()

Although this particular project isn’t the most glamorous or exciting to date, it has given us quite a bit of insight into the way a press-button switch functions and how it needs to be connected to the Raspberry Pi’s GPIO in order to properly operate. Most websites my son and I were able to find that discussed switches were fairly vague or difficult to understand. Our hope is that by presenting 4 different breadboard switch layouts along with Python script to read the switches, we will be able to help other Raspberry Pi enthusiasts.



Leave a Reply