Tony Tosi


Raspberry Pi + DS18B20 Temperature Sensor + RRDtool

Published September 20, 2012 ds18b20

I ordered a sample DS18B20 temperature sensor from Maxim that I coupled with my Raspberry Pi and wanted to do something a little more interesting than displaying the temperature from the console. I decided to use RRDtool to graph the temperature reading over time and push the graphs to my linux VPS so they could be easily viewed from a browser. What follows is a rough outline of how I accomplished that and by no means a comprehensive step-by-step guide.

Here's a link to the generated graphs. Note, I use my RPi for other things besides reading temperatures so there's a good chance it will have large gaps in the readings: (the test site has been temporarily taken offline)

Raspberry Pi:
My RPi runs Occidentalis v0.2 which is an excellent distro for people who like to tinker on the hardware side of things. It has a lot of cool modules already compiled into the kernel, including the required modules that make interfacing with the temperature sensor easy.

The hardware side is very straightforward to setup.

  • Connect pin 1 (GND) on the 18B20 to pin 6 (GND) on the RPi.
  • Connect pin 2 (DQ) on the 18B20 to pin 7 (GPIO4) on the RPi.
  • Connect pin 3 (VDD) on the 18B20 to pin 1 (3V3) on the RPi.
  • Finally, put a 4k7 resistor between Pins 2 and 3 on the 18B20.

It's a good idea to test the hardware setup before implementing all of the software modules. Ensuring the hardware is working correctly will narrow down the cause of any issues when you run the scripts presented below. Execute the following commands to set up the the required kernel modules and take your first temperature reading:

sudo modprobe w1-gpio
sudo modprobe w1-therm
cat /sys/bus/w1/devices/28-*/w1_slave

You should see something that resembles the output below:

Expected output from running the cat /sys/bus/w1/devices/28-*/w1_slave

Expected output from running the cat /sys/bus/w1/devices/28-*/w1_slave

To find the sampled temperature, divide the integer after the c= by 1000 (c=27265 in this example) and the result will give you the temperature in Celsius. For Fahrenheit, multiply the Celsius value by 1.8 and add 32. In the test run above, the temperature in my office was 27.6°C or 81.7°F.

If you don't get the desired output, check your hardware setup and try again. Note, you only need to load the kernel modules once.

I implemented the software tier in several modules using a variety of scripting languages (Perl, shell scripting, Python and PHP). The following steps setup the components required for the scripts below:

  • Install libwww-perl (this module is used to grab the outside temperature):
    sudo apt-get install libwww-perl
  • Install paramiko which is a Python SSH module that includes support for SFTP. This is only required if you wish to SFTP your graphs to another server that supports SFTP. If you decide to use a different method to transfer your graphs (like FTP or not transfer them off your RPi at all), you'll need to modify the script and the installation python-paramiko module is unnecessary.
    sudo apt-get install python-paramiko
  • Install rrdtool:
    sudo apt-get install rrdtool The first script sets up (creates) the round robin database. This only needs be run once.

rrdtool create hometemp.rrd --start N --step 300 \
DS:temp:GAUGE:600:U:U \
DS:outtemp: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 This script creates the daily, weekly, monthly, and yearly graph based on the current data in the rrdb. It's executed hourly by the script below. [Update 12/12/2012 now easier to switch between Celsius and Fahrenheit by setting the TEMP_SCALE variable to "C" or "F"]


#set to C if using Celsius

#define the desired colors for the graphs

rrdtool graph $DIR/temp_hourly.png --start -4h \
DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
AREA:temp$INTEMP_COLOR:"Inside Temperature [deg $TEMP_SCALE]" \
DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
LINE1:outtemp$OUTTEMP_COLOR:"Outside Temperature [deg $TEMP_SCALE]"

rrdtool graph $DIR/temp_daily.png --start -1d \
DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
AREA:temp$INTEMP_COLOR:"Inside Temperature [deg $TEMP_SCALE]" \
DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
LINE1:outtemp$OUTTEMP_COLOR:"Outside Temperature [deg $TEMP_SCALE]"

