Thursday, July 11, 2013

RPi-Monitor: Use a DHT11 or DHT22 humidity and temperature sensor

In this post we will see how to connect a DHT11 or DHT22 Temperature and Humidity sensor and configure RPi-Monitor to present and draw the outputs.

Photo from Flickr AttributionNoncommercialNo Derivative Works cc-by-nc-nd by Ham Hock
This article will also explain another capability of RPi-Monitor 2.x: the dual-axis.


Adafruit created a very good tutorial explaining how to use DHT11 or DHT22 . This tutorial is available at this address: http://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/wiring.


Electronic assembly
This electronic assembly is quite simple and will need:
  • 1 x DHT11 or 1 x DHT22
  • 1 x 4.7k resistor
Plug them as described in the following schema:

Schema extracted from Adafruit but using GPIO #27 instead of GPIO #4

Software installation
Thanks to Adafruit ( again ;-) ) the installation is quite simple and can be done with two command lines.
Download Adafruit_DHT form Adafruit's github repository and copy is in /usr/bin as follow:
wget http://goo.gl/oadpl -O Adafruit_DHT
sudo cp Adafruit_DHT /usr/bin/
To test the electronic assembly and the software installation execute the following command (for DHT11):
pi@raspberrypi ~ $ sudo Adafruit_DHT 11 27
Using pin #17Data (40): 0x28 0x0 0x18 0x0 0x40
Temp = 24 *C, Hum = 40 %
You should see the information about temperature and humidity displayed as shown upper.

Note: The DHT11 and DHT22 sensors will only respond every second so if you are not getting data, be sure to wait few seconds before trying again.


RPi-Monitor configuration

Warning: Be sure to use Linux linefeed format with line ending with LF (and not CR/LF like in Windows).

Let's now use this information and add humidity graphs on existing temperature graph.

We first have to extract the data. This is done like this:

For more information about this configuration, refer to the post:  RPi-Monitor: Version 2.0 advance usage and customization

We will now add the humidity curve into the graph of temperature. This can be done with the configuration bellow:
As the unit are different than the one existing on the initial axis, we will add a second axis for the percentage of humidity. This is the purpose of the two last lines of the configuration bellow.
The first line is defining the usage of axis number 2 for the humidity.
The last line is defining how this graph should be drawn: On the right, starting from 0 up to 100.

graph_options can have other usefull option. They are described in the documentation of javascriptrrd.

After restarting RPi-Monotor with the command:
service rpimonitor restart
You will see a new curve in Temperature graph as shown in the screenshot bellow:

Graph with 2 Y axis: °C in left axis and % humidity (fixed from 0% to 100%) on right axis


