Project 11: 16×2 LCD Alarm Clock With Snooze Button

What you will need:

  • Raspberry Pi
  • Breadboard
  • 16 x 2 LCD Screen
  • 10kΩ Potentiometer
  • Active Buzzer
  • Pushbutton Switch
  • 10 Female to Male Jumper Wires
  • 9 Male to Male Jumper Wires

Instructions:

This project is designed to use the Raspberry Pi to simulate a simple alarm clock with a buzzer and a snooze button. Our project utilizes the same 16 x 2 LCD screen from our previous projects while incorporating the active piezo buzzer from Project 10. Additionally, we have inserted a pushbutton switch into our breadboard layout to act as a simple snooze button.

Because this experiment builds upon Project 9 on this website and requires the Adafruit Raspberry Pi Python Code Library, be sure to follow the instructions in our Previous Project outlining the installation procedures before you continue.

After you have populated your breadboard and cloned the Adafruit library mentioned above, use your favorite editor to create the Python script below.

#!/usr/bin/env python
#
#  alarm_clock_LCD.py
#
# A simple alarm clock using Adafruit_CharLCD module
# plus a buzzer and 16x2 LCD display. A button is connected
# to GPIO 27 to simulate a snooze function.
#
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
# The positive side of the two pin active buzzer is attached to pin 18
# and the other pin goes to ground
#
#  Copyright 2015  Ken Powers
# 

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import time
import RPi.GPIO as GPIO

# Set some global constants
lcd = Adafruit_CharLCD()
buzzer_pin = 18
snooze_button = 27
alarm_sounding = False
RUNNING = True

# Set buzzer pin as a GPIO output and snooze button
# as an input with an internal pull-down resistor
GPIO.setup(buzzer_pin, GPIO.OUT)
GPIO.setup(snooze_button, GPIO.IN, GPIO.PUD_DOWN)

# Make the function to create a buzzing sound
# This function was originally written by Simon Monk
def buzz(pitch, duration):
	period = 1.0 / pitch
	delay = period / 2
	cycles = int(duration * pitch)
	for i in range(cycles):
		GPIO.output(buzzer_pin, True)
		time.sleep(delay)
		GPIO.output(buzzer_pin, False)
		time.sleep(delay)

