RaspberryPi Humidity and Temperature Sensor

From Wurst-Wasser.net
Jump to: navigation, search

Schematics

RaspberryPiDHT11.png
Remember that the Pi revisions have different pinouts! This will work for Revison 2, that is board revision 0004[1]. If you don't need humidity readings, I strongly recommend using a DS18B20 instead of the DHT11, as showed in RaspberryPi Temperature Sensor, because you can use the 1-wire kernel modules for reading the DS18B20, which makes it much easier to read and extend.

Configure the Pi

Update the OS

This is not necessary, but generally a good idea.

apt-get update
apt-get upgrade

Install missing packages

If you have already installed them, you can skip this step.

apt-get install gnuplot
apt-get install git

Install DHT11 driver

Since there seems to be no kernel module for DHT11, do this:

git clone git://git.drogon.net/wiringPi
cd wiringPi
git pull origin
./build

Create a file hum_temp.c with this content (Code taken from here from Rahul Kar):

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAX_TIME 85
#define DHT11PIN 7
int dht11_val[5]={0,0,0,0,0};

void dht11_read_val()
{
uint8_t lststate=HIGH;
uint8_t counter=0;
uint8_t j=0,i;
float farenheit;
for(i=0;i<5;i++)
{
    dht11_val[i]=0;
}
pinMode(DHT11PIN,OUTPUT);
digitalWrite(DHT11PIN,LOW);
delay(18);
digitalWrite(DHT11PIN,HIGH);
delayMicroseconds(40);
pinMode(DHT11PIN,INPUT);
for(i=0;i<MAX_TIME;i++)
{
	counter=0;
	while(digitalRead(DHT11PIN)==lststate)
	{
 		counter++;
		delayMicroseconds(1);
		if(counter==255)
			break;
	}
	lststate=digitalRead(DHT11PIN);
	if(counter==255)
      break;
 	// top 3 transistions are ignored
	if((i>=4)&&(i%2==0)){
		dht11_val[j/8]<<=1;
		if(counter>16)
			dht11_val[j/8]|=1;
		j++;
	}
}
// verify checksum and print the verified data
if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))
{
	farenheit=dht11_val[2]*9./5.+32;
	printf("Humidity: %d.%d%% Temperature: %d.%dC (%.1f *F)\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3],farenheit);
}
else
{
	printf("Invalid Data!!\n");
}
}

int main(void)
{
//printf("Interfacing Temperature and Humidity Sensor (DHT11) With Raspberry Pi\n");
if(wiringPiSetup()==-1)
{ 
	exit(1);
} 

dht11_read_val();

return 0;
}
gcc -o sensor hum_temp.c -L/usr/local/lib -lwiringPi
./sensor
Humidity: 46.0% Temperature: 22.0C (71.6 *F)

Code

This is how I read the device and generate a nice plot using GNUplot:

#/bin/bash
#set -x
#
# Script: readHumidityAndTemperature.sh
# Author: Heiko Kretschmer
# Purpose: Reading the humidity/temperature and generating a nice plot
#
#

#
# Globals
#
GBASENAME="readHumidityAndTemperature"
GTIMESTAMPFORMAT="%Y-%m-%d_%H:%M"
GTIMESTAMP="`date +${GTIMESTAMPFORMAT}`"
GTIMESTAMPTIME="`date '+%H:%M'`"
GTIMESTAMPDATE="`date '+%Y-%m-%d'`" # ISO 8601 date format
GTIMESTAMPDATEHUMANREADABLE="`date '+%A, %Y-%m-%d'`"
#GFOLDERBASE="/home/pi/Development/humidity_and_temperature"
GFOLDERBASE="/home/pi/Development/humidity_and_temperature/wiringPi"
GCMDSENSOR="${GFOLDERBASE}/sensor"
GFOLDERLOGS="${GFOLDERBASE}/logs"
GFOLDERGRAPHS="${GFOLDERBASE}/graphs"
GFOLDERTMP="${GFOLDERBASE}/tmp"
GFILELOGHUM="${GFOLDERLOGS}/${GBASENAME}_${GTIMESTAMPDATE}_Humidity.log"
GFILELOGTEMP="${GFOLDERLOGS}/${GBASENAME}_${GTIMESTAMPDATE}_Temperature.log"
GFILEGRAPHHUM="${GFOLDERGRAPHS}/${GBASENAME}_${GTIMESTAMPDATE}_Humidity.svg"
GFILEGRAPHTEMP="${GFOLDERGRAPHS}/${GBASENAME}_${GTIMESTAMPDATE}_Temperature.svg"
GFILEGRAPHHUMTEMP="${GFOLDERGRAPHS}/${GBASENAME}_${GTIMESTAMPDATE}_Humidity_Temperature.svg"
GFILEPLOTCOMMANDS="${GFOLDERTMP}/${GBASENAME}-plot.cmd"

