Summary: Students will use breadboard and attach LED and Pushbutton to the input/output pins of the micro controller. A simple driver circuit for the LED and reading the button will be provided. Software tutorial on the web will be referred to for activating pins for output and others for input. A python program will be written to blink the LED and one to read switches with debouncing. There will be one main loop and the program will be laid out as statemachine.
Learning Outcome: Ability to create prototype of simple electronic circuit. Ability to control and read input/output pins.
We will build the setups outline below (you can also play with Fritzing if you like and load Fritizing file for LED and Switch. But you will need to fit at least four LEDs and Buttons on your protoboard to earn maximum points for this assignment.
Please use the buttons in your kit and solder solid pins to it as shown in the example circuit in class. For the pull up resistor choose a value between 1kOhm and 10kOhm. Do not use anything smaller than 1kOhm. An LED usually has a voltage drop of 1.2-1.3V and a maximum current of 20mA. Use Ohms law to compute R for the current limiting resistor.
Some solder less breadboards have the power lines split in the middle of the board. The one illustrated below have the 2 horizontal lines on the top and bottom connected. If the red or blue color stops in the middle of the board there is no connection and you will need to place a jumper wire.
Active high means that you need to write a 1 to the output pin in order to turn on the LED.
Active low means that you need to write a 0 to the output pin in order to turn on the LED.
Active high means that when you push the button the signal to the microcontroller will read a one.
Active low means that when you push the button the signal to the microcontroller will read a zero.
We need to make sure that the RPi.GPIO libary is installed. Open Python either in shell or using the Python IDE from the desktop menu. Enter
import RPi.GPIO as GPIO
If this completes you are set and can check version using
GPIO.VERSION
The documentation for RPi.GPIO is sparse but cand be found here through the examples: https://pypi.python.org/pypi/RPi.GPIO
For later laboratories we will want to expand on GPIO and use I2C and potentially SPI interface.
Build the circuits above and test them on your breadboard. You will need to choose either active high or active low implementation. Don't build both.
You do not need software to test the Circuit. If your circuit needs active high signal you can temporarily connect the wire to +5V. If your circuit needs active low wire, you can connect it to GND for testing. The LEDs will light up if they are connected correctly during testing. The output of buttons can be measured with digital multimeter (at pin 18 in the examples above).
You will need to write some code:
Turn ON/OFF an LED
Turn ON/OFF both LEDs
Blink the LEDs
Read the status of the switches.
Make sure the mechanical bouncing does not trigger multiple time during a switch action.
This laboratory is designed to help you setup for the Simon Says game in the next laboratory. It is a typical engineering project with several smaller projects.
As an engineer you start with individual smaller projects and then build them together into a larger project.
One of the simplest projects is to make you LEDs light up and turn off. This is called a blink program. If you have two LEDs write a program that turns them on for 0.1 seconds then turns them off for 0.9 seconds. This will become your LED test program.
Next you will want to test your buttons/switches. Simply read the status and and print it in the command window. You can either have continuing prints of the status or print only if the status changed.
Since you can read the switch and turn on/off the LEDs next is the combination of both. When the button is pressed you turn on the LED associated with the button. Please do this for all buttons and LEDs. There is a caveat. Your program will have a setup section and a loop that continuously runs. You will want to make sure that the program is not checking the switches 100,000 per second. You can measure the time at the beginning of the loop and at the end. Then wait for a time it takes to make sure the loop is executed for example 100 times per second.
Please demo two test programs:
One that tests all your LEDs.
One that tests your switches (with or without LEDs).
The goal is that you can easily debug your hardware later when you work on Simon Says game and figure out if the LEDs are working or the switches are working. Please not there is no single correct solution or answer. There is only code that worked and you having completed the assignment and being able to turn LEDs on/off and read the status of the switches.
An example of extensive use of indicator LEDs can be seen here:
LEDs here are driven by a high power LED driver circuit that receives input similar to the setting above.
The examples listed below are not the solutions to be turned in! They are provided so you can write your own program.
Its is best to set the PIN number scheme to the BCM name as that is printed on your cobbler.
GPIO.setmode(GPIO.BCM)
Now you want to configure the pins for input and output properly. Lets work on the LED pin first
GPIO.setup(18, GPIO.OUT)
GPIO.setup(23, GPIO.OUT)
The following is the command syntax: GPIO.output([pin], [GPIO.LOW, GPIO.HIGH]) Syntax means you can not execute that code and it simply lists all the possibilities. Now you will want to turn them on and off with a real example:
GPIO.output(18, GPIO.HIGH)
GPIO.output(18, GPIO.LOW)
You can also dim the LED
pwm = GPIO.PWM(18, 1000)
pwm.start(50)
pwm.ChangeDutyCycle(25)
This will set the output PWM frequency to 1kHz and the duty cycle to 50% which should dim the LED to 50% brightness. The last statement will chagne brightness to 25%.
To see it at 50% you would need to wait with changing Duty Cycle to 25% as the code would run to fast for you to see the 50% brightness if this would be a program.
Now we will take care of inputs.
GPIO.setup(17, GPIO.IN)
GPIO.setup(27, GPIO.IN)
if GPIO.input(17):
print("Pin 17 is HIGH")
else:
print("Pin 17 is LOW")
if GPIO.input(27):
print("Pin 27 is HIGH")
else:
print("Pin 27 is LOW")
Usually we need to provide pull up resistors but Raspberry Pi has some build in you can activate using
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_UP)
However since we attached them physically, we should not enable any pull up or pull down resistors.
It might be useful to use delays and timing functions. These commands will help you:
import time
time.sleep(0.1)
The last command will slepp for 100 [ms]
At the end of your program you might want to clean up
GPIO.cleanup()
An example python program that is used on UAVUA underwater vehicle on a Raspberry Pi is listed here to demonstrate how to make sure your main loop is not running at excessive high speed:
#!/usr/bin/env python
#/////////////////////////////////////////////////////////////
#
# ROS related imports
#import rospy
#from std_msgs.msg import Float64
#from std_msgs.msg import Bool
#from rospy_tutorials.msg import Floats
# Other Imports
import sys
import os.path
import math
import time
import datetime
# GPIO realted imports
import RPi.GPIO as gpio
poll_interval = 10
#
# GPIO related functions
#/////////////////////////////////////////////////////////////////
# Mission Switch on GPIO4, there is pull up attached so by default input is high
# when pressed input is low
#def mission_engage():
# print("Engage!")
#
#/////////////////////////////////////////////////////////////////
# Startup
#/////////////////////////////////////////////////////////////////
# GPIO Startup
# Input
gpio.setmode(gpio.BCM)
gpio.setup(18, gpio.IN)
#
# ////////////////////////////////////////////////////////////////////////
# Main Loop
# ////////////////////////////////////////////////////////////////////////
#
previousDisplayTimeS = time.time()
while True:
currentTimeS = time.time()
print("Time %+6.3f" % (currentTimeS))
mission = False if gpio.input(4) else True
if mission:
print("Mission ON!")
else:
print("Mission OFF!")
# release task
timeRemaining = poll_interval/1000.0 - (time.time() - currentTimeS)
if (timeRemaining > 0):
time.sleep(timeRemaining)
The following is the example code from sparkfun tutorial adapted to a layout with two buttons and two switches
# External module imports
import RPi.GPIO as GPIO
import time
# Pin Definitons:
pwmPin = 18 # Broadcom pin 18
ledPin = 23 # Broadcom pin 23
butPin1 = 17 # Broadcom pin 17
butPin2 = 27 # Broadcom pin 27
dc = 95 # duty cycle (0-100) for PWM pin
# Pin Setup:
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
GPIO.setup(ledPin, GPIO.OUT) # LED pin set as output
GPIO.setup(pwmPin, GPIO.OUT) # PWM pin set as output
pwm = GPIO.PWM(pwmPin, 50) # Initialize PWM on pwmPin 100Hz frequency
GPIO.setup(butPin1, GPIO.IN) # Button pin set as input w/o pull-up
GPIO.setup(butPin2, GPIO.IN) # Button pin set as input w/o pull-up
# Initial state for LEDs:
GPIO.output(ledPin, GPIO.LOW)
pwm.start(dc)
print("Here we go! Press CTRL+C to exit")
try:
while 1:
if GPIO.input(butPin1): # button is released
pwm.ChangeDutyCycle(dc)
GPIO.output(ledPin, GPIO.LOW)
else: # button is pressed
pwm.ChangeDutyCycle(100-dc)
GPIO.output(ledPin, GPIO.HIGH)
time.sleep(0.075)
GPIO.output(ledPin, GPIO.LOW)
time.sleep(0.075)
except KeyboardInterrupt: # If CTRL+C is pressed, exit cleanly:
pwm.stop() # stop PWM
GPIO.cleanup() # cleanup all GPIO