My Eighth Project #8 [Sistem Embedded]: ESP32 Web Server dan ESP32 Advanced Weather Station

Vania Salsabila
11 min readApr 2, 2023

--

Hello!! Welcome back again guys!! All right, jadi kali ini aku akan menceritakan experience selama aku mengerjakan Project 8. Sesuai dengan judul blognya, di Project #8 ini kita akan membahas tentang ESP32 Web Server dan ESP32 Advanced Weather Station . Ooo iya tak terasa kalau Project #8 ini adalah project terakhirku di Mata Kuliah Sistem Embedded ini. Kepo gak kira kira bagaimana ya proses dan hasil dari Project terakhir ini.

— Introduction; —

Pada project ini, kita akan mencoba 2 percobaan terkait dengan Web Server. Pertama kita akan mencoba menyalakan dan mematikan kipas angin (dimana kipas angin ini dimodelkan dengan lampu LED) dengan menggunakan web browser. Lalu, yang kedua kita akan menggunakan eksternal sensor untuk mencoba membaca informasi temperature pada ruangan yang dapat dibaca dari jarak jauh menggunakan browser pada PC atau project ini disebut juga sebagai ESP32 Advanced Weather Station.

— Tools; —

Untuk mengerjakan project ini Tools yang dibutuhkan sama seperti pada Project#2 dan Project#4. Jadi teman teman bisa menyesuaikan saja ya!

1. Project Menyalakan dan Mematikan Lampu LED dengan menggunakan Web Server.

— Steps; —

  1. The Circuit

Pada bagian ini, rangkaian yang aku gunakan adalah seperti berikut:

2. The Code;

Berikut adalah kode program yang aku gunakan:

/*********
Rui Santos
Complete project details at http://randomnerdtutorials.com
*********/

// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid = "vaneeyaa";
const char* password = "hotspotku";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output18State = "off";
String output21State = "off";

// Assign output variables to GPIO pins
const int output18 = 18;
const int output21 = 21;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output18, OUTPUT);
pinMode(output21, OUTPUT);
// Set outputs to LOW
digitalWrite(output18, LOW);
digitalWrite(output21, LOW);

// 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(){
WiFiClient client = server.available(); // Listen for incoming clients

if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();

// turns the GPIOs on and off
if (header.indexOf("GET /18/on") >= 0) {
Serial.println("GPIO 18 on");
output18State = "on";
digitalWrite(output18, HIGH);
} else if (header.indexOf("GET /18/off") >= 0) {
Serial.println("GPIO 18 off");
output18State = "off";
digitalWrite(output18, LOW);
} else if (header.indexOf("GET /21/on") >= 0) {
Serial.println("GPIO 21 on");
output21State = "on";
digitalWrite(output21, HIGH);
} else if (header.indexOf("GET /21/off") >= 0) {
Serial.println("GPIO 21 off");
output21State = "off";
digitalWrite(output21, LOW);
}

// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");

// Web Page Heading
client.println("<body><h1>ESP32 Web Server</h1>");

// Display current state, and ON/OFF buttons for GPIO 26
client.println("<p>GPIO 18 - State " + output18State + "</p>");
// If the output26State is off, it displays the ON button
if (output18State=="off") {
client.println("<p><a href=\"/18/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/18/off\"><button class=\"button button2\">OFF</button></a></p>");
}

// Display current state, and ON/OFF buttons for GPIO 27
client.println("<p>GPIO 21 - State " + output21State + "</p>");
// If the output27State is off, it displays the ON button
if (output21State=="off") {
client.println("<p><a href=\"/21/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/21/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");

// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}

Sebelum menjalankan kode programnya, pastikan kita sudah menghubungkan ESP32 dengan WiFi kita. Disini, aku menggunakan hotspot seluler untuk menyambungkannya. Setelah berhasil terhubung, jalankan programnya. Kemudian, setelah berhasil di compile dan diupload, buka serial monitor pada Arduino IDE.

Tampilan Serial Monitor ketika berhasil compiling dan uploading

Setelah itu, di serial monitor akan muncul IP address Web Server. Copy dan paste IP Address tersebut pada browser kalian. Maka akan muncul tampilan seperti berikut:

Tampilan Web Server ESP32

Setelah muncul seperti gambar diatas, barulah kita bisa melakukan percobaan untuk menyalakan dan mematikan LEDnya.

— Result; —

Video Hasil Percobaan Menyalakan dan Mematikan LED melalui Web Server
Tampilan serial monitor ketika percobaan sedang dilakukan

2. Project Advance Weather Station

— Steps; —

  1. The Circuit

Pada project advanced weather station ini, rangkaian yang aku gunakan adalah seperti berikut:

2. The Code

/*********
Rui Santos
Complete project details at http://randomnerdtutorials.com
*********/

// Load Wi-Fi library
#include <WiFi.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10)
Adafruit_BMP280 bmp;

//uncomment the following lines if you're using SPI
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

#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

// Replace with your network credentials
const char* ssid = "SIMBA";
const char* password = "1708194599";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output4State = "off";
String output5State = "off";

// Assign output variables to GPIO pins
const int output4 = 4;
const int output5 = 5;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
Serial.begin(115200);

// Initialize the output variables as outputs
pinMode(output4, OUTPUT);
pinMode(output5, OUTPUT);
// Set outputs to LOW
digitalWrite(output4, LOW);
digitalWrite(output5, LOW);

bool status;

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

/* Default settings from datasheet. */
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

// 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() {
WiFiClient client = server.available(); // Listen for incoming clients

if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();

// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the table
client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}");
client.println("table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }");
client.println("th { padding: 12px; background-color: #0043af; color: white; }");
client.println("tr { border: 1px solid #ddd; padding: 12px; }");
client.println("tr:hover { background-color: #bcbcbc; }");
client.println("td { border: none; padding: 12px; }");
client.println(".sensor { color:white; font-weight: bold; background-color: #bcbcbc; padding: 1px; }");
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #555555;}</style></head>");

