Description
This guide demonstrates basic use of Raspberry Pi GPIO. Our inputs will be a simple push button and temperature data read from an I2C DS3231 device (RTC). Our outputs will be LEDs and an Amazon Web Services - Simple Notification Services (SNS) endpoint.
Parts List
- Raspberry Pi 2
- MicroSD card
- DS3231M RTC Module
- Pushbutton
- LEDs
Overview
This guide assumes you have an installed and functioning Raspberry Pi with an installed RTC. If not please see the RPi Initial Setup Guide and RTC DS3231 on the Raspberry Pi. It also assumes you are using SNS for notifications. If you do not have SNS, that portion may be easily skipped. Programs will be written in Python.
The steps to follow are:
- Using GPIO for input and output
- Using a GPIO interrupt
- LEDs
- Amazon Web Services - Simple Notification Services
- Connect with VNC
- Personalize your desktop
- Conclusion
Using GPIO for input and output
WARNING: The pi must be powered down whenever you are connecting or disconnecting pins.
Python's RPi.GPIO library supports using the GPIO pins on the pi. This library is installed by default on recent versions of Raspbian. It is a good idea to review the documentation for this library.
The layout of the pins is shown below. Note that there are two numbering schemes and for programming you MUST choose either BOARD or BCM.
To use a channel (pin), you must set it up. Output channels have fewer options than input channels.
Basic channel setup
In the python example below, channel should be replaced by the appropriate pin number.
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
# or
# GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Output with an optional initial GPIO.HIGH
GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
# Multiple channels with 1 call (Use your own pin numbers)
channel_list = [31,32,33]
GPIO.setup(channel_list, GPIO.OUT)
# Inputs with pull-up resistors
GPIO.setup(channel_list, GPIO.IN, pull_up_down=GPIO.PUD_UP
Pull-up or pull-down resistors are needed to prevent the input from floating. Instead of using a physical resistor, this may by set as port of the GPIO.
Using a GPIO interrupt
Interrupts are used to detect and act upon events. For example, you may wish to run a loop until a button is pressed. If the loop runs for 5 seconds, checking for the button press in the loop, called polling, would probably miss the button press. Instead, use event detection to capture the button press and check that status in the loop. Here is an example:
import RPi.GPIO as GPIO
import smbus
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(channel, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.add_event_detect(channel, GPIO.RISING, bouncetime=200)
while not GPIO.event_detected(BUTTON):
Celsius = getTemp(address)
Fahrenheit = 9.0/5.0 * Celsius + 32
print Fahrenheit, "*F /", Celsius, "*C"
time.sleep(10)
LEDs
Turning a light on with a circuit is a simple and effective way to check functioning and often leads directly to a product. LEDs have an anode and a cathode, meaning that current can only flow in one direction. LEDs also have very little resistance, meaning that they should be placed in series with a resistor in most circuits. LEDs have different specifications but a good resistor to place in series is 330 ohms.
On LEDs the longer lead is the anode and should be connected to the positive side of the circuit. If you don't recall and an easy way to check the functioning and color of an LED is to use a 3 volt button battery.
- View thisSparkfun LED Tutorial
Amazon Web Services - Simple Notification Services
Amazon SNS is a fast, flexible, fully managed publication-subscription messaging service. Use it as a cloud-based mobile app notification service to send push notifications, email, and SMS messages; or as an enterprise-messaging infrastructure.
This guide will not go into the details of SNS but assume that you have a functioning subscribed endpoint. Instead this guide will use boto3 to publish a message. The purpose of this is to demonstrate the connection of the virtual with the physical with the remote in the next section.
- Install boto3,
sudo pip install boto3
- Enter your credentials into the configuration as shown in the Boto3 Quickstart
- Publish a message as shown:
import boto3
client = boto3.client('sns')
# use your endpoint from Amazon
endpoint = 'arn:aws:sns:us-east-1:234567890:Alarms'
#Send alert via SNS
response = client.publish(
TopicArn=endpoint,
Message='My Alert Message!')
Those who have subscribed with an SMS phone number with receive and SMS text message. There are many other possible notifications that may be received.
Full example
The DS3231M has an operating temperature range of -45 C to 85 C. The RTC stores its temperature data in two registers. The upper 8 bits, representing an integer, are stored in two's complement form in register 11h. The lower 2 bits, representing the fractional portion, are in register 12h.
The RTC converts the temperature (updates the registers) every 64s. The maximum allowed by the chip is once every second. A convert may be forced by setting the CONV bit of the Control register (0Eh) to 1. Once the convert is completed, the CONV is set to 0 and the temperature may be read.
## python
import smbus
import os
import RPi.GPIO as GPIO
import time
import random
import boto3
# Pins
LED_FLASH_LOW = 40
LED_GREEN = 38
LED_YELLOW = 37
LED_RED = 35
LED_FLASH_HIGH = 36
BUTTON = 33
LDR = 31
# Release RTC 3231
os.system('sudo rmmod rtc_ds1307')
# Setup RTC 3231 for temperature reading
bus = smbus.SMBus(1)
address = 0x68
# Force a conversion and wait until it completes
def convTemp(address):
byte_control = bus.read_byte_data(address,0x0E)
if byte_control & 32 == 0:
bus.write_byte_data(address, 0x0E, byte_control|32)
byte_control = bus.read_byte_data(address,0x0E)
while byte_control & 32 != 0:
time.sleep(1)
byte_control = bus.read_byte_data(address,0x0E)
return True
# Get temperature in degrees C
def getTemp(address):
convTemp(address)
byte_tmsb = bus.read_byte_data(address,0x11)
byte_tlsb = bus.read_byte_data(address,0x12)
tinteger = (byte_tmsb & 0x7f) + ((byte_tmsb & 0x80) >> 7) * -2**8
tdecimal = (byte_tmsb >> 7) * 2**(-1) + ((byte_tmsb & 0x40) >> 6) * 2**(-2)
return tinteger + tdecimal
# Setup the AWS SNS client
client = boto3.client('sns')
endpoint = 'arn:aws:sns:us-east-1:234567890:Alarm'
##
#Work with LEDs
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
leds = [LED_FLASH_LOW,LED_GREEN,LED_YELLOW,LED_RED,LED_FLASH_HIGH]
# Temp in Fahrenheit
ALARM_LOW = 70
ALARM_OK = 80
ALARM_CAUTION = 90
ALARM_HIGH = 100
GPIO.setup(leds, GPIO.OUT)
#Use button to stop monitoring temperature
GPIO.setup(BUTTON, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.add_event_detect(BUTTON, GPIO.RISING, bouncetime=200)
counter = 0
alert_low_clear = False
alert_high_clear = False
alert_critical_clear = False
while not GPIO.event_detected(BUTTON) and counter < 100:
Celsius = getTemp(address)
Fahrenheit = 9.0/5.0 * Celsius + 32
print Fahrenheit, "*F /", Celsius, "*C"
temperature = Fahrenheit
if temperature < ALARM_LOW:
GPIO.output(leds, GPIO.LOW)
GPIO.output(LED_FLASH_LOW, GPIO.HIGH)
if alert_low_clear:
#Send notification via AWS SNS
response = client.publish(
TopicArn=endpoint,
Message='Temperature is low!')
alert_low_clear = False
elif temperature < ALARM_OK:
GPIO.output(leds, GPIO.LOW)
GPIO.output(LED_GREEN, GPIO.HIGH)
alert_low_clear = False
alert_high_clear = False
alert_critical_clear = False
elif temperature < ALARM_CAUTION:
GPIO.output(leds, GPIO.LOW)
GPIO.output(LED_YELLOW, GPIO.HIGH)
elif temperature < ALARM_HIGH:
GPIO.output(leds, GPIO.LOW)
GPIO.output(LED_RED, GPIO.HIGH)
if alert_high_clear:
#Send notification via AWS SNS
response = client.publish(
TopicArn=endpoint,
Message='Temperature Alert!')
alert_high_clear = False
else:
GPIO.output(leds, GPIO.LOW)
GPIO.output([LED_RED, LED_FLASH_HIGH], GPIO.HIGH)
if alert_critical_clear:
#Send notification via AWS SNS
response = client.publish(
TopicArn=endpoint,
Message='Temperature Critical! Meltdown Imminent')
alert_critical_clear = False
counter = counter + 1
time.sleep(5)
#Run cleanup routines
print "LEDs off"
GPIO.output(leds, GPIO.LOW)
GPIO.cleanup()
os.system('sudo modprobe rtc_ds1307')
Conclusion
Your pi now as a battery backed, accurate RTC installed and working. This allows quality data-logging and other applications. Additionally, the temperature data from the RTC is available for your use.