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:
- DHT11
- 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:
- Vcc
- Magistrala 1-przewodowa (podciągnięta do VCC przez rezystor, np. 5k1)
- Niepodłączone
- 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).

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.

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ę.

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
Można prosić o upload biblioteki UART?
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ę.
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?
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.
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.
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).