Obsługa czujników wilgotności DHT11/22 – biblioteka.

AM2302

W projekcie który w chwili obecnej wykonuję (opis z prac zostanie opublikowany wkrótce) jest dokonywany pomiar wilgotności. Czujnikiem dokonującym pomiar wilgotności będzie czujnik DHT22. Przedstawiony tutaj opis, oraz biblioteki dotyczy czujników:

  1. DHT11
  2. DHT22

Na tych czujnikach biblioteka została przetestowana, więc jeżeli posiadasz inny typ czujnika, a biblioteka razem z nim współpracuje, daj znać w komentarzach abym mógł umieścić tutaj tą informację. Możliwe, że będzie współpracować również z innymi tego samego producenta, bądź kod będzie wymagał kilku modyfikacji – nie daję pewności, że tak będzie (pisać w razie problemów).

Biblioteka nie posiada funkcji blokujących – w programie nie użyto opóźnień _delay, wszystko jest oparte o Timery sprzętowe i programowe. Konfiguracja i opis biblioteki w dalszej  części artykułu. Najpierw trochę informacji dotyczących samych czujników – sposób działania, konfiguracja i podłączenie.

Alternatywne nazwy dla czujników DHT wyglądają następująco:

  • DHT11 = RHT01
  • DHT21 = RHT02= AM2301 = HM2301
  • DHT22 = RHT03= AM2302
  • DHT33 = RHT04 = AM2303
  • DHT44 = RHT05

Ja używam czujnika DHT11, oraz brata bliźniaka DHT22, czujnik AM2302. Czujniki te posiadają 4 wyprowadzenia z czego jedno nie jest używane:

  1. Vcc
  2. Magistrala 1-przewodowa (podciągnięta do VCC przez rezystor, np. 5k1)
  3. Niepodłączone
  4. GND

Czujniki mogą być zasilane od około 3.3V do 5.5V (napięcia graniczne mogą się różnić od zastosowane czujnika – przed podłączeniem najpierw sprawdź notę katalogową zgodnie z posiadającym czujnikiem).

Zdjęcie z noty katalogowej DHT
Podłączenie czujnika DHT

Komunikacja z czujnikiem odbywa się przy użyciu magistrali jedno przewodowej. Nie jest to typowa 1-wire, lecz jej modyfikacja. Czasy dla stanu logicznego 1 i 0 są inne niż np. dla czujników DS18B20. Jedynka logiczna występuje gdy stan niski wynosi 50us, a stan wysoki 70us, natomiast zero logiczny w przypadku gdy stan niski wynosi również 50us, ale stan wysoki mieści się w zakresie od 26 do 28us.

Dane z noty katalgowej DHT11
Przebieg dla 0 i 1 logicznej

Po podaniu zasilania do układu, należy odczekać co najmniej 1 sekundę na ustabilizowanie się zasilania. Następnie nasz mikrokontroler ustawia linię danych w stan niski, który powinien trwać co najmniej 18ms, po czym stan wysoki powinien trwać od 20us do 40us. Po starcie, uC przechodzi w tryb odbierania Układ DHT potwierdza gotowość ustawiając 0, a następnie 1 logiczną przez 80us. Po tej odpowiedzi, wysyłane są dane, których pakiet wynosi 40bitów. Na zakończenie transmisji układ trzyma stan niski przez 50ms po czym zwalnia linię.

Zdjęcie z noty katalogowej - dht11
Wygląd ramki danych dla czujnika DHT

Pakiet odebranych danych wynosi 40bitów – 5 bajtów. Pierwsze dwa bajty dotyczą wilgotności, kolejne dwa bajty temperatury, natomiast w ostatnim bajcie znajduje się suma kontrolna. W zależności od zastosowanego czujnika, wartość wilgotności i temperatury zajmuje tylko 1 bajt (jak to mam miejsce w czujniku DHT11 ).

Jeżeli dane są poprawnie odebrane to suma 4 pierwszy bajtów jest równa sumie ostatniego bajtu.


Teraz kolej na część programową:

Biblioteka nie korzysta z delay’ów tylko z timerów sprzętowych i programowych. Do tego celu został wykorzystanie Timer0 który zgłasza przerwanie co 20us (implementacja i konfiguracja wewnątrz biblioteki), oraz dowolnego Timera konfigurowanego przez użytkownika – przerwanie musi być zgłaszane co 10ms.
Bibliotekę przystosowałem do mikrokontrolerów Atmega32 oraz 48, 88, 168
Możliwa praca z kwarcami 10MHz, 11.0592MHz, 14.7456MHz, 16MHz

Funkcja odczytu zwraca wartość średnią z obecnie dokonanego pomiaru, oraz ostatniej wartości średniej.

Minimalny odstęp między pomiarami wg producenta może wynieść 2sekundy.

