Skip to content

Instantly share code, notes, and snippets.

@iremlopsum
Last active November 4, 2021 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iremlopsum/4b08d1e8eca50b0b6e8394c1432d07a1 to your computer and use it in GitHub Desktop.
Save iremlopsum/4b08d1e8eca50b0b6e8394c1432d07a1 to your computer and use it in GitHub Desktop.
# Traffic light with Raspberry Pi
import RPi.GPIO as GPIO
import time
# import sys for warning
import sys
# Variable that states if polling should be used
polling = False
# Listen to flags passed in from command line
if len(sys.argv) > 1:
# If -p or --polling is passed in, set polling to true
if sys.argv[1] == "-p" or sys.argv[1] == "--polling":
polling = True
# Print that program is using polling
print("Using polling")
# If -i or --interrupt is passed in, set polling to false
elif sys.argv[1] == "-i" or sys.argv[1] == "--interrupt":
polling = False
# Print that program is using interrupt
print("Using interrupt")
# If -h or --help is passed in, print help message with available flags
elif sys.argv[1] == "-h" or sys.argv[1] == "--help":
print("Usage: trafficlight.py [flag]")
print("Flags:")
print(" -p, --polling: Use polling")
print(" -i, --interrupt: Use interrupt, as is ran by default")
print(" -h, --help: Print this help message")
exit(0)
# Set up GPIO mode to BOARD
GPIO.setmode(GPIO.BOARD)
# turn off warnings for GPIO pins
GPIO.setwarnings(False)
# Create a map of traffic lights to GPIO pins
traffic_lights = {
"red": 17,
"yellow": 18,
"green": 27
}
# Create a map of pedestrian lights to GPIO pins
pedestrian_lights = {
"red": 22,
"green": 23
}
# Create a map of controls lights with a blue light
control_lights = {
"blue": 24
}
# Create a map for pedestrian light button to GPIO pin
pedestrian_buttons = {
"button": 25
}
# Variable that holds button pressed state
was_button_pressed = False
# Variable that holds the state of while loop
# that runs the traffic light sequence
has_pedestrian_loop_started = False
# Connect traffic lights to GPIO pins
for light, pin in traffic_lights.items():
GPIO.setup(pin, GPIO.OUT)
# Connect pedestrian lights to GPIO pins
for light, pin in pedestrian_lights.items():
GPIO.setup(pin, GPIO.OUT)
# Connect pedestrian button to GPIO pin
GPIO.setup(pedestrian_buttons["button"], GPIO.IN, pull_up_down=GPIO.PUD_UP)
# Helper function that tells if a light is on
def is_light_on(light):
return GPIO.input(light) == GPIO.HIGH
# Function that can turn on either traffic light or pedestrian light
def turn_light_on(light):
GPIO.output(light, GPIO.HIGH)
# Function that turns off either traffic light or pedestrian light
def turn_light_off(light):
GPIO.output(light, GPIO.LOW)
# Function that turns a light on for n amount of seconds
# and then turns that light off
def turn_light_on_for_n_seconds(light, n):
turn_light_on(light)
time.sleep(n)
turn_light_off(light)
# Function that can turn on multiple lights at once for
# n amount of seconds and then turn those lights off
def turn_on_multiple_lights_for_n_seconds(lights, n):
for light in lights:
turn_light_on(light)
time.sleep(n)
for light in lights:
turn_light_off(light)
# Function that turns off all traffic lights and pedestrian lights
def turn_all_lights_off():
for light in traffic_lights:
turn_light_off(light)
for light in pedestrian_lights:
turn_light_off(light)
# Function that blinks light n times within n seconds with last state being on
def blink_light(light, n, s):
blink_time_off = 0
blink_time_on = (s - (blink_time_off * (n - 1))) / n
for i in range(n):
turn_light_on_for_n_seconds(light, blink_time_on)
# If we are not on the last iteration, we have a delay between blinks
# so that transition to next light would be smooth
if i != n:
time.sleep(blink_time_off)
# Callback function for when the button is pressed
def button_callback(channel):
# Use global variables
global was_button_pressed
global polling
# If button was pressed and button pressed state is false
# turn on blue light and set button pressed state to true
if GPIO.input(channel) == GPIO.LOW and was_button_pressed == False:
was_button_pressed = True
# If polling is set to true, turn on blue light
if polling:
turn_light_on(control_lights["blue"])
# Start listening for button press with a callback function
GPIO.add_event_detect(
pedestrian_buttons["button"], GPIO.FALLING, callback=button_callback, bouncetime=300)
# Turn off all of the lights when program starts
# because we want to start with all lights off
# in case previous program crashed
turn_all_lights_off()
# Function that runs the traffic light sequence in a while loop
def run_traffic_light_sequence():
# Use global variables
global polling
global was_button_pressed
global has_pedestrian_loop_started
while True:
# If button is pressed, and pedestrian loop has not started,
# turn on pedestrian green with traffic red and set pedestrian loop to true
# else turn on traffic red with pedestrian red
if was_button_pressed and not has_pedestrian_loop_started:
has_pedestrian_loop_started = True
turn_on_multiple_lights_for_n_seconds(
[traffic_lights["red"], pedestrian_lights["green"]], 5)
turn_light_on(pedestrian_lights["red"])
# If we use interrupt instead of polling, turn on blue light
if polling == False:
turn_light_on(control_lights["blue"])
else:
turn_light_on(pedestrian_lights["red"])
turn_light_on_for_n_seconds(traffic_lights["red"], 5)
turn_light_on_for_n_seconds(traffic_lights["yellow"], 1)
turn_light_on_for_n_seconds(traffic_lights["green"], 5)
blink_light(traffic_lights["yellow"], 3, 2)
# If button is pressed and pedestrian loop is set to true,
# set button pressed state to false, turn off blue light,
# and set pedestrian loop to false
if was_button_pressed and has_pedestrian_loop_started:
was_button_pressed = False
has_pedestrian_loop_started = False
turn_light_off(control_lights["blue"])
# Try to run the traffic light sequence, with keyboard exception
# and print the exception to the console
try:
run_traffic_light_sequence()
except KeyboardInterrupt:
# print reason of exit and clean up
print("\nProgram stopped by user")
turn_all_lights_off()
GPIO.cleanup()
except:
# print reason of exit and clean up
print("\nUnexpected error:", sys.exc_info()[0])
turn_all_lights_off()
GPIO.cleanup()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment