Web Server Asinkron ESP32 (dengan Tampilan IP di LCD)
Di proyek ini, kita mengubah ESP32 menjadi web server asinkron yang bisa kamu kendalikan dari ponsel atau komputer di jaringan Wi-Fi yang sama. Berkat library ESPAsyncWebServer, server bisa memproses beberapa permintaan bersamaan (berbeda dengan WebServer.h klasik, yang memblokir pada satu permintaan). Kamu bisa membuka alamat IP ESP32 di browser dan mengklik tombol ON/OFF (rute /on dan /off) untuk menyalakan dan mematikan LED yang tersambung ke GPIO 5.

Video
Skema rangkaian

Kode sumber
1// ─────────────────────────────────────────
2// BlueGrays · bluegrays.com
3// Web Server Asinkron ESP32 (dengan Tampilan IP di LCD)
4// ─────────────────────────────────────────
5// ESP32 menjalankan web server asinkron. Buka alamat IP-nya dari ponsel
6// atau komputer di Wi-Fi yang sama dan nyalakan atau matikan LED dengan
7// tombol ON/OFF. LCD I2C menampilkan alamat IP di baris atas dan status
8// LED di baris bawah.
9//
10// Pin:
11// GPIO 5 -> LED (dengan resistor 220 ohm, katoda ke GND)
12// GPIO 21 -> SDA LCD
13// GPIO 22 -> SCL LCD
14// LCD VCC -> VIN (5V), GND -> GND
15
16#include <Wire.h>
17#include <LiquidCrystal_I2C.h>
18#include <WiFi.h>
19#include <AsyncTCP.h>
20#include <ESPAsyncWebServer.h>
21
22// Data login Wi-Fi (default Wokwi). Pakai jaringanmu sendiri di hardware asli
23const char* WIFI_SSID = "Wokwi-GUEST";
24const char* WIFI_PASS = "";
25
26// Definisi pin
27#define LED_PIN 5
28
29bool ledState = false; // Apakah LED menyala
30AsyncWebServer server(80); // Web server di port 80
31LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat 0x27, 16x2
32
33// Me-refresh LCD: IP dan status LED
34void updateLcd() {
35 lcd.clear();
36 lcd.setCursor(0, 0);
37 // Lewati "IP:" jika IP lebih dari 13 karakter
38 String ip = WiFi.localIP().toString();
39 if (ip.length() <= 13) lcd.print("IP:");
40 lcd.print(ip);
41 lcd.setCursor(0, 1);
42 lcd.print(ledState ? "LED: ACIK " : "LED: KAPALI ");
43}
44
45// Halaman HTML, disimpan di flash (PROGMEM). processor() mengisi placeholder %STATE%
46const char INDEX_HTML[] PROGMEM = R"rawliteral(
47<!DOCTYPE html>
48<html lang="tr">
49<head>
50<meta charset="utf-8">
51<meta name="viewport" content="width=device-width,initial-scale=1">
52<title>BlueGrays LED Kontrol</title>
53<style>
54body{font-family:Arial;text-align:center;padding:20px;background:#1a1a2e;color:#fff}
55h1{color:#4ea8de}
56.state{font-size:28px;margin:30px}
57button{padding:18px 40px;font-size:18px;margin:8px;border:none;border-radius:8px;cursor:pointer;color:#fff}
58.on{background:#2ecc71}.off{background:#e74c3c}
59</style>
60</head>
61<body>
62<h1>BlueGrays LED Kontrol</h1>
63<div class="state">LED: %STATE%</div>
64<a href="/on"><button class="on">ON</button></a>
65<a href="/off"><button class="off">OFF</button></a>
66</body>
67</html>
68)rawliteral";
69
70// Mengganti %STATE% di halaman dengan status LED
71String processor(const String& var) {
72 if (var == "STATE") return ledState ? "ACIK" : "KAPALI";
73 return String();
74}
75
76void setup() {
77 pinMode(LED_PIN, OUTPUT);
78 digitalWrite(LED_PIN, LOW);
79
80 // I2C default V1: SDA=21 SCL=22
81 Wire.begin(21, 22);
82 lcd.init();
83 lcd.backlight();
84
85 // Layar pembuka, 3 s
86 lcd.setCursor(3, 0);
87 lcd.print("BlueGrays");
88 lcd.setCursor(2, 1);
89 lcd.print("WebServer v1");
90 delay(3000);
91 lcd.clear();
92
93 // Sambung ke Wi-Fi, tunggu sampai tersambung
94 lcd.setCursor(0, 0);
95 lcd.print("WiFi baglaniyor");
96 lcd.setCursor(0, 1);
97 lcd.print("Connecting...");
98
99 WiFi.mode(WIFI_STA);
100 WiFi.begin(WIFI_SSID, WIFI_PASS);
101 while (WiFi.status() != WL_CONNECTED) delay(500);
102
103 // Rute: "/" halaman, "/on" nyala, "/off" mati
104 server.on("/", HTTP_GET, [](AsyncWebServerRequest *r) {
105 r->send_P(200, "text/html", INDEX_HTML, processor);
106 });
107
108 server.on("/on", HTTP_GET, [](AsyncWebServerRequest *r) {
109 ledState = true;
110 digitalWrite(LED_PIN, HIGH);
111 updateLcd();
112 r->redirect("/");
113 });
114
115 server.on("/off", HTTP_GET, [](AsyncWebServerRequest *r) {
116 ledState = false;
117 digitalWrite(LED_PIN, LOW);
118 updateLcd();
119 r->redirect("/");
120 });
121
122 // Mulai server, tampilkan IP di LCD
123 server.begin();
124 updateLcd();
125}
126
127void loop() {
128 // Server async berjalan di latar belakang
129 delay(100);
130}
131FAQ
Kenapa web server asinkron lebih baik daripada WebServer biasa?
WebServer klasik memproses permintaan secara berurutan dan terus memanggil `handleClient()` di dalam loop. ESPAsyncWebServer memproses permintaan di latar belakang; beberapa browser bisa tersambung bersamaan, dan loop bebas untuk tugas lain.
Bagaimana cara menyiapkan library-nya?
Kamu butuh library ESPAsyncWebServer dan AsyncTCP. Kamu bisa mencari "ESPAsyncWebServer" (ESP32Async) di library manager Arduino IDE lalu menginstalnya; AsyncTCP ikut terinstal sebagai dependensi.
Bisakah aku membuka halamannya dari luar lewat internet?
Secara bawaan, aksesnya terbatas pada jaringan lokal yang sama. Untuk akses dari luar dibutuhkan port forwarding, tetapi itu berisiko bagi keamanan; sebagai gantinya, disarankan Blynk, MQTT, atau solusi berbasis cloud.
Apa artinya menyematkan HTML dengan PROGMEM?
Halaman HTML disimpan di memori flash sebagai teks di dalam kode dan tidak memakan RAM. Dengan begitu antarmuka web bisa disajikan tanpa menyiapkan sistem file terpisah (LittleFS).