W pliku nagłówkowym .h wybieramy do którego pinu podpięty jest nasz czujnik, oraz wybieramy rodzaj czujnika (poprzez wpisanie 1 bądź 2 przy #define DHT).

Na początku programu przed pętlą główną należy wykonać inicjalizację biblioteki poprzez funkcję

ds_init_dht();

(oraz odblokować przerwania – sei() ). Natomiast odczyt z czujnika dokonujemy poprzez funkcję

ds_read_dht( &wilg, &temp);

, gdzie wilg i temp to zmienne do których będą przepisana wartość wilgotności i temperatury. Użytkownik tej biblioteki musi skonfigurować we własnym zakresie przerwanie co 10ms i wstawić do obsługi następujący warunek:

if(dht_ms)
        dht_ms--;

Przykładowe użycie:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>;
#include <stdlib.h>

#include "DS_DHT/ds_dht.h"

//własne biblioteki
#include "DS_uart/uart.h"

char uart_buf[10];

// zmienne - timery programowe
volatile uint16_t Timer1;

uint16_t wilg, temp;

// obsługa timerów programowych
ISR( TIMER2_COMP_vect ) {
	 uint16_t n;

	n = Timer1;		/* 1ms Timer1 */
	if (n) Timer1 = --n;

	if(dht_ms)
		dht_ms--;
}

int main(void){

	// konfiguracja Timer2 
	TCCR2 |= (1<<WGM21);				// tryb CTC
	TCCR2 |= (1<<CS22)|(1<<CS21)|(1<<CS20);		// preskaler = 1024
	OCR2  = 96;					// 10ms 155 dla16
	TIMSK |= (1<<OCIE2);				// przerwanie Compare

	ds_init_dht();

	//konfiguracja rs232
	uart_init(RS_UBRR);

	//wysłanie powitania
	uart_text_P(PSTR("WITAM\n\r"));

	sei();

	//inicjalizacja dht11
	DHT_DDR |= (1 << DHT_PIN);
	DHT_OUT |= (1 << DHT_PIN);

	uint8_t ch = 0;

	while(1){

		if(!Timer1){
			Timer1 = 200;	//co 2s

			ch = ds_read_dht( &wilg, &temp);

			//czy odebrane dane były poprawne
			if(ch==1)
				uart_text_P(PSTR("OK!\n\r"));

			//wyświetlenie wilgotności
			itoa(wilg,uart_buf,10);
			uart_text(uart_buf);
			uart_text_P(PSTR("\n\r"));

			//wyświetlenie temperatury
			itoa(temp,uart_buf,10);
			uart_text(uart_buf);
			uart_text_P(PSTR("\n\n\r"));
		}
	}
}

Zachęcam do pobierania biblioteki i komentowania. W razie jakichś pytań bądź to uwag odnośnie biblioteki, piszcie w komentarzach, bądź przy użyciu formularza na stronie Kontakt.

Pobierz “DS_DHT.zip”

DS_DHT.zip – Pobrano 1276 razy – 3,55 KB

6 Komentarzy

  1. Insane

    Można prosić o upload biblioteki UART?

    1. danielos (Post autora)

      Cześć.
      Udostępniam jedynie bibliotekę do DHT. Przedmiotem wpisu nie była biblioteka do UART, więc jej nie udostępniam i nie udostępnię.

  2. Andrzej

    Witam. Bardzo cenne informacje, szczególnie dla „średnio zaawansowanego”. Rozumiem, że przy braku biblioteki UART trzeba sobie radzić samemu, a wyniki pomiarów są w zmiennych wilg i temp. Czy tak?

    1. danielos (Post autora)

      Dokładnie tak.
      Biblioteka UART, jest dołączona tylko po to żeby wypisać w terminalu odczytane dane. Temperatura, oraz wilgotność dostępne są w zmiennych, które są przekazywane jako argument do funkcji ds_read_dht() – należy pamiętać, że przekazujemy adres do tych zmiennych.

  3. Andrzej

    Dzięki za odpowiedź. Ten fragment kodu to dla mnie dobre pole treningowe. Ja postaram się wyrzucić wyniki na LCD 2×16. Podoba mi się, że to nie wykorzystuje float-ów. Muszę przemyśleć jak działa itoa. Zmienne wilg i temp są typu uint16_t, czegoś tu nie rozumiem, muszę się wczytać w opis tej funkcji.
    Pozdrawiam.

    1. danielos (Post autora)

      Może tego nie opisałem, więc opiszę tutaj: to co jest po przecinku jest zapisana jako wartość całkowita, tzn. jeżeli mamy temperaturę 22,4, w zmiennej będzie zapisane 224, aby ją wyświetlić poprawnie należy podzielić przez 10 (zwykłe dzielenie i modulo).

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *