Project #11 ESP32 - Data Visualization


Halo, apa kabar semuanya? Perkenalkan kembali saya Muhammad Vito Ibrahim. Pada kesempatan kali ini saya akan mencoba melakukan visualisasi data dengan ESP32.

Nah , project kali ini juga merangkap sebagai rekam jejak atau laporan saya untuk mata kuliah ( II2260 Sistem Embedded ). Agar lebih detail kali ini saya akan melakukan visualisasi data berupa plot chart yang merupakan hasil pembacaan sensor dan ESP32 serta dapat diakses melalui webserver hosting yang menggunakan integrasi antara database MYSQL dan PHP.


Data Visualization dengan PHP, MYSQL, BMP180, ESP32

Perangkat dan komponen yang digunakan:

1. Mikrokontroler ESP32 Development Board.
2. Arduino IDE.
3. Laptop/Desktop dengan USB port.
4. Kabel micro usb to USB A ( kabel data/charger pada umumnya).
5. Breadboard ( dapat digunakan maupun tidak).
6. Server hosting
7. Script PHP
8. Database MYSQL
9. Sensor BMP180

Penjelasan beberapa perangkat dan komponen:

1. Mikrokontroler adalah sebuah komputer kecil yang dikemas dalam bentuk chip IC (Integrated Circuit) dan dirancang untuk melakukan tugas atau operasi tertentu.

2. ESP-32 Development Board adalah adalah mikrokontroler chip dengan rangkaian sistem hemat biaya dan rendah daya pada dilengkapi WiFi yang terintegrasi dan Bluetooth.

3. Arduino IDE (Integrated Development Environment) adalah software yang digunakan untuk memprogram di arduino, dengan kata lain Arduino IDE sebagai media untuk memprogram board Arduino. Pada kali ini bisa juga digunakan untuk memprogram mikrokontoler lainnya yaitu ESP32 dengan konfigurasi tambahan.

4. Breadboard adalah papan tempat komponen elektronik tanpa harus disolder.

5. Sensor BMP-180

Pendahuluan :

Kali ini saya akan mencoba untuk menampilkan visualisasi data di webserver hosting, data visualisasi akan didapatkan dari hasil bacaaan sensor dengan ESP32 kemudian akan dilanjutkan dengan melakukan update post HTTP setiap 30 detik dan melakukan visualisasi data berupa plot chart oleh script PHP kemudian dapat diakses melalui webserver hosting. Webserver hosting yang digunakan adalah 000webhost dengan alasan selain karena gratis juga karena mudah untuk melakukan setup dan menggunakannya.

Langkah pengerjaan :

a. Menyiapkan webhosting

Menggunakan jasa webhosting gratis yaitu 000webhost.com


Melakukan "Sign in" kemudian "+ create new site"

b. Menyiapkan basisdata MYSQL untuk visualisasi

Memilih  Tools > Database Manager > + New Database



Kemudian memasukan identitas basisdata yang ingin dibuat dan akan melakukan proses "Creating database".



Selanjutnya membuka Manage  > PhpMyAdmin



Membuka Tab Databases dan memastikan bahwa database yang dipilih sudah benar dengan memilih database yang telah dibuat pada tahap sebelumnya.


Kemudian pilih database yang baru saja dibuat. Sebelumnya saya membuat database dengan nama visual data maka memilih database yang bernama visualdata dengan cara klik.



Dilanjutkan membuka Tab SQL untuk membuat tables di database dengan memasukkan kueri berikut ini.

CREATE TABLE Sensor (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    value1 VARCHAR(10),
    value2 VARCHAR(10),
    value3 VARCHAR(10),
    reading_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)



Akan dibuat data tables sensor pada database.

Jika sudah dilanjutkan dengan menekan tombol GO.




Jika kueri telah dijalankan dan database yang dipilih sudah benar maka akan menampilkan tampilan berikut dan tabel SensorData telah terdapat di dalam basisdata.




Maka berhasil menambahkan data tables yang bernama Sensor pada database.



c. Menyiapkan script PHP HTTP POST untuk melakukan input data dari ESP32 ke basisdata MYSQL.

Membuka kembali situs 000webhost.com dan login menggunakan akun yang telah dibuat untuk website di 000webhost pada tahap sebelumnya.

Pada dashboard website 000webhost.com buka Tools > File Manager





Selanjutnya tekan Upload Files dan akan menampilkan seperti berikut.



Selanjutnya klik pada folder public_html dan akan dibuat file post-data.php di dalamnya

Kemudian membuat file post-data.ph dengan cara memilih create new file dengan simbol seperti yang dilingkari pada gambar di bawah


Lalu masukkan kode berikut.

<?php
/*
  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.
*/

$servername = "localhost";

// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";

// Keep this API Key value to be compatible with the ESP32 code provided in the project page. If you change this value, the ESP32 sketch needs to match
$api_key_value = "tPmAT5Ab3j7F9";

$api_key = $value1 = $value2 = $value3 = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $api_key = test_input($_POST["api_key"]);
    if($api_key == $api_key_value) {
        $value1 = test_input($_POST["value1"]);
        $value2 = test_input($_POST["value2"]);
        $value3 = test_input($_POST["value3"]);
        
        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        } 
        
        $sql = "INSERT INTO Sensor (value1, value2, value3)
        VALUES ('" . $value1 . "', '" . $value2 . "', '" . $value3 . "')";
        
        if ($conn->query($sql) === TRUE) {
            echo "New record created successfully";
        } 
        else {
            echo "Error: " . $sql . "<br>" . $conn->error;
        }
    
        $conn->close();
    }
    else {
        echo "Wrong API Key provided.";
    }

}
else {
    echo "No data posted with HTTP POST.";
}

function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}
Kemudian mengubah bagian di bawah ini menyesuaikan dengan nama database, username database, dan password database yang telah dibuat pada langkah sebelumnya.

// Your Database name $dbname = "example_esp_data"; // Your Database user $username = "example_esp_board"; // Your Database user password $password = "YOUR_USER_PASSWORD";


Pada dashboard, buka Database Manager, bagian yang ditandai merah merupakan nama database sedangkan yang dilingkari biru merupakan username database.

Untuk memastikan kode script berjalan, pada panel 000webhost buka Website Settings > General.
Pada bagian tersebut ditampilkan nama website yang telah dihosting. 




Mengakses link website tersebut untuk memastikan bahwa script berjalan lancar.

Website name yang tertera pada gambar merupakan nama domain webserver hosting. Setelah mendapatkan nama domain, tambahkan "/post-data.php" di bagian setelahnya. 

Contoh :
http://nama-domain/post-data.php

menjadi :

http://konekdong.000webhostapp.com/post-data.php

Jika menampilkan tampilan seperti di atas, maka proses yang dilakukan sudah benar hanya saja tertera "No data posted..." yang artinya belum dilakukan input data apapun.




d. Menyiapkan script PHP untuk melakukan visualisasi data berupa plot chart.

Pada folder public_html membuat lagi file yang bernama esp-chart.php


File tersebut diisi dengan kode berikut.

<!--
  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.

-->
<?php

$servername = "localhost";

// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 

$sql = "SELECT id, value1, value2, value3, reading_time FROM Sensor order by reading_time desc limit 40";

$result = $conn->query($sql);

while ($data = $result->fetch_assoc()){
    $sensor_data[] = $data;
}

$readings_time = array_column($sensor_data, 'reading_time');

// ******* Uncomment to convert readings time array to your timezone ********
/*$i = 0;
foreach ($readings_time as $reading){
    // Uncomment to set timezone to - 1 hour (you can change 1 to any number)
    $readings_time[$i] = date("Y-m-d H:i:s", strtotime("$reading - 1 hours"));
    // Uncomment to set timezone to + 4 hours (you can change 4 to any number)
    //$readings_time[$i] = date("Y-m-d H:i:s", strtotime("$reading + 4 hours"));
    $i += 1;
}*/

$value1 = json_encode(array_reverse(array_column($sensor_data, 'value1')), JSON_NUMERIC_CHECK);
$value2 = json_encode(array_reverse(array_column($sensor_data, 'value2')), JSON_NUMERIC_CHECK);
$value3 = json_encode(array_reverse(array_column($sensor_data, 'value3')), JSON_NUMERIC_CHECK);
$reading_time = json_encode(array_reverse($readings_time), JSON_NUMERIC_CHECK);

