This project uses a Raspberry Pi 2 to collect temperature and humidity data from a DHT22 sensor, which is then uploaded to the ThingSpeak Internet of Things platform to be displayed in real-time.
This write-up is primarily intended to serve as documentation for the project, but may also be of use as a tutorial for others. It assumes a beginner skill level and that you are running the Raspberry Pi without a screen (referred to as a headless setup). It is broken into three main parts, with an optional fourth:
- Part 1: Setting up the Raspberry Pi 2
- Part 2: Configuring the Adafruit DHT22 Sensor
- Part 3: Getting Started with ThingSpeak
- Part 4: Running an Email Notification Script (Optional)
The instructions provided below are for Mac OSX. Instructions for other operating systems can be found in the official documentation for the Raspberry Pi (RPi): https://www.raspberrypi.org/documentation/
Step 1. Download Operating System Image
Download the latest Raspbian "lite" image from: https://www.raspberrypi.org/downloads/raspbian/
After downloading the .zip file, unzip it to get the image file (.img) that will be written to the micro SD card.
Step 2. Write Image to SD Card
In order to locate the disk identifier of your SD card (e.g. disk4), open a terminal and run:
diskutil list
Using this disk identifier, unmount the SD card to prepare for copying data to it:
diskutil unmountDisk /dev/disk<disk# from diskutil>
Copy the data to your SD card:
sudo dd bs=1m if=image.img of=/dev/rdisk<disk# from diskutil>
Where image.img is the filename of the latest Raspian image, e.g.:
sudo dd bs=1m if=2016-09-23-raspbian-jessie-lite.img of=/dev/rdisk<disk# from diskutil>
Insert the SD card to the Raspberry Pi, and provide power using either a micro USB cable or DC adapter.
Update September, 2017:
A much simpler method of writing the image to an SD card is to use the program Etcher. It can be downloaded from: https://etcher.io/
Once the program is opened, all you need to do is select the image, confirm the SD card drive, and hit Flash! Voila! You're all done.
Step 3: Enabling SSH
The most recent Raspbian releases (Dec 2016 onwards) have SSH disabled by default. To enable SSH, you must create a new file called "ssh" on the SD card. It is important to make sure your file doesn't have an extension like .txt, etc.
In macOS you can easily create this file by opening up a Terminal window and typing:
touch ssh
Next, drag and drop this extensionless file into the root directory of your SD card and you're done! When the Raspberry Pi boots up, it will detect the SSH file and enable access.
Step 4: Configure the Raspberry Pi
On a headless setup, the command line of the Raspberry Pi can be accessed remotely from another computer or device on the same network using SSH (Secure Shell).
In this case, the RPi is connected to the local network via ethernet, and Internet Sharing is enabled. Instructions on how to enable Internet Sharing are listed below:
- Open Sharing preferences (choose Apple menu > System Preferences, then click Sharing).
- Select the Internet Sharing checkbox.
- Click the “Share your connection from” pop-up menu, then choose Wi-Fi as the Internet connection you want to share.
- Select how you want to share your Internet connection to the Raspberry Pi in the “To computers using” list. In this case, the Internet connection will be shared over Ethernet.
Once connected via ethernet, the RPi will typically bind to an IP address in the 192.168.2.* range. You can find its IP by using Nmap to scan the local network. An active IP address with an open port 22 (SSH connects via this port) is your likely target.
nmap 192.168.2.*
- Note: If required, install Nmap using Homebrew:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install nmap
Once the local IP address of the RPi has been found, open terminal and establish an SSH connection using the default username/password combination of "pi" and "raspberry":
ssh pi@192.168.2.#
- Note: If you encounter the warning: "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!", you simply need to clear out the known_hosts file. Run the following code and remove the line of code pertaining to the IP address associated with the RPi.
sudo nano /Users/<username>/.ssh/known_hosts
Step 5: Update the Raspberry Pi
Upon first login to SSH, it is suggested to update/upgrade the Raspberry Pi using the following commands:
sudo apt-get update
sudo apt-get dist-upgrade
df -h #to check space
sudo apt-get clean #to removed archived .deb files
If you would like to change default password for pi user, you can access the Raspberry Pi Software Configuration Tool by running the command below and selecting option 2:
sudo raspi-config
Step 6: Setting up Wifi
Official guide: https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md
If you intend to have the RPi connect to the Internet using a wireless USB dongle, you must enter the details of your wifi connection in the wpa_supplicant.conf file.
To do so, run:
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
Then enter the details in the following format:
network={
ssid="ESSID"
psk="Your_wifi_password"
}
If you' like your Raspberry Pi to roam and connect to open networks, append the following to your wpa_supplicant.conf:
network={
key_mgmt=NONE
priority=-999
}
Finally, reboot your Raspberry Pi and discover its new IP address using Nmap, or by logging into your router and searching for the IP address associated with the "raspberrypi" hostname. Over a Wi-Fi connection, the RPI will usually bind to an address within the 192.168.1.* range.
sudo reboot
ssh pi@192.168.1.*
Part 2: Configuring the Adafruit DHT22 SensorThe DHT22 is a basic, low-cost digital temperature and humidity sensor, which uses a capacitive humidity sensor and a thermistor to measure the surrounding air and output a digital signal on the data pin.
Step 1: Wiring Diagram
As shown in the diagram below, the DHT22 requires Pin 1 to be connected to a 3.3V source, Pin 2 to the desired General-purpose input/output (GPIO) pin on the RPi, and Pin 4 to ground (GND). A 10kΩ resistor is placed between Pin 1 and Pin 2. Pin 3 in not used.
By examining the GPIO header in the figure below, we are able to determine that the corresponding connections on the Raspberry Pi are as follows:
- Pin 1: 3.3 V
- Pin 6: GND
- Pin 16: GPIO 23 (other GPIO pins can be selected)
With the correct pins identified, the circuit can be physically built and may end up looking similar to the diagram below:
Step 2: Download the Adafruit DHT Library
With the wiring complete, the next step is to download Adafruit’s DHT library to the RPi, which is required to read the temperature values from the sensor. This also requires that we first download some Python and git packages:
sudo apt-get install python-dev
sudo apt-get install python-pip
sudo apt-get install git
git clone https://github.com/adafruit/Adafruit_Python_DHT.git
cd Adafruit_Python_DHT
sudo python setup.py install
Once the DHT library is installed, the next step is to write the script to gather the data from the sensors and upload it to the Internet. To accomplish this, we will utilize the ThingSpeak Internet of Things platform.
Part 3: Getting Started with ThingSpeakOfficial guide: https://www.mathworks.com/help/thingspeak/getting-started-with-thingspeak.html
ThingSpeak is an Internet of Things (IoT) platform enabling the collection, storage, analysis, and visualization of data gathered from sensors such as the Arduino and Raspberry Pi.
ThingSpeak stores data in Channels, each of which can have up to 8 data fields, as well as location and status fields. Data can be sent to ThingSpeak at a rate of at every 15 seconds or longer.
ThingSpeak Configuration
Step 1. Sign up for new User Account
Step 2. Create a new Channel
- Select "Channels", "My Channels", and then "New Channel".
Step 3: Enter Channel Information
- Name: Raspberry Pi + DHT22 Temperature & Humidity Sensor
- Description: DHT22 temperature & humidity sensor driven by a Raspberry Pi 2 running a Python script.
- Field 1: Humidity (%)
- Field 2: Temperature (°C)
Step 4: Record Write API Key
- Once the Channel is created, click on "API Keys" and note down the "Write API Key". We will use this value later in our script.
Step 5: Script Creation
Create a folder in the /home/pi directory on the Raspberry Pi, then an empty Python script file by running:
mkdir ThingSpeak
cd ThingSpeak
sudo nano dht22.py
Next, copy the code listed below (or from the attached dht22.py at the end of this tutorial). Enter your API code to the "myAPI" variable. Press Ctrl+X to exit the editor, and select "Y" to save the file when prompted.
"""
dht22.py
Temperature/Humidity monitor using Raspberry Pi and DHT22.
Data is displayed at thingspeak.com
Original author: Mahesh Venkitachalam at electronut.in
Modified by Adam Garbo on December 1, 2016
"""
import sys
import RPi.GPIO as GPIO
from time import sleep
import Adafruit_DHT
import urllib2
myAPI = "<your API code here>"
def getSensorData():
RH, T = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 23)
return (str(RH), str(T))
def main():
print 'starting...'
baseURL = 'https://api.thingspeak.com/update?api_key=%s' % myAPI
while True:
try:
RH, T = getSensorData()
f = urllib2.urlopen(baseURL +
"&field1=%s&field2=%s" % (RH, T))
print f.read()
f.close()
sleep(300) #uploads DHT22 sensor values every 5 minutes
except:
print 'exiting.'
break
# call main
if __name__ == '__main__':
main()
Next, to test whether the script runs properly, you can use the following code:
sudo python dht22.py
If successful, you should see two lines as shown below:
pi@raspberrypi:~/ThingSpeak $ python dht22.py
starting...
5
In this case, the number "5" represents the entry made in the ThingSpeak channel. This will increment each time the script uploads data.
Step 6: Running the Script at Startup
If you plan on having your Raspberry Pi run automatically, a good idea is to have it start when the RPi is powered on. One method of doing so is to add a cron job. The command below will start the script and make the status outputs be directed to “null” (i.e. ignored), which ensures it runs in the background. It will also check every 5 minutes to see if the script is running, and restart it if necessary.
crontab -e
*/5 * * * * pgrep -f dht22.py || nohup python /home/pi/ThingSpeak/dht22.py > test.out
Another method of ensuring that the script is always running is to take the command from above, enter it into its own script add a cron job that will periodically check and restart the script if necessary. This can be accomplished by adding the following cronjob task and using the check_script.sh file attached to this project:
crontab -e
*/5 * * * * sh /home/pi/ThingSpeak/script_check.sh &>/dev/null
More discussion on restarting a script can be found here: http://unix.stackexchange.com/questions/107939/how-to-restart-the-python-script-automatically-if-it-is-killed-or-dies
- Note: If you are using Sublime Text to edit your code, make sure to not re-indent using tabs, as it may break Python's structure and render the script inoperable.
Step 7: Verify ThingSpeak Channel Data Uploads
If your script is working as intended, you should be able to see data uploading in real time. You can increase the frequency at which the script uploads data to verify it is working properly, rather than waiting the default 5 minutes.
ThingSpeak has a number of customizable features for the way the data is displayed, which you can read more about here:
https://www.mathworks.com/help/thingspeak/create-a-chart.html
A problematic aspect of running a headless Raspberry Pi setup is the lack of information regarding its current IP address, which may change if an Internet or power outages occurs. A helpful solution is to have the Raspberry Pi send out a notification email each time it reboots, or when the wireless adapter is assigned a new IP address.
To add this functionality to your RPi, we will utilize a mail utility program and a Gmail email address to notify the user of any changes to the IP address.
Step 1: Required Packages Installation
The first step is to update your package list and install the mailutils and ssmtp packages:
sudo apt-get update
sudo apt-get install mailutils ssmtp
Step 2: Edit Configuration Files
Next, to add the information specific to the Gmail account in the sstmp.conf file, run:
sudo nano /etc/ssmtp/ssmtp.conf
We are interested in changing/adding the information for the following four lines of code:
mailhub=smtp.gmail.com:587
AuthUser=<emailaddress>@gmail.com
AuthPass=<password>
UseSTARTTLS=YES
Warning: Your password is not protected when entered into the ssmtp.conf file.
It is highly suggested to create an email address specifically for this purpose, where security vulnerability is not a concern.
Note: It is also necessary to allow less secure apps to access your Gmail account. This can be accomplished using the following guide:
https://support.google.com/accounts/answer/6010255?hl=en
Save your changes when exiting, then open the revaliases file by running:
sudo nano /etc/ssmtp/revaliases
Add the last line of code shown below with your email address.
# sSMTP aliases
#
# Format: local_account:outgoing_address:mailhub
#
# Example: root:your_login@your.domain:mailhub.your.domain[:port]
# where [:port] is an optional port number that defaults to 25.
root:<email address>@gmail.com:smtp.gmail.com:587
Step 3: IP Address Checking Scripts
We will create two different IP checking scripts. One will be intended to run every 15 minutes to verify the IP address of the RPi hasn't changes, and one will be run only when the RPi reboots. Please note: Scripts are currently only meant to monitor changes to wlan0.
First, create a folder in the /home/pi directory to house your scripts:
mkdir ipcheck
Enter the folder, create the two script files and make them both executable:
sudo nano ipcheck.sh
sudo nano ipcheck2.sh
sudo chmod +x ipcheck.sh
sudo chmod +x ipcheck2.sh
Finally, copy the code to each script from the section below (or the scripts attached to this tutorial), while remembering to specify the email address you would like the notifications sent to.
Code for: ipcheck.sh
#! /bin/sh
sleep 20
SUBJ="Warning: Raspberry Pi - new IP Address"
SUBJ2="Warning: Raspberry Pi was restarted"
EMAIL="<email>@gmail.com"
ip1=""
ip2=""
read ip1 < /home/pi/ipcheck/ip.txt
ip2=$(/sbin/ip -o -4 addr list wlan0 | awk '{print $4}' | cut -d/ -f1)
if [ "$ip1" = "$ip2" ]
then
echo "Your Raspberry was restarted, the IP Address is the same as before: $ip2"| mail -s "$SUBJ2" $EMAIL;
else
echo "$ip2" > /home/pi/ipcheck/ip.txt;
echo "New IP Address was assigned to your Raspberry Pi: $ip2" | mail -s "$SUBJ" $EMAIL;
exit;
fi
Code for ipcheck2.sh
#! /bin/sh
SUBJ="Warning: Raspberry Pi - new IP Address"
EMAIL="<email>@gmail.com"
ip1=""
ip2=""
read ip1 < /home/pi/ipcheck/ip.txt
ip2=$(/sbin/ip -o -4 addr list wlan0 | awk '{print $4}' | cut -d/ -f1)
if [ "$ip1" = "$ip2" ]
then
exit
else
echo "$ip2" > /home/pi/ipcheck/ip.txt;
echo "New IP Address was assigned to your Raspberry Pi: $ip2" | mail -s "$SUBJ" $EMAIL;
exit
fi
Step 4: Add Scripts to Cronjob
The following cronjob entries will ensure the script will email a change in IP address upon reboot, and at 15 minute intervals
Run:
crontab -e
Add:
@reboot /home/pi/ipcheck.sh
0,15,30,45 * * * * sh /home/pi/ipcheck2.sh &>/dev/null
ConclusionIf everything has gone according to plan, you should be now have your Raspberry Pi uploading data to the ThingSpeak website!
This project was my first foray into the world of IoT devices, which, once everything eventually started working, I found to be quite rewarding. There were many bumps along the way, but it's only made me more keen to create bigger and more complicated IoT devices. If you've made it all the way through this project, I hope that this documentation has proven useful in some shape, way or form.
Cheers
CreditsThis project drew from a large number tutorials and forum posts, which I'd like to acknowledge and include for reference below:
Comments