Embedded System Project 10: Data Visualization dan Data Logging
Hi, I’m Michelle and today I’ll be continuing my blog series of the embedded systems project! ✨🤩 (You can read the previous blog here🤗)
The tenth project I’ll be doing is actually also a bonus project, so I won’t be explaining too much theory in this project, but it will be more of a documentation of my experiment. In this project, we will be doing an experiment about data visualization and data logging.
This project is also connected to the previous project, so make sure to read my ninth project first before starting this one :)
Project: Introduction
The components we’ll be using are listed below.
- ESP32 Development Board
- BME280 Sensor
- Micro-USB Cable
- Breadboard
- Male-to-Male jumper wires
- Laptop/PC with Arduino IDE installed and set
This is the main concept for this experiment.
Project: Data Visualization
1. Go to Manage Website > Tools > File Manager > Upload Files > Open public_html folder > New File > Name the new .php file > Create > Copy and paste the code below > Save
<!--
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 = "your dbname";
// REPLACE with Database user
$username = "your username";
// REPLACE with Database user password
$password = "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 SensorData 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>
Note: Don’t forget to change the database name, username, and password.
2. Open your websitename/phpfilename.php
It should show charts of ESP32 readings
Project: Data Logging
In this part, we will be learning on how to publish sensor readings to Google Sheets using ESP32. We will be using a third party service (IFTTT) to integrate the ESP32 and Google sheets.
1. Open https://ifttt.com/ > Sign up for a new account > My Applets > Create your own
2. Click Add beside the If This column
3. Search for Webhooks in choosing a service > Receive a web request > Connect
4. Type in your Event Name > Create trigger
5. Click Add beside the Then That column > Search for Google Sheets > Add row to spreadsheet
Note: You can just follow the steps like before, but this time with Google Sheets
6. Connect > Choose an account
7. You can change your google sheets account, spreadsheet name, drive folder path > Create action > Continue > Finish
8. The applet should now be created; Go to https://ifttt.com/maker_webhooks > Documentation to see your unique API Key
9. You will be shown your key > Change {event} to your event name > Test It
10. Open your google drive and you should see a new file created on a new folder IFTTT
Project: Schematics
1. Wire your ESP32 and BME280 sensor as following
2. Copy and paste the code below, compile and upload on Arduino IDE
/*
* 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_BME280.h>
// Replace with your SSID and Password
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Replace with your unique IFTTT URL resource
const char* resource = "REPLACE_WITH_YOUR_IFTTT_URL_RESOURCE";
// 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/bme280_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 -> I changed it to 2 mins = 120 seconds
uint64_t TIME_TO_SLEEP = 120;
// Uncomment to use BME280 SPI
/*#include <SPI.h>
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10*/
#define SEALEVELPRESSURE_HPA (1013.25)
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);
delay(2000);
// initialize BME280 sensor
bool status;
status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 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\":\"") + bme.readTemperature() + "\",\"value2\":\"" + (bme.readPressure()/100.0F)
+ "\",\"value3\":\"" + bme.readHumidity() + "\"}";
// Comment the previous line and uncomment the next line to publish temperature readings in Fahrenheit
/*String jsonObject = String("{\"value1\":\"") + (1.8 * bme.readTemperature() + 32) + "\",\"value2\":\""
+ (bme.readPressure()/100.0F) + "\",\"value3\":\"" + bme.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();
}
Note: Don’t forget to change your SSID, password, and resource
The resource format should be “/trigger/eventname/with/key/{API Key}”
3. Open your google sheets, and you should see the BME280 readings displayed in a table like this.
So yea, that’s the end of our tenth Embedded System Project: Data Visualization dan Data Logging. (yeah!! 🥳) Stay tune for the next projects and stay safe and healthy 🥰