The DHT11 sensor includes a temperature and a humidity sensor. I connected it with my raspberry pi and transmit the data to an external cacti server, which polls the data regularly from the raspberry pi.
Step 1: Wire the sensor
While facing the open side of the sensor (NOT the one with the sticker on it), connect the pins as following
- Leftmost pin = V+ — connect with 3V3 (Pin 1) from raspberry pi
- Second pin = DATA — connect with GPIO4 (Pin 7) from raspberry pi AND via a 4.7k-10k resistor with 3V3
- Third pin = Do NOT connect
- Rightmost pin = GND — connect with GND (Pin 6) from raspberry pi
Step 2: Get the BCM2835 library and compile / install
The latest version can always be found here: http://www.airspayce.com/mikem/bcm2835/
As the time of writing, this was 1.36
cd mkdir -p work/bcm2835 cd work/bcm2835 wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.36.tar.gz tar xvfz bcm2835-1.36.tar.gz cd ./bcm2835-1.36 ./configure make sudo make install
Step 3: Get the Adafruit python code
sudo apt-get update sudo apt-get -y install git git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code cd ./Adafruit-Raspberry-Pi-Python-Code cd ./Adafruit_DHT_Driver make
After successfully compiling the Adafruit Driver, you can check if your sensor is already working. Keep in mind that the DHT11 is SLOW and won’t react if asked more than once within 2 or 3 seconds. If you don’t get any result after the first query, wait a few seconds (at least 3) and try again. If the problem persists, your wiring might be wrong.
sudo ./Adafruit_DHT 11 4
Step 4: Modify Adafruit python code
The original Adafruit code is giving too much information for simple cacti input parameters. A modification of the source code is necessary. Along with changing the output, I also removed all references to DHT22 and AM2302 to make the file a bit smaller:
ada_sm.c
// How to access GPIO registers from C-code on the Raspberry-Pi // Example program // 15-January-2012 // Dom and Gert // Access from ARM Running Linux #define BCM2708_PERI_BASE 0x20000000 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <dirent.h> #include <fcntl.h> #include <assert.h> #include <unistd.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <bcm2835.h> #include <unistd.h> #define MAXTIMINGS 100 #define DHT11 11 int readDHT(int type, int pin); int main(int argc, char **argv) { if (!bcm2835_init()) return 1; if (argc != 3) { printf("usage: %s [11] GPIOpin#\n", argv[0]); printf("example: %s 11 4 - Read from an DHT11 connected to GPIO #4\n", argv[0]); return 2; } int type = 0; if (strcmp(argv[1], "11") == 0) type = DHT11; if (type == 0) { printf("Select 11 as type!\n"); return 3; } int dhtpin = atoi(argv[2]); if (dhtpin <= 0) { printf("Please select a valid GPIO pin #\n"); return 3; } readDHT(type, dhtpin); return 0; } // main int bits[250], data[100]; int bitidx = 0; int readDHT(int type, int pin) { int counter = 0; int laststate = HIGH; int j=0; // Set GPIO pin to output bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_write(pin, HIGH); usleep(500000); // 500 ms bcm2835_gpio_write(pin, LOW); usleep(20000); bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); data[0] = data[1] = data[2] = data[3] = data[4] = 0; // wait for pin to drop? while (bcm2835_gpio_lev(pin) == 1) { usleep(1); } // read data! for (int i=0; i< MAXTIMINGS; i++) { counter = 0; while ( bcm2835_gpio_lev(pin) == laststate) { counter++; //nanosleep(1); // overclocking might change this? if (counter == 1000) break; } laststate = bcm2835_gpio_lev(pin); if (counter == 1000) break; bits[bitidx++] = counter; if ((i>3) && (i%2 == 0)) { // shove each bit into the storage bytes data[j/8] <<= 1; if (counter > 200) data[j/8] |= 1; j++; } } if ((j >= 39) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) ) { if (type == DHT11) printf("temp:%d hum:%d\n", data[2], data[0]); return 1; } return 0; }
Compile the file with this command line (if you saved the above .c-file as „ada_sm.c“)
gcc ada_sm.c -l bcm2835 -std=gnu99 -o ada_sm
The output should be compatible with cacti:
$ sudo ./ada_sm 11 4 temp:23 hum:33
Step 5: Add a socat service
I’ve explained how to achieve this in another post, you only need a new shell script which will make sure that the readouts were given:
/usr/local/bin/dht11.sh
#!/bin/bash result="" while [ -z "${result}" ]; do result=$(sudo /home/pi/work/dht11/ada_sm 11 4) sleep 3 done echo ${result}
Here the contents the configuration file for socat:
/etc/default/socat
OPTIONS="-T 30 -t 30 tcp-l:9889,reuseaddr,fork,crlf system:\"/usr/local/bin/dht11.sh\""
Step 6: Read data from the socat service on the cacti host
This is explained in another post as well, but the needed script in the site/scripts
-directory is a bit different, here’s what I used. Keep in mind that you have to change „PI-IP“ to your local DNS or IP-Adress of the Raspberry Pi.
/usr/share/cacti/site/scripts/dht11.sh
#!/bin/bash outstring=$(/bin/nc PI-IP 9889 | tr -d '\r') echo "${outstring}"
Resources on the internet
These links helped me set this up:
http://www.messtechniklabor.de/artikel-h0000-temperatur_und_luftfeuchtigkeit_messen.html
https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/wiring
http://www.airspayce.com/mikem/bcm2835/