📜 ⬆️ ⬇️

Raspberry Pi: measure humidity and temperature with DHT11 / DHT22

On Habré already published an article about connecting the temperature sensor DS18B20 to the Raspberry Pi. In our new project, which is built on the Raspberry Pi, it was necessary to measure not only the temperature, but also the humidity. I'll tell you how to connect inexpensive Chinese humidity sensors to the Raspberry Pi. After reviewing several options for various sensors, he focused on the two most popular sensors on the market. This DHT11, which attracted its price of $ 3 (with delivery) and the sensor DHT22 (about $ 10 with delivery).

The main difference between them is in the range of temperatures and measurement accuracy:

DHT11


DHT22




Connection

Connecting to the Raspberry Pi is not particularly difficult: we connect + from the sensor to + 5V on the Raspberry Pi, "-" - to the ground, and a signal to one of the GPIO pins .

')
Install the software

Both sensors use their own protocol instead of the standardized 1 wire, so the software for taking sensor readings will also differ.

First install the C library to work with GPIO www.open.com.au/mikem/bcm2835/index.html
wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.15.tar.gz tar xzf bcm2835-1.15.tar.gz cd bcm2835-1.15/ ./configure make make install 


For reading the data from the sensor, the file on Adafruit_DHT_Driver C was taken as the basis . Without making some changes to work with DHT22, this code refused, I had to change a little.
Therefore, I present a modified version.
ReadDHT.c file
 // 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 <bcm2835.h> #include <unistd.h> #define MAXTIMINGS 100 #define DHT11 11 #define DHT22 22 #define AM2302 22 int readDHT(int type, int pin); int main(int argc, char **argv) { if (!bcm2835_init()) return 1; if (argc != 3) { printf("usage: %s [11|22|2302] GPIOpin#\n", argv[0]); printf("example: %s 2302 4 - Read from an AM2302 connected to GPIO #4\n", argv[0]); return 2; } int type = 0; if (strcmp(argv[1], "11") == 0) type = DHT11; if (strcmp(argv[1], "22") == 0) type = DHT22; if (strcmp(argv[1], "2302") == 0) type = AM2302; if (type == 0) { printf("Select 11, 22, 2303 as type!\n"); return 3; } int dhtpin = atoi(argv[2]); if (dhtpin <= 0) { printf("Please select a valid GPIO pin #\n"); return 3; } printf("Using pin #%d\n", dhtpin); 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; int i=0; // Set GPIO pin to output bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_write(pin, HIGH); usleep(100); 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; // read data! for (i=0; i< MAXTIMINGS; i++) { counter = 0; while ( bcm2835_gpio_lev(pin) == laststate) { counter++; nanosleep(1); // overclocking might change this? if (counter == 100) break; } laststate = bcm2835_gpio_lev(pin); if (counter == 100) break; bits[bitidx++] = counter; if ((i>3) && (i%2 == 0)) { // shove each bit into the storage bytes data[j/8] <<= 1; if (counter > 16) data[j/8] |= 1; j++; } } #ifdef DEBUG for (int i=3; i<bitidx; i+=2) { printf("bit %d: %d\n", i-3, bits[i]); printf("bit %d: %d (%d)\n", i-2, bits[i+1], bits[i+1] > 15); } #endif printf("Data (%d): 0x%x 0x%x 0x%x 0x%x 0x%x\n", j, data[0], data[1], data[2], data[3], data[4]); if ((j >= 39) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) ) { // yay! if (type == DHT11) printf("Temp = %d *C, Hum = %d \%\n", data[2], data[0]); if (type == DHT22) { float f, h; h = data[0] * 256 + data[1]; printf ("%s\n",h); h /= 10; f = (data[2] & 0x7F)* 256 + data[3]; f /= 10.0; if (data[2] & 0x80) f *= -1; printf("Temp = %.1f *C, Hum = %.1f \%\n", f, h); } return 1; } return 0; } 