rrdtool graph $DIR/temp_weekly.png --start -1w \
DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
AREA:temp$INTEMP_COLOR:"Inside Temperature [deg $TEMP_SCALE]" \
LINE1:outtemp$OUTTEMP_COLOR:"Outside Temperature [deg $TEMP_SCALE]"

rrdtool graph $DIR/temp_monthly.png --start -1m \
DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
AREA:temp$INTEMP_COLOR:"Inside Temperature [deg $TEMP_SCALE]" \
LINE1:outtemp$OUTTEMP_COLOR:"Outside Temperature [deg $TEMP_SCALE]"

rrdtool graph $DIR/temp_yearly.png --start -1y \
DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
AREA:temp$INTEMP_COLOR:"Inside Temperature [deg $TEMP_SCALE]" \
LINE1:outtemp$OUTTEMP_COLOR:"Outside Temperature [deg $TEMP_SCALE]" This script sets up the GPIO and therm modules (if needed), queries the DS18B20 for the inside temperature, grabs a metar report to get the outside temperature and writes the collected data to the the rrdb. Since the database was created with a 5 minute interval, I run it every 5 minutes via a cron job on my Raspberry Pi.
Note: The script currently uses a metar report from Dane County Regional Airport (located in Madison, Wisconsin, USA) to get the outside temperature. To find a metar station nearest you, use this list of stations and replace the ICAO code KMSN with the ICAO code of the station you would like to use at end of the $metar_url vairable.
[Update 10/11/2012 to include sanity checks in the while statement to avoid an infinite loop]
[Update 12/12/2012 now easier to switch between Celsius and Fahrenheit. To use Celsius, set $is_celsius to 1]

use LWP::UserAgent;

my $dir = '/path/to/your/temperature/scripts';
my $metar_url = '';
my $is_celsius = 0; #set to 1 if using Celsius

my $ua = new LWP::UserAgent;
my $request = new HTTP::Request('GET', $metar_url);
my $response = $ua->request($request);
my $metar= $response->content();

$metar =~ /([\s|M])(\d{2})\//g;
$outtemp = ($1 eq 'M') ? $2 * -1 : $2; #'M' in a METAR report signifies below 0 temps
$outtemp = ($is_celsius) ? $outtemp + 0 : ($outtemp * 9/5) + 32;

$modules = `cat /proc/modules`;
if ($modules =~ /w1_therm/ && $modules =~ /w1_gpio/)
        #modules installed
        $gpio = `sudo modprobe w1-gpio`;
        $therm = `sudo modprobe w1-therm`;

$output = "";
$attempts = 0;
while ($output !~ /YES/g && $attempts < 5)
        $output = `sudo cat /sys/bus/w1/devices/28-*/w1_slave 2>&1`;
        if($output =~ /No such file or directory/)
                print "Could not find DS18B20\n";
        elsif($output !~ /NO/g)
                $output =~ /t=(\d+)/i;
                $temp = ($is_celsius) ? ($1 / 1000) : ($1 / 1000) * 9/5 + 32;
                $rrd = `/usr/bin/rrdtool update $dir/hometemp.rrd N:$temp:$outtemp`;


#print "Inside temp: $temp\n";
#print "Outside temp: $outtemp\n"; This runs and SFTPs the graphs to my web server which is hosted on a VPS. I run this script hourly via a cron job that's executed on the Raspberry Pi.

import paramiko
from commands import getstatusoutput

DIR = '/path/to/your/temperature/scripts'

#generate graphs
getstatusoutput(DIR + '/')

ssh = paramiko.SSHClient()
ssh.connect('your_sftp_server', port=your_sftp_port, username='your_username', password='your_password')

sftp = ssh.open_sftp();
sftp.put(DIR + '/temp_hourly.png', 'rpi_temp/temp_hourly.png')
sftp.put(DIR + '/temp_daily.png', 'rpi_temp/temp_daily.png')
sftp.put(DIR + '/temp_weekly.png', 'rpi_temp/temp_weekly.png')
sftp.put(DIR + '/temp_monthly.png', 'rpi_temp/temp_monthly.png')
sftp.put(DIR + '/temp_yearly.png', 'rpi_temp/temp_yearly.png')

