August 27, 2014

Temperature Sensing with the Pi

I ordered a couple of gadget for my pi a while ago, and they finally came in the mail ( only had to wait 2 months!) Anyways, I ordered a water-proof digital temperature sensor (DS18B20) and a ultrasonic range finder (HC-SR04) to play around with. So firstly I wanted to get the temperature sensor going. I followed the adafruit tutorial, just to hook the temp sensor to the pi (https://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing/hardware) Once it was physically connected, lets check if it works

cd /sys/devices/w1_bus_master1/
 
 ls
28-0000056e9afb w1_master_attempts w1_master_search
driver w1_master_max_slave_count w1_master_slave_count
power w1_master_name w1_master_slaves
subsystem w1_master_pointer w1_master_timeout
uevent w1_master_pullup
w1_master_add w1_master_remove
 

There should be a listing under there that’s a whole bunch of numbers and letters (the devices ID). In my case it’s 28-0000056e9afb. cd into this folder and cat the file called w1_slave You should get output like so:

db 00 4b 46 7f ff 05 10 1a : crc=1a YES
db 00 4b 46 7f ff 05 10 1a t=13687
 

The first like is the checksum, to make sure the device is working correctly, and the second line is the temperature, in degree’s celcius, and to 3 decimal places (13687 = 13.687C) Now we know the temp sensor is working alright, we can make a nice python script to read it and log it. For this project, I used:

  1. plot.ly. All you need to do it create a free account and your good to go!
  2. weather underground You can create a free ‘dev’ account which gives you 500 API calls a day (This is what I use, the way I have set it up, it will only ever call 288 a day)
  3. Bureau of Meteorology. I used this just so I could compare the temperature with wunderground Both temperature gathering sites give out the data is JSON format, so it was easy enough to extract the data needed, and then pass it onto plot.ly.

And here is the python script I used to do this! all you need to do is go through and add your API key for the various sites, and add your location (you may have to play around to find the correct location code for this one) I’ve also set it up to pull my plot.ly key and username out of a file called config.json. I did this because I have multiple scripts using it :)

#!/usr/bin/env python
import os
import glob
import time
import plotly.plotly as py
from plotly.graph_objs import *
import datetime
import json
import urllib2
from time import sleep, localtime, strftime
import sys
with open('./config.json') as config_file:
    plotly_user_config = json.load(config_file)
py.sign_in(plotly_user_config["plotly_username"], plotly_user_config["plotly_api_key"])
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
def read_temp():
    lines = read_temp_raw()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c2 = float(temp_string) / 1000.0
        temp_c = round(temp_c2, 1)
        return temp_c
def read_pi_temp():
    file = open('/sys/class/thermal/thermal_zone0/temp' , 'r')
    lines = file.read()
    temp_c2 = float(lines) / 1000.0
    temp_cpi = round(temp_c2, 1)
    return temp_cpi

def read_temp_bom():
    f_bom = urllib2.urlopen('http://www.bom.gov.au/fwo/IDV60901/IDV60901.94866.json')
    json_string_bom = f_bom.read()
    parsed_json_bom = json.loads(json_string_bom)
    temp_c_bom = parsed_json_bom['observations']['data'][0]['air_temp']
    return temp_c_bom
# Weather Underground key
wu_key = "<APIKEY>"
wu_state = "Victoria"
wu_city = "Melbourne"
wu_retry = 2
def get_WUTemp(key, state, city, retries=2):
        #Get data from weather service
        #If exception occurs, retry a few times then quit
        for retry in range(retries):
                try:
                        f = urllib2.urlopen('http://api.wunderground.com/api/' \
                        + key + '/geolookup/conditions/q/' + state + '/' + \
                         city + '.json')
                        json_string = f.read()
                        #print json_string
                        parsed_json = json.loads(json_string)
                        location = parsed_json['location']['city']
                        temp_c = parsed_json['current_observation']['temp_c']
                except:
                        e = sys.exc_info()[0]
                        print (e)
                        temp_fc= None
                        sleep(0.1)
        if (f != None):
                f.close()
        return temp_c
pitemp = read_pi_temp()
series1 = {
  'name' : 'Pi CPU Temp',
  'x' : datetime.datetime.now(),
  'y' : read_pi_temp(),
  'type' : 'scatter',
  'mode' : 'lines'}
series2 = {
  'name' : 'Room Temp',
  'x' : datetime.datetime.now(),
  'y' : read_temp(),
  'type' : 'scatter',
  'mode' : 'lines'}
series3 = {
  'name' : 'Outdoor Temp (wunderground.com)',
  'x' : datetime.datetime.now(),
  'y' : get_WUTemp(wu_key, wu_state, wu_city),
  'type' : 'scatter',
  'mode' : 'lines'}
series4 = {
  'name' : 'Outdoor Temp (bom.gov.au)',
  'x' : datetime.datetime.now(),
  'y' : read_temp_bom(),
  'type' : 'scatter',
  'mode' : 'lines'}
data = [series1, series3, series2, series4]
url = py.plot(data,filename = 'Rpi Room Temp Multi', fileopt='extend')

 

Have Fun!