Panduan · 15 mnt baca

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.

Board pengembangan ESP32 (DevKit)
Board pengembangan ESP32: modul berpelindung logamnya menarik sekitar 10 µA ketika deep sleep, sementara regulator, LED power, dan chip USB-ke-serial di board mendorong angka itu naik sampai ke rentang miliampere.

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)

ModeApa yang tetap berjalan?Arus (chip ESP32)
Aktif: kirim Wi-Fi (802.11b, 19,5 dBm)CPU dan radio240 mA
Aktif: terima dan dengarkan Wi-FiCPU dan radio95–100 mA
Modem sleep, 240 MHzCPU berjalan, radio mati30–68 mA
Modem sleep, 80 MHzCPU berjalan lebih lambat, radio mati20–31 mA
Light sleepCPU dijeda, RAM tetap tersimpan0,8 mA
Deep sleep dengan ULP aktifDomain RTC dan koprosesor ULP150 µA
Deep sleepTimer RTC dan memori RTC10 µA
HibernasiHanya timer RTC dan sebagian pin RTC5 µA
Mati (pin EN LOW)Tidak ada1 µ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 arusArus ketika sleepSolusi
Modul ESP32 (deep sleep)≈10 µASudah rendah, tidak perlu diapa-apakan
Regulator AMS1117Biasanya 5 mA (arus diam)Pakai MCP1700 (arus diam 1,6 µA) atau HT7333 (sekitar 4 µA)
LED power1–3 mALepas LED atau resistornya
Chip USB-ke-serial (CP2102, CH340)Tergantung board, bisa sampai rentang mAPakai 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 dayaDari µA sampai mA, tergantung sensornyaBeri daya sensor dari GPIO atau MOSFET hanya ketika mengukur
Jangan pernah menghubungkan sel Li-ion seperti 18650 langsung ke pin 3V3: sel Li-ion yang penuh berada di 4,2 V, sedangkan ESP32 menerima paling tinggi 3,6 V. Memasukkan baterai ke pin VIN juga bukan jawaban yang baik, karena AMS1117 menurunkan tegangan sekitar 1 V dan output-nya jatuh di bawah 3 V begitu sel tinggal setengah. Cara yang benar adalah memberi daya ke pin 3V3 lewat LDO 3,3 V dengan arus diam rendah dan tegangan dropout rendah. LDO kecil seperti MCP1700 dan HT7333 hanya bisa memasok 250 mA, jadi tambahkan minimal 470 µF di output-nya untuk menutupi lonjakan arus Wi-Fi. Sel LiFePO4, yang tidak pernah melebihi 3,6 V bahkan ketika penuh, bisa dihubungkan langsung ke 3V3 tanpa regulator.

Sketch deep sleep pertamamu: wake-up dengan timer

  1. Di Boards Manager Arduino IDE, instal paket esp32 by Espressif Systems (versi 3.1 atau lebih baru) dan pilih ESP32 Dev Module sebagai board.
  2. Upload sketch di bawah dan buka Serial Monitor di 115200 baud.
  3. Board bangun setiap 10 detik; perhatikan jumlah boot yang terus naik dan alasan bangun yang tercetak sebagai Timer.
  4. Tekan tombol EN: penghitung kembali ke 1, karena ini reset biasa, bukan bangun dari deep sleep.
  5. Di proyek sungguhanmu, atur TIME_TO_SLEEP ke 600 (10 menit) atau 3600 (1 jam).
C++ (Arduino IDE)
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.

KejadianVariabel biasaRTC_DATA_ATTRPreferences (flash)
Bangun dari deep sleepDi-resetTetap tersimpanTetap tersimpan
Tombol EN atau ESP.restart()Di-resetKembali ke nilai awalTetap tersimpan
Baterai dilepas, listrik padamDi-resetHilangTetap tersimpan
Kode baru di-uploadDi-resetHilangTetap 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.

C++ (Arduino IDE)
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-upFungsiPinCatatan
Timeresp_sleep_enable_timer_wakeup()Tidak perlu pinWaktu dalam mikrodetik, 64-bit
ext0esp_sleep_enable_ext0_wakeup()Satu RTC GPIOBangun pada HIGH atau LOW; tidak bisa digabung dengan sentuhan atau ULP
ext1esp_sleep_enable_ext1_wakeup_io()Beberapa RTC GPIOANY_HIGH atau ALL_LOW; disarankan memakai resistor eksternal
SentuhantouchSleepWakeUpEnable()T0–T9 (10 pin)Bangun ketika nilainya turun di bawah ambang; tidak bisa digabung dengan ext0
Koprosesor ULPesp_sleep_enable_ulp_wakeup()Tergantung programnyaBisa membaca sensor ketika tidur; tingkat lanjut

Pengkabelan untuk rangkaian contoh

