Weather Station Visualization with ESP32

Haloo teman - teman semua !!!
Pada kesempatan kali ini aku akan menjelaskan mengenai bagaimana sih cara membuat visualisasi data berupa grafik dll dari alat pengukur cuaca BME280, yang tentunya menggunakan media ESP32. Sebelumnya aku mengucapkan banyak terimakasih kepada website www.randomnerdtutorials.com yang telah berbagi banyak informasi dan pengetahuan mengenai ESP32 yang membuat aku lebih mudah dalam mengerjakan proyek ini. Berkat adanya web tersebut, dalam sekali percobaan aku langsung berhasil membuat proyek ini. Aku sendiri pun awalnya ga percaya tapi ternyata usahaku yang serius langsung membuahkan hasil. Tanpa banyak berbasa - basi lagi langsung aja kita masuk ke dalam pembahasan bagaimana caranya. Cekidott!!!

FileSystem Uploader Plugin

Sebelum memulai langkahnya, kalian harus menngintall plugin dibawah ini kedalam aplikasi arduino IDE kalian agar nantinya file HTML yang kita buat, dapat diupload dan dibaca oleh ESP32 kita.
Link downloadnya dapat anda klik disini : ESP32 FileSystem Uploader Plugin

Libraries

Setelah selesai menginstall plugin tadi, install libraries berikut pada Arduino IDE kalian. Ada dua libraries yaitu ESPAsyncWebServer dan AsyncTCP. Perlu diperhatikan bahwa kedua libraries tersebut bukanlah libraries bawaan yang dapat didownload dari dalam aplikasi Arduino IDE. Jadi caranya adalah setelah kalian download, ekstrak filenya dan pindahkan foldernya ke dalam File Arduino -> Libraries. Selain itu kaian juga perlu libraries Adafruit BME280 Library dan Adafruit Unified Sensor Library yang dapat kalian download dari dalam aplikasi Arduino IDE.

Alat

1. ESP32 dan Kabel USB Type A to MicroUSB
2. BME280
3. Kabel jumper Female to Female 

Skema Diagram

Berikut adalah skema yang harus kalian susun untuk menghubungkan BME 280 dengan ESP32 milik kita. Setelah nantinya telah terpasang, lalu hubungkan ESP32 kita ke PC menggunakan Kabel yang telah disiapkan sebelumnya.

Organisasi File

Nanti akan disediakan sketch Arduino dan file HTML yang harus kalian copy dan simpan karena kedua file ini nantinya akann digunakan dalam pembuatan Web Servernya. Tetapi sebelum itu, kalian harus tau tata letak penyimpanan kedua file tersebut agar nantinya tidak terjadi kesalahan dalam pembuatan Web Servernya. File HTML harus berada di dalam folder yang bernama data yang dimana data ini terletak di File Sketch Arduino. Untuk gambaran lebih jelasnya, kalian dapat melihat skema di bawah ini.

File HTML

Berikut adalah file HTML yang harus kalian simpan sesuai dengan skema di atas. Kalian harus menympannya dengan nama index.html 

<!DOCTYPE HTML><html>
<!-- Rui Santos - Complete project details at https://RandomNerdTutorials.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. -->
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.highcharts.com/highcharts.js"></script>
  <style>
    body {
      min-width: 310px;
     max-width: 800px;
     height: 400px;
      margin: 0 auto;
    }
    h2 {
      font-family: Arial;
      font-size: 2.5rem;
      text-align: center;
    }
  </style>
</head>
<body>
  <h2>ESP Weather Station</h2>
  <div id="chart-temperature" class="container"></div>
  <div id="chart-humidity" class="container"></div>
  <div id="chart-pressure" class="container"></div>
</body>
<script>
var chartT = new Highcharts.Chart({
  chart:{ renderTo : 'chart-temperature' },
  title: { text: 'BME280 Temperature' },
  series: [{
    showInLegend: false,
    data: []
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    },
    series: { color: '#059e8a' }
  },
  xAxis: { type: 'datetime',
    dateTimeLabelFormats: { second: '%H:%M:%S' }
  },
  yAxis: {
    title: { text: 'Temperature (Celsius)' }
    //title: { text: 'Temperature (Fahrenheit)' }
  },
  credits: { enabled: false }
});
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var x = (new Date()).getTime(),
          y = parseFloat(this.responseText);
      //console.log(this.responseText);
      if(chartT.series[0].data.length > 40) {
        chartT.series[0].addPoint([x, y], true, true, true);
      } else {
        chartT.series[0].addPoint([x, y], true, false, true);
      }
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 30000 ) ;

var chartH = new Highcharts.Chart({
  chart:{ renderTo:'chart-humidity' },
  title: { text: 'BME280 Humidity' },
  series: [{
    showInLegend: false,
    data: []
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    }
  },
  xAxis: {
    type: 'datetime',
    dateTimeLabelFormats: { second: '%H:%M:%S' }
  },
  yAxis: {
    title: { text: 'Humidity (%)' }
  },
  credits: { enabled: false }
});
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var x = (new Date()).getTime(),
          y = parseFloat(this.responseText);
      //console.log(this.responseText);
      if(chartH.series[0].data.length > 40) {
        chartH.series[0].addPoint([x, y], true, true, true);
      } else {
        chartH.series[0].addPoint([x, y], true, false, true);
      }
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 30000 ) ;

var chartP = new Highcharts.Chart({
  chart:{ renderTo:'chart-pressure' },
  title: { text: 'BME280 Pressure' },
  series: [{
    showInLegend: false,
    data: []
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    },
    series: { color: '#18009c' }
  },
  xAxis: {
    type: 'datetime',
    dateTimeLabelFormats: { second: '%H:%M:%S' }
  },
  yAxis: {
    title: { text: 'Pressure (hPa)' }
  },
  credits: { enabled: false }
});
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var x = (new Date()).getTime(),
          y = parseFloat(this.responseText);
      //console.log(this.responseText);
      if(chartP.series[0].data.length > 40) {
        chartP.series[0].addPoint([x, y], true, true, true);
      } else {
        chartP.series[0].addPoint([x, y], true, false, true);
      }
    }
  };
  xhttp.open("GET", "/pressure", true);
  xhttp.send();
}, 30000 ) ;
</script>
</html>

Arduino Sketch

Berikut adalah file arduino yang harus kalian simpan sesuai dengan skema penyimpanan di atas. Dan perlu diperhatikan pada code ini ada bagian yang harus kalian edit yaitu kalian harus memasukkan kredensial network kalian (SSID dan Password) dari network yang kalian pakai. Beikut adalah kodenya.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#ifdef ESP32
  #include <WiFi.h>
  #include <ESPAsyncWebServer.h>
  #include <SPIFFS.h>
#else
  #include <Arduino.h>
  #include <ESP8266WiFi.h>
  #include <Hash.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>
  #include <FS.h>
#endif
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

String readBME280Temperature() {
  // Read temperature as Celsius (the default)
  float t = bme.readTemperature();
  // Convert temperature to Fahrenheit
  //t = 1.8 * t + 32;
  if (isnan(t)) {    
    Serial.println("Failed to read from BME280 sensor!");
    return "";
  }
  else {
    Serial.println(t);
    return String(t);
  }
}

String readBME280Humidity() {
  float h = bme.readHumidity();
  if (isnan(h)) {
    Serial.println("Failed to read from BME280 sensor!");
    return "";
  }
  else {
    Serial.println(h);
    return String(h);
  }
}

String readBME280Pressure() {
  float p = bme.readPressure() / 100.0F;
  if (isnan(p)) {
    Serial.println("Failed to read from BME280 sensor!");
    return "";
  }
  else {
    Serial.println(p);
    return String(p);
  }
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  
  bool status; 
  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

  // Initialize SPIFFS
  if(!SPIFFS.begin()){
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP32 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html");
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readBME280Temperature().c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readBME280Humidity().c_str());
  });
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readBME280Pressure().c_str());
  });

  // Start server
  server.begin();
}
 
void loop(){
  
}

Uploading Code and Files

Simpan file arduino yang telah dibuat tadi. Lalu kalian harus memastikan susunan skema file penyimpananya sudah tepat. Caranya pergi ke Sketch -> Show Sketch Folder


Dan disitu buatlah folder bernama data seperti yang sudah disebutkan sebelumnya.  Di dalam folder data tersebut, masukkanlah file. Setelah skema penyimpanan kedua file tersebut sudah dipastikan benar, lalu kita akan mengupload file HTML ke dalam ESP32 melalui aplikasi Arduino IDE. Caranya buka Tools -> ESP32 Sketch Data Upload. Untuk lebih jelasnya perhatikan gambar di bawah ini.

Setelah selesai lakukan upload code seperti biasa dengan cara mengklik tombol panah ke kanan di pojok kiri atas. Kemudian tunggu proses uploadnya selesai. Setelah berhasil diupload, buka Serial Monitor pada Tools dengan baud rate 115200. Kemudian tekan tombol EN pada ESP32 milik kita. Lalu akan muncul tampilan seperti ini. 

Demonstrasi 

Copy IP Adress yang terdapat di gambar di atas. Dan kemudian buka browser dan ketikkan atau paste IP Adress tersebut. Jika kalian telah berhasil melakukan seluruh langkah di atas, akan muncul tampilan gambar seperti di bawah ini.  Itu artinya kalian telah selesai melakukan proyek ini. Yeayyy!!!^^



Nanti grafik tersebut akan terus berjalan secara otomatis selama programnya masih berjalan dan ESP32 serta BME280 milik kalian masih terhubung. Berikut adalah demonstrasi berupa videonya.


Penutup

Demikianlah penjelasanku kali ini. Terimakasih buat semua teman-teman yang sudah membaca dan menggunakan blog ini sebagai referensi. Buat teman - teman yang masih kebingungan silahkan berkomentar di kolom komentar dan aku akan berusaha untuk menjawab dan membantu kalian semua secepat mungkin. Atas perhatian teman - teman semua, aku ucapkan terimakasih dan sampai berjumpa di artikel blog berikutnya. Bye!!!

Komentar

Postingan populer dari blog ini

Membuat LED Blink pada ESP32

Cara Menggunakan I2C Display dengan ESP32