Embedded System Project 10: Data Visualization dan Data Logging

Michelle Lim
8 min readMay 7, 2023

--

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.

  1. ESP32 Development Board
  2. BME280 Sensor
  3. Micro-USB Cable
  4. Breadboard
  5. Male-to-Male jumper wires
  6. Laptop/PC with Arduino IDE installed and set

This is the main concept for this experiment.

Concept Project 10

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.

new php file named esp32chart.php

2. Open your websitename/phpfilename.php

It should show charts of ESP32 readings

https://michellesbonusprojects.000webhostapp.com/esp32chart.php

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

https://ifttt.com/my_applets

2. Click Add beside the If This column

https://ifttt.com/create

3. Search for Webhooks in choosing a service > Receive a web request > Connect

Webhooks search
Webhooks page
Connect Webhooks service

4. Type in your Event Name > Create trigger

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

Add > Google Sheets > Add row to spreadsheet

6. Connect > Choose an account

Connect > Choose account

7. You can change your google sheets account, spreadsheet name, drive folder path > Create action > Continue > Finish

Changing spreadsheet name
Click Continue
Click Finish

8. The applet should now be created; Go to https://ifttt.com/maker_webhooks > Documentation to see your unique API Key

Click Documentation

9. You will be shown your key > Change {event} to your event name > Test It

Documentation page

10. Open your google drive and you should see a new file created on a new folder IFTTT

New google sheets file created

Project: Schematics

1. Wire your ESP32 and BME280 sensor as following

Wiring ESP32 and BME280

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.

google sheets

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 🥰

--

--