Witam!
Chciałbym tutaj przedstawić już chyba czwartą na majsterkowie stację meteorologiczną. Głównym celem projektu jest pomiar prędkości wiatru, kierunku wiatru, opadów deszczu, ciśnienia, oraz temperatury i wilgotności, a następnie przesyłanie wyników na zewnętrzny serwer.
Całość jest zrealizowana pod kontrolą płytki D1 R1 opartej na module WIFI ESP8266.
Założenia projektowe
- Projekt ma być prosty w realizacji i w miarę niezawodny.
- Pomiar prędkości wiatru.
- Pomiar kierunku wiatru.
- Pomiar opadów.
- Pomiar ciśnienia.
- Pomiar temperatury.
- Pomiar wilgotności.
- Przesyłanie wyników na zewnętrzny serwer przez WIFI.
- Wizualizacja danych w postaci ładnych wykresów.
- Możliwość łatwego odczytu danych zarówno z komputera jak i ze smartphona.
- Koszt poniżej 500 zł.
- Możliwość ewentualnej rozbudowy o kolejne sensory.
Lista części
- Płytka D1 R1
Cały projekt został zbudowany na płytce D1 R1 opartej o moduł WIFI ESP8266.
Płytka kosztuje 35 zł i zapewnia zarówno kontrolę projektu jak i łączność z siecią.
- Czujnik DHT22
Temperatura i wilgotność jest mierzona za pomocą czujnika DHT22. Zakres pomiaru temperatury to -40 C do 80 C a wilgotności od 0% do 100%. Dokładność pomiaru temperatury to +- 0.5 C* a wilgotności +- 2%.
- Czujnik BMP180
Ciśnienie jest mierzone za pomocą czujnika BMP180. Zapewnia on dokładność rzędu 0.02 hPa. Komunikacja z mikrokontrolerem odbywa się za pomocą magistrali I2C.
- Zestaw czujników pogodowych ( Anemometr, Wskaźnik kierunku wiatru, Deszczomierz ).
Jest to najdroższy element stacji (335 zł). Wcześniej próbowałem zbudować własne czujniki jednak po miesiącu zrezygnowałem i kupiłem gotowy zestaw.
- Pozostałe elementy
- Dwa gniazda RJ11. Niezbędne do podłączenia czujników prędkości i kierunku wiatru oraz deszczomierza bez obcinania kabli.
- Trzy kondensatory 100 nF.
- Dwa rezystory 4.7 K
- Dwa rezystory 10 K
- Jeden kabel pięciożyłowy do podłączenia płytki z czujnikami. Długość zależna od potrzeb, nie może być za długi bo sygnał będzie zniekształcony. Ja użyłem kabla o długości 1.5 metra i wszystko działa.
- Jeden kabel dwużyłowy do podłączenia zasilania, długość zależna od potrzeb.
- Kilka krótszych kabelków do podłączenia wszystkiego na płytkach uniwersalnych.
- Dwie płytki uniwersalne.
- Jedna ładowarka 9 V 0.5 A.
Generalnie koszt całości zamknął się poniżej 450 zł.
Odczyt danych z czujników
Jeśli chodzi o czujniki DHT22 i BMP180 odczyt danych jest prosty. Wystarczy podłączyć sensory i użyć odpowiednich bibliotek.
Problem pojawia się w przypadku czujników prędkości i kierunku wiatru oraz deszczomierza.
Z dokumentacji można się dowiedzieć, że czujniki te są czysto mechaniczne.
We wnętrzu deszczomierza znajduje się małe wahadełko. Kiedy do wnętrza wpadnie 0.2794 mm deszczu, wahadełko zmienia pozycje wylewając zawartość. Na wahadle znajduje się magnes który przechodzi przed kontaktronem powodując krótkie zwarcie obwodu. To oznacza, że odczyt danych można wykonać za pomocą takiego prostego układu :
Jeden pin jest podłączony do masy, drugi pin jest podłączony do 3.3V przez rezystor 4.7 K. Pin ten jest także podłączony do wejścia cyfrowego modułu ESP co umożliwia rejestrację impulsów. Kiedy kontaktron zwiera obwód, stan logiczny na pinie cyfrowym zmienia się z wysokiego na niski.
Kondensator 100 nF jest dodany w celu eliminacji drgań styków.
Jeśli chodzi o wyprowadzenia na wtyczce to w tym wypadku sprawa jest prosta :
We wtyczce są tylko dwa styki, a ponieważ kontaktron po prostu zwiera obwód, to nie jest ważne które wyprowadzenie jest które.
Czujnik prędkości wiatru działa podobnie jak deszczomierz. W środku znajduje się kontaktron który zwiera obwód dwa razy na obrót czaszy anemometru.
Z kolei czujnik kierunku wiatru działa jak rezystor. Wewnątrz znajduje się zestaw kontaktronów podłączonych przez rezystory.
Kiedy strzałka się obraca, magnes zwiera określone kontaktrony co zmienia rezystancję czujnika. Wartość tą można odczytać stosując dzielnik napięcia. Kiedy jeden rezystor będzie stały a drugi będzie zmieniał swoją wartość wtedy napięcia wyjściowe dzielnika będzie się zmieniać w zależności od kierunku wiatru wskazywanego przez czujnik.
Część odpowiedzialna za pomiar prędkości wiatru jest taka sama jak w przypadku deszczomierza.
Schemat potrzebny do pomiaru prędkości i kierunku wiatru.
Wtyczka wiatromierza ma nieco więcej wyprowadzeń niż wtyczka deszczomierza :
Jednak niestety nie obyło się bez problemów z podłączeniem czujników.
Pierwszy z nich dotyczył deszczomierza. Okazało się, że czasami zamiast zewrzeć i rozewrzeć obwód, kontaktron tylko obwód zwierał lub rozwierał. Problem leży gdzieś w części mechanicznej deszczomierza. Po kilku próbach zdecydowałem się problem obejść w programie sterującym. W końcu odczyt zmienia się przy zmianie położenia wahadła, nie da się tylko przewidzieć jak się zmieni.
Drugi problem dotyczył przerwań. Okazało się, że mimo eliminacji drgań styków ( sprawdzone oscyloskopem ), moduł ESP liczył jeden impuls z wiatromierza jako 2 a czasami 3. Po 2 godzinach w końcu zdecydowałem się na obejście problemu w programie sterującym. Prędkość wiatru nie jest mierzona za pomocą przerwań.
Trzeci problem dotyczył czujnika kierunku wiatru. Okazało się, że obliczenia napięcia z dzielnika wykonane na podstawie danych z dokumentacji, nie zgadzają się z rzeczywistymi wynikami. Problem został rozwiązany przez ponowną kalibrację czujnika.
Ostatni problem dotyczył samej płytki sterującej. Okazało się bowiem, że niektóre piny modułu ESP8266 mają przypisane różne funkcje które sprawiały, że po podłączeniu do nich sensorów albo sensory nie działały albo płytka nie działała. Problem rozwiązany sprawdzając po kolei różne kombinacje. W końcu udało się trafić na taką która działa.
Elektronika
Cała stacja składa się z 2 płytek. Na jednej znajduje się osprzęt czujników prędkości i kierunku wiatru oraz deszczomierza. Na drugiej znajduje się czujnik ciśnienia oraz czujnik DHT22.
Płytka z czujnikami jest bardzo prosta, to właściwie tylko moduł barometru BMP180 oraz czujnik DHT22. Pin DATA czujnika DHT22 jest podłączony do 3.3V przez rezystor 10K w celu utrzymania stanu wysokiego kiedy nie są przesyłane dane. Oprócz tego zastosowałem kondensator 100 nF w celu filtracji zakłóceń zasilania.
Sygnał z czujnika DHT22 jest podłączony do pinu D9, pin SDA barometru jest podłączony do SD14 natomiast SCL do SD15.
Na płytce głównej jest nieco więcej elementów. Jeden pin wyprowadzenia deszczomierza jest podłączony do 3.3V przez rezystor podciągający 4.7 K, jest on również podłączony do pinu D8 w celu odczytu danych. Drugi pin jest podłączony do GND (masy układu). Dzięki temu, kiedy wahadełko w deszczomierzu zmienia swoją pozycję, zmienia się również stan pinu modułu ESP. Pomiędzy tymi dwoma pinami dodałem również kondensator 100 nF w celu eliminacji drgań styków.
Anemometr działa tak samo jak deszczomierz więc osprzęt jest identyczny. Jeden pin podłączony przez rezystor 4.7 K do 3.3V, drugi podłączony do masy.
Z tym, że tym razem sygnał trafia do pinu oznaczonego jako D11/D7.
Sygnał z dzielnika napięcia trafia do wejścia analogowego A0.
Po montażu całość wygląda tak :
Zbliżenie na elektronikę :
Jak widać całość została zmontowana na płytkach uniwersalnych i zabezpieczona dużą ilością kleju na gorąco. Jednak najprawdopodobniej to nie jest ostateczna wersja projektu więc specjalnie mi to nie przeszkadza.
Instalacja płytki w Arduino IDE
Aby móc zaprogramować płytkę D1 R1 w Arduino IDE musimy ją najpierw zainstalować za pomocą menagera płytek.
Aby to zrobić trzeba :
- Uruchomić Arduino IDE i wejść w Plik -> Preferencje.
- W miejscu na dodatkowe adresy URL wkleić to : http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Kliknąć OK.
- Wejść w Narzędzia -> Płytka -> Menadżer płytek
- Zainstalować moduł ESP8266 będący prawdopodobnie na dole listy.
Od tej pory kiedy trzeba będzie wgrać program na naszą płytkę, trzeba będzie wejść w Narzędzia -> Płytka a następnie ustawić płytkę na WeMos D1 , prędkość procesora na 80 MHz, flash size na 4M ( 1 M SPIFFS) i upload speed na 921600.
Niestety zauważyłem pewne problemy z ładowaniem programu do płytki. Mimo, że wszystko jest dobrze ustawione, płytka często odmawia przyjęcia programu. Jednak po kilku próbach zazwyczaj się udaje. Jeśli nie to pomaga odłączenie i ponowne podłączenie do komputera. Jeśli nie to należy odłączyć wszystko od płytki i spróbować ponownie.
Testowy program
Po zmontowaniu elektroniki napisałem prosty program którego zadaniem jest sprawdzenie czy wszystko działa i kalibracja czujnika kierunku wiatru.
Kod jest bogaty w komentarze więc nie powinno być problemów z jego zrozumieniem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
// biblioteki #include <Wire.h> // Biblioteka do obsługi I2C #include <Adafruit_BMP085.h> // Biblioteka do obsługi BMP180 #include "DHT.h" // Biblioteka do obsługi DHT22 #include <Esp.h> // Biblioteka do obsługi zaawansowanych funkcji modułu ESP // Definicje pinów // Notatka : Nie chodzi o numer pinu (Dx ) tylko o numer interface ( GPIOx ). Numery te są zapisane na drugiej stronie płytki. #define DHTPIN 2 // Pin DHT22. #define DHTTYPE DHT22 // Nasz sensor to DHT22 #define DIR A0 // Pin do pomiaru kierunku wiatru #define WIN 12 // Pin do pomiaru prędkości wiatru #define RAI 0 // Pin do pomiaru opadów // Obiekty Adafruit_BMP085 bmp; // Obiekt sensora BMP180 DHT dht(DHTPIN, DHTTYPE); // Obiekt czujnika DHT22 // Zmienne globalne unsigned int rai=0;// Licznik deszczu bool r=0;// Flaga deszczomierza unsigned long timer=0;// Zmienna od opóźnienia między pomiarami void rn(){ // Wektor przerwania deszczomierza r=1;// Stawiamy flagę deszczomierza } void rai_maintenance(){// Funkcja sprawdzająca deszczomierz if(r==1){ // Sprawdzamy flagę deszczomierza delay(200);// Czekamy 200 ms to na wypadek gdyby impuls był poprawny r=0;// Resetujemy flagę deszczomierza rai++;// Zwiększamy licznik deszczu o 1 } } void setup() { Serial.begin(9600); // uruchamiamy serial port Serial.println("Uruchamianie"); if(!bmp.begin()) {// uruchamiamy czujnik BMP180 Serial.println("blad barometru"); while (1) {} } dht.begin();// uruchamiamy DHT22 // ustawiamy piny jako wejścia pinMode(DIR,INPUT); pinMode(WIN,INPUT); pinMode(RAI,INPUT); // uruchamiamy przerwanie deszczomierza, ustawiamy je na zmianę stanu logicznego (zawsze następującą po przechyleniu wahadełka) attachInterrupt(digitalPinToInterrupt(RAI), rn, CHANGE); } void loop() { rai_maintenance();// sprawdzamy deszczomierz if(millis()>timer){// jeśli czas na pomiary Serial.println("rozpoczynam pomiary"); // tworzymy zmienne na wyniki pomiarów float temp;// temperatura float wil;//wilgotność double cis;// ciśnienie float kier;// kierunek wiatru double desz;// opady int wia=0;// prędkość wiatru Serial.println("pomiar wiatru"); unsigned long timer2=millis()+3000;// czas pomiaru 3000 ms ( 3s ) bool stat=digitalRead(WIN);// zmienna poprzedniego stanu logicznego pinu wiatromierza bool v;// zmienna aktualnego stanu pinu wiatromierza ESP.wdtDisable();// wyłączamy watchdoga modułu esp8266 na czas pomiaru ( inaczej moduł by się zresetował) while(1){// pętla pomiaru wiatru rai_maintenance();// sprawdzamy deszczomierz unsigned long cur=millis();// aktualny czas if(cur>timer2){// jeśli czas pomiaru się skończył wtedy wychodzimy z pętli break; } v=digitalRead(WIN);// mierzymy stan logiczny pinu wiatromierza if(stat!=v){// jeśli stan różni się od stanu poprzedniego stat=v;// ustawiamy zmienną stanu poprzedniego na stan aktualny delay(5);// czekamy 5 ms wia++;// zwiększamy licznik wiatru o 1 } } ESP.wdtFeed();// resetujemy flagę watchdoga ESP.wdtEnable(3200);// uruchamiamy ponownie watchdog kier=analogRead(DIR);// mierzymy napięcie z dzielnika napięcia wil=dht.readHumidity();// mierzymy wilgotność temp=dht.readTemperature();// mierzymy temperaturę cis=bmp.readPressure();// mierzymy ciśnienie cis=cis/100;// mierzymy ciśnienie // wyświetlamy dane przez serial port Serial.println("----------------"); Serial.print("temperatura: "); Serial.print(temp); Serial.println(" C*"); Serial.print("Wilgotnosc: "); Serial.print(wil); Serial.println(" %"); Serial.print("cisnienie: "); Serial.print(cis); Serial.println("hPa"); Serial.print("Predkosc wiatru: "); Serial.println(wia); Serial.print("kierunek wiatru: "); Serial.println(kier); Serial.print("deszcz: "); Serial.println(rai); Serial.println(); timer=millis()+13000;// ustawiamy początek następnego pomiaru na za 13 s } } |
Po wgraniu kodu i uruchomienia monitora portu szeregowego powinno się pokazać coś takiego :
W polach temperatura i wilgotność podawane są dane z czujnika DHT22. Jeśli pojawią się tam wartości NAN ( Not A Number) to oznacza, że coś jest nie tak. W większości wypadków pomaga jednak zwykłe wyłączenie i włączenie zasilania. Jeśli to nie pomoże to oznacza, że problem leży w podłączeniu czujnika lub w samym czujniku.
Ciśnienie to wartość ciśnienia atmosferycznego , podawana w hektopaskalach.
W polu prędkość wiatru mamy ilość impulsów z wiatromierza zarejestrowanych podczas 3 sekund pomiarów. Na jeden pełny obrót czaszy powinny przypadać 4 impulsy. Za jeden impuls przyjąłem zmianę stanu logicznego wejścia.
Kierunek wiatru to wartość napięcia z dzielnika odczytana przez przetwornik analogowo cyfrowy. Powinna się zmieniać w zależności od położenia strzałki.
W polu deszcz mamy ilość impulsów z deszczomierza. Jeden impuls oznacza, że spadło 0.2794 mm deszczu.
Przeliczanie danych z czujników
Jeśli chodzi o temperaturę i wilgotność to nie musimy nic przeliczać. Dane są od razu podawane w procentach i stopniach celsjusza.
Jeśli chodzi o ciśnienie to jest ono podawane w paskalach. Żeby uzyskać bardziej przyjazną wartość w hektopaskalach należy ją podzielić przez 100.
Obliczanie opadów też jest dość proste. Należy po prostu pomnożyć ilość impulsów z deszczomierza razy 0.2794. Uzyskany wynik to ilość opadów w milimetrach.
Prędkość wiatru to zupełnie inna historia.
Cały proces został dokładnie opisany w akademii nettigo : http://akademia.nettigo.pl/czujnik_wiatru/
I przyznam, że wykorzystał kod właśnie stąd. Jednak z pewnymi modyfikacjami. Po pierwsze pomiar ilości impulsów trwa 3 sekundy a nie 1 sekundę. Po drugie na jeden obrót uzyskujemy 4 impulsy a nie 2 impulsy. Dlatego w linijce :
1 |
rpm = half_revolutions * 30; |
Zmieniłem 30 na 5 ( 30 /3 i potem jeszcze /2 ).
Zmodyfikowałem też sposób wykrywania impulsów i kilka innych drobiazgów.
Przeliczanie kierunku wiatru też jest dość skomplikowane.
Zaglądając do tabeli z dokumentacji zestawu można stwierdzić jakie kierunku jest w stanie wskazać czujnik :
Jest ich szesnaście. Przy każdym czujnik ma inną rezystancję co zmienia wartość napięcia z dzielnika. Niestety jak już wspomniałem uzyskiwane wyniki nie zgadzały się z tymi z obliczeń więc musiałem na nowo skalibrować czujnik. W tym celu wgrałem wspomniany już wcześniej program testowy a następnie powoli obracałem strzałkę i zapisywałem wartości odczytywane z dzielnika dla każdego kierunku.
Programowo rozpoznawanie kolejnych kierunków odbywa się za pomocą instrukcji warunkowych :
1 2 3 |
if ((value >122) && (value < 130)){ dir=157.5; } |
Value to wartość odczytana z dzielnika. Dir to kierunek wiatru.
Jak widać wystarczy wpisać wartości graniczne pomiędzy którymi musi znaleźć się odczyt dla danego kierunku wiatru. W tym wypadku muszą się one mieścić w przedziale (122,130). Okno ma szerokość +-3 jednostki.
Ponieważ możliwych kierunków jest 16 więc w finalnym programie znajduje się 16 instrukcji warunkowych rozpoznających kierunek wiatru.
Uruchomienie kanału na Thingspeak
Jako zewnętrzny serwer na który będą przesyłane dane wybrałem Thingspeak. Jest to bardzo wygodne rozwiązanie ponieważ Thingspeak automatycznie zapisuje dane, prezentuje je w formie wykresów a także umożliwia dostęp przez zewnętrzne aplikacje.
Pierwszym krokiem do zbierania danych w tym serwisie jest rejestracja.
W tym celu wchodzimy na https://thingspeak.com/ , klikamy sing up i przechodzimy przez cały proces rejestracji.
Kiedy już się zarejestrujemy, oczom naszym ukaże się taka strona.
Aby zacząć zbierać dane musimy utworzyć nowy kanał klikając “New Channel”.
Teraz powinna otworzyć się strona konfiguracyjna nowego kanału.
Możemy tutaj wprowadzić różne informacje ale obowiązkowe jest tylko pole nazwa.
No i musimy wybrać nazwę i ilość pól. Jedno pole odpowiada jednej wartości jaka będzie przesyłana do naszego kanału.
Po wprowadzeniu danych należy kliknąć “Save Channel”.
I na tym kończy się proces tworzenia nowego kanału.
Przesyłanie danych do Thingspeak
Na początku ważna uwaga : Do niedawna Thingspeak był całkowicie darmowy. Niedawno jednak został wprowadzony system płatnych licencji. To znaczy, że teraz za darmo można wysyłać max 3 000 000 wiadomości na rok a wielkość wiadomości nie może przekroczyć 3000 bitów. Jednak to w zupełności wystarcza dla tego projektu. Trzy miliony wiadomości na rok oznacza, że mogę wysyłać :
3000 000 / 365 / 24 / 60 ~ 5 wiadomości na minutę. To oznacza jedną co 12 sekund. A ponieważ nie można wysyłać danych częściej niż co 15 sekund więc przekroczenie limitu raczej mi nie grozi. Jednak ponieważ planuję w przyszłości jeszcze kilka projektów z wykorzystaniem Thingspeak więc postanowiłem wysyłać dane raz na 30 sekund co oszczędzi mi ponad 50% wiadomości na pozostałe projekty.
Ale do rzeczy.
Krótki program który wysyła dwie stałe liczby do kanału na Thinspeak.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#include <ESP8266WiFi.h> // biblioteka do łączenie z wifi String apiKey = "#############";// klucz zapisu do kanału const char* ssid = "######";// nazwa sieci wifi const char* password = "##########";// hasło do sieci wifi const char* server = "api.thingspeak.com";// adres serwera thingspeak WiFiClient client;// obiekt klienta sieci wifi void setup() { Serial.begin(9600); // uruchamiamy serial port Serial.println(); Serial.println(); Serial.print("Loncze z : "); Serial.println(ssid); WiFi.begin(ssid, password); //łączymy się z siecią while (WiFi.status() != WL_CONNECTED) { // czekamy na połączenie z siecią delay(500); Serial.print("."); } Serial.println(""); Serial.println("WIFI podlonczone"); } void loop() { if (client.connect(server,80)) { // łączymy się z serwerem na porcie 80 Serial.println("Wysylam dane..."); String postStr = apiKey; // tworzymy stringa wiadomości postStr +="&field1="; // pole 1 postStr += String(20); // wartość pola 1 ( liczba skonwerterowana do stringa ) postStr +="&field2="; // pole 2 postStr += String(10); // wartość pola ( liczba skonwerterowana do stringa) postStr += "\r\n\r\n"; // wysyłamy żądanie client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(postStr.length()); client.print("\n\n"); client.print(postStr); Serial.println("Dane wyslane!"); } delay(1000); // czekamy 1 s client.stop();// kończymy połączenie Serial.println("Czekam"); delay(20000);// czekamy 20 s } |
Przed wgraniem należy jednak wpisać kilka wartości :
1 |
const char* ssid = "######"; |
Tutaj w miejscu ##### należy wpisać nazwę sieci z jaką ma połączyć się moduł.
1 |
const char* password = "##########"; |
Tutaj należy wpisać hasło dostępu do sieci.
1 |
String apiKey = "#############"; |
Tutaj z kolei należy wpisać klucz który umożliwia zapis do kanału.
Klucz dostępu do kanału można znaleźć w zakładce API keys w menu kanału. Jest to klucz oznaczony jako Write API Key.
Jeśli wszystko dobrze skonfigurowaliśmy, po wgraniu kodu w serial monitorze powinno się pokazać coś takiego :
Natomiast na naszym kanale Thingspeak powinny się pokazać dane :
Finalny kod programu
Kiedy już mamy gotowy pomiar danych z sensorów i przesyłanie danych do Thingspeak, pora połączyć to wszystko w jedno.
Ważna uwaga : O ile do testowego programu potrzebny był kanał o ilości pól równej 2, teraz potrzebujemy 6 pól danych.
Kod programu :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
// biblioteki #include <ESP8266WiFi.h> #include <Wire.h> #include <Adafruit_BMP085.h> #include "DHT.h" #include <Esp.h> // stałe String apiKey = "#############"; const char* ssid = "######"; const char* password = "########"; const char* server = "api.thingspeak.com"; // definicje pinów #define DHTPIN 2 #define DHTTYPE DHT22 #define DIR A0 #define WIN 12 #define RAI 0 // obiekty Adafruit_BMP085 bmp; DHT dht(DHTPIN, DHTTYPE); WiFiClient client; // zmienne globalne unsigned int rai=0; bool r=0; unsigned long timer; void rn(){// wektor przerwania deszczomierza r=1; } void rai_maintenance(){// funkcja sprawdzająca deszczomierz if(r==1){ delay(200); r=0; rai++; } } void setup() { Serial.begin(9600); Serial.println("Uruchamianie"); if(!bmp.begin()) { // uruchamiamy barometr Serial.println("Barometr ERROR"); while (1) {} } dht.begin();// uruchamiamy czujnik DHT22 // ustawiamy piny jako wejścia pinMode(DIR,INPUT); pinMode(WIN,INPUT); pinMode(RAI,INPUT); attachInterrupt(digitalPinToInterrupt(RAI), rn, CHANGE); // uruchamiamy przerwanie deszczomierza Serial.println("Lonczenie z sieciom"); WiFi.begin(ssid, password);// odpalamy wifi while (WiFi.status() != WL_CONNECTED) {// czekamy na połączenie z siecią Serial.print("."); delay(500); } Serial.println("Polonczono!"); } void loop() { rai_maintenance();// sprawdzamy deszczomierz if(millis()>timer){// kiedy czas na pomiary... Serial.println("Pomiar..."); // zmienne na wyniki int win=0; float temp; float hum; float pres; float dir; double rain; //pomiary // prędkość wiatru Serial.println("Pomiar wiatru..."); unsigned long timer2=millis()+3000; bool state=digitalRead(WIN); bool val; ESP.wdtDisable(); while(1){ rai_maintenance(); unsigned long current=millis(); if(current>timer2){ break; } val=digitalRead(WIN); if(state!=val){ state=val; delay(5); win++; } } ESP.wdtFeed(); ESP.wdtEnable(3200); int value=analogRead(DIR); // liczenie // deszczomierz rain=rai*0.2794;// mnożymy razy 0.2794 aby uzyskać ilość deszczu w mm //prędkość wiatru win=win*5;//*30/3/2 float wind= 2.75 / 12 * 3.14 * win * 60 / 5280; wind = wind * 3.5; wind = wind * 1.609; // teraz zmienna wind przechowuje prędkość wiatru w km/h // kierunek wiatru // 16 instrukcji warunkowych na 16 kierunków wiatru if ((value >752) && (value < 760)){ dir=0; } if ((value >396) && (value < 404)){ dir=22.5; } if ((value >447) && (value < 455)){ dir=45; } if ((value >81) && (value < 89)){ dir=67.5; } if ((value >90) && (value < 94)){ dir=90; } if ((value >64) && (value < 72)){ dir=112.5; } if ((value >181) && (value < 189)){ dir=135; } if ((value >122) && (value < 130)){ dir=157.5; } if ((value >279) && (value < 287)){ dir=180; } if ((value >238) && (value < 236)){ dir=202.5; } if ((value >604) && (value < 612)){ dir=225; } if ((value >577) && (value < 585)){ dir=247.5; } if ((value >900) && (value < 908)){ dir=270; } if ((value >790) && (value < 798)){ dir=292.5; } if ((value >844) && (value < 852)){ dir=315; } if ((value >675) && (value < 883)){ dir=337.5; } // reszta pomiarów hum=dht.readHumidity(); temp=dht.readTemperature(); pres=bmp.readPressure(); pres=pres/100; // wysyłanie danych na thingspeak Serial.println("Wysylam dane..."); if (client.connect(server,80)) { String postStr = apiKey; // 6 pól danych postStr +="&field1="; postStr += String(temp); postStr +="&field2="; postStr += String(hum); postStr +="&field3="; postStr += String(pres); postStr +="&field4="; postStr += String(wind); postStr +="&field5="; postStr += String(dir); postStr +="&field6="; postStr += String(rain); postStr += "\r\n\r\n"; client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(postStr.length()); client.print("\n\n"); client.print(postStr); } delay(1000); client.stop(); Serial.println("Dane wyslane"); timer=millis()+26000;// czekamy 26 sekund do rozpoczęcia następnego pomiaru } } |
Po uruchomieniu na nasz kanał Thingspeak powinny zacząć spływać dane.
Fajną rzeczą na Thingspeak jest to, że możemy dodawać różne wizualizacje w oparciu o dane.
W tym wypadku postanowiłem dodać wizualizację prędkości i kierunku wiatru na kompasie.
Aby to zrobić trzeba wejść w MATLAB visualization w menu kanału.
Następnie trzeba wybrać wizualizację. Istnieje również napisanie własnego kodu.
Następnie należy uzupełnić kod tworzący wizualizację wpisując identyfikator kanału, numer pola z którego ma być pobierana prędkość wiatru, numer pola kierunku wiatru. Niezbędny jest też klucz API do odczytu danych. (Read API Key).
Dla ułatwienia, lista kanałów wraz z ich polami danych oraz kluczami wyświetla się po prawej stronie okna przeglądarki.
Następnie należy zaznaczyć do jakich kanałów należy dodać wizualizację i czy ma być ona publiczna czy prywatna.
Na koniec należy wizualizację uruchomić i zapisać za pomocą przycisku Save and Run.
Efekt :
Obudowa
Elektronika i program skończone więc pora na obudowę.
Ponieważ od niedawna jestem posiadaczem drukarki 3D więc postanowiłem wypróbować swoje siły w programie tinkercad i zaprojektować ją własnoręcznie.
Obudowa od modułu centralnego :
Jest to po prostu zwykłe pudełko o wymiarach 133x92x44mm. W ściankach znajdują się otwory na wyprowadzenie kabli a w środku są bolce które przytrzymują płytkę sterującą na miejscu.
Wydrukowałem z materiału PLA, grubość warstwy 0.3mm prędkość 40 mm/s. Niezbędne były podpory, inaczej nie wydrukowały by się otwory na kable.
Musiałem drukować w dwóch częściach bo pokrywka się nie zmieściła razem z pudełkiem. Pokrywka też z PLA, na takich samych ustawieniach. Pokrywka nie wymagała jednak podpór.
Drugą obudową jaką musiałem stworzyć była obudowa do płytki z sensorami:
Ustawienia takie same jak w przypadku poprzedniej obudowy. Wydruk wychodzi ładnie nawet bez podpór.
Pokrywka ma otwory które umożliwiają dopływ powietrza do czujnika temperatury i wilgotności. Duży otwór jest do wyprowadzenia kabli.
W spodzie pudełka są 4 otwory które umożliwiają odpływ wody (jeśli jakaś by się do środka dostała).
Góra pudełka jest nachylona do tyłu dzięki czemu woda nie cieknie bezpośrednio na kratkę.
Obudowy po wydrukowaniu :
Po doszlifowaniu krawędzi całość ładnie się złożyła.
Pliki STL są dostępne do pobrania na końcu artykułu.
Finalny montaż
Montaż całości zacząłem od dwóch spostrzeżeń. Pierwsze dotyczyło tego, że płytka sterująca razem z wtyczką zasilającą włożoną do gniazda nie zmieści się w obudowie ( sic! ). Drugie dotyczyło tego, że projektując obudowy nie uwzględniłem, że kable od płytki są przymocowane na stałe do komputera a płytka w żadnym razie nie przejdzie przez otwory na kable ( SIC! ).
Ponieważ nie chciałem wyrzucać obudowy i drukować kolejnej, zdecydowałem się na prowizoryczne rozwiązanie problemu. Wylutowałem gniazdo z płytki i przylutowałem przewody zasilające bezpośrednio w jego miejsce.
Po uporaniu się z pierwszym problemem musiałem uciąć taśmę łączącą czujniki z płytką sterującą aby przełożyć ją przez otwory na kable. Po zamontowaniu wszystkiego w obudowie, ponownie ją zlutowałem.
Na szczęście więcej problemów nie było i projekt gładko zmieścił się w obudowie. Zostało też całkiem sporo miejsca na wypadek potrzeby modernizacji.
Płytka z sensorami :
Po ostatecznym sprawdzeniu czy wszystko działa, zakleiłem klejem otwory na kable aby woda nie dostała się do środka.
A następnie zamknąłem obie obudowy pokrywkami.
Pokrywki wchodzą bardzo ciasno na wcisk więc nie powinny przepuszczać wody.
Gotowy do zamontowania zestaw :
Efekt końcowy :
Może balkon nie jest idealnym miejscem do pomiaru prędkości wiatru ale do testów wystarczy. Docelowo projekt znajdzie się na dachu.
Zainstalowałem też sobie widget Thingspeak na smartphona który pobiera dane z serwera co 5 minut.
Aplikację można pobrać ze sklepu google play. Nazwa to : IoT ThingSpeak Monitor Widget.
Klasyczny widok z okna przeglądarki.
Kilka słów na koniec
Na koniec chciałbym powiedzieć, że wszystkie założenia projektowe zostały zrealizowane.
Całość działa jak na razie bezproblemowo. Montaż na dachu jest planowany za miesiąc jak tylko potwierdzę, że nie ma żadnych problemów technicznych.
No i to tyle. : )
Robię coś podobnego, też używam dht22 i tego samego widżetu na androida, taki rezultat pomiarów póki co:
https://thingspeak.com/apps/plugins/140992
Tylko ja używam nodemcu v3 (esp8266), na zewnątrz kombinuje zasilanie solarne do czujnika. Chcę dołożyć jeszcze pomiar smogu, a później tym wszystkim sterować wentylacją i klimatyzacją. ;)
Poproszę o adres do pobrania widgeta dla Thingspeak’a
Możesz go pobrać z google play. Aplikacja nazywa się : IoT ThingSpeak Monitor Widget.
Pobrałem go i zainstalowałem, ale się nie uruchamia.
Mam androida 6 na hu…
Co robię źle?
Bardzo fajnie zrealizowany projekt. Ze swojej strony mogę podsunąć pomysł na bardzo znaczne obniżenie kosztów stacji. Ja swego czasu nabyłem gotową stację, w której po 3 latach zepsuł mi się nadajnik a ponieważ nie mogłem dostać nowego zacząłem szukać stacji używanych. I mi się udało nabyć stację zepsutą gdzie zepsuty był odbiornik. Pozostałe elementy były sprawne, tak więc prędkościomierz, kierunkomierz wiatru, czujnik opadów można za bardzo tanie pieniądze zdobyć kupując zepsutą stację.
Jednak wykorzystując czujniki z istniejącej stacji musiałbym najpierw je zhakować żeby odczytać z nich dane. W przypadku czujników które użyłem miałem całą dokumentację techniczną + gotowe przykłady w internecie. Jeśli chodzi o obniżanie kosztów to można to zrobić kupując czujniki na Ebay albo na Aliexpres. Myślę, że jakieś by się znalazły.
Spoko projekt.
Kawał dobrej roboty :)
Gdzie można kupić taki zestaw (czujnik wiatru, deszczomierz)? Chciałbym kupić taki sam
Możesz kupić ten zestaw na Botlandzie albo na Nettigo.
Ilekroć nie spojrzę na drukowaną obudowę zastanawiam się, czy autor nie widzi jakie to jest brzydkie i że lepszy efekt można uzyskać stosując gotowe obudowy zakupione w sklepie z elektroniką. Rozumiem, że posiadanie drukarki daje pewne możliwości.. ale no jednak te obudowy są po prostu brzydkie. Jeszcze, żeby były one idealnie spasowane i dostosowane do PCB czy elementów wewnętrznych – ale nie są. Wszystko przyklejone na klej. Czy tylko ja nie widzę w tym sensu?
Swoje urządzenia montuję w obudowach sklepowych, płytki umieszczam na tulejkach dystansowych i wygląda to schludnie z zewnątrz a i w środku przyjemny widok dla oka i nic nie odpadnie, nie zewrze się. Sprzyja to również ewentualnym naprawom – łatwiej rozkręcić niż pozbyć się takiego klejowego gluta.
Nie bierz tego specjalnie do siebie, ale dostrzegam ostatnio jakieś takie promowanie kiczu wśród populacji majsterkowiczów, zamiast faworyzowania rozwiązań, które warto naśladować i zastanawiam się, czy ja już jestem starej daty i nie ogarniam, że teraz się po prostu robi byle jak, w modelu chińskim. Szkoda trochę, bo na dobry projekt, do tego starannie wykonany – których ostatnio mało, to aż miło popatrzeć. A takie zlepki drucików, kleju i obudów w stylu rosyjskim z lat 80 ubiegłego wieku jakoś tak do mnie nie przemawiają. Jako prototyp owszem, ale nie jako urządzenie, które warto pokazać innym. Byle by szybko zlutować, pokleić, dodać Arduino i jakiś serwis webowy i pstryk… opublikować światu i czekać na lajki… To o to chodzi? Hmm.
Bartek, oczywiście że widzimy klej i brzydkie pudełka. Tylko sposób napisania o tym jest godny malkontenta. Ja bym napisał że projekt super ale popracuj nad estetyką wykonania. Estetyka wpłynie także na przejrzystość projektu bo ciężko np. znaleźć zimne luty w glucie plastiku. Opis zawiera schematy i zwraca uwagę na detale jak rezystory podciągające i kondensatory eliminujące drgania zestyków, opisuje także w jaki sposób podejść do uruchomienia integracji z serwisami chmurowymi (zwraca uwagę na testy i migrację produkcyjną). Kawał dobrej roboty!
Cały projekt jest fajnie opisany i mi na pewno pomoże bo walczę z czymś takim już trochę czasu. Na pewno wykorzystam ten materiał do swoich prób.
Pozdrawiam
Wielki szacun za naprawdę fajny projekt. Gratuluje pomysłu.
Mam zrobiony podobny projekt lecz na uno (nie pomysłem o D1 a nie chciałem korzystać z ESP2866), zamiast bmp 180 użyłem BME 280, ciśnienie, wigotnosc i temperatura w jednym module, dokładniejszy od DTH22, zamiast dwóch modułów wykorzystujemy jeden.
Dla osób chcących taniej kopić wiatromierz (2,49 £), deszczomierz (4,49 £), kierunkowskaz wiatru (9,99 £) w sumie daje w sumie 80 zl wiec 4,5 razy taniej niż pisze autor polecam sklep Maplin – wysyłają do PL.
Jak wygląda opad deszczu sam się kasuje po godzinie 0:00 na Thingspeak
Bo musisz w ustawieniach wykresu określić z jakiego zakresu czasu chcesz aby dane się wyświetlały
Rozumiem że jako “centrala” używane jest Arduino IDE i Płytka D1 R1? Proszę o poprawę jeżeli jest inaczej, jestem nowy w temacie.
Jako centrala używana jest płytka D1R1 ale dane trafiają do thingspeak a nie do arduino IDE.
Dzięki, napisałem bo zobaczyłem “Aby móc zaprogramować płytkę D1 R1 w Arduino IDE musimy ją najpierw zainstalować za pomocą menagera płytek.” myślałem że trzeba. A tak w ogóle to pomysł świetny, będę zabierał się za zrobienie go. Mógłbyś jeszcze podać linka do “Zestaw czujników pogodowych (Anemometr, Wskaźnik kierunku wiatru, Deszczomierz).” ? Gdzie się wpisuje te kody?
Kod źródłowy programu wpisuje się w arduino IDE a następnie kompiluje i wgrywa do płytki.
Jednak aby można było to zrobić najpierw trzeba zainstalować odpowiednie narzędzia w arduino IDE (przez menagera płytek).
Zestaw czujników można kupić na botlandzie lub na nettigo ale jak fenek4 wspomniał w komentarzu, czujniki te można kupić znacznie taniej w innym sklepie (pewno na aliexpress też będą).
No to czekaj. To w końcu D1R1 to płytka, a Arduino IDE jest potrzebne do stworzenia projektu?
D1R1 to płytka, a Arduino IDE to program który instalujesz na komputerze aby wgrać kod do tej płytki i zrobić testy.
Potem Arduino IDE nie jest potrzebne bo dane trafiają bezpośrednio do internetu.
Aha, myślałem że Arduino IDE to płytka. Dzięki za wyprowadzenie mnie z błędu.
Tą stację można jeszcze rozbudować o detektorów wyładowań atmosferycznych?
Myślę, że tak choć to zależy od tego jakiego interface używa detektor.
Witam można dostać wszystkie biblioteki bo jest z tym mały problem