// Web Page Heading
client.println("</style></head><body><h1>ESP32 Weather Station</h1>");
client.println("<table><tr><th>MEASUREMENT</th><th>VALUE</th></tr>");
client.println("<tr><td>Temp. Celsius</td><td><span class=\"sensor\">");
client.println(bmp.readTemperature());
client.println(" *C</span></td></tr>");
client.println("<tr><td>Temp. Fahrenheit</td><td><span class=\"sensor\">");
client.println(1.8 * bmp.readTemperature() + 32);
client.println(" *F</span></td></tr>");
client.println("<tr><td>Pressure</td><td><span class=\"sensor\">");
client.println(bmp.readPressure() / 100.0F);
client.println(" hPa</span></td></tr>");
client.println("<tr><td>Approx. Altitude</td><td><span class=\"sensor\">");
client.println(bmp.readAltitude(SEALEVELPRESSURE_HPA));
client.println(" %</span></td></tr>");
client.println("</body></html>");

// turns the GPIOs on and off
if (header.indexOf("GET /26/on") >= 0) {
Serial.println("GPIO 4 on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 4 off");
output4State = "off";
digitalWrite(output4, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("GPIO 5 on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("GPIO 5 off");
output5State = "off";
digitalWrite(output5, LOW);
}

// Display current state, and ON/OFF buttons for GPIO 4
client.println("<p>FAN 1 - State " + output4State + "</p>");
// If the output4State is off, it displays the ON button
if (output4State=="off") {
client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
}

// Display current state, and ON/OFF buttons for GPIO 5
client.println("<p>FAN 2 - State " + output5State + "</p>");
// If the output5State is off, it displays the ON button
if (output5State=="off") {
client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
}


// Display the current state of fan speed,
client.println("</body></html>");

// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}

Sama seperti bagian sebelumnya, sebelum menjalankan program pastikan ESP32 kita sudah terhubung dengan WiFi. Pada bagian ini aku menggunakan WiFi kos temanku. Dikarenakan aku tidak memiliki sensor BMP280, aku meminjamnya dan kami mengerjakan project ini bersama sekaligus agar kita bisa diskusi jika ada problem problem yang terjadi.

Jika sudah berhasil terhubung dengan WiFi dan berhasil compiling dan uploading selanjutnya cek serial monitor pada Arduino IDE. Lalu copy dan paste IP Address pada serial monitor ke Browser. Lalu akan muncul tampilan seperti berikut:

Tampilan Web Server ESP32 Weather Station

— Result; —

Terlihat pada video, saat aku mencoba untuk menyalakan dan mematikan video, web server juga berhasil melakukan pembacaan temperature, tekanan, dan altitude. Saat diklik tombol “ON” halaman web akan melakukan refresh dan data pengukuran sensor akan otomatis ter-update

Pada video diatas, aku menyentuh sensor eksternal untuk melakukan pembacaan suhu tubuhku. Untuk melihat setiap perubahannya, kita bisa melakukan refresh pada halaman web.

— The Problems; —

  1. Jika kamu mengerjakan project ini di kampus ITB. Pastikan kamu tidak menggunakan WiFi Eduroam untuk menghubungkan ESP32 dengan WiFi karena tidak bisa digunakan
  2. Ketika membuat rangkaian pastikan cable jumper disambungkan dengan pin sensor dan ESP32 yang tepat [JANGAN TERBALIK] karena saat aku merangkai kemarin terdapat kesalahan sehingga aku tersetrum dan menyebabkan sensor menjadi sangat panas. So, be careful frenss!!

— Conclusion; —

Menurutku project terakhir ini cukup seru karena banyak hal-hal yang baru yang belum ada di project-project sebelumnya. Dan karena aku mengerjakannya bersama dengan teman-temanku membuat project ini terasa mudah sehingga berjalan dengan lancar walaupun ada error error minor yang pada akhirnya solved juga hehehe..

All right, ternyata cukup panjang juga perjalanan project mata kuliah ini. Dimulai dari aku yang tidak tau apa apa mengenai Sistem Embedded, dan dibuka dengan project LED Blink yang sangat sederhana hingga saat ini aku sudah cukup mengenal komponen komponen terutama main character in this project is ESP32. Aku menjadi lebih mengetahui kalau ESP32 ini mempunyai kemampuan kemampuan yang sebelumnya aku tidak akan mengira bahwa barang sekecil itu bisa melakukan hal hal yang bisa dibilang canggih. Selama mengerjakan project project aku merasa enjoy-enjoy saja karena hanya mata kuliah inilah yang membuat aku menjadi bermain-main bahkan mengulik mengenai hardware.

Actually, masih ada satu hingga 2 project yang bersifat optional. Jika aku ada waktu lebih Insyaallah aku akan mencoba mengerjakannya. Tapi bisa saja aku mencobanya dan tidak aku tulis di blog karena mungkin aku belum sempat untuk menulisnya. So, kalau penasaran sama project selanjutnya, stay tune aja yaa hehe..

Byee all, thankkk uuu!! ❤

--

--

Vania Salsabila
Vania Salsabila

No responses yet