ESP8266 i DHT22 – pomiar temperatury i wilgotności przez WiFi

Pierwsze zabawy z ESP8266 już za mną, pora zrobić coś pożytecznego. Na pierwszy ogień pójdzie współpraca z czujnikiem wilgotności i temperatury – DHT22, a dokładniej – jego obudowaną wersją – AM2301. ESP będzie pracował pod kontrolą firmware NodeMcu, co oznacza, że program będziemy tworzyć w języku Lua.

ESP8266 i DHT22

Zacznijmy od sprzętu. Co będzie potrzebne? ESP-01, który jest najprostszą wersją ESP8266 i posiada wyprowadzone 2 wyjścia GPIO. Potrzebny będzie też sam czujnik temperatury – AM2301, który jest zgodny z popularnym sensowem DHT22. Całość trzeba jeszcze zasilić napięciem 3,3V, więc przyda się stabilizator napięcia. Ja użyłem popularnego LD33V. Stabilizator wymaga użycia dwóch kondensatorów. Całość wraz z goldpinami wlutowałem na płytkę uniwersalną dodając jeszcze na wszelki wypadek piny połączone z napięciem przez rezystory (1100Ω i 4700Ω), jakby kiedyś trzeba było podłączyć coś jeszcze (choćby przez one-wire). Do całości podłączony jest zasilacz 7,5V, ale skoro mamy stabilizator, to może napięcie być oczywiście inne.

Zasilanie (3,3V) i masa zostały podłączone zarówno do ESP, jak i czujnika DHT (czerwone i czarne przewody). Pomarańczowy przewód połączył zasilanie z CH_PD (ESP-01). A żółte przewody łączą przwód danych czujnika z pinem GPIO2 w ESP. Sprzętowo, jak widać, jest to bardzo prosty układ.

AM2301

Ciekawy jest sam czujnik wilgotności. AM2301, znany jako DHT21, zgodny z DHT22 oferuje dobry zakres pomiarów (0%-100% wilgotność i -40 do 80 stopni C), jak i niewielki błąd (poniżej 3 punktów procentowych wilgotności i ćwierć stopnia Ceslsjusza w najbardziej interesującym zakresie temperatur). Komunikacja odbywa się przez jeden przewód (plus oczywiście zasilanie). Czujnik nie wymaga kalibracji. Zasilany może być napięciem 3,3 – 5,2V, a przewód łączący z układem nadrzędnym może mieć do 20m (zapewne przy 3,3V – mniej). W roli higrometru pokojowego sprawdzi się więc idealnie. Sam czujnik sprawdziłem już przy okazji innegro projektu i spisuje się świetnie.

Sprzętowo wszystko jasne, więc możemy przejść do programowania. Jako, że to pierwszy projekt w NodeMcu, więc na początek kilka uwag praktycznych, które nasunęły mi się przy tworzeniu pierwszego programu. Sam kod jest bardzo prosty, natomiast jego pisanie, a przede wszystkim testowanie nastęczyło drobnych problemów. Nic wielkiego, ale jednak.

Przede wszystkim – pamięć. Komenda print(node.heap()) wyświetla rozmiar wolnej pamięci (sterty, możemy uznać, że jest to tożsame) i o ten rozmiar będziemy dbać. Dlaczego? Bo mamy jej bardzo ograniczoną ilość, szczególnie, że posługujemy się językiem skryptowym, interpretowanym, nieco rozrzutnym w tym względzie. Ja uznałem, że warto zwrócić na to uwagę, do tego stopnia, że przy każdej komunikacji z serwerem będę przesyłał informację o rozmiarze wolnej pamięci. Być może jestem nieco przewrażliwiony, natomiast można się spodziewać, że wycieki pamięci przy naszym programie, używanych modułach, a także w interpreterze języka mogą być (acz nie muszą) bolesne.

Być może jestem przewrażliwiony, natomiast projekt zrealizowałem na firmware z 8 stycznia, zamiast na najnowszym, bo w tym drugim był problem z dołączeniem biblioteki do DHT22 – być może ze względu na dostępną mniejszą wielkość wolnej pamięci. Dodatkowo postanowiłem restartować układ (node.restart()), gdy wielkość stosu spadnie poniżej jakiejś wartości. Trochę dmuchanie na zimne, bo układ pewnie zrobiłby to sam, natomiast dla działania tego projektu nie ma to żadnego znaczenia – nic z nim nie będzie się łączyć, nie jest istotne zachowanie stanów, chodzi jedynie o cykliczne wysyłanie pomiarów do serwera.

ESP8266 + AM2301 (DHT21)

