Halo!

Setelah sebelumnya kita berkutat dengan modul bluetooth dan ESP32, kali ini kita akan memanfaatkan metode lainnya yang sebenarnya cukup mirip dalam implementasinya, yaitu memanfaatkan modul WiFi dari ESP32. Ada dua rangkaian yang kali ini akan kita coba untuk buat, meskipun keduanya hanya berhasil setengah jalan dan tidak dapat mencapai tujuan awal sepenuhnya. Rangkaian-rangkaian tersebut adalah:

  • Dasar: ESP32 Web Server — Arduino IDE untuk menyalakan lampu yang terhubung.
  • Pengembangan: ESP32 Web Server — Arduino IDE untuk menampilkan hasil pembacaan sensor BMP280 pada server.

Untuk kedua rangkaian tersebut, komponen yang akan kita gunakan adalah:

  1. Breadboard
  2. Kabel Micro USB
  3. Kabel Jumper Male-to-male
  4. ESP32
  5. Sensor Lingkungan BMP 280
  6. Kabel jumper Female-to-female

Tentu saja, tidak semua komponen diatas kecuali ESP32 dan Kabel Micro USB akan digunakan untuk setiap rangkaian. Maka dari itu, mari kita langsung masuk ke rangkaian dasar yaitu ESP32 Web Server — Arduino IDE untuk menyalakan lampu yang terhubung.

Skema:

Rangkaian:

Tampak Atas Rangkaian
Tampak Samping Rangkaian

Dapat dilihat pada skema dan rangkaian, bahwa lampu LED terhubung pada GPIO 26 dan 27 menggunakan kabel jumper male-to-male dan resistor 330 ohm. Adapun untuk algoritma yang digunakan adalah:

Algoritma:

/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
// Load Wi-Fi library
#include <WiFi.h>
// Replace with your network credentials
const char* ssid = "<My Wifi SSID>";
const char* password = "<My Wifi Password";
// 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 output26State = "off";
String output27State = "off";
String outputLEDState = "off";
// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;
const int outputLED = LED_BUILTIN;
// 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(output26, OUTPUT);
pinMode(output27, OUTPUT);
pinMode(LED_BUILTIN,OUTPUT);
// Set outputs to LOW
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(output26, LOW);
digitalWrite(output27, 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 /26/on") >= 0) {
Serial.println("GPIO 26 on");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 26 off");
output26State = "off";
digitalWrite(output26, LOW);
} else if (header.indexOf("GET /27/on") >= 0) {
Serial.println("GPIO 27 on");
output27State = "on";
digitalWrite(output27, HIGH);
} else if (header.indexOf("GET /2/off") >= 0) {
Serial.println("LED_BUILTIN off");
outputLEDState = "off";
digitalWrite(outputLED, LOW);
} else if (header.indexOf("GET /2/on") >= 0) {
Serial.println("LED_BUILTIN on");
outputLEDState = "on";
digitalWrite(outputLED, HIGH);
} else if (header.indexOf("GET /27/off") >= 0) {
Serial.println("GPIO 27 off");
output27State = "off";
digitalWrite(output27, LOW);
}

// Display the HTML web page
client.println("<!DOCTYPE html><html>"); //menandakan bahwa yang dikirim adlah HTML
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");// membuat web server dapat digunakan dalam web browser
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons, yang dapat berubah adalah warna, ukuran, border, text, font size, margin, cursor, dll.
// 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 (Judul Web Page)
client.println("<body><h1>ESP32 Web Server</h1>");

// Display current state, and ON/OFF buttons for GPIO 26
client.println("<p>GPIO 26 - State " + output26State + "</p>");
// If the output26State is off, it displays the ON button
if (output26State=="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 27
client.println("<p>GPIO 27 - State " + output27State + "</p>");
// If the output27State is off, it displays the ON button
if (output27State=="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>");
}
client.println("</body></html>");
client.println("<p>Built-In LED - State " + outputLEDState + "</p>");
// If the outputLED is off, it displays the ON button
if (outputLEDState=="off") {
client.println("<p><a href=\"/2/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/2/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(LED_BUILTIN);
Serial.println("");

}
}

Baris 10 dan 11 disensor karena mengandung informasi pribadi:

const char* ssid = “<My WiFi SSID>”;
const char* password = “My WiFi Password”;

Penjelasan untuk algoritma di atas sudah terletak pada komentar-komentar yang ada di dalam baris algoritmanya. Tetapi ada beberapa baris kode tertentu yang perlu dijelaskan lebih lanjut, yaitu:

  • Blok kode untuk menyalakan dan mematikan lampu berdasarkan GPIO mereka, dengan mengubah outputGPIOState. “header.indexOf(“GET/26/on”) > = 0" : ini adalah baris kode yang akan membuat ESP32 menerima request dari button, saat URL berubah menjadi 26/ON URL. Saat headernya kemudian mengandung ekspresi GET/26/on, maka output26state diubah pula menjadi ON, dan dari itu ESP32 akan membuat LED yang terhubung dengan GPIO 26 menyala.

// turns the GPIOs on and off
if (header.indexOf(“GET /26/on”) >= 0) {
Serial.println(“GPIO 26 on”);
output26State = “on”;
digitalWrite(output26, HIGH);
} else if (header.indexOf(“GET /26/off”) >= 0) {
Serial.println(“GPIO 26 off”);
output26State = “off”;
digitalWrite(output26, LOW);
} else if (header.indexOf(“GET /27/on”) >= 0) {
Serial.println(“GPIO 27 on”);
output27State = “on”;
digitalWrite(output27, HIGH);
} else if (header.indexOf(“GET /2/off”) >= 0) {
Serial.println(“LED_BUILTIN off”);
outputLEDState = “off”;
digitalWrite(outputLED, LOW);
} else if (header.indexOf(“GET /2/on”) >= 0) {
Serial.println(“LED_BUILTIN on”);
outputLEDState = “on”;
digitalWrite(outputLED, HIGH);
} else if (header.indexOf(“GET /27/off”) >= 0) {
Serial.println(“GPIO 27 off”);
output27State = “off”;
digitalWrite(output27, LOW);
}

  • Baris kode untuk menginisialisasi tombol interaktif pada Web Server. Blok kode dibawah ini akan membaca outputState GPIO yang terkait, kemudian menampilkan button yang sesuai untuk state tersebut. (Apabila yang sedang muncul adalah yang ON, maka ditampilkan yang OFF, begitu juga sebaliknya)

// Display current state, and ON/OFF buttons for GPIO 26
client.println(“<p>GPIO 26 — State “ + output26State + “</p>”);
// If the output26State is off, it displays the ON button
if (output26State==”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 27
client.println(“<p>GPIO 27 — State “ + output27State + “</p>”);
// If the output27State is off, it displays the ON button
if (output27State==”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>”);
}
client.println(“</body></html>”);

client.println(“<p>Built-In LED — State “ + outputLEDState + “</p>”);
// If the outputLED is off, it displays the ON button
if (outputLEDState==”off”) {
client.println(“<p><a href=\”/2/on\”><button class=\”button\”>ON</button></a></p>”);
} else {
client.println(“<p><a href=\”/2/off\”><button class=\”button button2\”>OFF</button></a></p>”);
}
client.println(“</body></html>”);

Demo:

  • Uploading the Code and Initializing WiFi Connection (Mengupload kode dan mengkoneksikan WiFi)
  • Accessing the Web Server (Mengakses web server)
  • Menyalakan dan Mematikan Lampu berdasarkan Web Server
  • Proses Lengkap Demo

Analisis:

Dapat dilihat bahwa built-in LED bisa menyala, padahal algoritma untuk lampu LED tersebut hampir sama persis dengan lampu-lampu LED lainnya. Dapat disimpulkan bahwa hal yang membuat lampu-lampu tersebut tidak dapat dinyalakan adalah karena cara merangkai rangkaian tersebut yang mungkin kurang tepat atau memang ada komponen yang sudah rusak saat waktu pengetesan.

Pengembangan — ESP32 Web Server — Arduino IDE untuk menampilkan hasil pembacaan sensor BMP280 pada server.

Setelah berhasil menampilkan hal diatas, langkah selanjutnya dalam pengembangan kali ini adalah untuk menghubungkan sensor eksternal dengan ESP32, agar hasil pembacaan dari sensor eksternal dapat ditampilkan disana. Maka dari itu, hasilnya adalah sebagai berikut:

Skema:

Rangkaian:

Rangkaian yang dibuat tidak jauh berbeda dari rangkaian BMP280 biasanya. Seperti yang kita tahu, akan ada 4 pin untuk seluruh komponen yang memanfaatkan protokol I2C, yaitu VCC, GND, SCL, dan SDA. Pin-pin tersebut kemudian dihubungkan oleh kabel jumper warna-warni yang sebenarnya memiliki suatu pattern:

  • VCC (Dari ESP 32 pin 3v3 kabel coklat, terhubung dengan pin VCC BMP280 (
  • GND (Dari pin GND ESP32 kabel hijau, terhubung dengan pin GND di BMP280 )
  • SCL(Dari pin GPIO22 ESP32 kabel biru, terhubung dengan pin SCL di BMP280 )
  • SDA(Dari pin GPIO21 ESP32 kabel kuning, terhubung dengan pin SDA di BMP 280 )

Selanjutnya, untuk algoritma yang digunakan adalah sebagai berikut:

Algoritma:

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

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

//Load BMP Library
#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; // I2C
//Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
//Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);

// Replace with your network credentials
const char* ssid = “MyRepublic_C1012368”;
const char* password = “rumahomap3”;

String outputState = “off”;
// 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);
// Initialize the output variables as outputs
if (!bmp.begin(0x76)) {
Serial.println(F(“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;
String Temperature = String(0);
String Pressure = String(0);
String Altitude = String(0);
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 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>”);

//Read Sensor
Temperature = String(bmp.readTemperature());
Pressure = String(bmp.readPressure());
Altitude = String(bmp.readAltitude(1013.25));

// Display current state, and Temperature, Pressure Altitude
client.print(“<p>Temperature today: “+ Temperature +”</p>”);
client.println(“<p>Pressure today: “ + Pressure + “</p>”);
client.println(“<p>Temperature today: “ + Altitude + “</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(LED_BUILTIN);
Serial.println(“”);

}
}
}

Penjelasan untuk bagaimana cara kerja kode sudah tercantum dalam komentar di algoritma. Tetapi ada satu bagian yang berbeda dari algoritma sebelumnya, yaitu blok kode:

//Read Sensor
Temperature = String(bmp.readTemperature());
Pressure = String(bmp.readPressure());
Altitude = String(bmp.readAltitude(1013.25));

// Display current state, and Temperature, Pressure Altitude
client.print(“<p>Temperature today: “+ Temperature +”</p>”);
client.println(“<p>Pressure today: “ + Pressure + “</p>”);
client.println(“<p>Temperature today: “ + Altitude + “</p>”);

Blok kode Read Sensor digunakan untuk menyimpan hasil pembacaan temperatur, tekanan, dan ketinggian dari sensor BMP 280. Kemudian pada blok selanjutnya akan ditampilkan pada Web Server.

Demo:

Analisis:

Tujuan awal dari rangkaian diatas ini sebenarnya adalah untuk membuat Web Server yang akan menampilkan data temperatur, ketinggian, dan tekanan secara real-time. Tetapi sayangnya, saat dicoba baris kode yang akan melakukan refresh terhadap Web Page setiap suatu periode, kode tidak bisa-bisa dijalankan. Oleh karena itu, data hasil bacaan sensor yang ditampilkan dalam video di atas hanyalah data yang tercatat paling awal.

Diketahui cara-cara untuk membuat web page tersebut bisa melakukan refresh bisa dengan memanfaatkan meta header yang berisi refresh (akan melakukan refresh untuk seluruh web page) ataupun dengan memanfaatkan baris dari AJAX. Tetapi sayangya implementasi dari kedua kode tersebut pada kode yang kali ini digunakan dalam percobaan tidak berhasil.

Sekian dulu untuk kali ini, Terima Kasih!