Raspberry Pi data logger

I have mentioned previously in my blog that I have a couple of Raspberry Pi low cost low powered computer board aimed at getting kids enthused about computers and how they work. Well now I have managed to put one of them to work logging temperatures in my house, below is a description of how I did it.

First you need to gather some hardware together, I found all the bit I need from Sheep Walk Electronics who specialise in one wire bits and pieces. I purchased the following : DS9390R a USB to 1 Wire host adapter, and some DS18S20 temperature sensors. They also do pre-built sensor modules and connecting cables, but I have cable and crimpers to make my own. I also got from ebay some RJ45 couplers, which are straight through RJ45 network lead connectors. You will need some cable most people recommend using CAT5 cable, but you can get away with any cable with at least two cores, twisted pair is the best.

In order to try out the kit I had a quickly knocked up an RJ11 to RJ45 cable as per the pin outs here at the bottom of the page. Then I got some bread board and plugged in the 4 adaptors I had in parallel across the two important wires (1-wire data and 1-wire ground) the cter pin needs to fo to the data wire and the other two can go to ground. Before any of the stuff described above will be of any use you will need to get the Pi working.

I used Debian Squeeze image for no particular reason than it was easily available on the Raspberry Pi website and it is a widely used Linux Distribution. You will need to create an image on an SD card, I used a 4Gb one. Once you have the the Pi booting up OK, you may want to enable ssh so that you can log in remotely to the Pi, using your local PC or laptop. Just run the command below which will ensure that the ssh service runs when the Pi boots.

sudo mv /boot/boot_enable_ssh.rc /boot/boot.rc

You will need to know the IP address and if you are using windows you will need an ssh client, I use Putty which you can down load from http://www.chiark.greenend.org.uk/~sgtatham/putty/

Next you will need to login and install One Wire File System (http://owfs.org/) I was able to install it with the following command.
sudo apt-get install owfs
Once installed do a reboot for good measure, then you I would recommend using the lsusb command to make sure that the host adaptor is working OK. Here is what I see.


pi@raspberrypi ~ $ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 04fa:2490 Dallas Semiconductor DS1490F 2-in-1 Fob, 1-Wire adapter
pi@raspberrypi ~ $

The last line is the important one it shows that the 1-wire host adaptor has been identified by the operating system.

Next you need to edit /etc/owfs.conf

Mine now looks like below, I had to comment out the fake entry and uncomment the USB bit.

######################## SOURCES ########################
# With this setup, any client (but owserver) uses owserver on the
# local machine...
! server: server = localhost:4304
# ...and owserver uses the real hardware, by default fake devices
# This part must be changed on real installation
#server: FAKE = DS18S20,DS2405
# USB device: DS9490
server: usb = all
# Serial port: DS9097
#server: device = /dev/ttyS1
# owserver tcp address
# server: server = 192.168.10.1:3131
# random simulated device
# server: FAKE = DS18S20,DS2405
######################### OWFS ##########################
mountpoint = /mnt/1wire
allow_other
####################### OWHTTPD #########################
http: port = 2121
####################### OWFTPD ##########################
ftp: port = 2120
####################### OWSERVER ########################
server: port = localhost:4304

I had trouble getting owfs to start up correctly, do a clean boot and check for a director structure under /mnt/1wire mine lookos like this, yours should look similar.

pi@raspberrypi ~ $ ls /mnt/1wire/
10.146730020800 10.3C6330020800 81.164D30000000 bus.1 structure
10.146730020800 10.3C6330020800 81.164D30000000 settings system
10.398630020800 10.A47830020800 alarm simultaneous uncached
10.398630020800 10.A47830020800 bus.0 statistics
pi@raspberrypi ~ $

The numbers are the sensor devices and the host adaptor. There is also an httpd service running on port 2121 just point your browser to http://pi_ip_addrsss:2121 you should see a similar structure.

I change the service scripts to be compatible with the Debian LSB init processes. Here is what I ended up with:

#!/bin/sh

### BEGIN INIT INFO
# Provides: owfs
# Required-Start: $remote_fs $syslog $network $named
# Required-Stop: $remote_fs $syslog $network $named
# Should-Start: owserver
# Should-Stop: owserver
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: 1-wire TCP server
# Description: Start and stop a TCP server for 1-wire control.
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
CONFFILE=/etc/owfs.conf
DESC="1-Wire Files system"
NAME="owfs"
DAEMON=/usr/bin/$NAME
PIDDIR=/var/run/owfs
PIDFILE=$PIDDIR/$NAME.pid

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

. /lib/lsb/init-functions

d_start() {
 [ -d $PIDDIR ] || {
 mkdir -m 0775 -p $PIDDIR
 chown root:root $PIDDIR >/dev/null 2>&1
 }
 start-stop-daemon --start --quiet --oknodo --exec $DAEMON -- -c $CONFFILE \
 --pid-file $PIDFILE
 # ensure the daemon has been started
 sleep 1
 pidofproc -p $PIDFILE $DAEMON >/dev/null
}

d_stop() {
 start-stop-daemon --stop --quiet --oknodo --exec $DAEMON
 sleep 1
 if [ -f $PIDFILE ] && ! ps h `cat $PIDFILE` > /dev/null
 then
 # Stale PID file (owserver was successfilly stoped),
 #remove it
 rm -f $PIDFILE
 fi
}

d_status() {
 pidofproc -p $PIDFILE $DAEMON > /dev/null
}

case "$1" in
 start)
 log_daemon_msg "Starting $DESC" "$NAME"
 d_start
 log_end_msg $?
 ;;
 stop)
 log_daemon_msg "Stopping $DESC" "$NAME"
 d_stop
 log_end_msg $?
 ;;
 restart|force-reload)
 log_daemon_msg "Restarting $DESC" "$NAME"
 d_status && d_stop
 d_start
 log_end_msg $?
 ;;
 status)
 d_status
 if [ $? -eq 0 ];then
 log_success_msg "$NAME is running"
 else
 log_failure_msg "$NAME is not running"
 fi
 ;;
 *)
 echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2
 exit 1
 ;;
esac

exit 0

You can now restart the service by issuing the command sudo /etc/init.d/owfs restart I found that it also helpde to unmount the file system first using the following command sudo umount /mnt/1wire

Next you need to create some graphs, I am lazy and did a Google, and stumbled across this great website (http://happyfarming.com/2008/10/16/garden-air-temperature/) that has already done what I have done and more. Here is the code I used.

To make a graph:

#!/bin/bash
rrdtool create garage.rrd --start N --step 300 \
DS:temp:GAUGE:600:U:U \
RRA:AVERAGE:0.5:1:12 \
RRA:AVERAGE:0.5:1:288 \
RRA:AVERAGE:0.5:12:168 \
RRA:AVERAGE:0.5:12:720 \
RRA:AVERAGE:0.5:288:365

To update the graph.

#!/bin/bash

# Read temperature from sensor
tempread=`cat /mnt/1wire/10.A47830020800/temperature`

temp=`echo $tempread | cut -c -4`

# Update database
rrdtool update garage.rrd N:$temp

# Create graphs
rrdtool graph garage_h.png --start -1h DEF:temp=garage.rrd:temp:AVERAGE LINE1:temp#0000FF:"Temperature [deg C]"
rrdtool graph garage_d.png --start -1d DEF:temp=garage.rrd:temp:AVERAGE LINE1:temp#0000FF:"Temperature [deg C]"
rrdtool graph garage_w.png --start -1w DEF:temp=garage.rrd:temp:AVERAGE LINE1:temp#0000FF:"Temperature [deg C]"
rrdtool graph garage_m.png --start -1m DEF:temp=garage.rrd:temp:AVERAGE LINE1:temp#0000FF:"Temperature [deg C]"
rrdtool graph garage_y.png --start -1y DEF:temp=garage.rrd:temp:AVERAGE LINE1:temp#0000FF:"Temperature [deg C]"
#0000FF means blue trace color in the graphs.

To upload the graphs.

#!/bin/bash
sleep 30
lftp -u user,pass ftp.website.com <<EOF
cd /destination_directory/
lcd /home/pi/
put garage_h.png
put garage_d.png
put garage_w.png
put garage_m.png
put garage_y.png
quit 0
EOF

You will need to create cron jobs to the update and upload scripts. I rum them every 5 minutes, you will note the 30 second delay in the upload one, that ensure the update scripts have run.