From Webshed
Jump to: navigation, search
Line 1: Line 1:
 
= Multiple DS18x20 1-wire sensors on the Raspberry PI<br>  =
 
= Multiple DS18x20 1-wire sensors on the Raspberry PI<br>  =
  
In a previous article I&nbsp;showed how to use a 1-wire tempreature sensor with the Raspberry PI&nbsp;with minimal interface requirements. The nice thing with 1-wire sensors in that multiple devices can share the same bus. You just wire the sensors in parallel - all GND pins tired together, all DQ&nbsp;pins tied together and all VCC&nbsp;pins (if you use them) tired together.<br>  
+
In a [[RaspberryPI DS1820|previous article]] I&nbsp;showed how to use a 1-wire tempreature sensor with the Raspberry PI&nbsp;with minimal interface requirements. The nice thing with 1-wire sensors in that multiple devices can share the same bus. You just wire the sensors in parallel - all GND pins tired together, all DQ&nbsp;pins tied together and all VCC&nbsp;pins (if you use them) tired together.<br>  
  
 
The perl code developed for the previous article can only access a single sensor. To read multiple sensors we need to fist get the device IDs of all sensors on the bus, then read each sensor's data. <br>  
 
The perl code developed for the previous article can only access a single sensor. To read multiple sensors we need to fist get the device IDs of all sensors on the bus, then read each sensor's data. <br>  
Line 151: Line 151:
 
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \
 
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \
  
</pre>
+
</pre>  
 +
;
 +
 
 +
[[Category:Code]][[Category:Experiments]][[Category:HowTo]][[Category:RaspberryPI]][[Category:Projects]][[Category:Electronics]]

Revision as of 17:37, 16 December 2012

Multiple DS18x20 1-wire sensors on the Raspberry PI

In a previous article I showed how to use a 1-wire tempreature sensor with the Raspberry PI with minimal interface requirements. The nice thing with 1-wire sensors in that multiple devices can share the same bus. You just wire the sensors in parallel - all GND pins tired together, all DQ pins tied together and all VCC pins (if you use them) tired together.

The perl code developed for the previous article can only access a single sensor. To read multiple sensors we need to fist get the device IDs of all sensors on the bus, then read each sensor's data.

On the rPI using the w1 kernel drivers, the file "/sys/bus/w1/devices/w1_bus_master1/w1_master_slaves" contains a list of all the device IDs detected on the 1-wire bus. We can read this to get a list of IDs to iterate over, requesting data from each of them.

#!/usr/bin/perl
use warnings;
&check_modules;
&get_device_IDs;


foreach $device (@deviceIDs)
{
    $reading = &read_device($device);
        if ($reading != "9999")
    {
        push(@temp_readings,$reading);
    }
}

#update the database
`/usr/bin/rrdtool update  /home/pi/temperature/multirPItemp.rrd N:$temp_readings[0]:$temp_readings[1]`;

print "Temp 1 = $temp_readings[0]    Temp 2 = $temp_readings[1]\n";



sub check_modules
{
   $mods = `cat /proc/modules`;
if ($mods =~ /w1_gpio/ && $mods =~ /w1_therm/)
{
 print "w1 modules already loaded \n";
}
else 
{
print "loading w1 modules \n";
    `sudo modprobe w1-gpio`;
    `sudo modprobe w1-therm`;
} 
}


sub get_device_IDs
{
# The Hex IDs off all detected 1-wire devices on the bus are stored in the file
# "w1_master_slaves"    

# open file
open(FILE, "/sys/bus/w1/devices/w1_bus_master1/w1_master_slaves") or die("Unable to open file");
 
# read file into an array
 @deviceIDs = <FILE>;
 
 # close file 
 close(FILE);
}

sub read_device
{
    #takes one parameter - a device ID
    #returns the temperature if we have something like valid conditions
    #else we return "9999" for undefined
    
    $readcommand = "cat /sys/bus/w1/devices/".$_[0]."/w1_slave 2>&1";
    $readcommand =~ s/\R//g;
    $sensor_temp = `$readcommand`;

    if ($sensor_temp !~ /No such file or directory/)
    {
        if ($sensor_temp !~ /NO/)
        {
	       $sensor_temp =~ /t=(\d+)/i;
	       $temperature = (($1/1000));
        }
        else
        {
            $ret = "9999";
        }
    }
    else
    {
        $ret = "9999"
    }
}

This perl code writes data to a RRD database with two sensors - it should be pretty straightforward to extend this to any number of sensors.

The RRD database is created with this script

#!/bin/bash
rrdtool create multirPItemp.rrd  --step 300 \
DS:in_temp:GAUGE:600:-30:50 \
DS:out_temp:GAUGE:600:-30:50 \
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

The graphs are generated every five minutes from a cron job with with this script

#!/bin/bash
RRDPATH="/home/pi/temperature/"
RAWCOLOUR="#FF0000"
TRENDCOLOUR="#0000FF"
#hour
rrdtool graph $RRDPATH/mhour.png --start -6h \
DEF:intemp=$RRDPATH/multirPItemp.rrd:in_temp:AVERAGE \
DEF:outtemp=$RRDPATH/multirPItemp.rrd:out_temp:AVERAGE \
CDEF:intrend=intemp,1200,TREND \
CDEF:outtrend=outtemp,1200,TREND \
LINE2:intemp$RAWCOLOUR:"Inside temperature" \
LINE1:intrend$TRENDCOLOUR:"20 min average" \
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \
LINE1:outtrend$TRENDCOLOUR:"20 min average"

#day
rrdtool graph $RRDPATH/mday.png --start -1d \
DEF:intemp=$RRDPATH/multirPItemp.rrd:in_temp:AVERAGE \
DEF:outtemp=$RRDPATH/multirPItemp.rrd:out_temp:AVERAGE \
CDEF:intrend=intemp,1800,TREND \
CDEF:outtrend=outtemp,1800,TREND \
LINE2:intemp$RAWCOLOUR:"Inside temperature" \
LINE1:intrend$TRENDCOLOUR:"1h min average" \
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \
LINE1:outtrend$TRENDCOLOUR:"1h min average"

#week
rrdtool graph $RRDPATH/mweek.png --start -1w \
DEF:intemp=$RRDPATH/multirPItemp.rrd:in_temp:AVERAGE \
DEF:outtemp=$RRDPATH/multirPItemp.rrd:out_temp:AVERAGE \
LINE2:intemp$RAWCOLOUR:"Inside temperature" \
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \



#month
rrdtool graph $RRDPATH/mmonth.png --start -1m \
DEF:intemp=$RRDPATH/multirPItemp.rrd:in_temp:AVERAGE \
DEF:outtemp=$RRDPATH/multirPItemp.rrd:out_temp:AVERAGE \
LINE2:intemp$RAWCOLOUR:"Inside temperature" \
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \

#year
rrdtool graph $RRDPATH/myear.png --start -1y \
DEF:intemp=$RRDPATH/multirPItemp.rrd:in_temp:AVERAGE \
DEF:outtemp=$RRDPATH/multirPItemp.rrd:out_temp:AVERAGE \
LINE2:intemp$RAWCOLOUR:"Inside temperature" \
LINE2:outtemp$RAWCOLOUR:"Outside temperature" \