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. For the pull up resistor choose a value between 1kOhm and 10kOhm (10k is standard).
Please use the LEDs in your kit. 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. (R = (3.3V -1.2V)/0.02A = 100..500Ohms)
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.
You can choose between the two setups. Both with work. Usually you can sink more current through the pin of a microcontroller than it can provide. So the solution on the right is likely more often chosen.
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.
Either solution will work. It is common for digital signals to be considered idle when they are high. So the solution on the right is likely more often chosen.
We need to make sure that the RPi.GPIO libary is installed. In the shell/terminal open Python python3 and enter
import RPi.GPIO as GPIO
If this completes you are set and can check version using
GPIO.VERSION
You then can exit python with
exit()
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 input wire to +3.3V instead of the output pin. 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 27 in the examples above). This will only work if raspberry pi is turned on. But for general, when you build electronics, you build it when the circuit is powered OFF. So please turn the raspberry pi off before you continue with building.
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 leading to a final product.
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. Check lecture notes for example code.
Next you will want to test your buttons/switches. Simply read the status and print it in the command window. You can either have continuing prints of the status or print only if the status changed. Check lecture notes for example code.
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 a million times 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 20 times per second.
# Imports
import RPI.GPIO as GPIO
import time
...
some code
e.g. setting button pins as input
e.g. setting led pins as output
check the class notes
loop_interval = 0.05 # seconds, will run loop 20 times per second
stop = False
...
# Loop
while not stop:
# e.g. Example: blink
turn on LED
wait
turn off LED
wait
# e.g. Example: test button and led together
start_time = time.perfcounter()
if button pressed
turn on button LED
else
turn off button LED
# give some free time to CPU
delay = loop_interval - (time.perfcounter() - start_time)
if delay > 0:
time.sleep(delay)
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 see how other people are using the GPIO features.
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
#/////////////////////////////////////////////////////////////
# 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
#/////////////////////////////////////////////////////////////////
#
#/////////////////////////////////////////////////////////////////
# 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 Definitions:
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