#
# Functions 
#
FPLOTGRAPHDOUBLE() # Plotting a single graph into one diagramm
{
  DATAFILE1=$1
  LINE1COLOUR=$2
  LINE1LABEL=$3
  LINE1UNITS=$4
  DATAFILE2=$5
  LINE2COLOUR=$6
  LINE2LABEL=$7
  LINE2UNITS=$8
  OUTFILE=$9

  test -f "${GFILEPLOTCOMMANDS}" && rm "${GFILEPLOTCOMMANDS}"

  # Reset
  echo "reset" >> "${GFILEPLOTCOMMANDS}"

  # Set output file type to svg
  echo "set term svg size 640,480" >> "${GFILEPLOTCOMMANDS}"
  echo "set output \"${OUTFILE}\"" >> "${GFILEPLOTCOMMANDS}"
  
  # Key
  echo "set key inside right top vertical Right noreverse enhanced autotitles columnhead nobox" >> "${GFILEPLOTCOMMANDS}"

  # Set time format for X axis
  echo "set timefmt \"%H:%M\"" >> "${GFILEPLOTCOMMANDS}"
  echo "set xdata time" >> "${GFILEPLOTCOMMANDS}"
  echo "set format x \"%H:%M\"" >> "${GFILEPLOTCOMMANDS}"

  # Setup line style (#1) for the first line
  echo "set style line 1 lc rgb \"${LINE1COLOUR}\" pt 1 ps 1 lt 1 lw 2" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/

  # Setup line style (#2) for the second line
  echo "set style line 2 lc rgb \"${LINE2COLOUR}\" pt 1 ps 1 lt 1 lw 2" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/
  echo "set style data lines" >> "${GFILEPLOTCOMMANDS}"

  # Set X tics (one tic per hour, rotate that tick-labels by 90 deg and move em a bit)
  echo "set xtics \"01:00\" rotate by 90 offset 0,-2 out nomirror" >> "${GFILEPLOTCOMMANDS}"

  # Setup Grid (with line style #12)
  echo "set style line 12 lc rgb '#E0E0E0' lt 0 lw 1" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/
  echo "set grid back ls 12" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/

  # Setup Title
  echo "set title \"${LINE1LABEL} and ${LINE2LABEL} on ${GTIMESTAMPDATEHUMANREADABLE}\"" >> "${GFILEPLOTCOMMANDS}"

  # Label X and Y Axis
  echo "set ylabel \"${LINE1UNITS}\"" >> "${GFILEPLOTCOMMANDS}"
  echo "set y2label \"${LINE2UNITS}\"" >> "${GFILEPLOTCOMMANDS}"
  echo "set xlabel \"Time\" offset 0,-0.5" >> "${GFILEPLOTCOMMANDS}"

  # Setup Y range(s)
  echo "set yrange [ 0.000 : 100.000 ] noreverse nowriteback" >> "${GFILEPLOTCOMMANDS}"
  echo "set y2range [ 0.000 : 50.000  ] noreverse nowriteback" >> "${GFILEPLOTCOMMANDS}"

  # Tics on the outside, also do the tics for y2, too
  echo "set tics out" >> "${GFILEPLOTCOMMANDS}"
  echo "set y2tics" >> "${GFILEPLOTCOMMANDS}"

  # Plot line 1
  echo "plot \"${DATAFILE1}\" using 1:2 title '${LINE1LABEL}' with l ls 1 axes x1y1, \"${DATAFILE2}\" using 1:2 title '${LINE2LABEL}' with l ls 2 axes x1y2" >> "${GFILEPLOTCOMMANDS}"

  cat "${GFILEPLOTCOMMANDS}" 
  cat "${GFILEPLOTCOMMANDS}" | gnuplot 

} # end of FPLOTGRAPHDOUBLE


FPLOTGRAPHSINGLE() # Plotting a single graph
{
  DATAFILE=$1
  LINE1COLOUR=$2
  LINE1LABEL=$3
  LINE1UNITS=$4
  OUTFILE=$5
  test -f "${GFILEPLOTCOMMANDS}" && rm "${GFILEPLOTCOMMANDS}"
  echo "reset" >> "${GFILEPLOTCOMMANDS}"
  echo "set key inside right top vertical Right noreverse enhanced autotitles columnhead nobox" >> "${GFILEPLOTCOMMANDS}"

  # Set time format for X axis
  echo "set timefmt \"%H:%M\"" >> "${GFILEPLOTCOMMANDS}"
  echo "set xdata time" >> "${GFILEPLOTCOMMANDS}"
  echo "set format x \"%H:%M\"" >> "${GFILEPLOTCOMMANDS}"

  # Setup line style (#1) for the temperature line
  echo "set style line 1 lc rgb \"${LINE1COLOUR}\" pt 1 ps 1 lt 1 lw 2" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/
  echo "set style data lines" >> "${GFILEPLOTCOMMANDS}"

  # Set X tics (one tic per hour, rotate that tick-labels by 90 deg and move em a bit)
  echo "set xtics \"01:00\" rotate by 90 offset 0,-2 out nomirror" >> "${GFILEPLOTCOMMANDS}"

  # Setup Grid (with line style #12)
  echo "set style line 12 lc rgb '#E0E0E0' lt 0 lw 1" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/
  echo "set grid back ls 12" >> "${GFILEPLOTCOMMANDS}" # http://www.gnuplotting.org/tag/grid/

  # Setup Title
  echo "set title \"${LINE1LABEL} on ${GTIMESTAMPDATEHUMANREADABLE}\"" >> "${GFILEPLOTCOMMANDS}"

  # Label X and Y Axis
  echo "set ylabel \"${LINE1UNITS}\"" >> "${GFILEPLOTCOMMANDS}"
  echo "set xlabel \"Time\" offset 0,-0.5" >> "${GFILEPLOTCOMMANDS}"

  # Setup Y range
  echo "set yrange [ 0.000 : ] noreverse nowriteback" >> "${GFILEPLOTCOMMANDS}"

  # Set output file type to svg and plot it into file
  echo "set term svg size 640,480" >> "${GFILEPLOTCOMMANDS}"
  echo "set output \"${OUTFILE}\"" >> "${GFILEPLOTCOMMANDS}"
  echo "plot \"${DATAFILE}\" using 1:2 title '${LINE1LABEL}' with l ls 1" >> "${GFILEPLOTCOMMANDS}"
  cat "${GFILEPLOTCOMMANDS}" | gnuplot 
}

#
# Main
#

# Init
test ! -d "${GFOLDERLOGS}" && mkdir "${GFOLDERLOGS}"
test ! -d "${GFOLDERGRAPHS}" && mkdir "${GFOLDERGRAPHS}"
test ! -d "${GFOLDERTMP}" && mkdir "${GFOLDERTMP}"

# Get values
LINE="`sudo ${GCMDSENSOR}`"
echo "LINE: ${LINE}"
HUMIDITY="`echo \"${LINE}\" | cut -d: -f2 | cut -d\\% -f1 | awk '{printf $1}'`"
echo "HUMIDITY: ${HUMIDITY}"
TEMPERATURE="`echo \"${LINE}\" | cut -d: -f3 | cut -dC -f1 | awk '{printf $1}'`"
echo "TEMPERATURE: ${TEMPERATURE}"

if [ "${HUMIDITY}" != "Invalid" -a "${TEMPERATURE}" != "Invalid" ]; then

  # Write it into the log (one logfile per day to get nice graphs)
  echo -e "${GTIMESTAMPTIME}\t${HUMIDITY}" >> "${GFILELOGHUM}"
  echo -e "${GTIMESTAMPTIME}\t${TEMPERATURE}" >> "${GFILELOGTEMP}"
#  echo -e "${GTIMESTAMPTIME}\t${HUMIDITY}\t${TEMPERATURE}" >> "${GFILELOGHUMTEMP}"

else
  echo "Read from sensor failed, plotting (old data) anyway."
fi

  # Generate the graphs (single)
  FPLOTGRAPHSINGLE "${GFILELOGHUM}" '#0e1a8b' "Humidity" "%" "${GFILEGRAPHHUM}"
  FPLOTGRAPHSINGLE "${GFILELOGTEMP}" '#8b1a0e' "Temperature" "°C" "${GFILEGRAPHTEMP}"

  # Generate combined graph (double)
  FPLOTGRAPHDOUBLE "${GFILELOGHUM}" '#0e1a8b' "Humidity" "%" "${GFILELOGTEMP}" '#8b1a0e' "Temperature" "°C" "${GFILEGRAPHHUMTEMP}"


You might want to use a cronjob like this:

*/15 * * * *    /home/pi/Development/temperature/readHumidityAndTemperature.sh > /dev/null 2>&1

Resulting graph

And this is how it looks:
RaspberryPiDHT11TemperaturePlotExample.svg
RaspberryPiDHT11HumidityPlotExample.svg
RaspberryPiDHT11HumidityTemperaturePlotExample.svg


  1. Raspberry Board Revision Check