Raspberry Pi — DHT11


24.10.2014

Підключимо датчик температури та вологості DHT11 до Raspberry Pi. Я раніше писав про популярний датчик вологості і температури DHT11 у статті DHT11 — цифровой датчик температуры и влажности Документація по DHT11: DHT11.pdf, DHT11_a.pdf.

Розміри та розпіновка DHT11:

DHT11

Підключимо датчик до Raspberry Pi, як вказано на схемі.

RaspberryPi - DHT11

DHT11 & Raspberry Pi

Почнемо з прикладу на С. Створимо файл dht11.c:


#include <wiringPi.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAXTIMINGS	85
#define DHTPIN		7
int dht11_dat[5] = { 0, 0, 0, 0, 0 };

void read_dht11_dat()
{
	uint8_t laststate	= HIGH;
	uint8_t counter		= 0;
	uint8_t j		= 0, i;
	float	f; /* fahrenheit */

	dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;

	/* pull pin down for 18 milliseconds */
	pinMode( DHTPIN, OUTPUT );
	digitalWrite( DHTPIN, LOW );
	delay( 18 );
	/* then pull it up for 40 microseconds */
	digitalWrite( DHTPIN, HIGH );
	delayMicroseconds( 40 );
	/* prepare to read the pin */
	pinMode( DHTPIN, INPUT );

	/* detect change and read data */
	for ( i = 0; i < MAXTIMINGS; i++ )
	{
		counter = 0;
		while ( digitalRead( DHTPIN ) == laststate )
		{
			counter++;
			delayMicroseconds( 1 );
			if ( counter == 255 )
			{
				break;
			}
		}
		laststate = digitalRead( DHTPIN );

		if ( counter == 255 )
			break;

		/* ignore first 3 transitions */
		if ( (i >= 4) && (i % 2 == 0) )
		{
			/* shove each bit into the storage bytes */
			dht11_dat[j / 8] <<= 1;
			if ( counter > 16 )
				dht11_dat[j / 8] |= 1;
			j++;
		}
	}

	/*
	 * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
	 * print it out if data is good
	 */
	if ( (j >= 40) &&
	     (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
	{
		f = dht11_dat[2] * 9. / 5. + 32;
		printf( "Humidity = %d.%d %% Temperature = %d.%d *C (%.1f *F)",
			dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
	}else  {
		printf( "Data not good, skip" );
	}
}

int main( void )
{
	printf( "Raspberry Pi wiringPi DHT11 Temperature test program" );

	if ( wiringPiSetup() == -1 )
		exit( 1 );

	while ( 1 )
	{
		read_dht11_dat();
		delay( 1000 ); /* wait 1sec to refresh */
	}

	return(0);
}

У цій програмі використовується бібліотека wiringPi. Ми її встановлювали у попередній статті Raspberry Pi — PWM і Сервопривод. Якщо wiringPi ще не встановлено, це робиться наступним чином:


sudo apt-get install git-core
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
cd ..

Cкомпілюємо dht11.c:


gcc dht11.c -o dht11 -lwiringPi

Запустимо програму:


./dht11

На екрані маємо побачити наступне:

Raspberry Pi wiringPi DHT11 Temperature test program
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Data not good, skip
Data not good, skip
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Data not good, skip
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Humidity = 33.0 % Temperature = 27.0 *C (80.6 *F)
Тепер спробуємо приклад на Python. Створімо файл dht11.py:


import RPi.GPIO as GPIO
import time

def bin2dec(string_num):
    return str(int(string_num, 2))

data = []

GPIO.setmode(GPIO.BCM)

GPIO.setup(4,GPIO.OUT)
GPIO.output(4,GPIO.HIGH)
time.sleep(0.025)
GPIO.output(4,GPIO.LOW)
time.sleep(0.02)

GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)

for i in range(0,500):
    data.append(GPIO.input(4))

bit_count = 0
tmp = 0
count = 0
HumidityBit = ""
TemperatureBit = ""
crc = ""

try:
        while data[count] == 1:
                tmp = 1
                count = count + 1

        for i in range(0, 32):
                bit_count = 0

                while data[count] == 0:
                        tmp = 1
                        count = count + 1

                while data[count] == 1:
                        bit_count = bit_count + 1
                        count = count + 1

                if bit_count > 3:
                        if i>=0 and i<8:
                                HumidityBit = HumidityBit + "1"
                        if i>=16 and i<24:
                                TemperatureBit = TemperatureBit + "1"
                else:
                        if i>=0 and i<8:
                                HumidityBit = HumidityBit + "0"
                        if i>=16 and i<24:
                                TemperatureBit = TemperatureBit + "0"

except:
        print "ERR_RANGE"
        exit(0)

try:
        for i in range(0, 8):
                bit_count = 0

                while data[count] == 0:
                        tmp = 1
                        count = count + 1

                while data[count] == 1:
                        bit_count = bit_count + 1
                        count = count + 1

                if bit_count > 3:
                        crc = crc + "1"
                else:
                        crc = crc + "0"
except:
        print "ERR_RANGE"
        exit(0)

Humidity = bin2dec(HumidityBit)
Temperature = bin2dec(TemperatureBit)

if int(Humidity) + int(Temperature) - int(bin2dec(crc)) == 0:
        print "Humidity:"+ Humidity +"%"
        print "Temperature:"+ Temperature +"C"
else:
        print "ERR_CRC"

Запустимо його:


python ./dht11.py

Повинні побачити наступне:

Humidity:33%
Temperature:27C
Але інколи скрипт видає:
ERR_RANGE
Якщо ви звернули увагу приклад на С теж мав проблеми і не завжди міг чітко зчитувати дані. Я довго колупався з цією проблемою і намагався хоч якось її вирішити. Виявилося, що Raspberry Pi ...не працює в режимі реального часу! Тобто, програмні затримки не завжди точні. Це призводить до помилок при зчитуванні даних. Я не знайшов іншого шляху (він мені не подобається, але він працює), як написати скрипта, який намагається зчитувати дані з датчика до першої вдалої спроби. Кількість спроб обмежена 10.

Текст скрипта dht11_read.py:


# This script try to read from DHT11 10 times
# Return first correct result
# Note This script is a way to fix bug of reading from DHT11
import subprocess
counter = 0

while (counter < 10 ):
	result = subprocess.Popen("python /root/scripts/dht11.py", shell = True, stdout = subprocess.PIPE).communicate()[0]
	if (result == "32"):
		print result
		exit(1)
	counter +=1

Успіхів.

Дивись також:

Raspberry Pi
Коментарі:
Додати коментар
Code
* - обов'язкові поля

Архіви