Pendahuluan — Seri 2 ESP32/IoT
Selamat datang di artikel pembuka Seri 2 Koding Indonesia! Ini adalah lanjutan langsung dari janji deep sleep di roadmap artikel #10. Di capstone Seri 1 kamu sudah membangun dashboard hybrid Web + MQTT yang terus menyala. Itu cocok untuk proyek bertenaga adaptor USB di meja kerja.
Tapi bagaimana jika sensor harus dipasang di kebun, gudang, atau sudut rumah tanpa stop kontak? Node yang terus hidup akan menghabiskan baterai dalam hitungan jam. Solusinya: deep sleep — ESP32 tidur nyaris total, bangun sebentar untuk kirim data, lalu tidur lagi.
Dalam tutorial ini kita bangun node sensor DHT22 hemat baterai yang setiap beberapa menit:
- Bangun dari deep sleep
- Hubungkan WiFi
- Baca suhu & kelembaban
- Publish JSON ke MQTT (topic sama seperti Seri 1)
- Matikan radio WiFi dan tidur lagi
Prasyarat: Sudah paham WiFi ESP32, sensor DHT22, dan publish MQTT. Familiar dengan JSON MQTT dari proyek gabungan atau dashboard capstone akan membantu.
Light Sleep vs Deep Sleep
| Mode | CPU & WiFi | Konsumsi arus | Cocok untuk |
|---|---|---|---|
| Light sleep | CPU pause, RAM tetap | Lebih tinggi dari deep sleep | Bangun cepat, koneksi WiFi tetap hidup |
| Deep sleep | Hampir mati total; hanya RTC | ~10 µA (ideal) pada chip | Node baterai kirim data periodik |
Pada deep sleep, ESP32 reset penuh saat bangun — program dimulai lagi dari setup(). Itu normal dan justru disederhanakan: tidak perlu khawatir state lama di RAM.
Wake-up timer vs GPIO: Tutorial ini memakai esp_sleep_enable_timer_wakeup() (bangun tiap N detik). Alternatif lanjutan: bangun dari pin eksternal (mis. tombol atau sensor) dengan esp_sleep_enable_ext0_wakeup() — berguna jika event jarang terjadi.
Install Library
Install lewat Arduino IDE → Sketch → Include Library → Manage Libraries:
- DHT sensor library — Adafruit (+ Adafruit Unified Sensor)
- PubSubClient — Nick O'Leary
Board ESP32 via Board Manager sudah menyertakan esp_sleep.h — tidak perlu library tambahan untuk deep sleep.
Yang Kamu Butuhkan
- ESP32 DevKit + sensor DHT22 (GPIO 4, pull-up 10kΩ ke 3.3V)
- Kabel jumper & breadboard
- Power: USB untuk uji awal; opsional LiPo 3.7V + modul TP4056 untuk simulasi baterai
- Library: DHT sensor library, PubSubClient
- WiFi 2.4 GHz + MQTT Explorer (subscribe topic)
Catatan daya: Saat WiFi connect, arus bisa melonjak >100 mA meski sebentar. Itulah mengapa kita matikan WiFi sebelum tidur — bukan hanya deep sleep chip, tapi juga radio WiFi yang harus off.
Wiring DHT22
Sama seperti Seri 1 — jangan ubah pin tanpa alasan:
- VCC DHT22 → 3.3V
- GND → GND
- DATA → GPIO 4 + resistor pull-up 10kΩ ke 3.3V
Pin strapping: Hindari GPIO yang dipakai saat boot (mis. beberapa board sensitif di GPIO 0, 2, 12, 15). GPIO 4 aman untuk DHT22 di kebanyakan DevKit.
Arsitektur Node Sensor
| Tahap | Durasi tipikal | Catatan |
|---|---|---|
| Deep sleep | 10 menit (konfigurasi) | Hanya RTC timer hidup |
| Bangun + baca DHT22 | ~2–3 detik | delay(2000) setelah dht.begin() |
| WiFi + MQTT publish | ~3–10 detik | Sekali publish per siklus |
| Matikan WiFi → deep sleep | <1 detik | WiFi.mode(WIFI_OFF) |
Broker latihan: test.mosquitto.org:1883 (sama Seri 1).
Topic: kodingindonesia/esp32/dht22/data — payload JSON {"suhu":28.5,"kelembaban":65.2}.
Broker bukan website:
test.mosquitto.orgtidak dibuka di browser. Pakai MQTT Explorer ataumosquitto_sub. Detail di artikel MQTT.
Pro tip: Ganti segmen topic dengan nama unik, misalnya
kodingindonesia/anton/esp32/dht22/data, agar tidak bentrok dengan peserta tutorial lain di broker publik.
Kode Lengkap: Deep Sleep + DHT22 + MQTT
Ganti ssid dan password, lalu upload. Setelah upload, buka Serial Monitor 115200 — kamu akan melihat satu siklus lalu ESP32 tidur (Serial berhenti sampai bangun lagi).
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include "esp_sleep.h"
// Durasi tidur (detik) — ubah sesuai kebutuhan
const uint64_t DURASI_TIDUR_DETIK = 600; // 10 menit
const char* ssid = "NamaWiFiKamu";
const char* password = "PasswordWiFiKamu";
const char* mqttServer = "test.mosquitto.org";
const int mqttPort = 1883;
const char* topicSensor = "kodingindonesia/esp32/dht22/data";
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
WiFiClient espClient;
PubSubClient mqttClient(espClient);
void cetakAlasanBangun() {
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
switch (cause) {
case ESP_SLEEP_WAKEUP_TIMER:
Serial.println("Bangun: timer deep sleep");
break;
case ESP_SLEEP_WAKEUP_UNDEFINED:
default:
Serial.println("Bangun: boot / reset (upload atau tombol EN)");
break;
}
}
void matikanWiFi() {
mqttClient.disconnect();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
bool koneksiWiFi() {
Serial.print("WiFi");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
unsigned long mulai = millis();
while (WiFi.status() != WL_CONNECTED && millis() - mulai < 15000) {
delay(500);
Serial.print(".");
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\nWiFi gagal (timeout 15 detik)");
return false;
}
Serial.println("\nWiFi terhubung");
return true;
}
bool koneksiMQTT() {
mqttClient.setServer(mqttServer, mqttPort);
mqttClient.setBufferSize(512);
String clientId = "ESP32-Sleep-" + String(random(0xffff), HEX);
if (mqttClient.connect(clientId.c_str())) {
Serial.println("MQTT terhubung");
return true;
}
Serial.print("MQTT gagal, rc=");
Serial.println(mqttClient.state());
return false;
}
bool publishSensor() {
float kelembaban = dht.readHumidity();
float suhu = dht.readTemperature();
if (isnan(kelembaban) || isnan(suhu)) {
Serial.println("DHT22 gagal (NaN) — lewati publish");
return false;
}
String payload = "{\"suhu\":" + String(suhu, 1);
payload += ",\"kelembaban\":" + String(kelembaban, 1) + "}";
mqttClient.loop();
if (mqttClient.publish(topicSensor, payload.c_str())) {
Serial.print("Publish ");
Serial.print(topicSensor);
Serial.print(": ");
Serial.println(payload);
return true;
}
Serial.println("Publish gagal");
return false;
}
void masukDeepSleep() {
Serial.print("Deep sleep ");
Serial.print((unsigned long)DURASI_TIDUR_DETIK);
Serial.println(" detik...");
Serial.flush();
esp_sleep_enable_timer_wakeup(DURASI_TIDUR_DETIK * 1000000ULL);
esp_deep_sleep_start();
// tidak pernah sampai di sini
}
void setup() {
Serial.begin(115200);
delay(100);
cetakAlasanBangun();
// Hemat daya saat aktif (opsional, trade-off kecepatan)
setCpuFrequencyMhz(80);
randomSeed(micros());
dht.begin();
delay(2000); // stabilkan DHT22 setelah bangun
if (!koneksiWiFi()) {
matikanWiFi();
masukDeepSleep();
return;
}
if (!koneksiMQTT()) {
matikanWiFi();
masukDeepSleep();
return;
}
publishSensor();
matikanWiFi();
masukDeepSleep();
}
void loop() {
// Deep sleep: loop tidak dipakai — semua logika di setup() tiap bangun
}
Alur Program (Tiap Siklus Bangun)
setup()jalan dari awal (reset setelah deep sleep)- Cetak alasan bangun (timer atau boot pertama)
- Inisialisasi DHT22 + jeda 2 detik
- Connect WiFi (timeout 15 detik)
- Connect MQTT +
setBufferSize(512) - Publish satu payload JSON
- Disconnect MQTT & matikan WiFi
esp_deep_sleep_start()— tidurDURASI_TIDUR_DETIK
Uji Coba
- Upload sketch, buka Serial Monitor 115200
- Catat log: WiFi OK → MQTT → publish JSON → "Deep sleep 600 detik..."
- Serial berhenti — ESP32 tidur (normal)
- Di MQTT Explorer, connect ke
test.mosquitto.org, subscribekodingindonesia/esp32/dht22/data - Tunggu ~10 menit (atau ubah
DURASI_TIDUR_DETIKjadi60untuk uji cepat) — pesan baru muncul periodik
mosquitto_sub -h test.mosquitto.org -t "kodingindonesia/esp32/dht22/data" -v
Uji cepat: Set
DURASI_TIDUR_DETIK = 60saat development, kembalikan ke 600 (10 menit) untuk deploy baterai.
Optimasi Hemat Daya
setCpuFrequencyMhz(80)— kurangi konsumsi saat aktif (boleh 160 jika connect WiFi sering gagal)WiFi.mode(WIFI_OFF)— wajib sebelum sleep; jangan biarkan radio idle- Satu publish per bangun — hindari loop panjang di
loop() - Timeout WiFi — jangan infinite loop; gagal → tidur lagi agar baterai tidak habis di jaringan WiFi rumah yang lemah
- DHT22 — selalu
delay(2000)setelahbegin()pasca deep sleep - Multimeter — ukur arus di jalur 3.3V saat bangun vs saat tidur untuk validasi optimasi (harapkan lonjakan singkat saat WiFi connect)
Tips & Troubleshooting
- DHT22 NaN setelah bangun: Perpanjang delay; cek wiring & pull-up; hindari kabel panjang tanpa shield
- Boot loop tanpa tidur: Pastikan tidak ada kode setelah
esp_deep_sleep_start()yang mengharapkan lanjut; cek brownout jika pakai baterai lemah (gunakan supply stabil) - Tidak ada pesan MQTT: Topic case-sensitive; cek
setBufferSize(512); lihat artikel MQTT - Baterai cepat habis: Kurangi frekuensi bangun; pastikan WiFi benar-benar off; ukur arus dengan multimeter untuk baseline
- Upload gagal setelah sleep: Tekan tombol BOOT saat upload, atau colok USB lalu reset sebelum ESP32 sempat tidur
Langkah Selanjutnya (Seri 2)
- NVS + WiFiManager ESP32 — simpan kredensial WiFi di flash, tanpa hardcode
ssid/passworddi kode produksi - Broker Mosquitto pribadi — pindah dari
test.mosquitto.orgdengan autentikasi - Sensor BME280 via I2C — upgrade akurasi + tekanan udara untuk node lapangan
- Kembali ke dashboard capstone Seri 1 untuk membandingkan node always-on vs battery-powered
Keamanan: Jangan hardcode password WiFi di repo publik. Untuk proyek lapangan, gunakan NVS + WiFiManager atau simpan kredensial di file terpisah yang tidak di-commit.
Ini langkah pertama menuju node IoT yang benar-benar wireless — sensor di mana adaptor listrik tidak tersedia. Lanjutkan Seri 2 di halaman artikel Koding Indonesia.