Problemy z firmware nauczyły mnie jednej podstawowej rzeczy – przy tworzeniu rozwiązania nie warto umieszczać głównego od razu w init.lua. Jeżeli błąd spowoduje, że układ będzie się co chwilę restartował, to nie uda się wgrać poprawionego pliku i trzeba będzie zacząć od wgrania nowego firmware. Lepiej więc program umieścić np. w test.lua i uruchamiać go wydając komendę require(‚test’) lub dofile(‚test.lua’).

Przejdźmy do samego programu. Jego celem jest cykliczne odczytywanie pomiarów z czujnika i wysyłanie tych pomiarów do serwera www (przez zapytanie GET). Cykliczne wywołanie pomiarów będzie się odbywało przez jeden z zegarów, uruchomiony funkcją tmr.alarm. Po każdym pomiarze (także nieudanym) będzie uruchamiana komunikacja z serwerem (także przez zegar, dla zachowania jak największej asychroniczności i dla oddania wątku na obsługę systemu, np. wifi). Co jakiś czas będzie też uruchamiana funkcja sprawdzająca czy nie warto zrestartować układu (w przypadku niewielkiej dostępnej pamięci lub po określonej liczbie błędów komunikacji). Jak pisałem, to trochę dmuchanie na zimne, bo próby pokazują, że zaniki połączenia są dobrze obsługiwane, ale urządzenie ma pracować w trybie ciągłym, więc im więcej przypadków obsłużymy, tym lepiej. Poza rozmiarem pamięci przy każdym połączeniu raportowany będzie też numer komunikacji – dla wykrycia ewentualnych restartów.

dht22 = require("dht22")
gpio0 = 3
gpio2 = 4
local timeout=60000
local tmrtimeout=6
local lasttemp = -100
local lasthum = -100
local numreq=0;
local connwait=false;
local numerr=0;
local httpsend=function(txt)
 if connwait == true then
 numerr=numerr+1
 else
 connwait=true
 tmr.alarm(tmrtimeout, timeout, 0, function() conn:close() connwait=false numerr=numerr+1 end)
 conn=net.createConnection(net.TCP, 0) 
 conn:on("receive", function(conn, pl) print(pl) end)
 conn:on("sent", function(conn) numreq=numreq+1 end)
 conn:on("connection", function(conn) conn:send("GET /url/pomiar.php?i="..node.chipid().."&h="..node.heap().."&rq="..numreq..txt.." HTTP/1.0\nHost: www.luksoft.org\n\n") end)
 conn:on("disconnection", function(conn) conn:close() tmr.stop(tmrtimeout) connwait=false end)
 conn:connect(80,"www.mojserwer.com")
 end
end
local checknode=function()
 if numerr>20 then node.restart() end 
 if node.heap()<1000 then node.restart() end
end
local checkdht=function()
 dht22.read(gpio2)
 t = dht22.getTemperature()
 h = dht22.getHumidity()
if t>-400 then 
 lasttemp=t
 lasthum=h
 tmr.alarm(2, 50, 0, function() httpsend("&t="..lasttemp.."&h="..lasthum) end)
 else
 tmr.alarm(2, 50, 0, function() httpsend("&msg=dhtproblem") end)
 end
end
tmr.alarm(0, 10000, 1, checkdht)
tmr.alarm(1, 90000, 1, checknode)

Program wykorzystuje moduł do obsługi DHT22, który odpowiada za całą obsługę czujnika. Dla lepszej czytelności, trzy kluczowe funkcje zostały wyróżnione kolorami, natomiast do analizy kodu najlepiej skopiować go do jakiegoś edytora, żeby mieć pewność, że końce wierszy nie zostały ucięte. Przy powyższych parametrach, zapytania wykonywane są co 10 sekund. Docelowo planuję minutę, natomiast na razie testuję także stabilność układu, stąd częste zapytania.

Co po drugiej stronie? Skrypt php, który odbiera pomiary (dzieli przez 10, dla uzyskania właściwych wartości) i przez rddtool zapisuje w pliku. Następnie generowane są wykresy zmian temperatury i wiglotności. Poniważ ten fragment opisywałem już przy innej okazji, teraz nie będę do tego wracał.

Czy ESP8266 z oprogramowniem NodeMCU działa stabilnie? Zobaczymy. To pierwsze urządzenie ma między innymi na celu zdiagnozowanie stabilności układu i oprogramowania. ESP8266 posiadam od niedawna i do tej pory nie miałem problemu, jednak póki co najdłużej działający układ wykonuje zapytania dopiero czwartą dobę, trudno więc cokolwiek wyrokować. Ja w każdym razie wiążę z tym układem spore nadzieje.

Reklamy

19 Responses to ESP8266 i DHT22 – pomiar temperatury i wilgotności przez WiFi

  1. karaczan says:

    Jak u ciebie wyglądają odczyty wilgotności z DHT22 zasilanego z 3.3v?
    Bo u mnie bardzo zawyżają w stosunku do pomiarów przy zasilaniu 5v.
    Temperaturę podają ok, wilgotność jest zawyżana.

  2. Relius says:

    Zachecam autora do dalszego rozwoju bloga. Trafaia on w 100% w moje gusta 🙂

  3. Pluto says:

    Nie bawiłem się jeszcze ESP8266, ale podobno ma spore zapotrzebowanie na prąd co wyklucza zasilanie z baterii. Nie lepiej Arduino Pro Mini z nRF24L01+?

  4. rs says:

    Prośba o poprawny kod. Bo ten zamieszczony jest poucinany. Jest też błąd ” if node.heap()<1000en node.restart() end" Chyba po 1000 powinno byc then.
    pierwsza linia kodu "dht22 = require("dht22")"
    Czy czasem nie chodzi o zwykły plik dht22.lua (https://github.com/javieryanez/nodemcu-modules), a nie o bibliotekę. Bo jeśli jest to biblioteka, to skąd ją pobrać?
    Czy ten kod programu rzeczywiście pokazuje zbliżone temperatury do rzeczywistych. Może wrzucisz wyniki na thingspeak`a.
    Mój czujnik bardzo dobrze sprawuje się na Lankontrolerze. Na ESP8266 (z nodemcu) daleki jest od rzeczywistości.
    Proszę o odpowiedź ze strony autora.

    • techniczny says:

      U mnie kod widać poprawnie. Jeżeli coś ucina, to proponuję zaznaczyć cały kod i wkleić do schowka. Biblioteka to zasadniczo zwykły plik – zbiór funkcji/klas – tak chodzi o ten.

  5. kamil says:

    Możesz jeszcze napisać jak zamieścić program w pamięci esp8266?

  6. Leszek says:

    Cześć.

    Czy zauważyłeś u siebie, żeby temperatura była podawana jako dwukrotna wartość prawdziwej (np. zamiast 18 wyświetla 36)? U mnie tak się czasem dzieje i nie wiem, gdzie szukać błędu… Dotyczy to różnych egzemplarzy DHT22, więc raczej nie wina sprzętu.

    • techniczny says:

      Nie, przy dwóch czujnikach pracujących przynajmniej od roku, nie zauważyłem ani razu takiego stanu. Może masz coś z oprogramowaniem.

      • Leszek says:

        Ciekawe – ten sam program, ten sam egzemplarz DHT22, ale inny egzemplarz ESP8266 i działa poprawnie.

  7. Mike says:

    Muszę przyznać że ESP8266 Jest dosyć obiecujące.., Jako że drogi autor tego bloga posiada go dłużej, może pan powiedzieć coś o stabilności na ten moment?. Jeśli to cudeńko jest dosyć stabilne to z pewnością się skuszę na jego zakup. Pozdrawiam

  8. Michał says:

    Mam pytanie-mogę prosić o łopatologiczną podpowiedź jak zmusić esp do zapisu wilgotności i temp do dwóch oddzielnych plików na serwerze np 192.168.1.1?

    • techniczny says:

      Trzeba napisać skrypt, np. w php, który będzie zapisywał wartości do pliku. ESP ma wywoływać ten skrypt z parametrami – wilgotnością i temperaturą.

      • Michał says:

        Dane beda zbierane na RPI. Bawiłem sie w to z rddtool i 1 wire ale z esp to dla mnie nowość. Czy możecie podrzucić skrypt który zbierałby dane z esp i dht22?

        Chciałbym teź umieść pod dht czujnik nasłonecznienia i ciśnienia atmosferycznego..
        Będzie to wykorzystywane do zbierania danych z tunelu foliowego (30m x 7m)

  9. Michał says:

    Niestety, ale wywoływanie skryptu php na RPI nie działa. Skrypt z ręcznie podanymi wartościami w pasku dodaje wartości do bazy, jednak nie potrafię sobie poradzić z wywołaniem skryptu php na serwerze z poziomu esp..moge liczyć na pomoc?

  10. Subribe says:

    Witam, zamieścisz całość? Wszystkie potrzebne pliki do wgrania do ESP? Tak aby tylko podmienić dane do połączenia oraz ip bazy danych.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

%d blogerów lubi to: