W tym artykule kontynuujemy rozbudowę naszej zdalnej stacji pogodowej. Przebudujemy kod aplikacji do pracy z większą ilością czujników, podłączymy pierwszy czujnik oraz odpowiednio przechowamy dane w naszej bazie.
W pierwszej kolejności zajmiemy się podłączeniem naszego czujnika do modułu Nodemcu. Czujnik gazu wyposażony jest w dwa wyjścia służące do odczytu danych: D0 oraz A0. W pierwszym przypadku możemy za pomocą potencjometru ustawić wartość progową po przekroczeniu której czujnik będzie wysyłał nam sygnał o zbyt dużym stężeniu gazu. W przypadku wyjścia A0 odczytujemy wartości z zakresu od 0 do 1023 na wejściu przetwornika analogowo-cyfrowego. W naszej stacji pogodowej wykorzystamy wyjście A0.
Podłączenie czujnika jest niezwykle proste i sprowadza się jedynie do podłączenia dowolnego źródła zasilania 5 V do czujnika oraz wyjścia A0 czujnika do wejścia A0 modułu Nodemcu.
Jeżeli mamy prawidłowo podpięty czujnik, to możemy przejść do pisania kodu naszej aplikacji. W tym artykule zmienimy trochę koncepcję naszego projektu i zmienimy bibliotekę z której będziemy korzystać na FirebaseESP8266. Link do pobrania biblioteki znajdziecie w załączniku na końcu artykułu. Dodatkowo wprowadzimy do naszej bazy funkcjonalność pobierania aktualnej daty, którą wykorzystamy w późniejszym czasie do wyświetlania naszych pomiarów na wykresach. Bibliotekę do tego służącą pobieramy z menadżera bibliotek wpisując frazę „ESPDateTime”.
Pierwszą istotną zmianą w kodzie jest odejście od korzystania z klucza API na rzecz sekretnego tokenu. Pokażę teraz jak znaleźć taki token w kilku krokach.
- Wchodzimy w nasz projekt na platformie Firebase.
- Wchodzimy w zakładkę Project Settings.
- Wybieramy zakładkę Service accounts, a następnie klikamy w Database secrets.
- Najeżdżamy kursorem w pole Secret i za pomocą przycisku Show, ujawniamy nasz ciąg znaków. Całość kopiujemy i zapisujemy.
Drugim z istotnych elementów jest modyfikacja adresu naszej bazy. W poprzednim kodzie kopiowaliśmy cały adres łącznie z przedrostkiem https://, natomiast w tym przypadku wykorzystamy ten sam adres, ale bez przedrostka.
#include <FirebaseESP8266.h> #include <ESPDateTime.h> #include<sstream> #include <Arduino.h> #if defined(ESP32) #include <WiFi.h> #elif defined(ESP8266) #include <ESP8266WiFi.h> #endif #define WIFI_SSID "" // Nazwa naszej sieci wi-fi #define WIFI_PASSWORD "" // Hasło do naszej sieci #define HOST "" // Ciąg znaków z pola secrets. #define DATABASE_URL "" // Adres naszej bazy bez przedrostka https:// FirebaseData firebaseData; // Stworzenie objektu klasy FirebaseData void setup() { Serial.begin(9600); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { // Oczekujemy na połączenie z WiFi Serial.print("."); delay(300); } Firebase.begin(DATABASE_URL, HOST); // Łączymy się z bazą za pomocą adresu bazy i sekretnego ciągu znaków Firebase.reconnectWiFi(true); // Przeładowanie wiFi setupDateTime(); // Ustawiamy odpowiednie parametry do przechwycenia obecnej daty } void setupDateTime() { DateTime.setServer("time.pool.aliyun.com"); // Wybieramy serwer z którego będziemy pobierali datę DateTime.setTimeZone("GMT-2"); // Ustawiamy strefę czasową dla Polski DateTime.begin(); // Uruchamiamy nasze przechwytywanie daty DateTime.toISOString().c_str(); // Konwertujemy datę do typu String DateTime.now(); // Pobieramy czas w s jaki upłynął od daty bazowej : 01.01.1970 delay(1000); } template <typename T> // Ta funkcja służy do zniwelowania błędu który się pojawiał podczas próby użycia metody to_string. std::string to_string(T value) { std::ostringstream os ; os << value ; return os.str() ; } void pomiarDymu(int ilosc, int pomiar, String data) // Funkcja realizująca pomiar dymu { std::string sciezka = "Dym/Pomiar_" + to_string(ilosc); // Ustawiamy odpowiednią ścieżkę bazując na zmiennej ilosc String czujnikDymu = String(sciezka.c_str()); // Konwertujemy naszą ścieżkę na typ String String wskazanieCzujnikaDymu = czujnikDymu + "/Wskazanie"; // Ustawiamy ścieżkę dla wskazania czujnika String dataCzujnikaDymu = czujnikDymu + "/Data"; // Ustawiamy ścieżkę dla daty Firebase.setInt(firebaseData, wskazanieCzujnikaDymu, pomiar); // Przesyłamy wartość wskazania do bazy Firebase.setString(firebaseData, dataCzujnikaDymu, data); // Przesyłamy wartość daty do bazy } int iloscPomiarowDym() { // Funkcja sprawdzająca aktualną ilość pomiarów int iloscPomiarow; Firebase.getInt(firebaseData, "Dym/IloscPomiarow", &iloscPomiarow); // Pobieramy numer ostatniego pomiaru iloscPomiarow++; // Zwiększamy numer o 1 Firebase.setInt(firebaseData, "Dym/IloscPomiarow", iloscPomiarow); // Przesyłamy do bazy następny numer return iloscPomiarow; // Zwracamy numer } void loop() { delay(5000); // Czekamy 5s przed każdym pomiarem int pomiarCzujnikaDymu = analogRead(A0); // Pobieramy wartość wskazania czujnika z konwertera A/C dla pinu A0 String currentTime = DateTime.format(DateFormatter::SIMPLE).c_str(); // Ustawiamy format czasu na YYYY/MM/DD HH:MM:SS pomiarDymu(iloscPomiarowDym(), pomiarCzujnikaDymu, currentTime); // Realizujemy funkcję pomiaru zawartości dymu }
Na początku programu łączymy się z naszą bazą danych poprzez obiekt klasy FirebaseDatabase, następnie oczekujemy na połączenie się z siecią WiFi. Następnie konfigurujemy klasę DataTime, aby poprawnie wyświetlała wartość aktualnej daty dla czasu polskiego. Po przeprowadzeniu wstępnej konfiguracji w nieskończonej pętli wykonujemy następujące kroki:
- Odczekujemy 5s
- Odczytujemy wartość wskazania czujnika
- Ustawiamy format czasu na YYYY/MM/DD HH:MM:SS
- Wywołujemy funkcję pomiarDymu() z argumentami : iloscPomiarowDymu() jako zwracana obecna ilość pomiarów powiększona o 1, odczyt wartości jakości powietrza z konwertera oraz obecna data.
Po przepisaniu powyższego kodu możemy przejść do przygotowania naszej bazy do pierwszego pomiaru, później nie będzie to już konieczne. Tworzymy tabelę Dym, a następnie pod tą tabelą tworzymy zmienną IloscPomiarow o wartości 0.
Jeżeli kod poprawnie nam się skompilował powinniśmy uzyskać następujący rezultat: