Deep Sleep ESP32: Sumber Wake-Up, Konsumsi Arus, dan Umur Baterai
Penjelasan deep sleep ESP32: arus µA di setiap mode sleep, wake-up dengan timer, tombol, PIR, dan sentuhan (ext0/ext1), penghitung di memori RTC, dan hitungan umur baterai 18650.
Deep sleep ESP32 adalah mode daya di mana ESP32 mematikan CPU-nya, radio Wi-Fi dan Bluetooth-nya, serta memori utamanya, dan hanya membiarkan domain RTC yang kecil tetap hidup. Dalam mode ini, konsumsi chip turun dari 240 mA ketika mengirim lewat Wi-Fi menjadi sekitar 10 µA, alias dua puluh empat ribu kali lebih kecil. Board bangun ketika waktu yang kamu atur habis, ketika tombol ditekan, ketika sensor PIR mendeteksi gerakan, atau ketika sebuah pin disentuh; board menyelesaikan tugasnya dalam beberapa detik lalu tidur lagi. Begitulah stasiun cuaca bertenaga baterai, sensor kebun, alarm pintu, dan pencatat data jarak jauh bisa bertahan berbulan-bulan, bukan hanya beberapa hari, dengan satu sel 18650.
Di panduan ini kamu akan mempelajari mode sleep ESP32 dan nilai arusnya yang sebenarnya, cara membangunkan board dengan timer, tombol, sensor PIR (ext0 dan ext1), atau sentuhan, cara menyimpan penghitung dan hasil pembacaan di memori RTC yang tetap bertahan selama sleep, kenapa board pengembangan masih menarik arus miliampere ketika tidur, dan cara menghitung langkah demi langkah berapa bulan satu 18650 bisa bertahan. Sketch Arduino-nya ditulis untuk core Arduino ESP32 versi 3.1 atau lebih baru, dan di akhir kamu akan melihat cara melakukan hal yang sama dengan MicroPython.

Apa itu deep sleep ESP32 dan bagaimana cara kerjanya?
Di dalam ESP32 ada dua dunia yang terpisah. Yang pertama adalah domain utama berisi CPU, RAM 520 KB, dan radio Wi-Fi serta Bluetooth. Yang kedua adalah domain RTC, yang punya timer kecil sendiri, memori RTC FAST 8 KB dan RTC SLOW 8 KB, pin RTC GPIO, dan koprosesor berdaya sangat rendah bernama ULP. Ketika deep sleep, domain utama dimatikan total dan hanya domain RTC yang tetap berjalan. Begitu waktunya bangun, chip sebenarnya restart: bootloader berjalan, program dimuat lagi dari flash, dan setup() mulai dari atas. Karena itu, program deep sleep mengerjakan semua tugasnya di dalam setup() dan loop() tidak pernah berjalan. Variabel biasa di-reset setiap kali bangun; hanya variabel yang kamu taruh di memori RTC yang tetap tersimpan.
Mode sleep ESP32 dan konsumsi arusnya (µA)
| Mode | Apa yang tetap berjalan? | Arus (chip ESP32) |
|---|---|---|
| Aktif: kirim Wi-Fi (802.11b, 19,5 dBm) | CPU dan radio | 240 mA |
| Aktif: terima dan dengarkan Wi-Fi | CPU dan radio | 95–100 mA |
| Modem sleep, 240 MHz | CPU berjalan, radio mati | 30–68 mA |
| Modem sleep, 80 MHz | CPU berjalan lebih lambat, radio mati | 20–31 mA |
| Light sleep | CPU dijeda, RAM tetap tersimpan | 0,8 mA |
| Deep sleep dengan ULP aktif | Domain RTC dan koprosesor ULP | 150 µA |
| Deep sleep | Timer RTC dan memori RTC | 10 µA |
| Hibernasi | Hanya timer RTC dan sebagian pin RTC | 5 µA |
| Mati (pin EN LOW) | Tidak ada | 1 µA |
Nilai-nilai ini berasal dari datasheet ESP32 milik Espressif dan hanya mencakup chip-nya saja. Ada dua hal di tabel yang perlu diperhatikan. Pertama, ketika light sleep program melanjutkan dari baris tempat ia berhenti dan semua isi RAM tetap tersimpan, tetapi konsumsinya delapan puluh kali lebih tinggi daripada deep sleep, jadi cocok untuk jeda beberapa detik. Ketika deep sleep program mulai dari awal lagi, tetapi konsumsinya turun ke mikroampere, sehingga ini pilihan yang tepat untuk menunggu beberapa menit atau beberapa jam. Kedua, tidak ada mode sleep yang menjaga koneksi Wi-Fi atau Bluetooth tetap hidup; kamu harus menyambung ulang setiap kali bangun. Chip yang lebih baru sedikit berbeda: ESP32-C3 menarik sekitar 5 µA ketika deep sleep dan ESP32-S3 sekitar 7–8 µA.
Kalau ingin konsumsi yang lebih rendah lagi, kamu juga bisa mematikan periferal RTC dan memori RTC. Tulis esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF) dan baris yang sama untuk ESP_PD_DOMAIN_RTC_SLOW_MEM dan ESP_PD_DOMAIN_RTC_FAST_MEM, maka chip mendekati mode hibernasi di sekitar 5 µA. Dalam kasus itu, variabel di memori RTC hilang dan hanya timer atau ext1 yang bisa membangunkan board. Di kebanyakan proyek, selisih antara 10 µA dan 5 µA tidak berarti dibandingkan konsumsi bagian board lainnya, jadi perbaiki dulu masalah di bagian berikutnya.
Kenapa board pengembangan menarik arus miliampere ketika deep sleep?
Ketika kamu meng-upload sketch lalu menghubungkan multimeter, sering kali yang terlihat adalah 5–15 mA, bukan 10 µA. Masalahnya bukan di chip, tetapi di komponen tambahan pada board. Kebanyakan board DevKit dan NodeMCU-32S murah memakai regulator AMS1117 untuk menurunkan 5 V ke 3,3 V, dan regulator itu sendiri biasanya membuang 5 mA bahkan tanpa beban. Tambahkan LED power yang selalu menyala dan chip USB-ke-serial yang berkomunikasi dengan komputermu (CP2102 atau CH340). Totalnya biasanya sekitar 8 mA dan menguras sekitar 190 mAh sehari dari baterai meskipun ESP32 sedang tidur, sehingga 18650 3000 mAh dengan board seperti itu nyaris tidak bertahan dua minggu. Untuk mengukur arusnya, pasang multimeter secara seri di antara baterai dan rangkaian, lalu pindah ke rentang µA selama sleep; detailnya ada di panduan Cara Memakai Multimeter.
| Sumber arus | Arus ketika sleep | Solusi |
|---|---|---|
| Modul ESP32 (deep sleep) | ≈10 µA | Sudah rendah, tidak perlu diapa-apakan |
| Regulator AMS1117 | Biasanya 5 mA (arus diam) | Pakai MCP1700 (arus diam 1,6 µA) atau HT7333 (sekitar 4 µA) |
| LED power | 1–3 mA | Lepas LED atau resistornya |
| Chip USB-ke-serial (CP2102, CH340) | Tergantung board, bisa sampai rentang mA | Pakai board tanpa chip USB atau modul polos |
| Pembagi tegangan baterai 100 kΩ + 100 kΩ | 21 µA (pada 4,2 V) | Pakai 1 MΩ + 1 MΩ atau nyalakan pembagi dengan MOSFET hanya ketika mengukur |
| Sensor yang selalu diberi daya | Dari µA sampai mA, tergantung sensornya | Beri daya sensor dari GPIO atau MOSFET hanya ketika mengukur |
Sketch deep sleep pertamamu: wake-up dengan timer
- Di Boards Manager Arduino IDE, instal paket esp32 by Espressif Systems (versi 3.1 atau lebih baru) dan pilih ESP32 Dev Module sebagai board.
- Upload sketch di bawah dan buka Serial Monitor di 115200 baud.
- Board bangun setiap 10 detik; perhatikan jumlah boot yang terus naik dan alasan bangun yang tercetak sebagai Timer.
- Tekan tombol EN: penghitung kembali ke 1, karena ini reset biasa, bukan bangun dari deep sleep.
- Di proyek sungguhanmu, atur TIME_TO_SLEEP ke 600 (10 menit) atau 3600 (1 jam).
1// ESP32 deep sleep: zamanlayıcıyla uyanma ve RTC sayaç / timer wake-up and RTC counter
2#define uS_TO_S_FACTOR 1000000ULL // 1 saniye = 1.000.000 µs / 1 second = 1,000,000 µs
3#define TIME_TO_SLEEP 10 // uyku süresi, saniye / sleep time in seconds
4
5RTC_DATA_ATTR int bootCount = 0; // RTC belleğinde, derin uykuda silinmez / in RTC memory, kept in deep sleep
6
7void printWakeupReason() {
8 esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
9 switch (cause) {
10 case ESP_SLEEP_WAKEUP_TIMER: Serial.println("Zamanlayici / Timer"); break;
11 case ESP_SLEEP_WAKEUP_EXT0: Serial.println("ext0 (tek pin / single pin)"); break;
12 case ESP_SLEEP_WAKEUP_EXT1: Serial.println("ext1 (coklu pin / multiple pins)"); break;
13 case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("Dokunmatik / Touch"); break;
14 default: Serial.printf("Ilk acilis ya da reset / Power-on or reset (%d)\n", (int)cause); break;
15 }
16}
17
18void setup() {
19 Serial.begin(115200);
20 delay(500); // Seri Monitör'e zaman tanı / give the Serial Monitor time
21 bootCount++;
22 Serial.printf("Uyanis sayisi / Boot count: %d\n", bootCount);
23 printWakeupReason();
24
25 // Burada sensörü oku, veriyi gönder / read the sensor and send the data here
26
27 esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); // 10 s sonra uyan / wake after 10 s
28 Serial.println("Derin uyku basliyor / Entering deep sleep");
29 Serial.flush(); // yazı bitmeden uyuma / finish printing before sleeping
30 esp_deep_sleep_start(); // buradan sonrası çalışmaz / nothing below runs
31}
32
33void loop() {
34 // Derin uykuda loop() hiç çalışmaz / loop() never runs with deep sleep
35}Inti sketch ini ada di dua baris: esp_sleep_enable_timer_wakeup() mengatur waktu bangun dalam mikrodetik, dan esp_deep_sleep_start() langsung menidurkan chip; apa pun yang kamu tulis setelah baris itu tidak akan pernah dijalankan. Jangan lupa akhiran ULL (64-bit) ketika menghitung waktu: 3600 * 1000000 meluap (overflow) di int 32-bit, compiler hanya memberi peringatan, dan board bangun di waktu yang salah atau tidak pernah bangun sama sekali. Serial.flush() menunggu sampai buffer kirim kosong; tanpa baris ini, beberapa baris terakhir terpotong. esp_sleep_get_wakeup_cause() memberi tahu kenapa board bangun dan mengembalikan “tidak ada sumber sleep” setelah pertama kali dinyalakan atau setelah reset. Timer RTC yang menghitung waktu tidur secara bawaan berjalan dari osilator RC internal sekitar 150 kHz. Osilator ini tidak sestabil kristal dan bisa bergeser beberapa persen karena suhu, jadi di proyek yang butuh jam akurat, sebaiknya sinkronkan waktu lewat NTP ketika board bangun.
Menyimpan penghitung dan hasil pembacaan di memori RTC
Kalau kamu perlu mengingat sesuatu di antara dua kali bangun, taruh RTC_DATA_ATTR di depan variabelnya: compiler menempatkannya di memori RTC SLOW 8 KB, yang tetap diberi daya ketika deep sleep, bukan di RAM utama. Ini ideal untuk data kecil seperti penghitung, hasil pembacaan terakhir, informasi kanal Wi-Fi, atau suhu terakhir yang kamu kirim. Namun memori ini tidak permanen: menurut dokumentasi Espressif, data di memori RTC diinisialisasi ulang di setiap restart kecuali bangun dari deep sleep. Mengganti baterai, menekan EN, meng-upload kode baru, atau memanggil ESP.restart() akan me-reset penghitung. Simpan pengaturan yang harus bertahan ketika listrik padam ke flash dengan library Preferences, tapi jangan lakukan itu setiap kali bangun, karena flash punya jumlah siklus tulis yang terbatas.
| Kejadian | Variabel biasa | RTC_DATA_ATTR | Preferences (flash) |
|---|---|---|---|
| Bangun dari deep sleep | Di-reset | Tetap tersimpan | Tetap tersimpan |
| Tombol EN atau ESP.restart() | Di-reset | Kembali ke nilai awal | Tetap tersimpan |
| Baterai dilepas, listrik padam | Di-reset | Hilang | Tetap tersimpan |
| Kode baru di-upload | Di-reset | Hilang | Tetap tersimpan (kecuali flash dihapus) |
Kalau dipakai dengan cerdas, memori ini bisa melipatgandakan umur baterai. Menyambung ke Wi-Fi adalah bagian paling boros dari setiap kali bangun. Karena itu sketch di bawah mengukur tegangan baterai setiap 10 menit, tetapi menyalakan Wi-Fi hanya sekali per jam: enam hasil pembacaan menumpuk di sebuah array di memori RTC, lalu pada bangun keenam semuanya dikirim sekaligus. Sketch ini juga menyimpan kanal dan alamat MAC (BSSID) access point di memori RTC, sehingga pada koneksi berikutnya ESP32 langsung menuju access point itu tanpa memindai semua kanal, dan waktu koneksi jadi jauh lebih singkat.
1// RTC belleğinde ölçüm biriktirip saatte bir gönderme / buffer readings in RTC memory, send hourly
2#include <WiFi.h>
3
4const char* SSID = "AgAdi"; // Wi-Fi adı / Wi-Fi name
5const char* PASS = "Sifre123"; // Wi-Fi şifresi / Wi-Fi password
6const int BAT_PIN = 35; // 1M + 1M bölücünün orta noktası / divider midpoint
7const uint64_t SLEEP_US = 600ULL * 1000000ULL; // 10 dakika / 10 minutes
8const int BATCH = 6; // 6 ölçümde bir gönder / send every 6 readings
9
10RTC_DATA_ATTR float readings[BATCH]; // uykuda korunan ölçümler / readings kept in sleep
11RTC_DATA_ATTR int count = 0; // biriken ölçüm sayısı / number of stored readings
12RTC_DATA_ATTR int32_t savedChannel = 0; // son Wi-Fi kanalı / last Wi-Fi channel
13RTC_DATA_ATTR uint8_t savedBssid[6]; // modemin MAC adresi / access point MAC address
14
15bool connectFast() {
16 WiFi.mode(WIFI_STA);
17 if (savedChannel > 0) {
18 WiFi.begin(SSID, PASS, savedChannel, savedBssid); // taramadan bağlan / connect without scanning
19 } else {
20 WiFi.begin(SSID, PASS); // ilk sefer: normal bağlantı / first time: normal connect
21 }
22 unsigned long start = millis();
23 while (WiFi.status() != WL_CONNECTED) {
24 if (millis() - start > 10000) { // 10 s içinde bağlanamazsa vazgeç / give up after 10 s
25 savedChannel = 0; // bir dahaki sefere tara / scan next time
26 return false;
27 }
28 delay(50);
29 }
30 savedChannel = WiFi.channel();
31 memcpy(savedBssid, WiFi.BSSID(), 6);
32 return true;
33}
34
35void setup() {
36 Serial.begin(115200);
37 // Pili Wi-Fi açılmadan önce ölç / measure the battery before Wi-Fi starts
38 float v = analogReadMilliVolts(BAT_PIN) * 2 / 1000.0; // bölücü gerilimi yarıya indirir / divider halves it
39 readings[count++] = v;
40 Serial.printf("Olcum / Reading %d: %.2f V\n", count, v);
41
42 if (count >= BATCH) {
43 if (connectFast()) {
44 for (int i = 0; i < BATCH; i++) {
45 Serial.printf("Gonder / Send: %.2f V\n", readings[i]); // burada HTTP ya da MQTT / HTTP or MQTT here
46 }
47 count = 0;
48 } else {
49 for (int i = 1; i < BATCH; i++) readings[i - 1] = readings[i]; // en eskiyi at / drop the oldest
50 count = BATCH - 1;
51 }
52 WiFi.disconnect(true);
53 WiFi.mode(WIFI_OFF); // radyoyu kapat / turn the radio off
54 }
55
56 Serial.flush();
57 esp_sleep_enable_timer_wakeup(SLEEP_US);
58 esp_deep_sleep_start();
59}
60
61void loop() {
62}Tegangan baterai dibagi dua oleh pembagi tegangan 1 MΩ + 1 MΩ dan dibaca di GPIO 35, salah satu kanal ADC1. Kapasitor 100 nF di antara titik tengah pembagi dan GND menjaga pembacaan tetap stabil meskipun impedansi pembaginya setinggi itu. Mengukur sebelum Wi-Fi dinyalakan juga penting, karena arus yang ditarik selama radio bekerja membuat tegangan baterai turun sejenak. Kalau Wi-Fi gagal tersambung, hasil pembacaan tertua dibuang dan sisanya disimpan untuk percobaan berikutnya. Mematikan radio dengan rapi lewat WiFi.disconnect(true) dan WiFi.mode(WIFI_OFF) sebelum tidur juga disarankan oleh Espressif. Untuk mempercepat koneksi lagi, beri board IP statis dengan WiFi.config() dan lewati waktu tunggu DHCP. Hitungan pembaginya bisa kamu temukan di panduan pembagi tegangan dan rangkaian pengisiannya di panduan modul charger TP4056.
Bangun dengan tombol atau sensor PIR: ext0 dan ext1
Selain timer, sinyal dari dunia luar juga bisa membangunkan ESP32. Ada dua caranya dan keduanya hanya bekerja di pin RTC GPIO: 0, 2, 4, 12–15, 25–27, dan 32–39. ext0 mengawasi satu pin dan membangunkan board ketika pin itu mencapai level yang kamu pilih (HIGH atau LOW); karena ext0 menjaga periferal RTC tetap diberi daya, resistor pull-up dan pull-down internal tetap bekerja selama sleep. ext1 mengawasi beberapa pin sekaligus lewat bit mask. Di ESP32 klasik, ext1 punya dua mode: ESP_EXT1_WAKEUP_ANY_HIGH membangunkan board ketika salah satu pin yang dipilih menjadi HIGH, dan ESP_EXT1_WAKEUP_ALL_LOW membangunkannya ketika semuanya LOW secara bersamaan. Mode ANY_LOW, yang membangunkan board ketika pin mana pun menjadi LOW, hanya ada di ESP32-S2, S3, C6, dan H2. Jadi kalau kamu ingin beberapa tombol membangunkan ESP32 klasik, sambungkan tombol ke 3V3 dan beri setiap pin resistor pull-down 10 kΩ. Kamu juga bisa mengaktifkan beberapa sumber sekaligus; misalnya, dengan PIR dan timer per jam sama-sama aktif, board bangun oleh mana pun yang datang lebih dulu.
| Sumber wake-up | Fungsi | Pin | Catatan |
|---|---|---|---|
| Timer | esp_sleep_enable_timer_wakeup() | Tidak perlu pin | Waktu dalam mikrodetik, 64-bit |
| ext0 | esp_sleep_enable_ext0_wakeup() | Satu RTC GPIO | Bangun pada HIGH atau LOW; tidak bisa digabung dengan sentuhan atau ULP |
| ext1 | esp_sleep_enable_ext1_wakeup_io() | Beberapa RTC GPIO | ANY_HIGH atau ALL_LOW; disarankan memakai resistor eksternal |
| Sentuhan | touchSleepWakeUpEnable() | T0–T9 (10 pin) | Bangun ketika nilainya turun di bawah ambang; tidak bisa digabung dengan ext0 |
| Koprosesor ULP | esp_sleep_enable_ulp_wakeup() | Tergantung programnya | Bisa membaca sensor ketika tidur; tingkat lanjut |
Pengkabelan untuk rangkaian contoh
| Komponen | Pin komponen | Pin ESP32 | Catatan |
|---|---|---|---|
| Sensor PIR (HC-SR501 atau AM312) | OUT | GPIO 33 | Membangunkan board lewat ext0 |
| Sensor PIR | VCC / GND | 5V (HC-SR501) atau 3V3 (AM312) / GND | HC-SR501 butuh minimal 4,5 V |
| Tombol A | Satu kaki / kaki lainnya | 3V3 / GPIO 25 | Pull-down 10 kΩ di antara GPIO 25 dan GND |
| Tombol B | Satu kaki / kaki lainnya | 3V3 / GPIO 26 | Pull-down 10 kΩ di antara GPIO 26 dan GND |
| Pad sentuh atau kabel | – | GPIO 27 (T7) | Lebih andal kalau dibuat pendek |
| LED + 220 Ω | Anoda | GPIO 2 | Di kebanyakan DevKit, LED biru bawaan juga ada di pin ini |
| Pembagi tegangan baterai (1 MΩ + 1 MΩ) | Titik tengah | GPIO 35 | 100 nF di antara titik tengah dan GND |
| 18650 + TP4056 + LDO 3,3 V | Output LDO / GND | 3V3 / GND | Kapasitor 470 µF di output LDO |
Sketch wake-up dengan sensor PIR (ext0)
1// PIR ile uyanma (ext0) / wake on PIR motion (ext0)
2#include "driver/rtc_io.h"
3
4const gpio_num_t PIR_PIN = GPIO_NUM_33; // RTC GPIO olmalı / must be an RTC GPIO
5const int LED_PIN = 2; // uyarı LED'i / alert LED
6
7RTC_DATA_ATTR int motionCount = 0; // toplam hareket sayısı / total motion count
8
9void setup() {
10 Serial.begin(115200);
11 rtc_gpio_deinit(PIR_PIN); // pini yeniden normal GPIO yap / turn the pad back into a normal GPIO
12 pinMode(PIR_PIN, INPUT);
13 pinMode(LED_PIN, OUTPUT);
14
15 if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0) {
16 motionCount++;
17 Serial.printf("Hareket! / Motion! Toplam / Total: %d\n", motionCount);
18 digitalWrite(LED_PIN, HIGH); // burada bildirim gönderebilirsin / send a notification here
19 delay(1000);
20 digitalWrite(LED_PIN, LOW);
21 }
22
23 // PIR çıkışı LOW olana kadar bekle, yoksa hemen yeniden uyanır / wait for LOW or it wakes again at once
24 while (digitalRead(PIR_PIN) == HIGH) {
25 delay(100);
26 }
27
28 esp_sleep_enable_ext0_wakeup(PIR_PIN, 1); // pin HIGH olunca uyan / wake when the pin goes HIGH
29 rtc_gpio_pullup_dis(PIR_PIN);
30 rtc_gpio_pulldown_en(PIR_PIN); // boştayken LOW tut / keep it LOW while idle
31 Serial.println("Uyku / Sleep");
32 Serial.flush();
33 esp_deep_sleep_start();
34}
35
36void loop() {
37}Setelah bangun, sketch pertama-tama mengembalikan pin menjadi GPIO biasa dengan rtc_gpio_deinit(). Setelah wake-up ext0, pin tetap dalam mode RTC, dan tanpa baris ini digitalRead() bisa tidak bekerja dengan benar. Sketch menghitung gerakan, mengedipkan LED, lalu menunggu output PIR kembali LOW. Penantian ini wajib: kalau board tidur selagi output masih HIGH, board langsung bangun lagi dan terjebak dalam siklus nyala-mati beberapa kali per detik. HC-SR501 menahan output-nya HIGH selama waktu yang diatur di potensiometernya, jadi putar potensiometer waktu ke minimum untuk memperpendek penantian. Karena HC-SR501 butuh minimal 4,5 V, pilih modul PIR kecil AM312, yang juga bisa berjalan di 3,3 V, untuk proyek yang diberi daya satu 18650. Untuk pengaturan sensornya, lihat panduan sensor gerak PIR.
Sketch wake-up dengan dua tombol (ext1)
1// İki butonla uyanma (ext1) / wake with two buttons (ext1)
2#include "driver/rtc_io.h"
3
4const gpio_num_t BTN_A = GPIO_NUM_25; // buton A: 3V3'e, 10k pull-down / button A: to 3V3, 10k pull-down
5const gpio_num_t BTN_B = GPIO_NUM_26; // buton B: 3V3'e, 10k pull-down / button B: to 3V3, 10k pull-down
6const uint64_t WAKE_MASK = (1ULL << BTN_A) | (1ULL << BTN_B);
7
8void setup() {
9 Serial.begin(115200);
10 rtc_gpio_deinit(BTN_A); // pinleri normal GPIO'ya döndür / back to normal GPIO
11 rtc_gpio_deinit(BTN_B);
12 pinMode(BTN_A, INPUT);
13 pinMode(BTN_B, INPUT);
14
15 if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT1) {
16 uint64_t pins = esp_sleep_get_ext1_wakeup_status(); // hangi pin uyandırdı? / which pin woke us?
17 if (pins & (1ULL << BTN_A)) Serial.println("Buton A: isigi ac / Button A: lights on");
18 if (pins & (1ULL << BTN_B)) Serial.println("Buton B: isigi kapat / Button B: lights off");
19 } else {
20 Serial.println("Ilk acilis / First boot");
21 }
22
23 while (digitalRead(BTN_A) == HIGH || digitalRead(BTN_B) == HIGH) {
24 delay(10); // butonlar bırakılana kadar bekle / wait until released
25 }
26
27 esp_sleep_enable_ext1_wakeup_io(WAKE_MASK, ESP_EXT1_WAKEUP_ANY_HIGH); // biri HIGH olunca / any goes HIGH
28 Serial.flush();
29 esp_deep_sleep_start();
30}
31
32void loop() {
33}Setelah wake-up ext1, esp_sleep_get_ext1_wakeup_status() mengembalikan bit mask yang menunjukkan pin mana yang membangunkan board. Dengan begitu kamu bisa memberi dua tombol tugas yang berbeda: satu menyalakan lampu dan satunya mematikan, atau satu mengirim hasil pembacaan dan satunya membuka menu. Karena tombol disambungkan ke 3V3 dan pin ditarik ke GND dengan 10 kΩ, pin terbaca LOW ketika tombol dilepas dan HIGH ketika ditekan, persis seperti yang diharapkan mode ANY_HIGH. Sketch menunggu tombol dilepas sebelum tidur; kalau tidak, tombol yang masih ditekan akan langsung membangunkan board lagi. Kalau kamu memakai core Arduino ESP32 2.x atau 3.0.x, yang belum punya fungsi _io, tulis esp_sleep_enable_ext1_wakeup dengan parameter yang sama sebagai ganti esp_sleep_enable_ext1_wakeup_io. Kenapa resistor pull-down diperlukan, kamu akan tahu di panduan Cara Menghubungkan Push Button ke Arduino.
Bangun dengan sentuhan (touch wake-up)
Sepuluh pin ESP32 (T0–T9) bekerja sebagai sensor sentuh kapasitif dan bisa mendeteksi jarimu bahkan ketika deep sleep. Kabel, potongan pita tembaga, atau pad PCB yang dihubungkan ke pin itu berperilaku seperti tombol dan bahkan bisa diletakkan di balik penutup plastik atau kayu yang tipis. Di ESP32 klasik, nilai touchRead() turun ketika disentuh: dengan kabel pendek biasanya terbaca 60–80 ketika tidak disentuh dan 10–20 ketika disentuh. Taruh ambang wake-up di antara dua nilai ini; angka 40 di contoh adalah titik awal yang bagus. Di ESP32 klasik kamu bisa memakai beberapa pin sentuh sekaligus sebagai sumber wake-up. Namun di ESP32-S2 dan S3, hanya satu pin yang bisa membangunkan chip, nilainya naik ketika disentuh, dan ambangnya memakai skala yang sama sekali berbeda (5000 di contoh Espressif). Wake-up sentuh tidak bisa digabung dengan ext0; kalau kamu juga butuh tombol, pakai ext1. Untuk daftar pin dan kalibrasinya, baca panduan pin sentuh ESP32.
1// Dokunarak uyandırma: T7 = GPIO 27 / touch wake-up: T7 = GPIO 27
2#define THRESHOLD 40 // değer bunun altına inince uyanır / wakes when the value drops below this
3
4RTC_DATA_ATTR int touchWakes = 0;
5
6void setup() {
7 Serial.begin(115200);
8 delay(500);
9 if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TOUCHPAD) {
10 touchWakes++;
11 Serial.printf("Dokunusla uyanma / Touch wake #%d\n", touchWakes);
12 }
13 // Eşiği ayarlamak için dokunmadan ve dokunarak değeri izle / watch the value untouched and touched
14 Serial.printf("T7 degeri / value: %d\n", (int)touchRead(T7));
15
16 touchSleepWakeUpEnable(T7, THRESHOLD); // dokunmatikle uyanmayı aç / enable touch wake-up
17 Serial.flush();
18 esp_deep_sleep_start();
19}
20
21void loop() {
22}Deep sleep ESP32 dengan MicroPython
Kalau kamu memprogram ESP32 dengan MicroPython, hal yang sama bisa dilakukan dengan kode yang lebih pendek. machine.deepsleep(ms) menidurkan board selama jumlah milidetik yang diberikan, esp32.wake_on_ext0() menjadikan sebuah pin sumber wake-up, dan machine.RTC().memory() memberimu buffer byte yang tetap bertahan selama sleep; di ESP32 kapasitas bawaannya 2048 byte. Ketika bangun, main.py berjalan dari atas; machine.reset_cause() memberi tahu apakah board baru keluar dari deep sleep dan machine.wake_reason() memberi tahu apa yang membangunkannya. Pin RTC yang diatur dengan pull-up atau pull-down tetap mempertahankan pengaturan itu selama sleep. Kalau kamu baru mengenal MicroPython, mulai dari panduan dasar-dasar MicroPython.
1import machine, esp32, time
2from machine import Pin
3
4rtc = machine.RTC()
5led = Pin(2, Pin.OUT)
6
7mem = rtc.memory() # RTC belleğini oku / read RTC memory
8count = int.from_bytes(mem, "little") if mem else 0
9
10if machine.reset_cause() == machine.DEEPSLEEP_RESET:
11 count += 1
12 if machine.wake_reason() == machine.EXT0_WAKE:
13 print("Butonla uyandi / Woken by button")
14 else:
15 print("Zamanlayiciyla uyandi / Woken by timer")
16else:
17 count = 0
18 print("Ilk acilis / First boot")
19
20rtc.memory(count.to_bytes(4, "little")) # sayacı sakla / store the counter
21print("Uyanis / Wake:", count)
22
23led.on() # kısa iş: ölç ve gönder / short task: measure and send
24time.sleep_ms(200)
25led.off()
26
27button = Pin(33, Pin.IN, Pin.PULL_DOWN) # buton GPIO 33 ile 3V3 arasında / button between GPIO 33 and 3V3
28esp32.wake_on_ext0(button, esp32.WAKEUP_ANY_HIGH) # basınca uyan / wake on press
29machine.deepsleep(60000) # 60 s uyu / sleep for 60 sSebaliknya, Raspberry Pi Pico tidak punya deep sleep tingkat mikroampere seperti ESP32. Di MicroPython, machine.lightsleep(ms) menghentikan sebagian besar clock, menjeda CPU, dan menjaga isi RAM, sedangkan machine.deepsleep(ms) me-reset board setelah sleep yang serupa. Bahkan dalam mode-mode ini konsumsi board tetap di rentang miliampere. Jadi kalau kamu ingin membuat perangkat Pico yang berjalan dengan baterai selama berbulan-bulan, memutus daya board sepenuhnya di antara pengukuran dengan timer daya seperti TPL5110 memberi hasil yang lebih baik. Untuk dasar-dasar Pico, lihat panduan Apa Itu Raspberry Pi Pico?.
Sensor yang bertahan berbulan-bulan dengan satu 18650: menghitung umur baterai
Untuk mengetahui umur baterai perangkat yang tidur dan bangun, kamu hitung dulu arus rata-ratanya: Arus rata-rata = (Arus bangun × Waktu bangun + Arus sleep × Waktu sleep) / Waktu total. Lalu bagi kapasitas baterai yang bisa dipakai dengan rata-rata itu. Kamu tidak bisa memakai seluruh kapasitas 18650 berlabel 3000 mAh; menghitung sekitar 85%, atau 2550 mAh, untuk memperhitungkan batas tegangan cut-off, rugi-rugi regulator, dan penuaan baterai adalah angka yang realistis. Tabel di bawah dihitung untuk sensor yang bangun setiap 10 menit, mengirim data lewat Wi-Fi, dan menarik rata-rata 120 mA selama tersambung.
| Skenario | Arus sleep | Waktu bangun | Arus rata-rata | Perkiraan umur |
|---|---|---|---|---|
| Board DevKit | 8 mA | 3 dtk, 120 mA | 8,56 mA | ≈12 hari |
| Board DevKit, koneksi cepat | 8 mA | 1 dtk, 120 mA | 8,19 mA | ≈13 hari |
| Modul polos + MCP1700 + pembagi 1 MΩ | 15 µA | 3 dtk, 120 mA | 0,61 mA | ≈173 hari (5,7 bulan) |
| Modul polos, koneksi cepat | 15 µA | 1 dtk, 120 mA | 0,215 mA | ≈494 hari (16 bulan) |
| Modul polos, kirim data sekaligus per jam | 15 µA | 1 dtk Wi-Fi per jam (120 mA) + 5 × 0,3 dtk pembacaan (40 mA) | 0,065 mA | ≈4,5 tahun secara teori |
Kesimpulannya jelas: di board pengembangan, memperpendek waktu bangun hampir tidak mengubah apa-apa, karena yang benar-benar menguras baterai adalah arus 8 mA ketika sleep. Begitu arus sleep turun ke mikroampere, keadaannya berbalik dan setiap detik bangun jadi berarti: memangkas koneksi Wi-Fi dari 3 detik menjadi 1 detik membuat umur baterai hampir tiga kali lipat. Ketika arus rata-rata turun di bawah 0,1 mA, self-discharge (pengosongan sendiri) baterai mulai berpengaruh. Sel Li-ion kehilangan sekitar 2–3% kapasitasnya per bulan, sehingga 4,5 tahun secara teori menyusut menjadi sekitar 2 tahun dalam praktik. Untuk menghitung dengan nilaimu sendiri, pakai kalkulator umur baterai, dan baca tentang mAh dan Wh di panduan Apa Arti mAh?.
- Pilih board yang tepat: board tanpa chip USB dan LED power, atau modul ESP32 polos, hanya menarik arus mikroampere ketika sleep.
- Ganti regulatornya: pakai LDO dengan arus diam beberapa mikroampere sebagai ganti AMS1117.
- Beri daya sensor hanya ketika mengukur: sensor yang menarik beberapa mA bisa diberi daya langsung dari GPIO, dan beban yang lebih besar lewat MOSFET kanal-P; pasang resistor pull-up di gate MOSFET supaya tetap mati selama sleep. Detailnya ada di panduan Memakai MOSFET dengan Arduino.
- Nyalakan Wi-Fi sesekali saja: kumpulkan hasil pembacaan di memori RTC dan kirim sekaligus; kalau kamu mengirim data ke ESP32 lain di dekatmu, ESP-NOW mengirim dalam waktu yang jauh lebih singkat karena tidak perlu bergabung ke access point.
- Percepat koneksi: dengan IP statis serta kanal dan BSSID yang tersimpan, koneksi Wi-Fi sering kali butuh kurang dari satu detik.
- Hapus penantian yang tidak perlu: buang output Serial Monitor dan baris delay() yang panjang dari proyek yang sudah jadi; setiap milidetik bangun diambil dari baterai.
- Jangan lupakan pembagi tegangan dan LED: pembagi 100 kΩ + 100 kΩ yang terhubung permanen menarik arus dua kali lebih besar daripada ESP32 yang sedang tidur.
Ide proyek deep sleep ESP32
- Stasiun cuaca bertenaga baterai: ukur suhu, kelembapan, dan tekanan udara dengan BME280 setiap 10 menit dan kirim sekali per jam ke Home Assistant lewat MQTT.
- Sensor kelembapan kebun: bangun sekali per jam, ukur kelembapan tanah, dan kirim pesan ke ponselmu ketika tanahnya mulai kering.
- Alarm pintu dan jendela: ketika pintu terbuka, reed switch membangunkan ESP32 lewat ext0 dan bot Telegram mengirimimu pesan.
- Sensor keamanan bertenaga baterai: buat perangkat yang bangun dan mengirim peringatan ketika PIR mendeteksi gerakan, lalu tidur berbulan-bulan di sisa waktunya.
- Bel pintu sentuh: tempelkan pita tembaga di balik panel kayu; sentuhan membangunkan ESP32, yang lalu memberi sinyal ke bel di dalam rumah lewat ESP-NOW.
- Pencatat suhu bertenaga baterai: ukur suhu kulkas atau akuarium dengan DS18B20 versi tahan air, kumpulkan nilainya di memori RTC, dan kirim beberapa kali sehari.
Kesalahan umum dan cara mengatasinya
| Gejala | Penyebab | Solusi |
|---|---|---|
| Board langsung bangun begitu masuk sleep | Pin wake-up masih aktif (PIR HIGH, tombol ditekan) atau mengambang | Tunggu pin kembali ke level diamnya sebelum tidur dan tambahkan resistor pull-down atau pull-up |
| Board tidak bangun di waktu yang diharapkan | Overflow 32-bit di perhitungan waktu (3600 * 1000000) | Tambahkan ULL ke konstanta: 3600ULL * 1000000ULL |
| Penghitung selalu mulai dari 1 | Variabelnya bukan RTC_DATA_ATTR atau board di-reset | Tambahkan RTC_DATA_ATTR; pakai Preferences untuk data permanen |
| Terukur 5–15 mA ketika sleep | Regulator, LED power, chip USB, pembagi tegangan, atau sensor | Board hemat daya atau modul polos, LDO dengan arus diam rendah |
| Baris terakhir di Serial Monitor terpotong | Board tidur sebelum buffer kosong | Panggil Serial.flush() sebelum esp_deep_sleep_start() |
| digitalRead() memberi nilai salah setelah bangun | Pin wake-up masih dalam mode RTC | Panggil rtc_gpio_deinit() sebelum memakai pin |
| Tombol di GPIO 34–39 tidak membangunkan board | Pin-pin ini tidak punya resistor pull internal, jadi pin mengambang | Tambahkan resistor eksternal 10 kΩ |
| Kode tidak mau di-upload ketika board tidur | Board tidak punya rangkaian auto-reset; di S3 dan C3 port USB native menghilang selama sleep | Tahan BOOT, tekan lalu lepas EN (RESET), kemudian mulai upload |
| Relay atau LED berubah status ketika board masuk sleep | Pin digital mengambang (impedansi tinggi) ketika deep sleep | Pakai resistor pull atau tahan level pin dengan rtc_gpio_hold_en() |
Deep sleep ESP32 adalah kunci untuk menjalankan kode yang sama dengan baterai selama berbulan-bulan, bukan hanya beberapa hari: buat tugasnya singkat, pilih sumber wake-up yang tepat, simpan data kecil yang kamu perlukan di antara dua kali bangun di memori RTC, dan jangan pernah melupakan konsumsi board itu sendiri. Kalau ingin kembali ke dasar-dasar ESP32, panduan Apa Itu ESP32? adalah awal yang baik. Di aplikasi BlueGrays, proyek Deep Sleep ESP32: Hemat Baterai (OLED + Penghitung RTC RAM) memungkinkanmu mencoba logika timer dan penghitung RTC dari artikel ini di rangkaian dengan layar OLED, lengkap dengan skema rangkaian langkah demi langkah dan kode siap pakai.
Pertanyaan umum
Berapa arus yang ditarik ESP32 ketika deep sleep?
Menurut datasheet Espressif, chip ESP32 menarik sekitar 10 µA ketika deep sleep dengan timer RTC dan memori RTC aktif, dan 5 µA dalam mode hibernasi. Namun di board pengembangan seperti DevKit, regulator, LED power, dan chip USB-ke-serial biasanya mendorong arus sleep sampai 5–15 mA.
Bagaimana cara membangunkan ESP32 dari deep sleep?
Ada lima cara: timer RTC, satu pin RTC (ext0), beberapa pin RTC (ext1), pin sentuh, dan koprosesor ULP. Kamu mengatur sumber wake-up sebelum memanggil esp_deep_sleep_start() dan bisa mengaktifkan beberapa sumber sekaligus; hanya ext0 dan wake-up sentuh yang tidak bisa dipakai bersamaan.
Apakah variabel hilang ketika ESP32 deep sleep?
Ya, variabel biasa hilang, karena bangun dari deep sleep sama dengan restart dan setup() berjalan dari awal. Variabel yang ditandai RTC_DATA_ATTR disimpan di memori RTC dan tetap ada di antara dua kali bangun, tetapi kembali ke nilai awalnya setelah listrik padam, tombol EN ditekan, atau ada upload baru.
Berapa lama ESP32 bisa berjalan dengan baterai 18650?
Mulai dari satu hari sampai lebih dari setahun, tergantung board dan cara pemakaiannya. DevKit yang terus tersambung ke Wi-Fi hanya bertahan 1–2 hari dengan 18650 3000 mAh, dan DevKit yang bangun setiap 10 menit bertahan sekitar 12 hari. Rangkaian hemat daya yang mengerjakan tugas yang sama dengan arus sleep 15 µA bisa berjalan 5 sampai 16 bulan, tergantung berapa lama setiap koneksi berlangsung.
Apa beda light sleep dan deep sleep di ESP32?
Ketika light sleep, CPU dijeda tetapi RAM tetap tersimpan; begitu board bangun, program melanjutkan dari baris tempat ia berhenti, dan chip menarik sekitar 0,8 mA. Ketika deep sleep, RAM juga dimatikan dan konsumsi turun ke 10 µA, tetapi program mulai dari awal setiap kali bangun. Light sleep cocok untuk jeda beberapa detik, deep sleep cocok untuk menunggu beberapa menit atau beberapa jam.
Bagaimana cara meng-upload kode ke ESP32 yang sedang deep sleep?
Di board yang punya rangkaian auto-reset, upload biasanya langsung berjalan tanpa masalah, karena uploader me-reset chip lewat pin EN. Kalau tidak berhasil, tahan tombol BOOT, tekan lalu lepas EN (RESET), kemudian mulai upload. Di board dengan USB native seperti ESP32-S3 dan C3, port-nya menghilang selama sleep, jadi cara ini sering kali wajib dipakai.
Proyek untuk dibuat setelah membaca ini
Lihat semua proyek
LED Berkedip dengan ESP32
Mengajarkan penggunaan output GPIO dasar dengan ESP32. Kita membuat efek berkedip dengan menyalakan dan mematikan LED dari pin digital. Versi ESP32 dari proyek blink klasik di Arduino UNO; perintah blink dasar di lingkungan Arduino sama, tetapi susunan pin ESP32 dan level GPIO 3,3 V-nya berbeda dengan Arduino UNO.

Kendali LED dengan Tombol Tekan ESP32 (Tekan)
LED menyala ketika tombol ditekan dan mati ketika dilepas. Menunjukkan cara memakai pin input digital ESP32 dan resistor pull-up internalnya. Mode INPUT_PULLUP membuat resistor eksternal tidak diperlukan.

Deep Sleep ESP32: Hemat Baterai (OLED + Penghitung RTC RAM)
Mode Deep Sleep ESP32 menurunkan konsumsi arus hingga ~10 µA dengan mematikan CPU dan sebagian besar periferal, sehingga sangat penting untuk perangkat IoT bertenaga baterai. Di proyek ini, kita memakai tiga sumber bangun yang berbeda: timer (15 detik), pin eksternal (EXT0, tombol GPIO 33), dan sentuhan (T0/GPIO 4). Variabel yang ditandai RTC_DATA_ATTR dipertahankan selama deep sleep; penghitung boot, penghitung bangun karena timer, dan penghitung bangun karena tombol terus dilacak.

Sistem Alarm Gerakan ESP32 (PIR + Buzzer + LED + Telegram)
Sistem alarm keamanan pintar yang menyalakan buzzer dan LED ketika sensor PIR mendeteksi gerakan, sekaligus mengirim notifikasi instan ke pemilik lewat Telegram. Cooldown 30 detik membatasi seberapa sering alarm berulang; mekanisme ini tidak memvalidasi deteksi PIR atau menghilangkan pemicu palsu. Cocok untuk rumah, garasi, gudang, atau ruang kerja. Dengan ESP32-CAM bisa ditambahkan notifikasi berfoto; dengan ESP32 DevKit V1 klasik, notifikasinya berupa teks.

Lampu Otomatis dengan Sensor Gerak PIR ESP32
Di proyek ini, sensor gerak PIR HC-SR501 mendeteksi ketika seseorang masuk ke ruangan dan otomatis menyalakan LED. Lama LED menyala dilacak dengan millis(); setiap bacaan HIGH memperbarui waktu gerakan terakhir, dan LED mati minimal 10 detik setelah bacaan HIGH terakhir. Kode yang sekarang juga menunggu 50 ms di setiap loop dengan delay(50), jadi loopnya belum sepenuhnya non-blocking. Proyek ini bisa dipakai untuk lampu tangga.

Suhu dan Kelembapan DHT22 ESP32 (dengan Layar LCD)
Proyek ini mengukur suhu dan kelembapan sekitar dengan sensor DHT22 dan menampilkan datanya secara real-time di LCD I2C 16x2. Data dibaca dari sensor dengan protokol satu kabel lewat library Adafruit DHT. Proyek ini menjadi dasar untuk stasiun cuaca IoT, otomasi rumah pintar, atau sistem pemantauan lingkungan di rumah kaca. Komunikasi dengan DHT22 dilakukan lewat pin GPIO 4 ESP32.

Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)
Buat pencatat suhu bercap waktu dengan ESP32! Baca suhu/kelembapan DHT22 setiap menit, ambil waktu sebenarnya dari RTC DS1307, dan catat ke kartu microSD sebagai CSV. OLED menampilkan suhu langsung (font besar), kelembapan, cap waktu, dan penghitung catatan. File /temp_log.csv bisa dibuka di Excel, Google Sheets, atau Python pandas; cocok untuk rumah kaca, suhu kamar, data laboratorium, penyimpanan makanan, atau sarang lebah.
Artikel lainnya
Aplikasi BlueGrays
Rakit rangkaian ini langkah demi langkah di ponselmu
Skema pengkabelan, kode, dan daftar komponen dalam satu layar. 200+ proyek Arduino, ESP32, dan Pico siap dibuat.
Pindai dengan ponselmu
Arahkan kamera ke kode ini dan toko aplikasi di ponselmu akan terbuka.
atau buka toko aplikasi