# Define a function that returns a correct 24 hour result after
# snooze time has been added
def snooze(alarm):
	# Add 9 minutes to the alarm time for the snooze
	alarm += 9
	# Separate time into hours and minutes
	hours = int(alarm / 100)
	minutes = alarm - hours * 100

	# Make sure new alarm time fits 24 hour format
	if (minutes > 59):
		plushrs = int(minutes//60)
		minutes = minutes % 60
		hours = hours + plushrs
	if (hours > 23):
		hours = hours - 24

	# Reconstruct alarm time and return to main loop
	alarm = hours * 100 + minutes
	return alarm

try:
	# Get alarm time from user
	response = raw_input("Enter the alarm time in 24-Hour format HHMM: ")
	print("Alarm time has been set for %s hrs" % response)
	buzz(500,0.1)

	alarm = int(response)

	# Clear LCD screen
	lcd.clear()

	while RUNNING:
		# Continually get the time as an integer
		# Output time in 24-Hour format to the LCD
		curr_time = int(time.strftime("%H%M"))
		lcd.home()
		lcd.message("  Current Time\n")
		lcd.message(time.strftime("    %H:%M:%S\n"))

		# Trigger the buzzer function when the alarm time is reached
		# The buzzer will have two different tones just for fun
		if curr_time == alarm:
			lcd.clear()
			lcd.home()
			lcd.message("    Wake Up!")
			buzz(10,0.25)
			time.sleep(0.1)
			buzz(20,0.25)
			time.sleep(0.1)
			alarm_sounding = True

		# Check for snooze button press
		input_button = GPIO.input(snooze_button)
		if alarm_sounding == True and input_button == True:
			print('Snooze Pressed!')

			# Call function to add snooze time
			alarm = snooze(alarm)

			print('New Alarm Time Is: %s' % alarm)
			alarm_sounding = False

			# Wait until the button is released to move on
			while input_button == True:
				input_button = GPIO.input(snooze_button)
				# Let the system have a brief break
				time.sleep(0.01)

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

Code Analysis:

Our Raspberry Pi Python script begins by telling the interpreter we are using the Python language. We also include some descriptive comments that help to let readers know what the script will accomplish as well as indicating what Raspberry Pi GPIO pins we are using.

#!/usr/bin/env python
#
#  alarm_clock_LCD.py
#
# A simple alarm clock using Adafruit_CharLCD module
# plus a buzzer and 16x2 LCD display. A button is connected
# to GPIO 27 to simulate a snooze function.
#
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
# The positive side of the two pin active buzzer is attached to pin 18
# and the other pin goes to ground
#
#  Copyright 2015  Ken Powers
#

Next, we import all the required function libraries, instantiate an LCD using the Adafruit library, and define some necessary constants.

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import time
import RPi.GPIO as GPIO

# Set some global constants
lcd = Adafruit_CharLCD()
buzzer_pin = 18
snooze_button = 27
alarm_sounding = False
RUNNING = True

At this point in our script, we setup our GPIO so our buzzer pin is an OUTPUT and our snooze button is an INPUT that is utilizing an internal pull-down resistor.

# Set buzzer pin as a GPIO output and snooze button
# as an input with an internal pull-down resistor
GPIO.setup(buzzer_pin, GPIO.OUT)
GPIO.setup(snooze_button, GPIO.IN, GPIO.PUD_DOWN)

Our first function definition was written by Simon Monk and is designed to make a sound through our active buzzer.

# Make the function to create a buzzing sound
# This function was originally written by Simon Monk
def buzz(pitch, duration):
	period = 1.0 / pitch
	delay = period / 2
	cycles = int(duration * pitch)
	for i in range(cycles):
		GPIO.output(buzzer_pin, True)
		time.sleep(delay)
		GPIO.output(buzzer_pin, False)
		time.sleep(delay)

Our next function definition is used for our snooze button. If the alarm is sounding and the snooze button is depressed, this function is called.

Every alarm clock I have ever owned has had a snooze time of 9 minutes. I have no idea why 10 minutes isn’t used. This function sticks with that unusual convention and adds 9 minutes to the current alarm time.

Next, the time is broken into hours and minutes so we can ensure that the new alarm time fits standard 24-hour format conventions.

# Define a function that returns a correct 24 hour result after
# snooze time has been added
def snooze(alarm):
	# Add 9 minutes to the alarm time for the snooze
	alarm += 9
	# Separate time into hours and minutes
	hours = int(alarm / 100)
	minutes = alarm - hours * 100

	# Make sure new alarm time fits 24 hour format
	if (minutes > 59):
		plushrs = int(minutes//60)
		minutes = minutes % 60
		hours = hours + plushrs
	if (hours > 23):
		hours = hours - 24

	# Reconstruct alarm time and return to main loop
	alarm = hours * 100 + minutes
	return alarm

The main loop of our script prompts the user for their desired alarm time in 24-hour format. Our LCD screen is continually updated with the current time and the alarm buzzer is sounded if our alarm time is reached. While the alarm is sounding, a press of the snooze button calls our snooze() function and the new alarm time is returned. The entire process continues until Ctrl + C is pressed.

try:
	# Get alarm time from user
	response = raw_input("Enter the alarm time in 24-Hour format HHMM: ")
	print("Alarm time has been set for %s hrs" % response)
	buzz(500,0.1)

	alarm = int(response)

	# Clear LCD screen
	lcd.clear()

	while RUNNING:
		# Continually get the time as an integer
		# Output time in 24-Hour format to the LCD
		curr_time = int(time.strftime("%H%M"))
		lcd.home()
		lcd.message("  Current Time\n")
		lcd.message(time.strftime("    %H:%M:%S\n"))

		# Trigger the buzzer function when the alarm time is reached
		# The buzzer will have two different tones just for fun
		if curr_time == alarm:
			lcd.clear()
			lcd.home()
			lcd.message("    Wake Up!")
			buzz(10,0.25)
			time.sleep(0.1)
			buzz(20,0.25)
			time.sleep(0.1)
			alarm_sounding = True

		# Check for snooze button press
		input_button = GPIO.input(snooze_button)
		if alarm_sounding == True and input_button == True:
			print('Snooze Pressed!')

			# Call function to add snooze time
			alarm = snooze(alarm)

			print('New Alarm Time Is: %s' % alarm)
			alarm_sounding = False

			# Wait until the button is released to move on
			while input_button == True:
				input_button = GPIO.input(snooze_button)
				# Let the system have a brief break
				time.sleep(0.01)

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

The addition of a snooze button to our previous project turned out to be a bit of a challenge. Making sure the adjusted alarm time remained in proper 24-hour format required a bit of thought. Enjoy the project and have fun modifying it to suit your own needs. Above all, however, have fun!

Project 10: 16×2 LCD Alarm Clock With Buzzer

What you will need:

  • Raspberry Pi
  • Breadboard
  • 16 x 2 LCD Screen
  • 10kΩ Potentiometer
  • Active Buzzer
  • 9 Female to Male Jumper Wires
  • 8 Male to Male Jumper Wires

Instructions:

This project is designed to use the Raspberry Pi to simulate a simple alarm clock. Our project utilizes the same 16 x 2 LCD screen from our previous projects while incorporating an active piezo buzzer. A buzzer that is similar to what my son and I used for this project can be found through Adafruit Industries.

Because this experiment builds upon Project 9 on this website and requires the Adafruit Raspberry Pi Python Code Library, be sure to follow the instructions in our Previous Project outlining the installation procedures before you continue.

After you have populated your breadboard and cloned the Adafruit library mentioned above, use your favorite editor to create the Python script below. Our breadboard layout is identical to our previous 16 x 2 LCD screen projects except for the addition of an active buzzer. Notice that we have connected the anode (+) of the buzzer to GPIO 18 of our Raspberry Pi and the cathode is attached to our ground () rail.

#!/usr/bin/env python
#
#  alarm_clock_LCD.py
#
# A simple alarm clock using Adafruit_CharLCD module
# plus a buzzer and 16x2 LCD display
#
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
# The positive side of the two pin active buzzer is attached to pin 18
# and the other pin goes to ground
#
#  Copyright 2015  Ken Powers
# 

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import time
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

# Set some global constants
lcd = Adafruit_CharLCD()
buzzer_pin = 18
RUNNING = True

# Set buzzer pin as a GPIO output
GPIO.setup(buzzer_pin, GPIO.OUT)

# Make the function to create a buzzing sound
# This function was originally written by Simon Monk
def buzz(pitch, duration):
	period = 1.0 / pitch
	delay = period / 2
	cycles = int(duration * pitch)
	for i in range(cycles):
		GPIO.output(buzzer_pin, True)
		time.sleep(delay)
		GPIO.output(buzzer_pin, False)
		time.sleep(delay)

try:
	# Get alarm time from user
	response = raw_input("Enter the alarm time in 24-Hour format HHMM: ")
	print("Alarm time has been set for %s hrs" % response)
	buzz(500,0.1)

	alarm = int(response)

	# Clear LCD screen
	lcd.clear()

	while RUNNING:
		# Continually get the time as an integer
		# Output time in 24-Hour format to the LCD
		curr_time = int(time.strftime("%H%M"))
		lcd.home()
		lcd.message("  Current Time\n")
		lcd.message(time.strftime("    %H:%M:%S\n"))

		# Trigger the buzzer function when the alarm time is reached
		# The buzzer will have two different tones just for fun
		if curr_time == alarm:
			lcd.clear()
			lcd.home()
			lcd.message("    Wake Up!")
			buzz(10,0.5)
			time.sleep(0.25)
			buzz(20,0.5)
			time.sleep(0.25)

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

Code Analysis:

Our Raspberry Pi’s Python script begins by letting the interpreter know what language we are using. It also provides some simple comments that let readers understand the script’s purpose as well as indicating which GPIO pins are being utilized.

#!/usr/bin/env python
#
#  alarm_clock_LCD.py
#
# A simple alarm clock using Adafruit_CharLCD module
# plus a buzzer and 16x2 LCD display
#
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
# The positive side of the two pin active buzzer is attached to pin 18
# and the other pin goes to ground
#
#  Copyright 2015  Ken Powers
#

Next, the required function libraries are imported, some constants are defined, and an LCD is instantiated by utilizing the Adafruit function library. Finally, the Raspberry Pi GPIO pin we are using for our buzzer is set to output mode.

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import time
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

# Set some global constants
lcd = Adafruit_CharLCD()
buzzer_pin = 18
RUNNING = True

# Set buzzer pin as a GPIO output
GPIO.setup(buzzer_pin, GPIO.OUT)

Our Python script next defines a function which was written by Simon Monk to cycle the buzzer on and off to create a specific pitch. This will be used to sound our alarm.

# Make the function to create a buzzing sound
# This function was originally written by Simon Monk
def buzz(pitch, duration):
	period = 1.0 / pitch
	delay = period / 2
	cycles = int(duration * pitch)
	for i in range(cycles):
		GPIO.output(buzzer_pin, True)
		time.sleep(delay)
		GPIO.output(buzzer_pin, False)
		time.sleep(delay)

Our Raspberry Pi’s main Python script loop begins by asking the user to enter the alarm time in 24 hour format (HHMM). The user’s response is printed to our main screen and a beep is sounded to acknowledge the receipt of the information before continuing.

Next, we create a loop to continually update the current time displayed on our LCD screen. Once our alarm time has been reached, we display the message “Wake Up!” on our LCD screen, and trigger our buzzer.

The alarm clock script continues until Ctrl + C is pressed.

try:
	# Get alarm time from user
	response = raw_input("Enter the alarm time in 24-Hour format HHMM: ")
	print("Alarm time has been set for %s hrs" % response)
	buzz(500,0.1)

	alarm = int(response)

	# Clear LCD screen
	lcd.clear()

	while RUNNING:
		# Continually get the time as an integer
		# Output time in 24-Hour format to the LCD
		curr_time = int(time.strftime("%H%M"))
		lcd.home()
		lcd.message("  Current Time\n")
		lcd.message(time.strftime("    %H:%M:%S\n"))

		# Trigger the buzzer function when the alarm time is reached
		# The buzzer will have two different tones just for fun
		if curr_time == alarm:
			lcd.clear()
			lcd.home()
			lcd.message("    Wake Up!")
			buzz(10,0.5)
			time.sleep(0.25)
			buzz(20,0.5)
			time.sleep(0.25)

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

The Raspberry Pi Python script above demonstrates how easy it is to build upon previous projects in order to create more complex experiments. Try building upon this simple script by changing the information that is displayed on the LCD screen or add a snooze button to make things more functional. Above all, however, have fun!

Project 9b: 16×2 LCD Screen Weather Report

What you will need:

  • Raspberry Pi
  • Breadboard
  • 16 x 2 LCD Screen
  • 10kΩ Potentiometer
  • 8 Female to Male Jumper Wires
  • 7 Male to Male Jumper Wires

Instructions:

The second project my son and I created utilizing a 16 x 2 LCD screen uses the identical breadboard layout from Project 9 and simply displays a basic weather report by using the API from Weather Underground.

Because this experiment builds upon Project 9 and requires the Adafruit Raspberry Pi Python Code Library, be sure to follow the instructions in our Previous Project outlining the installation procedures before you continue. Also, stop by the Weather Underground API site to sign up for a free API. You will need the API code to make this project work.

Once you have your breadboard populated, the Adafruit Library cloned, and an API key from the Weather Underground, enter the Python script below using your favorite editor:

#!/usr/bin/env python
#
#  weather_LCD.py
#
# A short program using the wunderground.com API and
# Adafruit's 'Adafruit_CharLCD' library to monitor
# current weather conditions in a city and to then
# update a 16x2 LCD display in 4 bit mode
#
# Get an API key for Weather Underground at:
# http://wunderground.com/weather/api
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
#  Copyright 2015  Ken Powers
#

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import urllib2
import json
import time
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

lcd = Adafruit_CharLCD()
RUNNING = True

# Set your access keys as configured
myapi = "YOUR_API_KEY_FROM_WEATHER_UNDERGROUND"

try:
	while RUNNING:
		# Use JSON to obtain weather information using
		# Wunderground.com API call.

		f = urllib2.urlopen('http://api.wunderground.com/api/' + myapi + '/geolookup/conditions/q/WA/Tacoma.json')
		json_string = f.read()
		parsed_json = json.loads(json_string)
		location = parsed_json['location']['city']
		temp_f = parsed_json['current_observation']['temp_f']
		feelslike_f = parsed_json['current_observation']['feelslike_f']
		wind_mph = parsed_json['current_observation']['wind_mph']
		wind_dir = parsed_json['current_observation']['wind_dir']
		f.close()
		print ("Current temperature in %s is: %s F" % (location, temp_f))
		print ("Feels like: %s degrees F" % (feelslike_f))
		print ("Current wind speed in %s is: %s MPH" % (location, wind_mph))
		print ("Current wind direction is: %s\n\n" % (wind_dir))

		for x in range(0, 5):
			lcd.clear()
			lcd.home()
			lcd.message("Temp: " + str(temp_f) + " F\nFeels As: " + str(feelslike_f) + " F")
			time.sleep(3)
			lcd.clear()
			lcd.home()
			lcd.message("Wind: " + str(wind_mph) + " MPH\nWind Dir: " + str(wind_dir))
			time.sleep(3)

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

Code Analysis:

Like all our other projects, our Raspberry Pi’s Python script begins by letting the interpreter know the language we are using as well as providing some brief comments that indicate our script’s purpose. We have also chosen to indicate which pins from our LCD screen are attached to our Raspberry Pi’s GPIO.

#!/usr/bin/env python
#
#  weather_LCD.py
#
# A short program using the wunderground.com API and
# Adafruit's 'Adafruit_CharLCD' library to monitor
# current weather conditions in a city and to then
# update a 16x2 LCD display in 4 bit mode
#
# Get an API key for Weather Underground at:
# http://wunderground.com/weather/api
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
#  Copyright 2015  Ken Powers
#

Next, we import the necessary libraries and modules, define our constants, instantiate an LCD using the Adafruit function library, and define a constant called myapi for our Weather Underground API key. The API key will be unique for you and your purposes which is why we can’t show the one we used in our code.

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import urllib2
import json
import time
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

lcd = Adafruit_CharLCD()
RUNNING = True

# Set your access keys as configured
myapi = "YOUR_API_KEY_FROM_WEATHER_UNDERGROUND"

Our main loop builds a URL using our unique API key. Notice that our URL in the code ends with a /WA/Tacoma.json. The WA is for the state of Washington in the United States of America and Tacoma is the town in which we reside.

It will be necessary for you to modify the location portion of the URL in order to get information that is correct for your locale. The location can be inside or outside the USA and more information can be found on the Weather Underground API Geolookup page.

Our script then parses the returned information from Weather Underground so we have a location, temperature in Fahrenheit, a windchill temperature, wind speed, and wind direction.

Next, we print this information to our main screen so we can make sure everything is being retrieved correctly.

Finally, we clear the screen of our 16×2 LCD, home the cursor, and display the temperature and windchill. After a 3 second delay, we clear the screen and display the wind speed and direction.

The main Python loop continues until Ctrl + C is depressed.

try:
	while RUNNING:
		# Use JSON to obtain weather information using
		# Wunderground.com API call.

		f = urllib2.urlopen('http://api.wunderground.com/api/' + myapi + '/geolookup/conditions/q/WA/Tacoma.json')
		json_string = f.read()
		parsed_json = json.loads(json_string)
		location = parsed_json['location']['city']
		temp_f = parsed_json['current_observation']['temp_f']
		feelslike_f = parsed_json['current_observation']['feelslike_f']
		wind_mph = parsed_json['current_observation']['wind_mph']
		wind_dir = parsed_json['current_observation']['wind_dir']
		f.close()
		print ("Current temperature in %s is: %s F" % (location, temp_f))
		print ("Feels like: %s degrees F" % (feelslike_f))
		print ("Current wind speed in %s is: %s MPH" % (location, wind_mph))
		print ("Current wind direction is: %s\n\n" % (wind_dir))

		for x in range(0, 5):
			lcd.clear()
			lcd.home()
			lcd.message("Temp: " + str(temp_f) + " F\nFeels As: " + str(feelslike_f) + " F")
			time.sleep(3)
			lcd.clear()
			lcd.home()
			lcd.message("Wind: " + str(wind_mph) + " MPH\nWind Dir: " + str(wind_dir))
			time.sleep(3)

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

This simple Raspberry Pi demonstration of the 16×2 LCD screen really shows how the Raspberry Pi and a simple display can be very versatile for use in more complex future projects. Feel free to modify the code above to extract different information from Weather Underground. Above all, however, have fun!

Project 9a: 16×2 LCD Stock Ticker

What you will need:

  • Raspberry Pi
  • Breadboard
  • 16 x 2 LCD Screen
  • 10kΩ Potentiometer
  • 8 Female to Male Jumper Wires
  • 7 Male to Male Jumper Wires

Instructions:

Once my son and I were able to get our 16 x 2 LCD Screen operating with the Raspberry Pi, we decided to create some simple projects that utilize it. Our first variation, uses the identical breadboard layout from Project 9 and creates a simple stock ticker by using the Yahoo! Finance API.

This project builds upon Project 9 and requires the Adafruit Raspberry Pi Python Code Library. Be sure to follow the instructions in our Previous Project outlining the installation procedures before you continue.

Once you have your breadboard populated and the Adafruit Library cloned, enter the Python script below using your favorite editor:

#!/usr/bin/env python
#
#  stock_ticker_LCD.py
#
# A short program using the Yahoo Finance API and
# Adafruit's 'Adafruit_CharLCD' library to monitor
# stock values and to
# update a 16x2 LCD display in 4 bit mode
#
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
#  Copyright 2015  Ken Powers
# 

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import urllib2
import json
import time
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

lcd = Adafruit_CharLCD()
RUNNING = True

# Create a list of stocks to check
stocks = ("^IXIC","YHOO","AAPL","WPZ","ETE","OKE","MWE")

try:
	while RUNNING:
		# Use JSON to obtain stock information
		# using an API call to Yahoo Finance

		for i in range(len(stocks)):
			f = urllib2.urlopen('http://download.finance.yahoo.com/d/quotes.csv?s=' + stocks[i] + '&f=sghn')
			json_string = f.read()

			# Create a list from the returned information by splitting at the comma character
			stockquotes = json_string.split(",")

			# Strip the quotes from the stock name in the first item
			stockquotes[0] = stockquotes[0].strip('"')
			stockdiff = float(stockquotes[2]) - float(stockquotes[1])

			# Print the stock information to the screen
			print(stockquotes[0])
			print("Low: %s" % stockquotes[1])
			print("High: %s" % stockquotes[2])
			print(stockdiff)
			print("\n")

			# Send information to 16x2 LCD screen Using Adafruit_CharLCD
			lcd.clear()
			lcd.home()
			# Set number of columns and rows of LCD display
			lcd.begin(16,2)
			# Set cursor position and scroll info from right to left
			lcd.setCursor(17,0)
			if stockdiff > 0:
				updown = '   ^'
			else:
				updown = '   v'
			lcd.message(stockquotes[0] + updown + str(abs(stockdiff)))
			lcd.setCursor(17,1)
			ticker = ('L: ' + stockquotes[1] + '  H: ' + stockquotes[2])
			lcd.message(ticker)
			for x in range(0, len(ticker)):
				lcd.DisplayLeft()
				time.sleep(.25) 

			time.sleep(.1)
			f.close()

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

Code Analysis:

As in previous projects, our Raspberry Pi’s Python script begins by letting the interpreter know which language we are using as well as providing some comments that indicate the purpose of our program. We also take some effort to make some LCD screen GPIO pin connection notes for added clarity.

#!/usr/bin/env python
#
#  stock_ticker_LCD.py
#
# A short program using the Yahoo Finance API and
# Adafruit's 'Adafruit_CharLCD' library to monitor
# stock values and to
# update a 16x2 LCD display in 4 bit mode
#
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
#  Copyright 2015  Ken Powers
#

Next, we import the required modules and libraries necessary for our script to operate properly. We also create our constants, instantiate an LCD using the Adafruit library, and create a list of the stock symbols we wish to check with our ticker. Feel free to modify this list to reflect your own stock interests.

# Import the required libraries
from Adafruit_CharLCD import Adafruit_CharLCD
import urllib2
import json
import time
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

lcd = Adafruit_CharLCD()
RUNNING = True

# Create a list of stocks to check
stocks = ("^IXIC","YHOO","AAPL","WPZ","ETE","OKE","MWE")

Our main loop simply builds a URL for each of the stock symbols in our list using the Yahoo! Finance API. It then parses the returned information, removes the quotation marks, and prints the stock information to our main screen.

Next, the loop clears our LCD screen, sets the cursor position, displays the stock information, scrolls the data to the left, and continues until Ctrl + C is pressed.

try:
	while RUNNING:
		# Use JSON to obtain stock information
		# using an API call to Yahoo Finance

		for i in range(len(stocks)):
			f = urllib2.urlopen('http://download.finance.yahoo.com/d/quotes.csv?s=' + stocks[i] + '&f=sghn')
			json_string = f.read()

			# Create a list from the returned information by splitting at the comma character
			stockquotes = json_string.split(",")

			# Strip the quotes from the stock name in the first item
			stockquotes[0] = stockquotes[0].strip('"')
			stockdiff = float(stockquotes[2]) - float(stockquotes[1])

			# Print the stock information to the screen
			print(stockquotes[0])
			print("Low: %s" % stockquotes[1])
			print("High: %s" % stockquotes[2])
			print(stockdiff)
			print("\n")

			# Send information to 16x2 LCD screen Using Adafruit_CharLCD
			lcd.clear()
			lcd.home()
			# Set number of columns and rows of LCD display
			lcd.begin(16,2)
			# Set cursor position and scroll info from right to left
			lcd.setCursor(17,0)
			if stockdiff > 0:
				updown = '   ^'
			else:
				updown = '   v'
			lcd.message(stockquotes[0] + updown + str(abs(stockdiff)))
			lcd.setCursor(17,1)
			ticker = ('L: ' + stockquotes[1] + '  H: ' + stockquotes[2])
			lcd.message(ticker)
			for x in range(0, len(ticker)):
				lcd.DisplayLeft()
				time.sleep(.25) 

			time.sleep(.1)
			f.close()

except KeyboardInterrupt:
	RUNNING = False
	print "\nQuitting"

# Clear LCD screen upon exit
# Don't forget to clean up after so we
# can use the GPIO next time
finally:
	lcd.clear()
	GPIO.cleanup()

This was a fun project because we got to see our LCD screen interact with real data from the Internet and the American stock market. Have fun fiddling with which stock data is being read as well as the way the LCD screen displays the information. Above all, however, have fun!

Project 9: 16×2 LCD Screen Test

What you will need:

  • Raspberry Pi
  • Breadboard
  • 16 x 2 LCD Screen
  • 10kΩ Potentiometer
  • 8 Female to Male Jumper Wires
  • 7 Male to Male Jumper Wires

Instructions:

My son and I recently purchased a 16×2 LCD screen and decided it was time to see if we could make it operate. Although not exact, an identically functioning screen similar to what we purchased can be found through Adafruit Industries.

The LCD screen that we found needed to have header pins soldered to it so we could use it with our breadboard. We simply snapped off 16 pins from a 0.1″ header strip, inserted the strip’s pins through the LCD screen’s board, and soldered the pins to the corresponding pads.

If you have never soldered before, this is a great opportunity to learn. There are many tutorials online that show how simple it is. Just be sure to use a minimal amount of heat from your soldering iron in order to avoid damaging the LCD screen’s board.

Once you have soldered the header pins to the LCD screen and connected it to the breadboard, make the connections shown in the breadboard layout above. This is a good time to note that the 10kΩ Potentiometer in the layout can be bypassed but is a convenient contrast control.

Be very careful when connecting all the breadboard layout’s wires as there are a lot of connections to make. Double check your work to avoid damaging your Raspberry Pi.

I should note at this time that our screen was set up to use 5 volts so we used the Raspberry Pi’s 5 volt GPIO power supply pin for the project. Make sure your LCD screen requires 5 volts before you use this pin. If in doubt, use pin 1 from the Raspberry Pi’s GPIO which only supplies 3.3 volts.

The next step necessary to get the LCD screen to work is to download Adafruit Industries’ Open Source Raspberry Pi Python Code Library. It is a growing collection of libraries and example python scripts for controlling a variety of electronics and there is an excellent selection of functions for the 16 x 2 LCD screen we are using.

The easiest way we found to download the library is to use git to clone the library to our Raspberry Pi. First, make sure you have git installed by entering the following commands from a terminal window or the Raspberry Pi’s command line:

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade
pi@raspberrypi ~ $ sudo apt-get install -y git dialog

My son and I had set up a projects folder on the Raspbian desktop for easy access and that is the location to which we downloaded the Adafruit library. We simply navigated to our directory from the Raspberry Pi command line by typing:

pi@raspberrypi ~ $ cd Desktop/Projects

Next, we cloned the Adafruit Raspberry Pi Python Code Library to our directory by typing:

pi@raspberrypi ~/Desktop/Projects $ git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git

The above command clones the entire library to our directory but for now we are only interested in the Adafruit_CharLCD functions. There is a directory by that name within the library and within that directory is a file named Adafruit_CharLCD.py. We want to copy that file to the same directory where we have the projects on which we have been working.

In our case, we executed a copy command from within our Projects directory which copied the file from the Adafruit directory to our main Projects folder.

pi@raspberrypi ~/Desktop/Projects $ cp Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCD/Adafruit_CharLCD.py .

Once the Adafruit_CharLCD.py file is within your projects directory, use your favorite editor to enter the following Python script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  LCD_screen_test.py
#
# A short Python script to test a 16 x 2 LCD display
# by using the Adafruit Raspberry Pi Python Library
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
#  Copyright 2015  Ken Powers
#  

from Adafruit_CharLCD import Adafruit_CharLCD
import RPi.GPIO as GPIO
import time

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

RUNNING = True
lcd = Adafruit_CharLCD()

lcd.clear()
lcd.message(" Nicholas\n Powers")
print("Press Ctrl + C to Quit")

# Main loop
try:
    while RUNNING:

		# Scroll LCD screen text off to the right
		for x in range (0, 16):
			lcd.scrollDisplayRight()
			time.sleep(.2)

		# Wait 2 seconds
		time.sleep(2)

		# Scroll LCD screen text back into view
		for x in range (0, 16):
			lcd.DisplayLeft()
			time.sleep(.2)

		# Wait 2 seconds
		time.sleep(2)

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

# Actions under 'finally' will always be called
# regardless of what stopped the program
finally:
    # Stop and cleanup so the pins
    # are available to be used again
    GPIO.cleanup()

Code Analysis:

As in previous projects, our Python script begins by letting the interpreter know what language we are using. Next, we have a series of comments designed to clarify the intention of our script and to indicate which pins from the LCD screen are attached to our Raspberry Pi’s GPIO port.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  LCD_screen_test.py
#
# A short Python script to test a 16 x 2 LCD display
# by using the Adafruit Raspberry Pi Python Library
#
# LCD Screen 16x2 Pins
# --------------------
# Pin 1  to GND
# Pin 2  to 5v
# Pin 3  to variable resistor then to GND 'Contrast Adjustment'
# Pin 4  to GPIO 25 for 'Command or Data Mode Switching'
# Pin 5  to GND for 'Read/Write Mode'
# Pin 6  to GPIO 24 for 'Enable Pin'
# Pin 7  to Not Connected
# Pin 8  to Not Connected
# Pin 9  to Not Connected
# Pin 10 to Not Connected
# Pin 11 to GPIO 23 for 'Data 4'
# Pin 12 to GPIO 17 for 'Data 5'
# Pin 13 to GPIO 21 for 'Data 6'
# Pin 14 to GPIO 22 for 'Data 7'
# Pin 15 to 5v for 'Backlight Anode' - Could use variable resistor as a 'Brightness Control'
# Pin 16 to GND for 'LED Backlight Cathode'
#
#  Copyright 2015  Ken Powers
#

Next, we import the modules our Python script will require. We also define a constant that is used to determine if our main loop will execute followed by a command to instantiate an LCD via the Adafruit functions.

from Adafruit_CharLCD import Adafruit_CharLCD
import RPi.GPIO as GPIO
import time

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

RUNNING = True
lcd = Adafruit_CharLCD()

Next, we clear the LCD screen, by using the Adafruit library’s clear() function and display some text on the 16 x 2 LCD screen by using the message() function. In our case, we chose to display my son’s name which helped to keep him interested in the project. The \n in the text is interpreted as a return character which puts my son’s last name on the second line of the LCD screen.

lcd.clear()
lcd.message(" Nicholas\n Powers")
print("Press Ctrl + C to Quit")

Our main loop uses the Adafruit library’s scroll functions to slide our text off the screen to the right and back again until Ctrl + C is pressed. scrollDisplayRight() moves the text to the right and DisplayLeft() moves it left. The functions are inconsistently named so please note that only the first function has the word scroll in front of it.

# Main loop
try:
    while RUNNING:

		# Scroll LCD screen text off to the right
		for x in range (0, 16):
			lcd.scrollDisplayRight()
			time.sleep(.2)

		# Wait 2 seconds
		time.sleep(2)

		# Scroll LCD screen text back into view
		for x in range (0, 16):
			lcd.DisplayLeft()
			time.sleep(.2)

		# Wait 2 seconds
		time.sleep(2)

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

# Actions under 'finally' will always be called
# regardless of what stopped the program
finally:
    # Stop and cleanup so the pins
    # are available to be used again
    GPIO.cleanup()

The Python script above performs a very simple task but was a really fun introduction to the 16 x 2 LCD screen and Adafruit’s library of functions. There are several more functions in the library that we haven’t used yet and we may incorporate them into some of our future projects. For now, however, have fun modifying the Python script above.

Project 8: Temperature Sensing Thermistor

What you will need:

  • Raspberry Pi
  • Breadboard
  • Red LEDs
  • 2 Yellow LEDs
  • 2 Green LEDs
  • 2 Blue LEDs
  • 1 330nf Ceramic Disk Capacitor
  • 2 1kΩ Resistors —[III I]—
  • 1 10kΩ NTC Radial Thermistor
  • 8 220Ω to 330Ω Resistor —[III I]—
  • 11 Female to Male Jumper Wires
  • 1 Male to Male Jumper Wires

Instructions:

This Raspberry Pi project definitely increased the complexity of what my son and I had accomplished to date. It incorporated elements from our Project 4: Sequential LEDs while bringing in many new concepts. The purpose of this project is to attempt to read our room’s ambient temperature by utilizing a thermistor while visually indicating the temperature through illuminated LEDs.

A thermistor is a device which changes its resistance based upon temperature. The thermistor we chose to use for this project was a Vishay 10k NTC Radial variety that we found on Amazon.com. Since we are located in the United States, our entire project uses Fahrenheit for temperatures.

As a side note, be extra careful when populating the breadboard layout above, we discovered a popular thermistor tutorial online that had the capacitor charging and discharging pins reversed on their layout which caused difficulties for us during troubleshooting. Our thermistor circuit is using GPIO pins 23 and 24. We are also using a lot of additional GPIO pins for this Raspberry Pi project so be sure the LEDs are correctly connected to GPIO pins 17, 27, 22, 10, 9, 11, 13, and 26.

After you have finished populating the breadboard, create the following Python script in your favorite editor:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  temp_LED.py
#
# Use a thermistor to read temperatures and illuminate
# a number of LEDs based upon the returned temperature
#
#  Copyright 2015  Ken Powers
#

import time, math
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

# Define our constants
RUNNING = True
led_list = [17,27,22,10,9,11,13,26] # GPIO pins for LEDs
temp_low = 70 # Lowest temperature for LEDs (F)
temp_high = 86 # Highest temperature for LEDs (F)
a_pin = 23
b_pin = 24

# Set up our LED GPIO pins as outputs
for x in range(0,8):
	GPIO.setup(led_list[x], GPIO.OUT)
	GPIO.output(led_list[x], GPIO.LOW)

# Try to keep this value near 1 but adjust it until
# the temperature readings match a known thermometer
adjustment_value = 0.97

# Create a function to take an analog reading of the
# time taken to charge a capacitor after first discharging it
# Perform the procedure 100 times and take an average
# in order to minimize errors and then convert this
# reading to a resistance
def resistance_reading():
	total = 0
	for i in range(1, 100):
		# Discharge the 330nf capacitor
		GPIO.setup(a_pin, GPIO.IN)
		GPIO.setup(b_pin, GPIO.OUT)
		GPIO.output(b_pin, False)
		time.sleep(0.01)
		# Charge the capacitor until our GPIO pin
		# reads HIGH or approximately 1.65 volts
		GPIO.setup(b_pin, GPIO.IN)
		GPIO.setup(a_pin, GPIO.OUT)
		GPIO.output(a_pin, True)
		t1 = time.time()
		while not GPIO.input(b_pin):
			pass
		t2 = time.time()
		# Record the time taken and add to our total for
		# an eventual average calculation
		total = total + (t2 - t1) * 1000000
	# Average our time readings
	reading = total / 100
	# Convert our average time reading to a resistance
	resistance = reading * 6.05 - 939
	return resistance

# Create a function to convert a resistance reading from our
# thermistor to a temperature in Celsius which we convert to
# Fahrenheit and return to our main loop
def temperature_reading(R):
    B = 3977.0 # Thermistor constant from thermistor datasheet
    R0 = 10000.0 # Resistance of the thermistor being used
    t0 = 273.15 # 0 deg C in K
    t25 = t0 + 25.0 # 25 deg C in K
    # Steinhart-Hart equation
    inv_T = 1/t25 + 1/B * math.log(R/R0)
    T = (1/inv_T - t0) * adjustment_value
    return T * 9.0 / 5.0 + 32.0 # Convert C to F

# Main loop
try:
    while RUNNING:
		# Get the thermistor temperature
		t = temperature_reading(resistance_reading())

		# Print temperature values in real time
		print(t)

		# Turn off LEDs
		for x in range(0,8):
			GPIO.output(led_list[x], GPIO.LOW)

		# Calculate how many LEDs to illuminate
		# within our temp_low to temp_high range
		if t <= temp_low:
			t = temp_low
		if t >= temp_high:
			t = temp_high

		num_leds = int(round(((t-temp_low) / (temp_high-temp_low))*8))

		# Turn LEDs on
		for x in range(0,num_leds):
			GPIO.output(led_list[x], GPIO.HIGH)

		# Time interval for taking readings in seconds
		time.sleep(0.1)

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

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

Code Analysis:

Once again, our Python script begins by letting the interpreter know which language we are using in addition to supplying some brief comments that indicate our script’s purpose.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  temp_LED.py
#
# Use a thermistor to read temperatures and illuminate
# a number of LEDs based upon the returned temperature
#
#  Copyright 2015  Ken Powers
#

Next, we import our necessary function libraries.

import time, math
import RPi.GPIO as GPIO

We then define our script’s constants. This includes a list of the pins we are using for our LEDs and two Fahrenheit temperature constants that determine the high and low limits of our LED temperature indicator. In this same code section, we make sure our Raspberry Pi’s LED GPIO pins are set to output mode and are initially turned off.

We also take the opportunity to create an adjustment_value variable that we can tweak in order to make our temperature reading coincide with a known thermometer. You should try to keep this close to a value of 1 but since there is a lot of variance between components, this is a handy addition to our code.

When we originally created this Python script, we just read the ambient temperature and lit a proportionate number of LEDs. However, the result was very boring and didn’t change much.

Therefore, we decided to change our script’s functionality so our ambient temperature lit a single LED and if we held the thermistor between our fingers, the LEDs sequentially lit until they hit about 86 degrees Fahrenheit. This made it a bit more fun with which to interact. Feel free to modify these two temperature values to provide the best effect when holding the thermistor between your fingers to increase its temperature reading.

# Define our constants
RUNNING = True
led_list = [17,27,22,10,9,11,13,26] # GPIO pins for LEDs
temp_low = 70 # Lowest temperature for LEDs (F)
temp_high = 86 # Highest temperature for LEDs (F)
a_pin = 23
b_pin = 24

# Set up our LED GPIO pins as outputs
for x in range(0,8):
	GPIO.setup(led_list[x], GPIO.OUT)
	GPIO.output(led_list[x], GPIO.LOW)

# Try to keep this value near 1 but adjust it until
# the temperature readings match a known thermometer
adjustment_value = 0.97

Our next section of the script defines 2 key functions which are based upon the Steinhart-Hart Equation as well as the work of Simon Monk from MonkMakes.com.

The first function, resistance_reading(), completely discharges our 330nf capacitor and then times how long it takes to charge it to the point where our GPIO pin returns a HIGH reading (around 1.65 volts). This process is repeated 100 times in order to reduce errors and the results are averaged. This average is used to calculate the thermistor’s current resistance.

Our second function takes the resistance supplied by our resistance_reading() function and converts it to a Celsius temperature by using the Steinhart-Hart Equation. Next, we convert this temperature to Fahrenheit and return the value to our Python script’s main loop.

It is important to note that the value of variable B in the second function was obtained from our thermistor’s Datasheet. Variable R0 also needs to indicate the resistance value of the thermistor being used.

#!/usr/bin/env python
# Create a function to take an analog reading of the
# time taken to charge a capacitor after first discharging it
# Perform the procedure 100 times and take an average
# in order to minimize errors and then convert this
# reading to a resistance
def resistance_reading():
	total = 0
	for i in range(1, 100):
		# Discharge the 330nf capacitor
		GPIO.setup(a_pin, GPIO.IN)
		GPIO.setup(b_pin, GPIO.OUT)
		GPIO.output(b_pin, False)
		time.sleep(0.01)
		# Charge the capacitor until our GPIO pin
		# reads HIGH or approximately 1.65 volts
		GPIO.setup(b_pin, GPIO.IN)
		GPIO.setup(a_pin, GPIO.OUT)
		GPIO.output(a_pin, True)
		t1 = time.time()
		while not GPIO.input(b_pin):
			pass
		t2 = time.time()
		# Record the time taken and add to our total for
		# an eventual average calculation
		total = total + (t2 - t1) * 1000000
	# Average our time readings
	reading = total / 100
	# Convert our average time reading to a resistance
	resistance = reading * 6.05 - 939
	return resistance

# Create a function to convert a resistance reading from our
# thermistor to a temperature in Celsius which we convert to
# Fahrenheit and return to our main loop
def temperature_reading(R):
    B = 3977.0 # Thermistor constant from thermistor datasheet
    R0 = 10000.0 # Resistance of the thermistor being used
    t0 = 273.15 # 0 deg C in K
    t25 = t0 + 25.0 # 25 deg C in K
    # Steinhart-Hart equation
    inv_T = 1/t25 + 1/B * math.log(R/R0)
    T = (1/inv_T - t0) * adjustment_value
    return T * 9.0 / 5.0 + 32.0 # Convert C to F

Our Python script’s main loop begins by using our functions to get the current temperature. We print this temperature to the screen so we can keep track of things. Next, we use a simple loop to turn all our LED GPIO pins to LOW which is an off state.

Next, we make sure our current temperature falls within the range we defined by our constants temp_low and temp_high. We use a simple equation to determine how many LEDs to illuminate with respect to our current temperature.

Next, we create a simple loop to set each LED’s GPIO pin to a HIGH state which is on for .1 seconds and then the entire process repeats until Ctrl + C is pressed.

# Main loop
try:
    while RUNNING:
		# Get the thermistor temperature
		t = temperature_reading(resistance_reading())

		# Print temperature values in real time
		print(t)

		# Turn off LEDs
		for x in range(0,8):
			GPIO.output(led_list[x], GPIO.LOW)

		# Calculate how many LEDs to illuminate
		# within our temp_low to temp_high range
		if t <= temp_low:
			t = temp_low
		if t >= temp_high:
			t = temp_high

		num_leds = int(round(((t-temp_low) / (temp_high-temp_low))*8))

		# Turn LEDs on
		for x in range(0,num_leds):
			GPIO.output(led_list[x], GPIO.HIGH)

		# Time interval for taking readings in seconds
		time.sleep(0.1)

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

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

My son and I were extremely pleased we were able to read a temperature from a simple thermistor connected to our Raspberry Pi. It was even more fun to directly correlate the temperature with a number of lit LEDs. We spent quite a bit of time taking turns holding the thermistor and watching the LEDs sequentially light and then sequentially extinguish once we let go.

Have fun experimenting with the above Python script and see what other modifications you can make. Above all, have fun!

Project 7a: Switched LED

What you will need:

  • Raspberry Pi
  • Breadboard
  • 1 Push-button Switch
  • 1 Red LED (or whatever color you have handy)
  • 1 1kΩ Resistors —[III I]—
  • 1 220Ω Resistor —[III I]—
  • 1 .1μF Ceramic Disk Capacitors
  • 6 Female to Male Jumper Wires
  • 4 Male to Male Jumper Wires

Instructions:

In Project 7, we discussed multiple ways to implement a push-button switch with Python and the Raspberry Pi microcomputer. The obvious next step is to accomplish something with that information. What better way to connect what we have learned so far than by using the switch to turn on an LED?

My son and I basically combined Project 2 and Project 7 in order to arrive at this particular experiment. As before, once you connect all your components by following the breadboard layout above, use your favorite editor to enter the Python script below:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  switched_LED.py
#
# A short program to test implementing a switch
# connected to GPIO pin 18 which will turn on an LED
# connected to GPIO 23
#
#  Copyright 2015  Ken Powers
# 

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

# Set constants
RUNNING = True
led_button = 18
led = 23

# Select GPIO numbering method and set switch pin
# as an input with internal pull-down resistance
# and LED pin as an output
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_button, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(led, GPIO.OUT)
GPIO.output(led, GPIO.LOW)

# Illuminate an LED connected to GPIO 23
# if the push-button is pressed.

print("Press button to illuminate LED")

try:
	while RUNNING:
		while True:
			input_value = GPIO.input(led_button)
			if input_value == True:
				GPIO.output(led, GPIO.HIGH)
			while input_value == True:
				input_value = GPIO.input(led_button)
				time.sleep(0.01)
			GPIO.output(led, GPIO.LOW)

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

# Actions under 'finally' will always be called, regardless of
# what stopped the program (be it an error or an interrupt)
finally:
    # Stop and cleanup to finish cleanly so the pins
    # are available to be used again
    GPIO.cleanup()

Code Analysis:

Once again, we begin our Python script by letting the interpreter know which language we are using. Next, we make a few comments that let readers know some of the details of our program. Specifically, we want programmers to know that we are connecting a switch to the Raspberry Pi’s GPIO 18 and an LED to GPIO 23. By the way, although we suggest a red LED in our project requirements, you can utilize any color you have handy.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  switched_LED.py
#
# A short program to test implementing a switch
# connected to GPIO pin 18 which will turn on an LED
# connected to GPIO 23
#
#  Copyright 2015  Ken Powers
#

Our next section of code simply imports some necessary modules we will be using and defines some necessary constants.

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

# Set constants
RUNNING = True
led_button = 18
led = 23

We then define our GPIO numbering method, set the appropriate GPIO pins as inputs and outputs, and toggle the internal pull-down resistance for our push-button input. It is very important to make sure the push-button switch pin is set as an INPUT and NOT an OUTPUT as this could potentially damage the Raspberry Pi.

# Select GPIO numbering method and set switch pin
# as an input with internal pull-down resistance
# and LED pin as an output
GPIO.setmode(GPIO.BCM)
GPIO.setup(led_button, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(led, GPIO.OUT)
GPIO.output(led, GPIO.LOW)

Our main Python script loop simply checks the status of the push-button pin. If it is TRUE (or depressed) the LED pin’s status is changed to HIGH (or on). Once the switch is released, the LED is turned off and the script continues until CTRL + C is pressed.

# Illuminate an LED connected to GPIO 23
# if the push-button is pressed.

print("Press button to illuminate LED")

try:
	while RUNNING:
		while True:
			input_value = GPIO.input(led_button)
			if input_value == True:
				GPIO.output(led, GPIO.HIGH)
			while input_value == True:
				input_value = GPIO.input(led_button)
				time.sleep(0.01)
			GPIO.output(led, GPIO.LOW)

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

# Actions under 'finally' will always be called, regardless of
# what stopped the program (be it an error or an interrupt)
finally:
    # Stop and cleanup to finish cleanly so the pins
    # are available to be used again
    GPIO.cleanup()

As you can see, it is very simple to combine the elements from our previous Projects to accomplish the task of turning an LED on and off. An additional fun experiment might be to attempt to modify the Python script to allow the LED to turn on with a single press of the switch and off with an additional press much like a standard light switch. Above all, however, have fun with your projects and what you have learned!

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.

Project 6: RGB LED

What you will need:

  • Raspberry Pi
  • Breadboard
  • 1 RGB LED
  • 3 220Ω Resistors —[III I]—
  • 4 Female to Male Jumper Wires
  • 1 Male to Male Jumper Wire

Instructions:

The previous projects my son and I have done have dealt exclusively with simple LEDs that represent a single color. This project, however, is using an RGB LED which hosts a Red, Green, and a Blue Light Emitting Diode in a single housing. The RGB LED we are using has a common shared cathode () connection and a separate anode (+) connection for each of the three colors. Our LED’s cathode is leg 2 while the Red, Green, and Blue legs are 1, 3, and 4. Check the datasheet for your specific RGB LED in order to correctly connect it within the circuit.

To keep things simple, we are using 3 220Ω resistors to limit current to each anode and to prevent the LED from burning out. Several other RGB LED tutorials online calculate the specific resistance required for each anode in order to equalize each color’s brightness. For our purpose, however, 220Ω to 330Ω resistors will work fine.

Most of the RGB tutorials we found were simply toggling each color LED on or off by setting each GPIO pin’s state from HIGH to LOW. For this project, however, we decided to utilize the Raspberry Pi Python Library’s software-based Pulse Width Modulation (PWM) functions to control individual brightness levels.

As with our previous projects, after you have completed the breadboard layout above, use your favorite editor to create the following Python script:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  RGB_LED.py
#
# A short program to control an RGB LED by utilizing
# the PWM functions within the Python GPIO module
#
#  Copyright 2015  Ken Powers
#   

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

# Set GPIO to Broadcom system and set RGB Pin numbers
RUNNING = True
GPIO.setmode(GPIO.BCM)
red = 17
green = 18
blue = 27

# Set pins to output mode
GPIO.setup(red, GPIO.OUT)
GPIO.setup(green, GPIO.OUT)
GPIO.setup(blue, GPIO.OUT)

Freq = 100 #Hz

# Setup all the LED colors with an initial
# duty cycle of 0 which is off
RED = GPIO.PWM(red, Freq)
RED.start(0)
GREEN = GPIO.PWM(green, Freq)
GREEN.start(0)
BLUE = GPIO.PWM(blue, Freq)
BLUE.start(0)

# Define a simple function to turn on the LED colors
def color(R, G, B, on_time):
	# Color brightness range is 0-100%
	RED.ChangeDutyCycle(R)
	GREEN.ChangeDutyCycle(G)
	BLUE.ChangeDutyCycle(B)
	time.sleep(on_time)

	# Turn all LEDs off after on_time seconds
	RED.ChangeDutyCycle(0)
	GREEN.ChangeDutyCycle(0)
	BLUE.ChangeDutyCycle(0)

print("Light It Up!")
print("Press CTRL + C to quit.\n")
print(" R  G  B\n---------")

# Main loop
try:
    while RUNNING:
		for x in range(0,2):
			for y in range(0,2):
				for z in range(0,2):
					print (x,y,z)
					# Slowly ramp up power percentage of each active color
					for i in range(0,101):
						color((x*i),(y*i),(z*i), .02)

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

# Actions under 'finally' will always be called
# regardless of what stopped the program
finally:
    # Stop and cleanup so the pins
    # are available to be used again
    GPIO.cleanup()

Code Analysis:

Our Python script begins by letting the interpreter know which language we are using and by making a few comments as to the script’s functionality.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  RGB_LED.py
#
# A short program to control an RGB LED by utilizing
# the PWM functions within the Python GPIO module
#
#  Copyright 2015  Ken Powers
#

Next, we import the modules we will be using.

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

We then define our constants. At this point, we are creating a variable that helps us know when to terminate our main loop. Then, we define which GPIO pins we will be using by assigning them to corresponding color-named variables. We also decided to use the GPIO.setmode command to put our GPIO into Broadcom mode so we could use our preferred numbering system.

# Set GPIO to Broadcom system and set RGB Pin numbers
RUNNING = True
GPIO.setmode(GPIO.BCM)
red = 17
green = 18
blue = 27

Next, we set each of our LED’s GPIO pins to output mode. We also define a constant called Freq to 100Hz as this is required by the PWM function we will be using.

# Set pins to output mode
GPIO.setup(red, GPIO.OUT)
GPIO.setup(green, GPIO.OUT)
GPIO.setup(blue, GPIO.OUT)

Freq = 100 #Hz

This section of code defines a simple function that utilizes the GPIO PWM function to turn each Red, Green, or Blue LED on for a specific amount of time and at a brightness level of 0% to 100%. Then, it turns each LED off.

# Define a simple function to turn on the LED colors
def color(R, G, B, on_time):
	# Color brightness range is 0-100%
	RED.ChangeDutyCycle(R)
	GREEN.ChangeDutyCycle(G)
	BLUE.ChangeDutyCycle(B)
	time.sleep(on_time)

	# Turn all LEDs off after on_time seconds
	RED.ChangeDutyCycle(0)
	GREEN.ChangeDutyCycle(0)
	BLUE.ChangeDutyCycle(0)

The next section of code sets everything up to use the GPIO library’s PWM function and gives each LED an initial duty cycle of 0% power which is the equivalent of turning the particular LED off.

# Setup all the LED colors with an initial
# duty cycle of 0 which is off
RED = GPIO.PWM(red, Freq)
RED.start(0)
GREEN = GPIO.PWM(green, Freq)
GREEN.start(0)
BLUE = GPIO.PWM(blue, Freq)
BLUE.start(0)

Usually, I don’t mention much about the simple print statements we have been including in our Python scripts. This time, however, we decided to not only print a statement that indicates the program has begun but we also indicate which LED colors are being lit at any given time by displaying a 1 (on) or a 0 (off) in a table.

Our main program loop simply toggles each LED color on and off in order to supply every combination of Red, Green, and Blue. The for i in range(0,101): loop uses our color function to ramp the chosen LED combinations up from 0% to 100% brightness.

The main loop continues until Ctrl + C is pressed. Then, the GPIO.cleanup() function is called so our GPIO pins will be ready for the next program.

print("Light It Up!")
print("Press CTRL + C to quit.\n")
print(" R  G  B\n---------")

# Main loop
try:
    while RUNNING:
		for x in range(0,2):
			for y in range(0,2):
				for z in range(0,2):
					print (x,y,z)
					# Slowly ramp up power percentage of each active color
					for i in range(0,101):
						color((x*i),(y*i),(z*i), .02)

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

# Actions under 'finally' will always be called
# regardless of what stopped the program
finally:
    # Stop and cleanup so the pins
    # are available to be used again
    GPIO.cleanup()

As can be seen from the above code, the RGB LED could simply have each color turned off or on. Instead, we chose to use the Raspberry Pi’s GPIO PWM function to change the LEDs’ individual brightness levels. An additional fun project might be to modify the Python script to display every combination of Red, Green, and Blue LED at every possible brightness combination for each individual color. Have fun playing around with the code!

Project 5a: Two Traffic Light LEDs

What you will need:

  • Raspberry Pi
  • Breadboard
  • Red LEDs
  • Yellow LEDs
  • Green LEDs
  • 6 220Ω to 330Ω Resistor —[III I]—
  • 7 Female to Male Jumper Wires
  • 6 Male to Male Jumper Wires

Instructions:

Project 5 introduced the use of functions within a Python script. It also very simply simulated a 3 light American traffic light. For this project, my son and I wanted to build upon our simple simulation by adding the lights for the opposite direction within an intersection. While one vehicle is stopped, the other is allowed to proceed and our traffic lights need to reflect this logic.

To begin, we wired 6 LEDs (Red, Yellow, and Green) in a similar manner to our previous projects. We utilized GPIO 18, 23, and 24 for one traffic light and GPIO 17, 27, and 22 for the other. As before, we utilized the Geany IDE within the Raspbian desktop to create the Python script shown below. However, you could use your favorite command line editor if desired.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  traffic_light_two_LED.py
#
# Simulate 2 American traffic lights
#
#  Copyright 2015  Ken Powers
#

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

# Assign constants for the traffic light GPIO pins
red_led = 18
yellow_led = 23
green_led = 24

red_led_two = 17
yellow_led_two = 27
green_led_two = 22

RUNNING = True

# Configure the GPIO to BCM and set the pins to output mode
GPIO.setmode(GPIO.BCM)
GPIO.setup(red_led, GPIO.OUT)
GPIO.setup(yellow_led, GPIO.OUT)
GPIO.setup(green_led, GPIO.OUT)
GPIO.setup(red_led_two, GPIO.OUT)
GPIO.setup(yellow_led_two, GPIO.OUT)
GPIO.setup(green_led_two, GPIO.OUT)

# Define function to control 1st traffic light
def trafficState(red, yellow, green):
	GPIO.output(red_led, red)
	GPIO.output(yellow_led, yellow)
	GPIO.output(green_led, green)

# Define function to control 2nd traffic light
def trafficStateTwo(red, yellow, green):
	GPIO.output(red_led_two, red)
	GPIO.output(yellow_led_two, yellow)
	GPIO.output(green_led_two, green)

print "Two Traffic Lights Simulation. Press CTRL + C to quit"

# Main loop
try:
    while RUNNING:
		# 1st Light Green for 10 seconds 2nd Light Red
		trafficState(0,0,1)
		trafficStateTwo(1,0,0)
		time.sleep(10)
		# 1st Light Yellow for 3 seconds 2nd Light Red
		trafficState(0,1,0)
		trafficStateTwo(1,0,0)
		time.sleep(3)
		# 1st Light Red for 10 seconds 2nd Light Green
		trafficState(1,0,0)
		trafficStateTwo(0,0,1)
		time.sleep(10)
		# 1st Light Red for 3 seconds 2nd Light Yellow
		trafficState(1,0,0)
		trafficStateTwo(0,1,0)
		time.sleep(3)

# 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:

Once again, 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 -*-
#
#  traffic_light_two_LED.py
#
# Simulate 2 American traffic lights
#
#  Copyright 2015  Ken Powers
#

Next, we import some of the external modules we plan to incorporate into our code.

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

We define the constants used for this particular project.

# Assign constants for the traffic light GPIO pins
red_led = 18
yellow_led = 23
green_led = 24

red_led_two = 17
yellow_led_two = 27
green_led_two = 22

RUNNING = True

We then configure the GPIO to use the Broadcom numbering system and set our LED pins to output mode.

# Configure the GPIO to BCM and set the pins to output mode
GPIO.setmode(GPIO.BCM)
GPIO.setup(red_led, GPIO.OUT)
GPIO.setup(yellow_led, GPIO.OUT)
GPIO.setup(green_led, GPIO.OUT)
GPIO.setup(red_led_two, GPIO.OUT)
GPIO.setup(yellow_led_two, GPIO.OUT)
GPIO.setup(green_led_two, GPIO.OUT)

As in the previous project, we create a function to control our traffic light. However, since we are going to have a traffic light for each direction at our intersection, we need two functions instead of one. We are able to call the functions by name from our main program loop and pass either a zero or a one to indicate whether the Red, Yellow, or Green LEDs are to be illuminated.

# Define function to control 1st traffic light
def trafficState(red, yellow, green):
	GPIO.output(red_led, red)
	GPIO.output(yellow_led, yellow)
	GPIO.output(green_led, green)

# Define function to control 2nd traffic light
def trafficStateTwo(red, yellow, green):
	GPIO.output(red_led_two, red)
	GPIO.output(yellow_led_two, yellow)
	GPIO.output(green_led_two, green)

Our main loop is virtually identical to Project 5 except for the fact that it controls the state of LEDs for two separate traffic lights at the intersection by calling the functions trafficState and trafficStateTwo. When one light is Green, the other will be Red. When one light is Yellow, the other is Red. Each Red light will last for 13 seconds. Each Green light will last for 10 seconds. Each Yellow light will last for 3 seconds.

# Main loop
try:
    while RUNNING:
		# 1st Light Green for 10 seconds 2nd Light Red
		trafficState(0,0,1)
		trafficStateTwo(1,0,0)
		time.sleep(10)
		# 1st Light Yellow for 3 seconds 2nd Light Red
		trafficState(0,1,0)
		trafficStateTwo(1,0,0)
		time.sleep(3)
		# 1st Light Red for 10 seconds 2nd Light Green
		trafficState(1,0,0)
		trafficStateTwo(0,0,1)
		time.sleep(10)
		# 1st Light Red for 3 seconds 2nd Light Yellow
		trafficState(1,0,0)
		trafficStateTwo(0,1,0)
		time.sleep(3)

# 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()

This was a really exciting project for my son because it not only demonstrated physical computing but incorporated the concept into an example that relates to the real-world. If you would like to make the project exciting for yourself, try modifying the Python script to change the delay times for each light state. The modification possibilities for this project are endless. See what you can accomplish. Above all, have fun!