Compile
 gcc readDHT.c -lbcm2835 -lrt -o readDHT 

We try to read data
 ./readDHT {  11  22} { GPIO  Raspberry PI} 

For example DHT11 is connected to GPIO4
 root@raspberrypi /var/www/application/scripts/DHT # ./readDHT 11 4 Using pin #4 Data (40): 0x23 0x0 0x17 0x0 0x3a Temp = 23 *C, Hum = 35 % 

or DHT22 is connected to GPIO17
 root@raspberrypi /var/www/application/scripts/DHT # ./readDHT 22 17 Using pin #17 Data (40): 0x1 0x75 0x0 0xea 0x60 Temp = 23.4 *C, Hum = 37.3 % 


When implementing the readDHT call, you need to take into account that if the access speed is high (more than once per second) you will receive a CRC Error instead of data.

Saving data from sensors


The data you need to save somewhere, give an example of how you can save data to Google.docs. Since PHP is closer to me, saving is done in PHP using Zend_Gdata_Spreadsheets.

image Prepare google docs. Create a new table and give it a name. We give the names of the columns of the first datetime, the second temperature, the third humidity. From the address bar, copy the id of our table, it will be accessed to the table.

Install php:
 pi@raspberrypi ~ $ sudo apt-get php5 php5-curl unzip 

Create a folder for our project:
 pi@raspberrypi ~ $ mkdir /home/pi/dht 

Download and unzip the Zend Framework:
 pi@raspberrypi ~ $ mkdir /home/pi/dht/library pi@raspberrypi ~ $ cd /home/pi/dht/library pi@raspberrypi ~ $ wget http://packages.zendframework.com/releases/ZendFramework-1.12.0/ZendFramework-1.12.0-minimal.zip pi@raspberrypi ~ $ unzip ZendFramework-1.12.0-minimal.zip pi@raspberrypi ~ $ ln -s ZendFramework-1.12.0-minimal/library/Zend Zend 


DHTtoGoogleDocs.php
 <?php ini_set("include_path",get_include_path().':/home/pi/dht/library'); require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_Spreadsheets'); Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); define('GDATA_USER','googleusername'); define('GDATA_PASSWORD','google user password'); define('GDATA_SPREADSHEET_KEY','spreadsheetkey from url'); define('GDATA_WORKSHEET_ID','od6'); try { $t = new Temperature_DHT(); // get data from sensor $data = $t->getData(11,4); $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME; $client = Zend_Gdata_ClientLogin::getHttpClient(GDATA_USER, GDATA_PASSWORD, $service); $service = new Zend_Gdata_Spreadsheets($client); // add row to spreadsheet $row = array( 'datetime'=>date("Ymd H:i:s"), 'temperature'=>$data[0], 'humidity'=>$data[1], ); $service->insertRow($row, GDATA_SPREADSHEET_KEY, GDATA_WORKSHEET_ID); } catch (Exception $e) { die( $e->getMessage() ); } class Temperature_DHT { private $_maxFailCount=5; public function getData($type, $pin) { $count = 0; while ($count<=$this->_maxFailCount) { $count++; $filename = '/home/pi/dht/readDHT'; $out = exec ("$filename $type $pin"); if(preg_match("'^Temp = ([0-9\.]+) \*C, Hum = ([0-9\.]+) %'", $out,$result)) { return array($result[1],$result[2]); } } } } 


Check file operation, run:
 pi@raspberrypi ~ $ php DHTtoGoogleDocs.php 

It remains only to put the call "php DHTtoGoogleDocs.php" in cron.

As an experiment, data were collected for almost a month with an interval of 10 minutes in the same room and stored in google docs, the sensors were located nearby. Who is interested can look at the range of values .
From the data collected by both sensors, it can be said that if you just need to understand whether the humidity is changing, then the DHT11 sensor is enough. But, if you want the displayed value to be close to the value of a household weather station, then it is better to use DHT22.

Source: https://habr.com/ru/post/167459/


All Articles