KomponenPin komponenPin ESP32Catatan
Sensor PIR (HC-SR501 atau AM312)OUTGPIO 33Membangunkan board lewat ext0
Sensor PIRVCC / GND5V (HC-SR501) atau 3V3 (AM312) / GNDHC-SR501 butuh minimal 4,5 V
Tombol ASatu kaki / kaki lainnya3V3 / GPIO 25Pull-down 10 kΩ di antara GPIO 25 dan GND
Tombol BSatu kaki / kaki lainnya3V3 / GPIO 26Pull-down 10 kΩ di antara GPIO 26 dan GND
Pad sentuh atau kabel–GPIO 27 (T7)Lebih andal kalau dibuat pendek
LED + 220 ΩAnodaGPIO 2Di kebanyakan DevKit, LED biru bawaan juga ada di pin ini
Pembagi tegangan baterai (1 MΩ + 1 MΩ)Titik tengahGPIO 35100 nF di antara titik tengah dan GND
18650 + TP4056 + LDO 3,3 VOutput LDO / GND3V3 / GNDKapasitor 470 µF di output LDO
Hindari GPIO 0, 2, 12, dan 15 sebagai input wake-up. Pin-pin ini adalah pin strapping; kalau tombol atau sensor menahannya di level yang salah ketika reset, board masuk mode download atau sama sekali tidak mau menyala. Misalnya, kalau GPIO 12 bernilai HIGH ketika boot, tegangan flash diatur ke 1,8 V dan board tidak bisa boot. GPIO 34–39 hanya input dan tidak punya resistor pull-up atau pull-down internal, jadi tambahkan resistor dari luar kalau kamu membangunkan board dengan pin-pin ini. Peta pin lengkap board-mu bisa kamu cek dengan alat Pinout.

Sketch wake-up dengan sensor PIR (ext0)

C++ (Arduino IDE)
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)

C++ (Arduino IDE)
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.

C++ (Arduino IDE)
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.

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 s

Sebaliknya, 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.

SkenarioArus sleepWaktu bangunArus rata-rataPerkiraan umur
Board DevKit8 mA3 dtk, 120 mA8,56 mA≈12 hari
Board DevKit, koneksi cepat8 mA1 dtk, 120 mA8,19 mA≈13 hari
Modul polos + MCP1700 + pembagi 1 MΩ15 µA3 dtk, 120 mA0,61 mA≈173 hari (5,7 bulan)
Modul polos, koneksi cepat15 µA1 dtk, 120 mA0,215 mA≈494 hari (16 bulan)
Modul polos, kirim data sekaligus per jam15 µA1 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

GejalaPenyebabSolusi
Board langsung bangun begitu masuk sleepPin wake-up masih aktif (PIR HIGH, tombol ditekan) atau mengambangTunggu pin kembali ke level diamnya sebelum tidur dan tambahkan resistor pull-down atau pull-up
Board tidak bangun di waktu yang diharapkanOverflow 32-bit di perhitungan waktu (3600 * 1000000)Tambahkan ULL ke konstanta: 3600ULL * 1000000ULL
Penghitung selalu mulai dari 1Variabelnya bukan RTC_DATA_ATTR atau board di-resetTambahkan RTC_DATA_ATTR; pakai Preferences untuk data permanen
Terukur 5–15 mA ketika sleepRegulator, LED power, chip USB, pembagi tegangan, atau sensorBoard hemat daya atau modul polos, LDO dengan arus diam rendah
Baris terakhir di Serial Monitor terpotongBoard tidur sebelum buffer kosongPanggil Serial.flush() sebelum esp_deep_sleep_start()
digitalRead() memberi nilai salah setelah bangunPin wake-up masih dalam mode RTCPanggil rtc_gpio_deinit() sebelum memakai pin
Tombol di GPIO 34–39 tidak membangunkan boardPin-pin ini tidak punya resistor pull internal, jadi pin mengambangTambahkan resistor eksternal 10 kΩ
Kode tidak mau di-upload ketika board tidurBoard tidak punya rangkaian auto-reset; di S3 dan C3 port USB native menghilang selama sleepTahan BOOT, tekan lalu lepas EN (RESET), kemudian mulai upload
Relay atau LED berubah status ketika board masuk sleepPin digital mengambang (impedansi tinggi) ketika deep sleepPakai resistor pull atau tahan level pin dengan rtc_gpio_hold_en()
Selama pengembangan, tambahkan sementara jeda 5 detik di awal setup(), atau kondisi yang melewati sleep selama sebuah tombol ditahan. Dengan begitu kamu punya waktu untuk membuka Serial Monitor dan meng-upload kode baru meskipun board terus-menerus tidur; jangan lupa menghapusnya ketika proyek sudah selesai. Kalau board sesekali me-reset sendiri ketika memakai baterai, penyebab yang paling mungkin adalah lonjakan arus Wi-Fi; solusinya ada di panduan error brownout ESP32.

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.

Lihat semua proyek
LED Berkedip dengan ESP32
#103Pemula

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.

4.7(37)
99
Kendali LED dengan Tombol Tekan ESP32 (Tekan)
#104Pemula

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.

4.6(36)
55
Deep Sleep ESP32: Hemat Baterai (OLED + Penghitung RTC RAM)
#135Mahir
Premium

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.

4.3(10)
16
Sistem Alarm Gerakan ESP32 (PIR + Buzzer + LED + Telegram)
#145Mahir
Premium

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.

0.0(0)
9
Lampu Otomatis dengan Sensor Gerak PIR ESP32
#121Menengah
Premium

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.

4.4(24)
38
Suhu dan Kelembapan DHT22 ESP32 (dengan Layar LCD)
#117Menengah

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.

4.8(38)
56
Pencatat Data Suhu ESP32 (DHT22 + RTC DS1307 + microSD + OLED)
#144Mahir
Premium

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.

4.7(7)
12