38 comments :

  1. Hello.
    I am using Rpi-monitor for use radiooaficionado Raspberry with.
    But I am unable to join in a plot temp and hum with the DHT22.
    Adafruit command if I read well the values, but I can not do well because the temp change I always get 0.
    Can you help?

    dynamic.15.name=humidity
    dynamic.15.source=Adafruit_DHT 22 10
    dynamic.15.regexp=Hum = (\S+)
    dynamic.15.postprocess=$1/1
    dynamic.15.rrd=GAUGE

    dynamic.16.name=temperature
    dynamic.16.source=Adafruit_DHT 22 10
    dynamic.16.regexp=Temp = (\d+)$
    dynamic.16.postprocess=$1/1
    dynamic.16.rrd=GAUGE


    ==============================

    web.statistics.1.content.9.name=Temperature & Humidity BOX
    web.statistics.1.content.9.graph.1=humidity
    web.statistics.1.content.9.graph.2=temperature
    web.statistics.1.content.9.ds_graph_opts.humidity.label=Humidity (%)
    web.statistics.1.content.9.ds_graph_opts.temperature.label=Temperature (*C)
    web.statistics.1.content.9.ds_graph_opts.humidity.yaxis=1
    web.statistics.1.content.9.ds_graph_opts.temperature.yaxis=2
    web.statistics.1.content.9.graph_opts.y1axis={ position: "right", min: 0, max: 100 }
    web.statistics.1.content.9.graph_opts.y2axis={ position: "right", min: 0, max: 100 }

    ReplyDelete
    Replies
    1. Hello,

      The first thing is to check if the command from Adafruit is working. I guess you checked that. Be sure th install this command in /usr/bin to ensure it is in the path.

      To configure rpimonitor, you should ensure that the dynamic Id (15 and 16 in your example) are immédialtely followin the last number already existing in the configuration file.

      The same comment goes to the Id of web.satsistics.1.content.

      You don't need to pose process the result. You can let the temperature axis be defined automatically (remove y1axis).

      The regexp for temperature is wrong, it should be: dynamic.16.regexp=Temp = (\S+)

      I hope it will help.

      You can refer to github to see how I did customize my installation.
      https://github.com/XavierBerger/RPi-Monitor/blob/master/rpimonitor/custo.conf

      Delete
    2. Hello, I am having the same issue, I have changed the temp to (\S+), and my code is nearly identical. Cant quite get it to work. Any suggestions? Thanks

      Delete
    3. Hello,

      To define the exact command and regular expression to add in customized configuration file, it is recommended to test and validate the command before adding it into the configuration file. This can be done easily like this:

      COMMAND | perl -ne '/REGEXP/' and print "$1\n"'

      Example:

      Adafruit_DHT 11 27 | perl -ne '/Hum = (\S+)/' and print "$1\n"'

      The expected result is a valid number (integer or real).

      Note: $1 can be replaced by the porsprocessing formula.

      Once you are sure the value is extracted correctly, you can check if the configuration made is not going in conflict with other definition.

      Delete
    4. In fact there is a double space after the = sign in Adafruit_DHT's output.

      Putting two spaces between = and (\S+) works fine in my custom config, without the additional space it was returning 0.0.

      It looks like double spaces are suppressed in the comment publishing
      dynamic.16.regexp=Temp = (\S+)

      Delete
  2. Hello guys,

    I am also using DHT11 with adafruit code, and I found a possible bug.
    In the file Adafruit_DHT.c, line 94, the while loop waits for the gpio pin to rise.
    However, if for some reason this does not happens, the program hangs.
    So I added a counter (named safety) to wait maximum 1 millisec.
    If no answer comes, the function returns with error code 2.


    int safety=0;
    while (bcm2835_gpio_lev(pin) == 1 || safety > 1000) { // wait max 1000us
    usleep(1);
    safety++;
    }
    if (safety > 1000){ // if no answer, quit
    return 2;

    ReplyDelete
  3. My conf
    ########################################################################
    # Living root temperature and humidity added in dedicated pages
    ########################################################################
    dynamic.15.name=living_room_temp
    dynamic.15.source=Adafruit_DHT 2302 4
    dynamic.15.regexp=Temp = (\d+)$
    dynamic.15.postprocess=$1/1
    dynamic.15.rrd=GAUGE

    web.status.2.name=Living room
    web.status.2.content.1.name=Temperature
    web.status.2.content.1.icon=cpu_temp.png
    web.status.2.content.1.line.1="Ambiant Temperature: "+data.living_room_temp+"°C"

    web.statistics.2.name=Living room
    web.statistics.2.content.1.name=Temperature
    web.statistics.2.content.1.graph.1=living_room_temp
    web.statistics.2.content.1.ds_graph_options.living_room_temp.label=Ambient temp. (deg C)

    dynamic.16.name=humidity
    dynamic.16.source=Adafruit_DHT 22 4
    dynamic.16.regexp=Hum = (\S+)
    dynamic.16.postprocess=$1/1
    dynamic.16.rrd=GAUGE

    web.statistics.2.content.1.graph.2=humidity
    web.statistics.2.content.1.ds_graph_options.humidity.label=Humidity (%)
    web.statistics.2.content.1.ds_graph_options.humidity.yaxis=2
    #web.statistics.2.content.1.graph_options.legend= { position: "sw"}
    web.statistics.2.content.1.graph_options.y2axis={ position: "right", min: 0, max: 100 }

    dht22 on 4
    Humidty is ok but not temp. Adafruit_DHT 2302 4 write right temp and hum.
    What is wrong? Please help My Raspberry http://aiamaa.no-ip.org:8888

    ReplyDelete
    Replies
    1. I notice that command used as source is different... sometime 22 sontime 2302...
      You also use a postprocess command which have no sense: $1/1
      Did you check the regular expression? I would advise to read the comments I mase upper, you will certainly find interresting tips helping you to find the solution.

      Delete
  4. rpi-monitor 2.0
    /etc/rpimonitor.conf
    part of this file
    ########################################################################
    # Living root temperature and humidity added in dedicated pages
    ########################################################################
    dynamic.15.name=living_room_temp
    dynamic.15.source=Adafruit_DHT 22 4
    dynamic.15.regexp=Temp = (\d+)$
    dynamic.15.postprocess=$1/1000
    dynamic.15.rrd=GAUGE

    web.status.2.name=Living room
    web.status.2.content.1.name=Temperature
    web.status.2.content.1.icon=cpu_temp.png
    web.status.2.content.1.line.1="Ambiant Temperature: "+data.living_room_temp+"°C"

    web.statistics.2.name=Living room
    web.statistics.2.content.1.name=Temperature
    web.statistics.2.content.1.graph.1=living_room_temp
    web.statistics.2.content.1.ds_graph_options.living_room_temp.label=Ambient temp. (deg C)

    dynamic.16.name=humidity
    dynamic.16.source=Adafruit_DHT 22 4
    dynamic.16.regexp=Hum = (\S+)
    dynamic.16.postprocess=$1/1
    dynamic.16.rrd=GAUGE

    web.statistics.2.content.1.graph.2=humidity
    web.statistics.2.content.1.ds_graph_options.humidity.label=Humidity (%)
    web.statistics.2.content.1.ds_graph_options.humidity.yaxis=2
    #web.statistics.2.content.1.graph_options.legend= { position: "sw"}
    web.statistics.2.content.1.graph_options.y2axis={ position: "right", min: 0, max: 100 }

    not working.

    Adafruit_DHT 22 4 command working ok. Where is error ?

    ReplyDelete
    Replies
    1. What's not working? You description of the problem is not detailled enough to allow me to help you but I'll try....

      Did you check the regular expression as proposed in my previous answer? (Ref comment of September 10, 2013 at 11:34 AM) ... I guess no :-(.

      If the output of DHT22 is the same as DHT11:

      Temp = 24 *C, Hum = 40 %

      Then, your regular expression for tempetature is wrong. Remove the tailing $ and check the RegExp with the command line described upper.
      Once your regular expression will work, then add it into the configuration file.

      Delete
  5. Good morning Xavier,
    first thanks very much for your nice and valuable monitor!!
    I added the DHT11 to my RPI and found, thst every 2nd or 3rd measurement goes to zero, and so there are gaps in the graph. I think this is due to much to short delays between triggering of the readout program.
    My question is, how to stretch the delay between the measurements?

    Many Regards,
    Christoph

    ReplyDelete
    Replies
    1. Hi Christoph,

      The delay is configurable. There is a parameter to set into /etc/rpimonitord.conf.
      I let you read the comment in this file to find the parameter to update.
      This value will be active after restarting rpimonitord: sudo service rpimonitor restart

      Cheers,
      Xavier

      Delete
  6. Hi Xavier

    I really appreciate you making this tool available. Thank you.

    I am having trouble with a DHT22 and version 2.5.1. When I run on 2.4 version 2.4 I get nice clean graph.

    After updating to 2.5.1 I get a very noisey graph with lots of 0 values.

    If I downgrade to 2.4.1 the graph becomes clean again

    I think its because the DHT22 gives lots of unknown data readings and because the two versions of RPi-Monitor treat unknown data differently.

    Can you tell me a little about what

    "Update rrd graph with unkown data if fetched information is not a valid number"

    means in the 2.5.1 release notes?

    Regards
    Brian Pratt

    ReplyDelete
    Replies
    1. Hi Brian,

      RPi-Monitor is designed to graph the data extracted. In previous version the behavior of the graph was not reliable since sometime no data were stored in the RRD. Now, it stored the data extracted or unknow, there is no more hole in the RRD.
      You are experiencing a side effect now and it let me wonder if your previous graph was correct or not... Not sure that the timeline was correct.
      With a sensor which is not reliable, I would propose to do like this:
      1/Create a script which is getting the info from the sensor and updating a file when the data is correct.
      2/Configure Rpi-Monitor to read the information in this file.
      Like this, if your sensor doesn't send information, the data stored in RRD will be the same as the previous one.

      I think this will solve your issue.

      Rgds,
      Xavier

      Delete
  7. Hi Xavier,

    I can't put temperature readings from DHT22 to RPi-mon statistics. My DHT22 (AM2302) are working fine and I am able to get temp and hum data from it:
    sudo Adafruit_DHT 2302 18
    Using pin #18
    Data (40): 0x0 0xd1 0x1 0x2c 0xfe
    Temp = 30.0 *C, Hum = 20.9 %
    Can you help me to add both temperature and humidity data from DHT22 to RPi-monitor?

    ReplyDelete
    Replies
    1. Here is my config:


      dynamic.21.name=t5
      dynamic.21.source=Adafruit_DHT 2302 18
      dynamic.21.regexp=Temp = (\S+)
      dynamic.21.postprocess=
      dynamic.21.rrd=GAUGE

      dynamic.22.name=humidity
      dynamic.22.source=Adafruit_DHT 2302 18
      dynamic.22.regexp=Hum = (\S+)
      dynamic.22.postprocess=
      dynamic.22.rrd=GAUGE

      web.statistics.1.content.8.graph.7=t5
      web.statistics.1.content.8.ds_graph_options.t5.label=t5 (deg C)
      web.statistics.1.content.8.graph.8=humidity
      web.statistics.1.content.8.ds_graph_options.humidity.label=Humidity (%)
      web.statistics.1.content.8.ds_graph_options.humidity.yaxis=2
      web.statistics.1.content.8.graph_options.y2axis={ position: "right", min: 0, max: 100 }

      What's wrong with it?

      Delete
    2. Nothing obvious...
      I would advise to read upper comments about perl command to check the regular expression and to have a look to the sample files in github like https://github.com/XavierBerger/RPi-Monitor/blob/master/rpimonitor/custo.conf

      Delete
  8. Solved:

    dynamic.21.regexp=Temp =<--!!ADD TWO SPACES HERE!!-->(\S+)

    So, the line should be:

    dynamic.21.regexp=Temp = (\S+)

    And only ONE space for Humidity line:

    dynamic.22.regexp=Hum = (\S+)

    Take care!

    ReplyDelete
  9. Hi Xavier,

    first I would like to thank you for this great tool!
    It took me a bit of tinkering but now I got it (mostly) to show what I want.

    There is one thing that I would like to correct: I am reading information from a remote sensor into a file. Among other I read the voltage of the battery in form of a number like 115. Then I calculate the voltage 115*0.02+1 (3.3V) this value is stored in the database.
    dynamic.24.name=voltage
    dynamic.24.source=/home/pi/script/sensor.txt
    dynamic.24.regexp=/(.*?)/(.*?)/(.*)
    dynamic.24.postprocess=$3*0.02+1
    dynamic.24.rrd=GAUGE
    The status page shows 3.3 which is correct but the statistic page shows values like:
    3.3000000000000007
    3.2999999999999994
    Is there a way to correct this?

    Cheers
    Harry

    ReplyDelete
    Replies
    1. Ok here is how I solved the problem:
      web.statistics.2.content.3.graph_options.yaxis={min: 3, max: 5}
      This prevents it from auto-scaling the y-axis.

      Cheers
      Harry

      Delete
  10. Xaiver:

    This is a great tool, thanks for pulling it together.

    The DHT22 has an issue where it returns bad data if you query it too often. To work around that, I've created a script that queries the sensor once for temperature and humidity and then appends it to a file. The script is executed by cron on a periodic basis.

    I then configured rpimonitor to read that file for the values as follows:

    dynamic.17.name=ambient_humid
    dynamic.17.source=/home/pi/humid.out
    dynamic.17.regexp=Hum = (\S+)
    dynamic.17.postprocess=
    dynamic.17.rrd=GAUGE

    dynamic.18.name=ambient_temp
    dynamic.18.source=/home/pi/humid.out
    dynamic.18.regexp=Temp = (\S+)
    dynamic.18.postprocess=($1*1.8)+32
    dynamic.18.rrd=GAUGE

    Collection and graphing seem to be working as I expect, but I'm curious as to what method rpimonitor uses to read a file.

    If I'm reading the code right, sub Process() in package Monitor handles this. It looks to me as though it iterates through all lines in the data file and will write each value into the RRD. However, when I dump the rrd, I see far fewer datapoints than I'd expect if it were doing that. Instead, rpimonitor looks as though it is looking at the last line in the file only. (Which is what I want it to do.)

    Can you shed some light on this? Does rpimonitor read all lines and aggregate the data, or does it just read the last?

    Thanks.

    ReplyDelete
    Replies
    1. Hello,

      I didn't design rpimonitor to read more than one postprocess line and I don't know how it will behave if more than one.

      Cheers,

      Xavier

      Delete
  11. Hello Xavier!

    Thank you for your RPI monitor, its awesome, but something is not working for me.

    Well the DHT22 is works fine i get temperatures. But the graph is wrong, i can't do the same like your. This is my config and graph:

    https://dl.dropboxusercontent.com/u/13922338/Screen%20Shot%202013-12-31%20at%2017.18.07.png

    All i want same the cpu temperature or your graph, but i can't fix that. :(

    Best Regards,
    Szergely

    ReplyDelete
  12. Everything worked perfectly, thanks Xavier.

    ReplyDelete
  13. Hello Xavier, when I try to test Adafruit_DHT it says: sudo: Adafruit_DHT: command not found
    First I run:
    wget http://goo.gl/oadpl -O Adafruit_DHT
    sudo cp Adafruit_DHT /usr/bin/

    Do I need to chmod Adafruit_DHT?

    Thanks

    ReplyDelete
  14. Alright, I installed like the tutorial link above and copied to /usr/bin, now it works in terminal, I just have to write:
    'sudo Adafruit_DHT 2302 4' instead of 'Adafruit_DHT 2302 4', don't know why I need sudo...

    ReplyDelete
  15. Xavier, I edit the /etc/rpimonitord.conf/default.conf and added this:

    'dynamic.17.name=humidity
    dynamic.17.source=Adafruit_DHT 2302 4
    dynamic.17.regexp=Hum = (\S+)
    dynamic.17.postprocess=
    dynamic.17.rrd=GAUGE'

    and this:

    'web.statistics.1.content.8.graph.3=humidity
    web.statistics.1.content.8.ds_graph_options.humidity.label=Humidity (%)
    web.statistics.1.content.8.ds_graph_options.humidity.yaxis=2
    web.statistics.1.content.8.graph_options.y2axis={ position: "right", min: 0, max: 100 }'

    But know when I go to Statics in Rpi-monitor it gimes me the following error:

    'File stat/null.rrd is not a valid RRD archive!'

    note that I used 'dynamic.17.source=Adafruit_DHT 2302 4' instead of Adafruit_DHT 11 27

    Hope you can help me.

    ReplyDelete
  16. On the basis of all of the above I was able to do so. Everything works.

    dynamic.16.name=humidity
    dynamic.16.source=/home/pi/humid.out
    dynamic.16.regexp=Hum = (\S+)
    dynamic.16.postprocess=
    dynamic.16.rrd=GAUGE

    dynamic.17.name=temperature
    dynamic.17.source=/home/pi/humid.out
    dynamic.17.regexp=Temp = (\S+)
    dynamic.17.postprocess=
    dynamic.17.rrd=GAUGE


    web.statistics.1.content.9.name=Temperature & Humidity
    web.statistics.1.content.9.graph.1=humidity
    web.statistics.1.content.9.graph.2=temperature
    web.statistics.1.content.9.ds_graph_opts.humidity.label=Humidity (%)
    web.statistics.1.content.9.ds_graph_opts.temperature.label=Temperature (*C)
    web.statistics.1.content.9.ds_graph_opts.humidity.yaxis=1
    web.statistics.1.content.9.ds_graph_opts.temperature.yaxis=2
    web.statistics.1.content.9.graph_opts.y1axis={ position: "right", min: 0, max: $
    web.statistics.1.content.9.graph_opts.y2axis={ position: "right", min: 0, max: $

    Script that writes data to a file:
    #!/usr/bin/python

    import subprocess
    import re
    import sys

    while(True):
    output = subprocess.check_output(["./Adafruit_DHT", "22", "4"]);
    f1 = open("humid.out", 'w')
    f1.write (output)
    f1.close()
    print output
    matches = re.search("Temp =\s+([0-9.]+)", output)
    if (not matches):
    time.sleep(2)
    continue
    temp = float(matches.group(1))
    matches = re.search("Hum =\s+([0-9.]+)", output)
    if (not matches):
    time.sleep(2)
    continue
    humidity = float(matches.group(1))
    sys.exit()

    ReplyDelete
    Replies
    1. Alezxxx when I try to run your script this is what I get:

      "pi@raspberrypi ~ $ ./humid.out
      File "./humid.out", line 8
      output = subprocess.check_output(["./Adafruit_DHT", "22", "4"]);
      ^
      IndentationError: expected an indented block"

      Already tried with sudo and the result is the same.


      When I run: sudo ./Adafruit_DHT 22 4
      Using pin #4
      Data (40): 0x2 0x17 0x0 0xa9 0xc2
      Temp = 16.9 *C, Hum = 53.5 %

      The results are ok, but if I try to run without sudo this is what I get:
      "bcm2835_init: Unable to open /dev/mem: Permission denied"

      What I'm doing wrong?
      Hope you can help me.
      Thanks.

      Delete
    2. This comment has been removed by the author.

      Delete
  17. What is the problem with sampling? It's common for an undefined value. I have DHT11.
    Screnshot from graph:
    http://dl.dropbox.com/u/3577295/Kijel%C3%B6l%C3%A9s_015.png

    ReplyDelete
    Replies
    1. I often answer to such a question...
      You will now find the answer into the FAQ page.

      Delete
    2. Try to record the temperature and humidity readings in a file with check writing the correct value, and then add the file to the chart.

      Delete
  18. Dear Xavier,

    first of all, thank for sharing your work with us. I am not a programmer just a computer enthusiast. I am trying to do something...easy I think but due to lack of knowledge I stuck. I want to graph 3 sources on the same graph (I have a BMP085 sensor connected to a Pi), Temp, Hum and Pressure. The problem is the value of the barometric pressure which is hundred of times higher that the temperature and humidity and can't be represented on the same axis without jeopardizing the other two. I want to transfer the Pressure values on the left vertical axis of the graph table but...I don't know how! I have tried several things but no luck. Could you please help me ?

    Thanks in Advance!

    ReplyDelete
    Replies
    1. RPi-Monitor is fully configurable. Each configuration is different and have his specificity. It is not possible to provide a configuration for each situation.
      Nevertheless, to reach you objective, I would advise you to read carefully this article and try to reproduce what is described here sharply. Once this will work, you will have enough knowledge to update and customize your configuration file to your wishes.

      Delete
    2. Thanks for your reply. I solved it somehow by following your example. This is my configuration:

      dynamic.17.name=pressure
      dynamic.17.source=bmp085
      dynamic.17.regexp=Pressure (\S+)
      dynamic.17.postprocess=
      dynamic.17.rrd=GAUGE

      dynamic.18.name=humidity
      dynamic.18.source=nice -20 loldht 7
      dynamic.18.regexp=Humidity = (\S+)
      dynamic.18.postprocess=$1/1
      dynamic.18.rrd=GAUGE

      dynamic.19.name=temperature
      dynamic.19.source=bmp085
      dynamic.19.regexp=Temperature (\S+)
      dynamic.19.postprocess=$1/1
      dynamic.19.rrd=GAUGE

      web.statistics.1.content.9.name=PC Room
      web.statistics.1.content.9.graph.1=humidity
      web.statistics.1.content.9.graph.2=pressure
      web.statistics.1.content.9.graph.3=temperature
      web.statistics.1.content.9.ds_graph_options.humidity.label=Hum (%)
      web.statistics.1.content.9.ds_graph_options.pressure.label=Bar (hPa)
      web.statistics.1.content.9.ds_graph_options.temperature.label=Temp (*C)
      web.statistics.1.content.9.ds_graph_options.humidity.yaxis=1
      web.statistics.1.content.9.ds_graph_options.pressure.yaxis=2
      web.statistics.1.content.9.graph_options.y1axis={ position: "right", min: 0, max: 100 }
      web.statistics.1.content.9.graph_options.y2axis={ position: "left", min: 0, max: 1150 }


      Thanks again and keep up good work.

      Delete
  19. This comment has been removed by the author.

    ReplyDelete