temperature.php: The HTML lives on the web server and simply displays the graphs. The only reason for the PHP is to grab the last modified date of one of the images and display it on the page.

<? $lastmod = date("F d, Y g:i A", filemtime("temp_daily.png")); ?>
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="refresh" content="3600" >
	<title>RPi Temperature</title>
				font-family: arial; 
				font-size: 10pt;
				background-repeat: no-repeat; background-position: center center; 

			H2, H3 { margin-bottom: 0; }
	<div style="width: 800px; margin-left: 100px;" >
		<h2>RPi Temperature Inside & Outside</h2>
		<i>Last Modified: <?=$lastmod?></i>
		<img src="temp_daily.png" />
		<img src="temp_weekly.png" />
		<img src="temp_monthly.png" />
		<img src="temp_yearly.png" />
Comments (99) Trackbacks (8)
  1. Would you be interested in doing an extensive detailed how to on this? I really am wanting to do this for my own home and also for some server rooms at work! Maybe even with multiple sensors. Thanks for the insight.

    • Sure, I'd be happy to write up more detailed how-to guide. I should have something posted by the end of the week.

      • Thank you so much! I have it all kinda working now. I can't get the crontab to run the scripts at the intervals. Then again I can't get the perl script to run on its own. Probably due to the fact of me being a noob to alot of this. But instead of the FTP up to a site I'm copying it to a local web server on the pi and hosting the page straight from it.

  2. I have it all together and kinda running. I just can't get cron to run the scripts. I actually can't get the perl script to run on its own, but that's probably because I'm such a noob at most of this. I modified it a little bit and instead of the FTP to another site I just move the files to the local page I'm hosting on the pi. Thank you for putting this together and sharing it with the world!

    • Hi Joe,
      Glad to hear that you got it (mostly) working! Getting cron to run tasks can sometimes be tricky. I edit my cron jobs using the crontab -e command (crontab -l will list your currently installed cron jobs). The cron job I use to run very 5 minutes looks like this:

      */5 * * * * /path/to/

      For the script I use to FTP the graphs (or, in your case, move the files locally on your RPi) every hour looks like this:

      00 * * * * /path/to/

      Also be sure that you issue these commands: chmod 755 and chmod 755 This will mark them as executable and will allow cron (or you) to run them directly.

      What error, if any, are you getting when you try to execute One thing I didn't mention in the post was that you'll need to install the libwww-perl module with this command: sudo apt-get install libwww-perl. If it still doesn't work after that, let me know what error you're seeing and I'll be more than happy to help.

      Also, I updated the script to include some checking in the "while" loop at the end. Without the additional checks the script could get caught up in an infinite loop and that wouldn't be good! It now will exit gracefully if the DS18B20 isn't found or, if after 5 attempts, the sensor doesn't return a reading that passes the checksum.

  3. I believe I have it working now! The only problem I really was having was permission issues, and as for the perl not wanting to run that was fixed with the libwww-perl module. So now I am going to bed and we will see in the morning what we have! Thank you again!

  4. Hello, thanks for sharing ! very interesting !

    What modifications should I do to get the temperature in celsius ?

    Many thanks !

    • Hi Raphael,

      For celsius, change line 40 in the perl script from:

      $temp = ($1 / 1000) * 9/5 + 32;


      $temp = ($1 / 1000);


      • You'd probably want to update the labels on the results page to be C instead of F. It looks like you're doing this primarily as images, and for yourself, but it might be useful/somewhat good practice to add in a way to switch which units the display is in for the visitor.

        • Good catch, bender. Raphael, you'll want to also modify the script to show that the readings were done in celsius. Just replace all of the [deg F] with [deg C].

          The suggestion to allow users to switch between celsius and fahrenheit is a good one but the images, as you saw, are static. To achieve this, you'd need to generate a second rrd database to hold the celsius results, modify the perl script to output both celsius and fahrenheit (which would probably be best implemented by passing in a cli option so that one script is used for two cron jobs) and then upload the two sets of graphs. Lastly, temperature.html would need to be modified to handle switching between the celsius and fahrenheit images.

  5. I have Last "Modified: January 01, 1970 1:00 AM"

    Why? in other php is $ date = date ("d.m.Y"); ok

    • Hi Jetiman,

      I'm not sure why your date is showing January 01, 1970 but you did catch an error I had in my code. I was using fileatime (which retrieves the last access date) what I really want to see is when the file was last modified (uploaded to the server) which fileatime retrievs. Line two should be:

      $lastmod = date("F d, Y g:i A", filemtime("temp_daily.png"));

      I've updated the code in above to reflect this change.

  6. Ahh for German filemtime, not fileatime

    • Can I get outside for a DS18B20? if so, what should I do

      • Are looking to read the temperature outside from a second DS18B20 sensor? It's possible since the DS18B20 is a I2C device ( which allows communication with multiple devices attached to the same bus. You'd need to make significant modifications to the almost all of the scripts above to achieve this.

        It is almost always as accurate to get the temperature by reading the closest metar report (which is usually the closet airport to your location). The notes above describe how to do this.

        I hope that helps.

      • I've got six DS18B20's running right now collecting data every minute for 5 rooms + outside. The changes to the scripts were fairly minimal. Basically I modified them to use database and sensor id's passed from the command line and deleted the METAR stuff since I'm reading an outside sensor. Also, since I'm running the web server on my Pi, I modified the php file to display the value for the last temperature reading and to only create the graphs when the web page is called.

        Any interest and I could post my files here.


        • Forgot to mention. My house is wired with cat5e in every room. I used that wiring to run the temp sensors in the rooms where the cat5e wasn't being used for ethernet. I built the sensor into an RJ45 plug and then just plug them in and hook the Pi GPIO up to the ethernet cabling.

          • Kyle. Would you be so kind and point me in right direction. I'd like to achieve similar goal. Having at least 5 sensors (DS18B20's), how to connect them together (via bus) and to the Pi.
            Oh, and I like to mention, I'm totaly noob in Pi and electronics btw :(
            Thanks in advance for any answer!

          • mirogster,

            Hey I'm a noob too.

            One of the beautiful things about the DS18B20 is that it has a unique 'serial' number, so you can put as many of them on a single pin as you'd like provided they can all be powered. I'm reading all six of mine off GPIO4 (P1-7) using a butchered cell phone charger (5V) to supply power and jumping the common ground off the pi board (P1-6) to the ground on the cell charger. So I have hundreds of feet of cat5e cable connecting all the the sensors to that one pin and the cell charger using only 3 wires from the 8 in the cable - a waist I know, but the wires were already in the walls when I bought the place. So to be painfully clear, I have all the sensors connected to the cat5e blue wire on Vdd, cat5e white-blue on DQ, and cat5e white-green on GND. Then the blue wire is connected to +5V on the cell charger, white-blue is connected to GPIO4 (P1-7), and white-green is connected to ground on the Pi (P1-6) as well as ground on the cell charger. Then all the ethernet cables from each room and outside are connected in my garage color-for-color.

            I modified the in the following ways (original line first, my mod 2nd):

            $output = `sudo cat /sys/bus/w1/devices/28-*/w1_slave 2>&1`;
            $output = `sudo cat /sys/bus/w1/devices/$ARGV[1]/w1_slave 2>&1`;

            $rrd = `/usr/bin/rrdtool update $dir/hometemp.rrd N:$temp:$outtemp`;
            $rrd = `/usr/bin/rrdtool update $dir/$ARGV[0]_temps.rrd N:$temp`;

            These changes then allow me call the script and pass (as arguments on the command line) the database I want to modify ($ARGV[0]) and the sensor 'serial' that is associated with that database ($ARGV[1]). I have a database for each room and outside. The command looks like this:

   outside 28-00000490a86d

            The script can be modified similarly but since its a shell script and not perl, the first command line argument is $1 and not ARGV[0].

            Hope this helps!


    • Every locale should use filemtime. Using the original code will display the file accessed time which won't produce the desired output.

  7. I have 6 sensors, which sensor it uses?

    • I'm not sure what you mean? Do you want to use your RPi to read from 6 different temperature sensors? If that's so, the details of how to do that is outside the scope of this post, although it's definitely possible!

  8. Hi. Having problem with metar data. For example;
    2012/12/11 18:50
    EFOU 111850Z AUTO 07004KT 030V110 CAVOK M08/M09 Q1026 1239//43
    Causes the outtemp to be null;
    Inside temp: 23.687
    Outside temp:

    • Great catch jukka, thank you. I wrote in the fall and failed to take into consideration below zero temperatures, which, in a METAR report, is signified by an M in front of the temperature reading. I've updated the regular expression to take that into account. 

      Also, I decided to not be an ignorant American and make it easier to switch between Celsius and Fahrenheit. In, add line 5, set TEMP_SCALE to "C" and change [deg F] to [deg $TEMP_SCALE]. In, add line 6, make the modifications/additions to lines 14-16, and make the change to line 41. Finally set $is_celsius equal to 1.

      • Hi Tony. Thanks for your prompt answer. Fried of mine already helped me with this one. I'll test your solution soon also. My script;
        my $request = new HTTP::Request('GET', $metar_url);
        my $response = $ua->request($request);
        my $content = $response->content();

        # look for Mnn/Mnn starting for 2nd row (M optional) and replace M with -
        $content =~ /\n.*\s([M0-9]+)\/([M0-9].+)\s/;
        $outtemp =  $1;
        $outtemp =~ s/M/-/;
        BR, Jukka.

        • That looks like it'll work as well! Don't forget to multiply the $outtemp result by -1 if there's an M in front of the temperature. 

          • I just took a look at your code snippet again and I hadn't noticed that you're replacing the 'M' with a '-', so please disregard my comment above. When I originally looked at it I thought you were replacing the M with an empty string. Happy below zero temperature reading! :-)

  9. This morning according to my script we had 120C outside.. I checked metar;
    2012/12/16 06:50
    EFOU 160650Z AUTO 16014KT 9999 -SN BKN018/// BKN089/// M09/M11 Q1023 120/0086

    So my script did not work. I changed to your script and it worked. Could you explain shortly what '
    $metar =~ /([\s|M])(\d{2})\//g;
    $outtemp = ($1 eq 'M') ? $2 * -1 : $2; #'M' in a METAR report signifies below 0 temps

    Thank you, Jukka.

    • Sure. I'd read the regular expression like this: find some white space, '\s', OR find an 'M' (the '|' means or) and because the '[\s|M]' is surrounded by parentheses remember it for later by putting the match into $1 (this is called back referencing). Next, find some digits, '\d',  that's two numbers '{2}' long and those two numbers must have a  '/' after them (the '/' is a special character so it must be escaped with a backslash which is why it looks like this, '\/'). And, again, because the '\d{2}' is inside parentheses, save that match into $2. The 'g' simply means to search the string globally and find all matches (it probably isn't even necessary for this expression).

      The second line uses a ternary operator (the '?' and the ':') which is a shorthand for an if..then..else statement.  It could be written the same this way:

      if( $1 eq 'M')
          $outtemp = $2 * -1  <-- $2 is the temperature
          $outtemp = $2

      I'd be happy to answer any others questions you have.

  10. hi Tony,

    i want to implement your example. to open the temperature.php and see the actual diagram. but i am a absolut beginner and i am not sure on which location which script/file i have to set. can you give me a manual how to handle with wich file and path?

    • Hi,
      I'm not entirely sure what you're specifically asking. Were you able run the scripts to successfully create the images (temp_hourly.png, etc..)? If you do have the images created. you should just be able to copy them to your PC and view them directly from there. If you want to be able to view them from a website, you'll need a web server (like apache or nginx).

  11. Hi Tony,
    Very nice tutorial !
    I am a very new to all this stuff! But I learn Fast :D
    I am doing similar project to yours! But I don't have a VPS. I have done my PI as a web server . So instead of sent them to a server can I make these values available on my web site(RPI)?

  12. Hello!
    I am using ds1820 as an outdoor temperature meter.
    Your regular expression ($output =~ /t=(\d+)/i;) will not work with temperatures below zero.

    It took me some time to understand, why i have zero in output, because i dont know perl)

    However, thanks for great manual!

  13. I seem to have a problem where the driver is not waiting long enough to get the conversion from the DS18B20. I verified with some code I wrote for an arduino using the same DS18B20 chips...if I set the wait delay to 500 mS I get 85 C as the temperature reading every time. If I increase the delay to 1000 mS I get the correct temp reading every time. I have tried this with 2 different DS18B20 chips with the same results. the spec sheet claims that conversion may take as long as 750 mS. Anyone else have this issue? ...going to see if i can dig into the driver...

    • Hmm...found a 3rd DS18B20 and this one works just fine. 2 bad ones? ...or at least slow? All's well now, I guess. I'll order up a few more to check...

      • Hi Jim,

        ive got the same problem here on my second Raspi. On my first Raspi reading /sys/bus.. works fine, but on the 512MB version i got 85 C too. Have you found a way to change the driver to 1000ms?


        • I have the same issue. Some days it works, but the last three days i always get 85 degree. How can i change the delay to 1000ms ?

  14. Interesting project and writeup!

    I am getting this error when running the create graphs script. 5: TEMP_SCALE: not found

    What does TEMP_SCALE refer to?



  15. Thanks for this great work! Without knowing anything about Perl I was able to rewrite your code to use two different sensors for inside / outside. :)

  16. Hi,
    have you considered using (or tried) the PI's internal pull-up resistor feature on pin 7? I guess there is no need to include that 4k7 resistor then.

  17. @Tony Tosi:
    I have rewritten the code for using two DS18B20 (inside and outside) and fixed the problem for negative degrees on Celsius. Maybe it´s interessting for you an you want to publish it here.

    Please feel free to contact me an my mail thebang2 at gmail dot com.

  18. hi mate!

    thank's for this great website! now i know how to solve my graph issue!


  19. very nice
    I was doing such a thing, then I saw this.
    I built the first prototype, the same as yours, now I'm running small changes
    I can publish it in Italy? enclosing the link to your page, as the initial project?

  20. Hi!

    Great tutorial!

    Is it possible to print out min max and average temperature to the png-files?



    • I believe so. I would look into the RRD documentation and I think it's not very difficult. You'll need to modify the file once you figure out the configuration syntax.

  21. Hi Tony

    Did you have any concerns with the data line of the temperature sensor driving 5V into the RPi input? My understanding is that you don't want to exceed the 3.3V level.



  22. How come Inside/Outisde Temperature gives only "[deg ]", not actual temperature ?

  23. What should I do with the graph - to negative temperatures?
    Now he time 0 - 100 Will grad but also minus (-30-100 degrees)

  24. Hi,
    there is a little Bug in ""

    rrdtool graph $DIR/temp_monthly.png --start -1m \
    DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
    DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
    AREA:temp$INTEMP_COLOR:"Inside Temperature [deg F]" \
    LINE1:outtemp$OUTTEMP_COLOR:"Outside Temperature [deg F]" <= should be "$TEMP_SCALE"
    ^^^^^ =====================

    Otherwise you have 3 Graphs with "[deg C]" and one with "[deg F]" as Label (the Values are still correct)

    Nevertheless, awsome work!

  25. I'm missing something. I have a ds18b20 hooked up to 3.3V, Grd, and a data pin on a BBB and I get the /sys/bus/w1 directories but not any for 28_* so no temps are read. Does the chip just start reading temps and writing out to its directory when power is applied?? Or do you have to send it reset and read commands? I have the 3.3 volts going into both the DQ and Pdd pins, over a 4k7 Ohm resister to the DQ.

    • From what you described I would guess that the modules are not loaded correctly or one is loaded and the other is not. A good way to check if they're loaded properly is to run lsmod and you should see both w1-gpio and w1-therm somewhere in that listing. Are you using Occidentalis v0.2? I'm also not sure what you're referring to with BBB.

  26. i have all setup but none of the data is saving to the hometemp.rrd all that is in the file is "RRD"

    below is a copy of script

    use LWP::UserAgent;

    my $dir = '/home/pi/temp_db';
    my $metar_url = '';
    my $is_celsius = 1; #set to 1 if using Celsius

    my $ua = new LWP::UserAgent;
    my $request = new HTTP::Request('GET', $metar_url);
    my $response = $ua->request($request);
    my $metar= $response->content();

    $metar =~ /([\s|M])(\d{2})\//g;
    $outtemp = ($1 eq 'M') ? $2 * -1 : $2; #'M' in a METAR report signifies below 0 temps
    $outtemp = ($is_celsius) ? $outtemp + 0 : ($outtemp * 9/5) + 32;

    $modules = `cat /proc/modules`;
    if ($modules =~ /w1_therm/ && $modules =~ /w1_gpio/)
    #modules installed
    $gpio = `sudo modprobe w1-gpio`;
    $therm = `sudo modprobe w1-therm`;

    $output = "";
    $attempts = 0;
    while ($output !~ /YES/g && $attempts &1`;
    if($output =~ /No such file or directory/)
    print "Could not find DS18B20\n";
    elsif($output !~ /NO/g)
    $output =~ /t=(\d+)/i;
    $temp = ($is_celsius) ? ($1 / 1000) : ($1 / 1000) * 9/5 + 32;
    $rrd = `/usr/bin/rrdtool update $dir/hometemp.rrd N:$temp:$outtemp`;


    #print "Inside temp: $temp\n";
    #print "Outside temp: $outtemp\n";

  27. Hi all,
    I've inserted in the crontab the following 2 rows:

    */5 * * * * root /opt/dallas/
    */5 * * * * root /opt/dallas/

    but I think that the crontab doesn't work because I don't see the new graphs every 5 minutes.
    I ran the command: "service cron status" and the response has been "cron is running" but I don't see the update of the graphs.
    What's the problem?

  28. Hi all,
    I've solved the problem.
    The cause was that I logged like "PI" user and isn't possible to launch commands in the folders out of the /Home folder (for example in the folder /opt/dallas/etc.etc.
    The solution is insert behind the word "sudo" and write:
    */5 * * * * sudo /opt/dallas/
    */5 * * * * sudo /opt/dallas/

    Best regards

  29. Hi.

    This is an excellent sollution :)
    Thatn you for the writeup.

    I have several temp sensors.
    How can i modify the script to read all the sensors and write them to the rrd with different names.
    And log them with different colors to the graph ?

  30. Great article - got me up and running with my Pi real quick!!

    My application for the temp probe is in a high RF environment - lighting ballasts, etc.
    I made up a simple 3 wire non-sheilded cable (10 foot) with the temp sensor. On my desk it works fine. When I move the probe towards the location where it needs to be I get random temp readings.

    Will sheilded microphone cable (2 wires plus shield) work for me?

  31. Hi. Great tutorial. Got it running (modified to read both values from sensors).
    Works fine ->
    However monthly graph ("miesieczny") has very low "resolution" There is one plotted value per day. All of them are generated every five minutes, how can I increase the resolution of monthly?

    here is the part of

    rrdtool graph $DIR/temp_weekly.png --start -1w \
    DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
    AREA:temp$INTEMP_COLOR:"W pokoju [$TEMP_SCALE]" \
    DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
    LINE1:outtemp$OUTTEMP_COLOR:"Na zewnatrz [$TEMP_SCALE]"

    rrdtool graph $DIR/temp_monthly.png --start -1m \
    DEF:temp=$DIR/hometemp.rrd:temp:AVERAGE \
    DEF:outtemp=$DIR/hometemp.rrd:outtemp:AVERAGE \
    AREA:temp$INTEMP_COLOR:"W pokoju [$TEMP_SCALE]" \
    LINE1:outtemp$OUTTEMP_COLOR:"Na zewnatrz [$TEMP_SCALE]"

    thanks in advance and greetings! :)

  32. Thank for Your work.

    I use Celsius, but in graph on vertical scale i got (i guest) F numbers. example from ~30-~75, when outside is ~zerro and inside +/- 20 C

    • Can you verify that you have the $is_celsius value set to 1 (line 6 in the script).

      • @tony - You are right.
        in first try your manual I cant work (get errors), then i start debug/copy/uncoment-out lines and miss this clearly explained. My fault.

        it not a critical, but:
        - is there free GUI for rrd db format
        - is possible to convert alredy collected data in F to C (only for learning process)

  33. how to configure graphs to show vertical measure values on right (or maybe on both) side of graphs?

  34. Thank you for this great and easy tutorial! :)

  35. I show both Celcius and Fahrenheit on the graph using

    --right-axis "1.8:32"
    --right-axis-label "Fahrenheit"

    You can also use a CDEF in your graph if you want to convert C to F



  36. Hi Tony, stumbled across this article while I was finishing up my 4-sensor run of waterproof ds18b20's to sample temps out at my wood burner. Once I realized there was a 'munin-node' port to the raspberry pi thou, I shaved this yak by creating a munin 'ds18b20' plugin that just spits out the sensor temps when queried by the munin-master. I leverage munin (which uses rrdtool on the back end just like you do) to poll and graph.

    It's a different way of tackling this particular problem, particularly if you've got more than one data source that you want to graph, and don't want to get lost in the intricacies of doing nice RRD graphs. :)

    Visual at

    I see sporadic reports of both being unable to read the temp (w1_slave_driver kernel bark) as well as what I've termed a 'Suspicious 85' reading. I'm currently sleeping a second between polling the sensors; wonder if it will help to increase that delay and/or retry...


  37. I constantly spent my half an hour to read this blog's articles or reviews everyday along with a mug of coffee.

  38. Do you have a spam problem on this site; I also am a blogger, and I was wondering your situation;
    many of us have created some nice practices and we
    are looking to trade techniques with others, please shoot me an e-mail if interested.

  39. Very good info. Lucky me I ran across your website by chance (stumbleupon).
    I've book-marked it for later!

  40. Hi,

    First of all i want to thank you for this. It works great!
    But i have two questions.
    I think my temperature is showing a few degrees to much, can i adjust that?
    And second, on the website i would like to have the degrees showing in numbers aswell, is it possible?


    • This is how he adjusts the outtemp to C/F
      $outtemp = ($is_celsius) ? $outtemp + 0 : ($outtemp * 9/5) + 32;

      using this you should be able to answer your first question.
      Can't help you with the second since I don't use the website

  41. Great stuff - thanks for the post.

  42. Hi, I'm a beginner and I kindly ask you a purpose of explanation step by step commands. Sorry but I tried to send the codes and I do not work, repeat the beginner and I kindly ask you a more basic explanation.

  43. Your script gives the following error message:
    File "", line 2
    use LWP::UserAgent;
    SyntaxError: invalid syntax

    What shall I do?

  44. Great work, Toni

    I will set up this instruction in my environment

  45. Two things -

    1) with the newest version of raspbian (v 3.18 and up) 1-wire won't work unless you make a change to the config.txt (see

    2) Can you explain how/where, in the perl script, the rrdtool is called.

  46. Impressive. Your code got me interested and I managed to setup my own project. I'm totally new to these kind of stuff but the more I look at the code, the more it captures me. My project still offers more to wish but your platform and support from google gives me something really fun to do. Thank you.

  47. Thanks for finally talking about >Raspberry Pi + DS18B20 Temperature Sensor + RRDtool ? Tony
    Tosi <Liked it!

  48. Stumbled on this while trying to find a way to do just this. However, the noaa .txt file, has stopped working as of aug1, 2016.

    Any new method of grabbing the data from outside using their newer HTML version of the .TXT file?

    Maybe you've moved on to other things...worth asking.

Cancel reply

8 − eight =