Obsługa czujnika DHT11 / DHT22 na przykładzie Arduino

dht11_arduino

DHT11, oraz DHT22 to czujniki temperatury i wilgotności powietrza. Często wykorzystuje się je, choćby do budowy amatorskich stacji pogodowych. Czujniki oferują całkiem dobrą jakość odczytów, a ich obsługa jest bardzo prosta. W tym wpisie pokażę jak je obsługiwać, na przykładzie mikrokontrolera esp8266 i „języka” Arduino. Jednak bez większych problemów przepiszesz całość do innego standardu.

Kod github: https://github.com/mcinm/arduino/tree/main/DHT11_22

DHT11/22 Komunikacja

Czujniki te posiadają tylko cztery wyprowadzenia. Oczywiście, VCC i GND do zasilenia układu, pin zazwyczaj oznaczony jako „S” od słowa „Signal”, oraz czwarty pin, który nie pełni żadnej funkcji. W przypadku płytek przeznaczonych dla arduino, wyprowadzone są najczęściej tylko trzy piny.
Mimo, że do sterowania używa się tylko jednego pinu, transmisja nie jest realizowana za pośrednictwem protokołu 1-Wire. Co często, błędnie jest podawane w różnych źródłach.

DHT11 pinout (DHT22 wygląda podobnie)

Poniżej zamieszczam grafikę przedstawiającą proces komunikacji z modułem. Schematy pochodzą z jednej z wielu dostępnych w Internecie dokumentacji.

DHT11 / 22 Komunikacja
DHT get data
DHT odbiór danych

Na samym początku, musimy wysłać polecenie start (zapytanie) do modułu. Jest to dobrze przedstawione na grafice – wystarczy wystawić stan niski na pinie Signal, przez co najmniej 18 ms.
Kolejno, z powrotem przywrócić stan wysoki i odczekać ok. 20 – 40 us. I w ten sposób powstaje nasza pierwsza funkcja „request”.

#define DHT_GPIO 0

void request(void)
{
  pinMode(DHT_GPIO, OUTPUT);
  digitalWrite(DHT_GPIO, LOW);
  delay(20);
  digitalWrite(DHT_GPIO, HIGH);
  delayMicroseconds(35);
}

Następnym krokiem będzie odebranie odpowiedzi od modułu. Ten wystawia stan niski na 80 us, a następnie stan wysoki, także na 80 us. W kodzie nie użyłem teraz funkcji opóźniających, a po prostu pętle. Przed nimi, trzeba jeszcze zmienić tryb pracy wyprowadzenia mikrokontrolera na wejściowy.

void response(void)
{
  pinMode(DHT_GPIO, INPUT);
  while (digitalRead(DHT_GPIO));
  while (!(digitalRead(DHT_GPIO)));
  while (digitalRead(DHT_GPIO));	
}

Odczyt danych

Po tej prostej sekwencji, mikrokontroler powinien być gotowy na przyjęcie nadchodzących danych.
Z modułu nadejdzie pięć bajtów. Będą to kolejno:

  1. Wilgotność powietrza (wartość po przecinku)
  2. Wilgotność powietrza (wartość całkowita)
  3. Temperatura (wartość po przecinku)
  4. Temperatura (wartość całkowita)
  5. Suma kontrolna (Checksum)

Suma kontrolna to wartość sumy wszystkich czterech wartość (bajty 1-4). W ten sposób sprawdzać będziemy, czy odczyt został poprawnie odebrany.

Samo odbieranie danych jest bardzo proste. Układ wystawia najpierw stan niski, a następnie wysoki, to czy nadchodzący bit jest zerem, czy jedynką weryfikujemy przez sprawdzenie czasu trwania impulsu wysokiego. Jeżeli trwa on 26-28 us, to bit jest zerem, a jeżeli trwa 70 us – jedynką. W taki sposób układ czujnika wysyła 8 bitów, jeden po drugim.
Powtarza to 5 razy (5 bajtów). Tak będzie wyglądał kod odbioru bajtu:

unsigned char get_data(void)
{
  unsigned char data = 0;
  for (unsigned char i=0; i<8; i++)
  {
    while (!(digitalRead(DHT_GPIO)));
    delayMicroseconds(30);
    if (digitalRead(DHT_GPIO)) data = (data<<1) | (0x01);
    else data = (data<<1);
    while (digitalRead(DHT_GPIO));
  }
  return data;
}

DHT11 / DHT22 przykład

To w zasadzie wszystko, teraz wystarczy w kodzie programu dodać naszą bibliotekę i stworzyć tablice przechowującą dane, oraz funkcję je pobierającą. Ja zrobiłem to w taki sposób:

unsigned char tab[5];

void get_mes(void)
{
  request();
  response();
  
  tab[0] = get_data();
  tab[1] = get_data();
  tab[2] = get_data();
  tab[3] = get_data();
  tab[4] = get_data();
  
  unsigned char control = tab[0] + tab[1] + tab[2] + tab[3];
  if (control != tab[4]) get_mes();
}

Funkcja ta będzie pobierała odczyty z modułu i wstawiała je w utworzoną wcześniej tabelę. Z tymi danymi możemy już zrobić cokolwiek potrzebujemy. Poniżej podałem przykład zastosowania z użyciem mikrokontrolera esp8266, jako prosty czujnik ze zdalnym dostępem. Kod tego programu także znajduje się na github’ie.

Nasz program obsługujący czujnik DHT, nie jest oczywiście zbyt pewnym rozwiązaniem. Brakuje w nim zabezpieczeń przeciwko błędom w odczycie. Przykładowo, jeżeli podczas odbioru danych wystąpią jakieś zakłócenia i nie przejdzie jeden bit, mikrokontroler może zostać zablokowany w nieskończonej pętli.
Ale akurat rozwiązać ten problem jest bardzo prosto – wystarczy dodać kilka sekwencji sprawdzających w kodzie.

Kod ten bez większych problemów można oczywiście przepisać na dowolny język/mikrokontroler.

Dodaj komentarz

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