W dzisiejszym artykule zajmiemy się kontynuacją rozbudowy naszej zdalnej stacji pogodowej. Stworzymy istotny element naszego projektu jakim jest komunikacja moduły Nodemcu z bazą danych oraz wyświetlimy otrzymane wyniki na stworzonym poprzednio emulatorze.
Jako przykład wykorzystamy ultradźwiękowy czujnik odległości HC-SR04. Prześlemy wartości otrzymane z czujnika za pomocą komunikacji WiFi z wykorzystaniem modułu Nodemcu V3, który zawiera wbudowany moduł esp8266. Do połączenia modułu z bazą posłużymy się dedykowaną dla arduino biblioteką Firebase.
W pierwszej kolejności podłączymy nasz układ. Schemat podłączenia prezentuje się następująco :
Po podłączeniu układu możemy przejść do odpowiedniego zaprogramowania naszego modułu mcu. W tym celu uruchamiamy naszą bazę danych. Stworzenie bazy danych krok po kroku zostało opisane w poprzednim artykule. Wchodzimy w zakładkę RealTime Database i kopiujemy widoczny tam link do naszej bazy.
Następnie wchodzimy w settings->project settings i kopiujemy znajdujący się tam Web API Key.
Po skopiowaniu obu linków przechodzimy do programowania naszego modułu. Po uruchomieniu arduino przechodzimy do menadżera bibliotek, wpisujemy frazę “Firebase” i instalujemy następującą bibliotekę:
Tworzymy nowy plik i wpisujemy kod naszego programu.
#include <Arduino.h> #if defined(ESP32) #include <WiFi.h> #elif defined(ESP8266) #include <ESP8266WiFi.h> #endif #include <Firebase_ESP_Client.h> #include "addons/TokenHelper.h" #include "addons/RTDBHelper.h" #define WIFI_SSID "Nazwa wifi do którego podłączony jest komputer" #define WIFI_PASSWORD "Hasło do wifi" #define trigPin D0 #define echoPin D1 #define API_KEY "Tu wklej skopiowany wcześniej WEB API KEY" #define DATABASE_URL "Tu wklej link do bazy" FirebaseData fbdo; FirebaseAuth auth; FirebaseConfig config; unsigned long sendDataPrevMillis = 0; int count = 0; bool signupOK = false; long czas, dystans; void setup(){ Serial.begin(9600); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to Wi-Fi"); while (WiFi.status() != WL_CONNECTED){ Serial.print("."); delay(300); } Serial.println(); Serial.print("Connected with IP: "); Serial.println(WiFi.localIP()); Serial.println(); config.api_key = API_KEY; config.database_url = DATABASE_URL; if (Firebase.signUp(&config, &auth, "", "")){ Serial.println("ok"); signupOK = true; } else{ Serial.printf("%s\n", config.signer.signupError.message.c_str()); } config.token_status_callback = tokenStatusCallback; Firebase.begin(&config, &auth); Firebase.reconnectWiFi(true); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } void loop(){ if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 3000 || sendDataPrevMillis == 0)){ sendDataPrevMillis = millis(); digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); czas = pulseIn(echoPin, HIGH); dystans = czas / 58; Firebase.RTDB.setInt(&fbdo, "Pomiar/int", dystans); } }
Jeżeli wszystko wykonaliśmy poprawnie, po wgraniu programu do naszego modułu i podłączeniu czujnika do źródła zasilania w naszej bazie danych powinny pojawiać się wartości mierzonej przez czujnik odległości.
Możemy przejść do napisania aplikacji mobilnej wyświetlającej w czasie rzeczywistym uzyskaną przez bazę danych wartość . Przerabiamy nieco naszą aplikację z poprzedniego artykułu usuwając przycisk oraz modyfikując pola tekstowe. Gotowy plik activity_main.xml wygląda następująco:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:layout_width="371dp" android:layout_height="112dp" android:text="StacjaPogodowaAjmaker" android:textAlignment="center" android:textSize="80px" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.111" /> <TextView android:id="@+id/describe" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="176dp" android:layout_marginTop="201dp" android:layout_marginEnd="177dp" android:layout_marginBottom="511dp" android:text="Aktualna wartość odległości w cm : " app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/distance" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="176dp" android:layout_marginTop="235dp" android:layout_marginEnd="177dp" android:layout_marginBottom="477dp" android:text=" " app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Przechodzimy do najważniejszego, czyli pliku MainActivity.java który odpowiada za działanie naszej aplikacji. Wklejamy odpowiedni kod uzyskując tym samym gotową do uruchomienia aplikację.
package com.example.stacjapogodowaajmaker; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; public class MainActivity extends AppCompatActivity { TextView currentDistance; DatabaseReference firebaseDatabase; @Override protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); currentDistance = findViewById(R.id.distance); firebaseDatabase = FirebaseDatabase.getInstance().getReference(); DatabaseReference usersRef = firebaseDatabase.child("Pomiar/int"); usersRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { Long test = snapshot.getValue(Long.class); currentDistance.setText(Long.toString(test)); } @Override public void onCancelled(@NonNull DatabaseError error) { } }); super.onCreate(savedInstanceState); } }
Odpalamy stworzony wcześniej emulator i obserwujemy zmieniającą się wartość odległości.
Podsumowując dotychczasowe artykuły, udało nam się zrealizować funkcję zapisywania danych do bazy z poziomu aplikacji mobilnej, modułu esp8266 oraz odczyt danych. W kolejnym artykule zajmiemy się rozbudową naszego projektu o nowy wygląd, stworzymy szkielet aplikacji wykorzystując programowanie obiektowe oraz uporządkujemy naszą bazę danych tak aby była przejrzysta i prosta w obsłudze.