[II2260 — Embedded System, 10th Project] ESP32 : Data Visualization and Data Logging
— Pengantar
Setelah menyelesaikan project kesembilan (Insert Data into MySQL Database using PHP and Arduino IDE), selanjutnya kita akan membahas tentang Data Visualization and Data Logging.
— Komponen
Adapun komponen yang digunakan yaitu :
- ESP32 + breadboard
- BMP280
- Kabel Jumper male-to-male
- Kabel micro USB
— Hands-On
Adapun langkah-langkah pengerjaannya dibagi menjadi tiga bagian, yaitu :
— — Get Date and Time using NTP
Adapun tujuan ini ialah untuk mendapatkan timestamp pembacaan sensor pada Data Logging. Langkah-langkahnya seperti berikut :
- Download NTP Client Library
- Buka Arduino IDE, lalu include library file zip yang sudah didownload seperti gambar berikut
3. Setelah itu silahkan salin dan upload code berikut
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
Based on the NTP Client library example
*********/
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Variables to save date and time
String formattedDate;
String dayStamp;
String timeStamp;
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Initialize a NTPClient to get time
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(3600*7);
}
void loop() {
while(!timeClient.update()) {
timeClient.forceUpdate();
}
// The formattedDate comes with the following format:
// 2018-05-28T16:00:13Z
// We need to extract date and time
formattedDate = timeClient.getFormattedDate();
Serial.println(formattedDate);
// Extract date
int splitT = formattedDate.indexOf("T");
dayStamp = formattedDate.substring(0, splitT);
Serial.print("DATE: ");
Serial.println(dayStamp);
// Extract time
timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
Serial.print("HOUR: ");
Serial.println(timeStamp);
delay(1000);
}
Perlu diperhatikan bahwasanya pada potongan code timeClient.setTimeOffset(3600*7)
karena saya berada di GMT+7. Sesuaikanlah dengan daerah waktu kalian masing-masing. Dan perlu diperhatikan juga bahwasanya kalian harus mengganti potongan code const char* ssid = "blabla"
dan const char* password = "blabla"
Gantilah nilai blabla dengan nama ssid kalian dan password dari ssid kalian.
4. Jika berhasil, bukalah Serial Monitor 115200 baud lalu hasilnya akan seperti berikut
— — Plot Sensor Reading in Real Time Chart
Setelah berhasil menampilkan timestamp, selanjutnya kita akan melakukan plotting terhadap pembacaan sensor secara real time pada web server.
Adapun langkah-langkahnya seperti berikut :
- Download ESP32FS-1.1.zip
- Buka Arduino IDE kalian, lalu carilah sketchbook location dengan cara tekan menu File > Preferences
3. Setelah itu buka sketchbook location, lalu buatlah folder tools
4. Extract file .zip yang sudah didownload ke folder tools
5. Download ESPAsyncWebServer dan AsyncTCP libraries
6. Lakukan include terhadap kedua file .zip libraries di atas
Selanjutkan kita akan merangkai rangkainnya. Adapun langkah-langkahnya seperti berikut :
- Pasang ESP32 dan BMP280 pada breadboard
- Sambungkan pin GND di ESP32 ke pin GND pada BMP280
- Sambungkan pin 3V3 di ESP32 ke pin VCC pada BMP280
- Sambungkan pin GPIO21 ke pin SDA di BMP280
- Sambungkan pin GPIO22 ke pin SCL di BMP280
6. Download dan extract folder project berikut
7. Perlu diperhatikan bahwasanya pada project ini saya menggunakan BMP280, jika kalian menggunakan BMP280, maka kalian bisa mengganti setiap potongan code BME280
menjadi BMP280
karena by default, isi file ESP_Chart_Web_Server.ino tersebut khusus untuk project menggunakan BME280
Adapun code yang saya ubah pada file index.html sebagai berikut :
<!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>Hafidz Shidqi's 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: 'BMP280 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();
}, 3000 ) ;
var chartP = new Highcharts.Chart({
chart:{ renderTo:'chart-pressure' },
title: { text: 'BMP280 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();
}, 3000 ) ;
</script>
</html>
8. Buka file ESP_Chart_Web_Server.ino pada folder yang sudah diextract, lalu silahkan pergi ke menu Tools > ESP32 Sketch Data Upload
Perlu diperhatikan bahwasanya untuk bisa melakukan ESP32 Sketch Data Upload, hanya bisa dilakukan pada Arduino IDE versi 1.8.19 kebawah. Karena saya sudah mencoba beberapa kali pada Arduino IDE versi 2 dan lebih, yang mana tidak bisa.
9. Setelah melakukan sketch data upload, silahkan upload file ESP_Chart_Web_Server.ino
10. Buka Serial Monitor 115200 baud, lalu buka browser dan pergi ke halaman IP Address yang terdapat pada Serial Monitor
11. Jika berhasil, maka tampilan pada web akan seperti berikut
Kalian juga bisa membukanya pada device yang lain, asalkan device tersebut tersambung pada ssid yang sama. Berikut ialah tampilan pada device smartphone
— — Publish Sensor Reading to Google Sheet
Adapun langkah-langkahnya dibagi menjadi dua, yaitu tahap pembuatan connection google sheet dan tahap rangkaian.
Adapun tahap pembuatan connection to google sheet yaitu :
- Silahkan kunjungi ifttt.com dan lakukan registrasi akun
- Setelah itu, tekan tombol My Applets > New Applet
- Tekan tombol This, lalu pilih service webhooks
4. Setelah itu, pilihlah Receive a web request dan namai event name dengan “bmp280_readings” Lalu tekan tombol Create trigger
5. Setelah itu tekan tombol That, lalu pilih service Google Sheets
6. Pilih Add row to spreadsheet lalu konfigurasi seperti gambar kedua pada gambar di bawah
7. Setelah itu, silahkan kunjungi Webhooks Service page, dan click tombol “Documentation”
8. Lalu lakukan hal berikut seperti gambar di bawah yang saya berikan kotak merah. Adapun tujuannya untuk melakukan test apakah data sudah bisa dikirim ke Google Sheets
9. Buka Google Drive pada akun yang telah kalian daftarkan pada ifttt.com. Lalu buka Google Sheets yang bernama “BMP280_Readings” seperti yang sudah kita konfigurasi pada langkah ke-6.
Setelah berhasil membuat connection to Google Sheets, selanjutnya kita akan membuat rangkaiannya. Adapun langkah — langkahnya sebegai berikut :
- Pasang ESP32 dan BMP280 pada breadboard
- Sambungkan pin GND di ESP32 ke pin GND pada BMP280
- Sambungkan pin 3V3 di ESP32 ke pin VCC pada BMP280
- Sambungkan pin GPIO21 ke pin SDA di BMP280
- Sambungkan pin GPIO22 ke pin SCL di BMP280
6. Buka Arduino IDE kalian, lalu salin dan upload code berikut
/*
* Rui Santos
* Complete Project Details http://randomnerdtutorials.com
*/
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
// Replace with your SSID and Password
const char* ssid = "KENARI LANTAI 3";
const char* password = "kenari851";
// Replace with your unique IFTTT URL resource
const char* resource = "/trigger/bmp280_readings/with/key/iJZrRM050NItz0wvcwjzVG1ftvoD2TsvrUcAiReI3zX";
// How your resource variable should look like, but with your own API KEY (that API KEY below is just an example):
//const char* resource = "/trigger/BMP280_readings/with/key/nAZjOphL3d-ZO4N3k64-1A7gTlNSrxMJdmqy3";
// Maker Webhooks IFTTT
const char* server = "maker.ifttt.com";
// Time to sleep
uint64_t uS_TO_S_FACTOR = 1000000; // Conversion factor for micro seconds to seconds
// sleep for 30 minutes = 1800 seconds
uint64_t TIME_TO_SLEEP = 1800;
// Uncomment to use BMP280 SPI
/*#include <SPI.h>
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10*/
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BMP280 BMP; // I2C
//Adafruit_BMP280 BMP(BMP_CS); // hardware SPI
//Adafruit_BMP280 BMP(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK); // software SPI
void setup() {
Serial.begin(115200);
delay(2000);
// initialize BMP280 sensor
bool status;
status = BMP.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
while (1);
}
initWifi();
makeIFTTTRequest();
#ifdef ESP32
// enable timer deep sleep
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Going to sleep now");
// start deep sleep for 3600 seconds (60 minutes)
esp_deep_sleep_start();
#else
// Deep sleep mode for 3600 seconds (60 minutes)
Serial.println("Going to sleep now");
ESP.deepSleep(TIME_TO_SLEEP * uS_TO_S_FACTOR);
#endif
}
void loop() {
// sleeping so wont get here
}
// Establish a Wi-Fi connection with your router
void initWifi() {
Serial.print("Connecting to: ");
Serial.print(ssid);
WiFi.begin(ssid, password);
int timeout = 10 * 4; // 10 seconds
while(WiFi.status() != WL_CONNECTED && (timeout-- > 0)) {
delay(250);
Serial.print(".");
}
Serial.println("");
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failed to connect, going back to sleep");
}
Serial.print("WiFi connected in: ");
Serial.print(millis());
Serial.print(", IP address: ");
Serial.println(WiFi.localIP());
}
// Make an HTTP request to the IFTTT web service
void makeIFTTTRequest() {
Serial.print("Connecting to ");
Serial.print(server);
WiFiClient client;
int retries = 5;
while(!!!client.connect(server, 80) && (retries-- > 0)) {
Serial.print(".");
}
Serial.println();
if(!!!client.connected()) {
Serial.println("Failed to connect...");
}
Serial.print("Request resource: ");
Serial.println(resource);
// Temperature in Celsius
String jsonObject = String("{\"value1\":\"") + BMP.readTemperature() + "\",\"value2\":\"" + (BMP.readPressure()/100.0F)
+ "\",\"value3\":\"" + BMP.readAltitude() + "\"}";
// Comment the previous line and uncomment the next line to publish temperature readings in Fahrenheit
/*String jsonObject = String("{\"value1\":\"") + (1.8 * BMP.readTemperature() + 32) + "\",\"value2\":\""
+ (BMP.readPressure()/100.0F) + "\",\"value3\":\"" + BMP.readHumidity() + "\"}";*/
client.println(String("POST ") + resource + " HTTP/1.1");
client.println(String("Host: ") + server);
client.println("Connection: close\r\nContent-Type: application/json");
client.print("Content-Length: ");
client.println(jsonObject.length());
client.println();
client.println(jsonObject);
int timeout = 5 * 10; // 5 seconds
while(!!!client.available() && (timeout-- > 0)){
delay(100);
}
if(!!!client.available()) {
Serial.println("No response...");
}
while(client.available()){
Serial.write(client.read());
}
Serial.println("\nclosing connection");
client.stop();
}
Perlu diperhatikan bahwasanya kalian harus mengganti potongan code const char* ssid = "blabla"
,const char* password = "blabla"
, dan const char* resource =”blabla"
Gantilah nilai blabla dengan nama ssid, password kalian, serta resource dengan API key kalian yang terdapat pada langkah kedelapan di atas.
7. Setelah berhasil diupload, bukalah Serial Monitor dengan baud 115200 dan hasilnya akan seperti berikut
8. Jika terdapat pesan berhasil, silahkan refresh Google Sheets kalian, dan pastinya terdapat data pembacaan sensor yang diinput secara otomatis
Adapun potongan code di atas by defaultnnya memiliki frekuensi pengiriman data yang sangat jarang (30 menit per data). Kalian bisa mengubahnya potongan code uint64_t TIME_TO_SLEEP = 2
yang mana artinya membutuhkan 2 detik setelah tersambung ke wifi untuk mengirim data.
Sekian yang bisa saya sampaikan, terima kasih sudah membaca tulisan ini dan selamat mencoba! Jika ada kendala bisa tuliskan di kolom komentar ya.