ESP32 #9 : Web Server x Weather Station

Halo semuanya balik lagi nih kita ngerjain challenge Mikrokontroler ESP32. Masih bareng aku Ananta, gak kerasa kita udah mulai memasuki tantangan ke sembilan nih minggu ini. Semoga belum pada bosen ya.

Nah minggu ini kita bakalan kombinasiin beberapa tantangan sebelumnya jadi satu challenge yaitu Tantangan #4: External Sensor with BMP280, Tantangan #6: Weather Station with BMP280 and OLED, serta tantangan minggu lalu Tantangan #8: Web Server.

Mungkin kalian juga udah bisa nebak, kita bakalan nampilin hasil pembacaan sensor BMP280 bukan lagi pada OLED, melainkan pada web server. Kita tidak perlu lagi menyambungkan ESP32 kita pada sebuah display eksternal, namun pada tantangan kali ini kita harus mempunyai server sendiri (Wi-FI).

KOMPONEN

oke langsung aja, komponen yang bakal kita perluin dalam tantangan kali ini:

  1. ESP32 dan breadboard
  2. Kabel jumper
  3. Adafruit BMP280
  4. PC dengan Arduino IDE yang tersambung pada Wi-Fi

RANGKAIAN

Nah skema rangkaian yang aku gunakan bisa diliat dibawah

Sambungkan Ground ESP32 dengan Ground BMP280, V3V ESP32 dengan VDD BMP280, serta SDA BMP280 dengan SDA ESP32 (GPIO21), dan SCL BMP280 dengan SCL ESP32 (GPIO22).

SOURCE CODE

Source code bisa dilihat pada laman ini: https://randomnerdtutorials.com/esp32-web-server-with-bme280-mini-weather-station/

Source code yang tersedia ditujukan untuk BME280, namun dengan sedikit modifikasi, source code dapat berjalan untuk BMP280, jangan lupa untuk mengganti alamat BMP280 menjadi 0x76, penjelasannya ada disini.

/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
// Load Wi-Fi library
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
//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_BMP280 bmp; // 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 = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// 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);
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 BME280 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(){
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; }");

// Web Page Heading
client.println("</style></head><body><h1>ESP32 with BME280</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(" m</span></td></tr>");
// client.println("<tr><td>Humidity</td><td><span class=\"sensor\">");
//client.println(bmp.readHumidity());
// client.println(" %</span></td></tr>");
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("");
}
}

Dan jangan lupa untuk mengganti baris ini sesuai dengan konfigurasi wifi yang kalian gunakan

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

Beberapa hal yang perlu diperhatikan

  • Pastikan semua atribut dari BME280 sudah dimodifikasi untuk BMP280 termasuk library dan object.
  • BMP280 tidak bisa membaca kelembapan yang ada di sekitar kita, maka jangan lupa menghapus command kelembapan dari source code yang disediakan randomnerdtutorial
  • Alamat dari sensor harus disesuaikan. Jika tidak, ESP32 tidak akan mampu membaca sensor sehingga akan keluar pesan error.

DEMO

Mari kita coba!

CSS

Jujur melihat tampilan default web server membuat mataku sedikit sakit, terutama saat melihatnya pada malam hari atau dalam ruangan gelap, maka dari itu, aku membuat versi gelap (dark-mode) dari web server default. Beberapa hal yang harus dilakukan adalah:

  • Mengubah background layar menjadi hitam dan memberi keterangan warna font putih dengan menambahkan keterangan background pada line css berikut:
client.println("<style>body { text-align: center; background: #000000; font-family: \"Trebuchet MS\", Arial; color: white;}");
  • Ubah background sensitif (hanya keluar ketika ditunjuk kursor) menjadi abu-abu yang lebih gelap:
client.println("tr:hover { background-color: #222222; }");
client.println("td { border: none; padding: 12px; }");
client.println(".sensor { color:white; font-weight: bold; background-color: #222222; padding: 1px; }");

Sehingga hasilnya akan seperti ini:

ANALISIS

Kurang lebih hal yang dipelajari sama dengan minggu lalu, yaitu modifikasilah tampilan dari tampilan default menjadi tampilan yang lebih baik sesuai dengan pengelihatan kita terlebih dahulu. Kegiatan ini akan memberi experience yang lebih baik pada penggunanya. User experience researching tidak hanya akan berguna untuk diri kita sendiri namun mungkin juga berguna bagi orang lain yang menggunakan produk yang sama.

Baik itu aja dulu buat minggu ini, sampai ketemu minggu depan!

(18219038 — I Wayan Ananta Suandira)

--

--