Основная разница между ними в диапазоне температур и точности измерения:
DHT11
- Влажность 20-80% +- 5%
- Температура 0-50 °С+- 2%
- Данные считываются в целых единицах.
DHT22
- Влажность 0-100% +- 5%
- Температура -40-125 °С +- 0.5%
- Данные считываются с точностью до десятых.
Подключение
Подключение к Raspberry Pi особой сложности не представляет: подключаем + от датчика к +5V на Raspberry Pi, "-" — к земле, и сигнал к одному из GPIO выводов.
Устанавливаем ПО
Оба датччика используют свой протокол вместо стандартизированного 1 wire, поэтому программное обеспечение для снятия показаний датчика тоже будет отличаться.
Сначала установим библиотеку на С для работы с 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
Для чтения данных с датчика за основу был взят файл на С Adafruit_DHT_Driver. Без внесения некоторых изменений работать с DHT22, этот код отказывался, пришлось немного изменить.
// 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; }
Компилируем
gcc readDHT.c -lbcm2835 -lrt -o readDHT
Пробуем считывать данные
./readDHT {тип датчика 11 или 22} {номер GPIO вывода Raspberry PI}
Например DHT11 подключен к 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 %
или DHT11 подключен к 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 %
При реализации вызова readDHT нужно учитывать, что если скорость обращения будет высокая ( чаще чем раз в секунду) вместо данных Вы будете получать CRC Error.
Сохранение данных с датчиков
Полученные данные нужно куда-то сохранять, приведу пример как можно сохранять данные в Google.docs. Т.к. мне ближе PHP, сохранение сделал на PHP с использованием Zend_Gdata_Spreadsheets.
Подготовим google docs. Создадим новую таблицу и дадим ей имя. Дадим имена колонкам первой datetime, второй temperature, третей humidity. Из адресной строки скопируем id нашей таблицы, по нему будет производиться обращение к таблице.
Устанавливаем php:
pi@raspberrypi ~ $ sudo apt-get php5 php5-curl unzip
Создадим папку для нашего проекта:
pi@raspberrypi ~ $ mkdir /home/pi/dht
Загрузим и распакуем 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
<?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("Y-m-d 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]); } } } }
Проверяем работу файла, запускаем:
pi@raspberrypi ~ $ php DHTtoGoogleDocs.php
Осталось только поставить вызов «php DHTtoGoogleDocs.php» в cron.
В качестве эксперимента данные собирались почти месяц с интервалом в 10 минут в одном помещении и сохранялись в google docs, датчики были расположены рядом. Кому интересно можете посмотреть на разброс значений.
Из данных, которые собирали оба дачика, можно сказать, что если нужно просто понять меняется ли влажность, то датчика DHT11 вполне достаточно. Но, если Вы хотите, что бы отображаемое значение было близко к значению бытовой метеостанции, то лучше использовать DHT22.
ссылка на оригинал статьи http://habrahabr.ru/post/167459/
Добавить комментарий