/*echo $value1;
echo $value2;
echo $value3;
echo $reading_time;*/

$result->free();
$conn->close();
?>

<!DOCTYPE html>
<html>
<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: 1280px;
    	height: 500px;
      margin: 0 auto;
    }
    h2 {
      font-family: Arial;
      font-size: 2.5rem;
      text-align: center;
    }
  </style>
  <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>
<script>

var value1 = <?php echo $value1; ?>;
var value2 = <?php echo $value2; ?>;
var value3 = <?php echo $value3; ?>;
var reading_time = <?php echo $reading_time; ?>;

var chartT = new Highcharts.Chart({
  chart:{ renderTo : 'chart-temperature' },
  title: { text: 'BME280 Temperature' },
  series: [{
    showInLegend: false,
    data: value1
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    },
    series: { color: '#059e8a' }
  },
  xAxis: { 
    type: 'datetime',
    categories: reading_time
  },
  yAxis: {
    title: { text: 'Temperature (Celsius)' }
    //title: { text: 'Temperature (Fahrenheit)' }
  },
  credits: { enabled: false }
});

var chartH = new Highcharts.Chart({
  chart:{ renderTo:'chart-humidity' },
  title: { text: 'BME280 Humidity' },
  series: [{
    showInLegend: false,
    data: value2
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    }
  },
  xAxis: {
    type: 'datetime',
    //dateTimeLabelFormats: { second: '%H:%M:%S' },
    categories: reading_time
  },
  yAxis: {
    title: { text: 'Humidity (%)' }
  },
  credits: { enabled: false }
});


var chartP = new Highcharts.Chart({
  chart:{ renderTo:'chart-pressure' },
  title: { text: 'BME280 Pressure' },
  series: [{
    showInLegend: false,
    data: value3
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    },
    series: { color: '#18009c' }
  },
  xAxis: {
    type: 'datetime',
    categories: reading_time
  },
  yAxis: {
    title: { text: 'Pressure (hPa)' }
  },
  credits: { enabled: false }
});

</script>
</body>
</html>
Kemudian mengubah bagian di bawah ini menyesuaikan dengan nama database, username database, dan password database yang telah dibuat pada langkah sebelumnya.

// Your Database name $dbname = "example_esp_data"; // Your Database user $username = "example_esp_board"; // Your Database user password $password = "YOUR_USER_PASSWORD";


Pada dashboard, buka Database Manager, bagian yang ditandai merah merupakan nama database sedangkan yang dilingkari biru merupakan username database.

Kemudian membuka situs webserver host dengan cara menambahkan nama domain.

http://nama-domain/esp-chart.php

Pada webserver host saya menjadi :

http://konekdong.000webhostapp.com/esp-chart.php

jika berhasil akan menampilkan tampilan seperti berikut.




Jika tampilan seperti di atas atau masih kosong maka proses sudah dapat dikatakan berhasil dan siap untuk dimasukkan data dan visualisasi dari hasil bacaan sensor ESP32.


e. Menyiapkan ESP32

Untuk wiring mengikuti sesuai skema berikut.




Kemudian di ArduinoIDE masukan kode berikut.

/*
  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.

*/

#ifdef ESP32
  #include <WiFi.h>
  #include <HTTPClient.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESP8266HTTPClient.h>
  #include <WiFiClient.h>
#endif

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

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

// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "http://example.com/post-data.php";

// Keep this API Key value to be compatible with the PHP code provided in the project page. 
// If you change the apiKeyValue value, the PHP file /post-data.php also needs to have the same key 
String apiKeyValue = "tPmAT5Ab3j7F9";

/*#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

void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  // (you can also pass in a Wire library object like &Wire2)
  bool status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring or change I2C address!");
    while (1);
  }
}

void loop() {
  //Check WiFi connection status
  if(WiFi.status()== WL_CONNECTED){
    HTTPClient http;
    
    // Your Domain name with URL path or IP address with path
    http.begin(serverName);
    
    // Specify content-type header
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    // Prepare your HTTP POST request data
    String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bme.readTemperature())
                           + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
    
    // You can comment the httpRequestData variable above
    // then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
    //String httpRequestData = "api_key=tPmAT5Ab3j7F9&value1=24.75&value2=49.54&value3=1005.14";

    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);
     
    // If you need an HTTP request with a content type: text/plain
    //http.addHeader("Content-Type", "text/plain");
    //int httpResponseCode = http.POST("Hello, World!");
    
    // If you need an HTTP request with a content type: application/json, use the following:
    //http.addHeader("Content-Type", "application/json");
    //int httpResponseCode = http.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");
    
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
  }
  else {
    Serial.println("WiFi Disconnected");
  }
  //Send an HTTP POST request every 30 seconds
  delay(30000);  
}
// Replace with your network credentials const char* ssid = "REPLACE_WITH_YOUR_SSID"; const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Mengubah bagian tersebut dengan menyesuaikan identitas kredensial jaringan WIFI dan mengubah bagian di bawah ini dengan nama-domain website yang telah dibuat sebelumnya.

const char* serverName = "http://example.com/post-data.php";

Berikut adalah kode yang sudah saya modifikasi sehingga dapat dijalankan dengan sensor BMP180



// Load Wi-Fi library
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085.h>

const char* ssid = "";
const char* password = "";

const char* serverName = "http://example.com/post-data.php";

String apiKeyValue = "tPmAT5Ab3j7F9";

Adafruit_BMP085 bmp;

void setup() {
 Serial.begin(115200);
 bool status;
// default settings
 // (you can also pass in a Wire library object like &Wire2)
 //status = bmp.begin(); 
 if (!bmp.begin(0x76)) {
 Serial.println("Could not find a valid bmp180 sensor, check wiring!");
 while (1);
 }
// Connect to Wi-Fi network with SSID and password
 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());
 server.begin();
}


void loop(){
//Check WiFi connection status
  if(WiFi.status()== WL_CONNECTED){
    HTTPClient http;
    
    // Your Domain name with URL path or IP address with path
    http.begin(serverName);
    
    // Specify content-type header
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    // Prepare your HTTP POST request data
    String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bmp.readTemperature())
                           + "&value2=" + String(bmp.readSealevelPressure()) + "&value3=" + String(bmp.readPressure()/100.0F) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
    
    // You can comment the httpRequestData variable above
    // then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
    //String httpRequestData = "api_key=tPmAT5Ab3j7F9&value1=24.75&value2=49.54&value3=1005.14";

    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);
     
    // If you need an HTTP request with a content type: text/plain
    //http.addHeader("Content-Type", "text/plain");
    //int httpResponseCode = http.POST("Hello, World!");
    
    // If you need an HTTP request with a content type: application/json, use the following:
    //http.addHeader("Content-Type", "application/json");
    //int httpResponseCode = http.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");
    
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
  }
  else {
    Serial.println("WiFi Disconnected");
  }
  //Send an HTTP POST request every 30 seconds
  delay(30000);  

}

const char* ssid = "";
const char* password = "";
const char* serverName = "http://example.com/post-data.php";

Menyesuaikan ketiga bagian tersebut dengan jaringan WIFI dan webserver hosting.

Kemudian upload kode dan buka serial monitor set baud rate 115200, jika menampilkan tampilan seperti berikut ini maka proses sudah berjalan dengan baik.



Jika proses berhasil buka webserver hosting dengan url berikut.

http://nama-domain/esp-chart.php

http://konekdong.000webhostapp.com/esp-chart.php

Akan menampilkan tampilan seperti berikut.




Kompilasi video pengerjaan :




Error dan troubleshooting:

Pada project kali ini, kesulitan saya hanyalah pada saat membuat webhosting bekerja dengan seharusnya dan troubleshoot yang dilakukan adalah memastikan untuk memasukkan nama database, username database, dan password database dengan benar. Selain itu saya tidak menemukan error apapun.

Kesimpulan:

Menampilkan visualisasi data hasil bacaan sensor BMP180 ke webserver dengan ESP32 MYSQL dan PHP.

Referensi :

1. randomnerdtutorials.com
2. wikipedia

Terimakasih!







Posting Komentar

0 Komentar