ESP32 & ESP8266

ESP32 Deep Sleep: Hemat Baterai Hingga Setahun

πŸ‘‘ Premium

Tutorial komprehensif mode tidur ESP32 untuk proyek battery-powered β€” dari timer wake, GPIO wake, hingga ULP coprocessor

1. Mengapa Deep Sleep? Perbandingan Daya & Umur Baterai

ESP32 adalah mikrokontroler yang sangat powerful dengan WiFi dan Bluetooth built-in, namun kemampuan tersebut datang dengan konsumsi daya yang relatif besar jika dibandingkan mikrokontroler sederhana seperti ATtiny85. Saat mode aktif penuh dengan WiFi aktif, ESP32 bisa mengonsumsi hingga 240 mA β€” jumlah yang cukup untuk menghabiskan baterai AAA dalam waktu kurang dari dua hari.

Inilah mengapa ESP32 menyediakan fitur Deep Sleep: mode tidur ultra-rendah daya yang hanya mengonsumsi sekitar 5-10 Β΅A. Selisihnya luar biasa β€” hampir 50.000 kali lebih hemat daya dibanding mode aktif!

Skenario Konsumsi Daya Umur Baterai 1000mAh
WiFi aktif (RX/TX)240 mA~4 jam
WiFi idle, aktif150 mA~6.7 jam
Modem Sleep (CPU on)20 mA~50 jam
Light Sleep0.8 mA~52 hari
Deep Sleep0.005 mA (5 Β΅A)~22 tahun*
Hibernate0.0025 mA (2.5 Β΅A)~45 tahun*
⚠️ Perhatian

*Umur baterai pada Deep Sleep dihitung secara teoretis tanpa memperhitungkan self-discharge baterai (sekitar 5-20% per tahun), arus bocor regulator tegangan, dan arus sensor yang terpasang. Umur baterai nyata biasanya 1-3 tahun untuk proyek IoT sederhana yang bangun setiap 5-15 menit sekali.

πŸ’‘ Analogi Sederhana

Bayangkan ESP32 seperti manusia. Mode aktif adalah saat berlari maraton (boros energi). Deep Sleep adalah tidur nyenyak di malam hari β€” tubuh tetap hidup tapi konsumsi energi sangat minimal. Setiap kali terbangun, ESP32 perlu "pemanasan" sebentar sebelum bisa beraktivitas kembali.

2. Mode Daya ESP32

ESP32 memiliki lima mode operasi utama, masing-masing menawarkan keseimbangan berbeda antara fungsionalitas dan efisiensi daya. Memahami perbedaan masing-masing mode adalah kunci untuk merancang proyek IoT hemat daya yang efektif.

Diagram: Perbandingan Mode Daya ESP32
Konsumsi Daya (mA)
β”‚
β”‚  β–  Active Mode (WiFi ON)     β‰ˆ 240 mA
β”‚  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
β”‚
β”‚  β–  Active Mode (WiFi OFF)    β‰ˆ 24 mA
β”‚  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
β”‚
β”‚  β–  Modem Sleep               β‰ˆ 20 mA
β”‚  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ
β”‚
β”‚  β–  Light Sleep               β‰ˆ 0.8 mA
β”‚  ▏
β”‚
β”‚  β–  Deep Sleep                β‰ˆ 0.005 mA (5 Β΅A)
β”‚  Β·
β”‚
β”‚  β–  Hibernate                 β‰ˆ 0.0025 mA (2.5 Β΅A)
β”‚  Β·
└──────────────────────────────────────────────────────────

2.1 Active Mode (Mode Aktif)

Dalam mode aktif, kedua core CPU berjalan penuh. Modul WiFi dan/atau Bluetooth bisa aktif atau dimatikan. Mode ini cocok untuk perhitungan berat atau komunikasi real-time, tetapi paling boros daya. Gunakan hanya saat benar-benar diperlukan.

2.2 Modem Sleep

CPU tetap berjalan tetapi modul WiFi/Bluetooth dimatikan saat tidak digunakan. ESP32 akan mematikan modem secara otomatis saat tidak ada paket data yang ditransmisikan. Mode ini sangat berguna untuk aplikasi yang memproses data secara lokal tanpa komunikasi konstan.

2.3 Light Sleep

CPU berhenti sementara clock dimatikan, namun semua RAM tetap terisi. ESP32 bisa terbangun dari timer, GPIO, atau peripheral lainnya. Kekurangannya: waktu wake-up relatif cepat dan semua state tetap tersimpan, tetapi konsumsi daya masih terlalu tinggi untuk baterai kecil.

2.4 Deep Sleep

Mode yang paling banyak digunakan untuk proyek hemat daya. CPU, WiFi, Bluetooth, dan sebagian besar peripheral dimatikan. Yang tetap aktif hanyalah:

⚠️ Yang Hilang di Deep Sleep

Saat masuk Deep Sleep, semua isi SRAM hilang. Program akan dimulai ulang dari awal (seperti reboot). Inilah sebabnya kita perlu menyimpan data penting di RTC Memory atau EEPROM/SPIFFS sebelum tidur.

2.5 Hibernate

Mode paling hemat daya. Hampir semua komponen dimatikan termasuk RTC. Hanya skema wake-up eksternal yang tetap aktif. ESP32 harus boot ulang dari awal setiap kali terbangun β€” tidak ada RTC memory yang tersimpan. Cocok untuk skenario wake-up eksternal yang sangat jarang.

Mode CPU WiFi/BT RAM Wake Source
Activeβœ… Runningβœ… Bisa ON/OFFβœ… Full-
Modem Sleepβœ… Running❌ Dimatikanβœ… Full-
Light Sleep❌ Dijeda❌ Dimatikanβœ… FullTimer, GPIO, UART
Deep Sleep❌ Mati❌ Mati⚠️ RTC onlyTimer, GPIO, Touch, ULP
Hibernate❌ Mati❌ Mati❌ HilangGPIO eksternal

3. Deep Sleep dengan Timer Wakeup

Mode wakeup paling sederhana dan paling sering digunakan. ESP32 akan bangun secara otomatis setelah interval waktu tertentu yang ditentukan. Ini cocok untuk aplikasi seperti sensor lingkungan yang membaca data secara berkala.

Cara Kerja Timer Wakeup

Diagram: Siklus Timer Wakeup
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  BOOT   │────▢│  Bekerja  │────▢│  Deep Sleep  β”‚
  β”‚ (reset) β”‚     β”‚ (baca &   β”‚     β”‚  (tunggu     β”‚
  β”‚         │◀────│  kirim)   │◀────│   timer)     β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β–²                                  β”‚
       β”‚         Waktu: T wake           β”‚
       β”‚         Waktu: T sleep          β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  Rasio duty cycle = T_sleep / (T_wake + T_sleep)
  Contoh: 300 detik sleep, 5 detik wake = 98.3% duty cycle

Library ESP32 Arduino menyediakan fungsi bawaan yang sangat mudah digunakan:

C++ β€” deep_sleep_timer.ino
// ESP32 Deep Sleep dengan Timer Wakeup
// IoTHub - https://iothub.id

#include <Arduino.h>

// Definisikan waktu tidur dalam mikrosekon
// 1 detik  = 1000000 Β΅s
// 5 menit  = 300000000 Β΅s
// 15 menit = 900000000 Β΅s
#define TIME_TO_SLEEP  300  // 300 detik = 5 menit

RTC_DATA_ATTR int jumlahBangun = 0;

void setup() {
  Serial.begin(115200);
  Serial.flush();

  // Tambah jumlah wake counter di RTC Memory
  jumlahBangun++;

  Serial.println("=== ESP32 Deep Sleep Timer ===");
  Serial.print("Wake-up ke-: ");
  Serial.println(jumlahBangun);
  Serial.print("Timestamp: ");
  Serial.println(millis());
  Serial.print("Menghabiskan waktu selama: ");
  Serial.print(TIME_TO_SLEEP);
  Serial.println(" detik...");

  // --- Lakukan pekerjaan di sini ---
  // Baca sensor, kirim data, kontrol LED, dll.

  // Nyalakan LED indikator selama 1 detik
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);

  // Atur waktu sleep dan masuk Deep Sleep
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * 1000000ULL);
  Serial.println("Masuk Deep Sleep...");
  Serial.flush();  // Pastikan serial selesai terkirim
  esp_deep_sleep_start();

  // Kode di bawah TIDAK akan pernah dieksekusi
}

void loop() {
  // Tidak digunakan karena ESP32 bangun dari setup()
}
Output Serial Monitor: === ESP32 Deep Sleep Timer === Wake-up ke-: 1 Timestamp: 12 Menghabiskan waktu selama: 300 detik... Masuk Deep Sleep... (setelah 5 menit) === ESP32 Deep Sleep Timer === Wake-up ke-: 2 Timestamp: 14 Menghabiskan waktu selama: 300 detik... Masuk Deep Sleep...
ℹ️ Apa itu RTC_DATA_ATTR?

RTC_DATA_ATTR adalah atribut yang menandai variabel disimpan di RTC Memory, bukan SRAM biasa. RTC Memory tetap terisi meskipun ESP32 dalam Deep Sleep, sehingga variabel jumlahBangun tidak akan hilang meskipun ESP32 berulang kali masuk dan keluar Deep Sleep. Maksimal 8 KB data bisa disimpan di RTC Memory.

4. Deep Sleep dengan GPIO Wakeup (Touch/Button)

Selain timer, ESP32 juga bisa dibangunkan dari Deep Sleep menggunakan perubahan sinyal pada pin GPIO tertentu. Ini sangat berguna untuk aplikasi interaktif β€” misalnya menekan tombol untuk mengaktifkan display, atau touch sensor untuk menyalakan lampu.

4.1 GPIO Wakeup dengan Tombol Push-Button

Diagram: Rangkaian GPIO Wakeup dengan Tombol
       ESP32                  Tombol
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         β”‚           β”‚        β”‚
    β”‚  3.3V   β”œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€  Pin 1 β”‚
    β”‚         β”‚     β”‚     β”‚        β”‚
    β”‚ GPIO 33 β”œβ”€β”€β”€β”€β”€β”€     β””β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
    β”‚  (EXT0) β”‚   [10kΞ©]     β”‚
    β”‚         β”‚     β”‚     β””β”€β”€β”€β”˜
    β”‚   GND   β”œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  Catatan: Tombol menghubungkan GPIO ke GND saat ditekan.
  Resistor pull-up 10kΞ© memastikan GPIO HIGH saat tombol tidak ditekan.
  GPIO 33 mendukung wake-up dari Deep Sleep (EXT0).
C++ β€” deep_sleep_gpio.ino
// ESP32 Deep Sleep dengan GPIO Wakeup (Tombol)
// IoTHub - https://iothub.id

#include <Arduino.h>

#define BUTTON_PIN     33    // Pin tombol untuk wake up
#define LED_PIN        2     // LED indikator
#define TIMEOUT_WAKE   300   // Auto wake setelah 5 menit

RTC_DATA_ATTR int wakeCount = 0;
RTC_DATA_ATTR int buttonWakes = 0;

void setup() {
  Serial.begin(115200);
  Serial.flush();

  wakeCount++;

  // Tentukan alasan bangun
  esp_sleep_wakeup_cause_t penyebab = esp_sleep_get_wakeup_cause();

  switch (penyebab) {
    case ESP_SLEEP_WAKEUP_EXT0:
      Serial.println("Bangun karena: Tombol ditekan (EXT0)!");
      buttonWakes++;
      break;
    case ESP_SLEEP_WAKEUP_TIMER:
      Serial.println("Bangun karena: Timer timeout");
      break;
    default:
      Serial.println("Bangun karena: Boot pertama kali / reset");
      break;
  }

  Serial.print("Total wake-up: ");
  Serial.println(wakeCount);
  Serial.print("Bangun dari tombol: ");
  Serial.println(buttonWakes);

  // --- Lakukan pekerjaan ---
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);
  delay(2000);  // Nyalakan LED selama 2 detik
  digitalWrite(LED_PIN, LOW);

  // Konfigurasi 2 wake-up source:
  // 1. GPIO 33 (tombol) β€” EXT0
  // 2. Timer sebagai cadangan (timeout)
  esp_sleep_enable_ext0_wakeup((gpio_num_t)BUTTON_PIN, 0);
  esp_sleep_enable_timer_wakeup(TIMEOUT_WAKE * 1000000ULL);

  Serial.println("Masuk Deep Sleep... (tekan tombol untuk bangun)");
  Serial.flush();
  esp_deep_sleep_start();
}

void loop() {
  // Tidak digunakan
}

4.2 GPIO Wakeup dengan Touch Pad

ESP32 memiliki 10 pin touch yang bisa mendeteksi sentuhan manusia tanpa komponen mekanis apapun. Pin touch dapat membangunkan ESP32 dari Deep Sleep saat jari menyentuh elektroda tembaga yang terhubung ke pin touch.

C++ β€” deep_sleep_touch.ino
// ESP32 Deep Sleep dengan Touch Wakeup
// IoTHub - https://iothub.id

#include <Arduino.h>

// Pin touch yang mendukung wake-up dari Deep Sleep
#define TOUCH_PIN       T0    // GPIO 4 β€” Touch channel 0

// Threshold sensitivitas touch
#define TOUCH_THRESHOLD 40

RTC_DATA_ATTR int wakeCount = 0;

void setup() {
  Serial.begin(115200);
  Serial.flush();

  wakeCount++;

  esp_sleep_wakeup_cause_t penyebab = esp_sleep_get_wakeup_cause();

  if (penyebab == ESP_SLEEP_WAKEUP_TOUCHPAD) {
    Serial.println("Bangun karena: Sentuhan pada pad!");
    // Tampilkan channel touch yang memicu wake
    touch_pad_t touchPad = esp_sleep_get_touchpad_wakeup_status();
    Serial.print("Channel: T");
    Serial.println((int)touchPad);
  } else {
    Serial.println("Bangun karena: Boot pertama kali");
  }

  Serial.print("Total wake: ");
  Serial.println(wakeCount);

  // Tampilkan nilai pembacaan touch
  uint32_t nilaiTouch;
  touch_pad_read(TOUCH_PIN, &nilaiTouch);
  Serial.print("Nilai touch saat ini: ");
  Serial.println(nilaiTouch);

  // Aktifkan touch wakeup
  touch_pad_init();
  touch_pad_set_meas_time(TOUCH_PAD_MEAS_TIME_DEFAULT,
                          TOUCH_PAD_MEAS_TIME_DEFAULT);
  touch_pad_config(TOUCH_PIN, TOUCH_THRESHOLD);
  esp_sleep_enable_touchpad_wakeup();

  Serial.println("Masuk Deep Sleep... (sentuh pad untuk bangun)");
  Serial.flush();
  esp_deep_sleep_start();
}

void loop() {
  // Tidak digunakan
}
πŸ’‘ Tips Elektroda Touch

Untuk elektroda sentuh, cukup hubungkan sepotong kawat tembaga atau foil ke pin GPIO yang diinginkan. Semakin luas area elektroda, semakin sensitif deteksinya. Hindari elektroda yang terlalu besar karena bisa meningkatkan false trigger.

5. Deep Sleep dengan ULP Coprocessor

ULP (Ultra Low Power) Coprocessor adalah prosesor kecil 32-bit yang tetap aktif bahkan saat ESP32 dalam Deep Sleep. ULP bisa menjalankan program sederhana, membaca sensor analog (ADC), dan membangunkan prosesor utama saat kondisi tertentu terpenuhi.

Keunggulan utama ULP: menghemat daya secara signifikan karena prosesor utama tetap tidur, sementara ULP hanya mengonsumsi sekitar 5 Β΅A tambahan saat menjalankan program.

Kapan Menggunakan ULP?

C++ β€” deep_sleep_ulp.ino
// ESP32 Deep Sleep dengan ULP Coprocessor
// Membaca sensor analog dari ADC dan membangunkan
// ESP32 saat nilai melampaui threshold
// IoTHub - https://iothub.id

#include <Arduino.h>
#include "soc/rtc_io.h"
#include "esp_sleep.h"

// Pin sensor analog
#define SENSOR_PIN    36     // GPIO 36 (VP) β€” ADC1_CH0
#define THRESHOLD     2000   // Threshold ADC (0-4095)

// Deklarasi fungsi assembly ULP
extern const uint8_t ulp_machine_start[] asm("_binary_ulp_program_bin_start");
extern const uint8_t ulp_machine_end[] asm("_binary_ulp_program_bin_end");

RTC_DATA_ATTR int wakeCount = 0;

void setup() {
  Serial.begin(115200);
  Serial.flush();

  wakeCount++;

  // Cek alasan wake-up
  esp_sleep_wakeup_cause_t penyebab = esp_sleep_get_wakeup_cause();

  if (penyebab == ESP_SLEEP_WAKEUP_ULP) {
    Serial.println("Bangun karena: ULP Coprocessor!");

    // Baca nilai sensor terakhir dari RTC memory
    uint32_t nilaiSensor;
    rtc_gpio_isolate(GPIO_NUM_36);  // Isolasi pin setelah bangun
    Serial.println("Kondisi threshold tercapai!");
  } else {
    Serial.println("Bangun karena: Boot / Reset");
  }

  Serial.print("Wake-up ke-: ");
  Serial.println(wakeCount);

  // --- Lakukan pekerjaan utama ---
  int bacaSensor = analogRead(SENSOR_PIN);
  Serial.print("Nilai sensor: ");
  Serial.println(bacaSensor);

  // Konfigurasi ULP
  initUlpSensor();

  // Masuk Deep Sleep
  Serial.println("Masuk Deep Sleep (ULP aktif)...");
  Serial.flush();
  esp_deep_sleep_start();
}

void initUlpSensor() {
  // Load program ULP dari binary yang dikompilasi
  size_t ukuran = ulp_machine_end - ulp_machine_start;
  esp_err_t err = ulp_load_binary(0, ulp_machine_start, ukuran);

  if (err != ESP_OK) {
    Serial.print("Error loading ULP program: ");
    Serial.println(esp_err_to_name(err));
    return;
  }

  // Konfigurasi ULP untuk membaca ADC
  ulp_set_wakeup_period(0, 5000000);  // Bangun setiap 5 detik

  // Set threshold di RTC memory
  // Posisi RTC memory yang digunakan oleh ULP
  // untuk menyimpan hasil pembacaan

  // Mulai ULP
  err = ulp_run(&ulp_machine_start - (uint32_t *)rtc_get_address());

  if (err != ESP_OK) {
    Serial.print("Error starting ULP: ");
    Serial.println(esp_err_to_name(err));
  }
}

void loop() {
  // Tidak digunakan
}
ℹ️ Catatan tentang ULP Program

Program ULP ditulis dalam bahasa assembly khusus ULP dan perlu dikompilasi terpisah menggunakan toolchain ulp_as dari ESP-IDF. Dalam contoh di atas, binary ULP dimuat dari file ulp_program.bin yang sudah dikompilasi sebelumnya. Proses ini lebih kompleks dan memerlukan pemahaman ESP-IDF di luar Arduino IDE.

6. Mengukur Konsumsi Daya (Multimeter & INA219)

Tidak ada gunanya menulis kode hemat daya jika Anda tidak bisa membuktikan hasilnya. Mengukur konsumsi daya aktual adalah langkah penting untuk memvalidasi optimasi yang dilakukan.

6.1 Menggunakan Multimeter Digital

Diagram: Rangkaian Pengukuran Arus dengan Multimeter
                    Multimeter (mode Amperemeter)
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   200mA /    β”‚
                    β”‚   20mA /     β”‚
    Baterai (+) ──▢│   2mA range  │──▢ ESP32 VIN (+)
    3.7V LiPo     β”‚              β”‚
                    β”‚   ⚠️ Series! β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

    Baterai (-) ────────────────────▢ ESP32 GND (-)

  ⚠️ PENTING: Multimeter dipasang SERIAL (putuskan kabel VCC
     dan hubungkan melalui multimeter). JANGAN paralel!

Langkah-langkah pengukuran:

  1. Putuskan kabel positif (+) dari baterai ke ESP32
  2. Hubungkan probe merah multimeter ke kabel dari baterai (+)
  3. Hubungkan probe hitam multimeter ke pin VIN ESP32
  4. Atur multimeter ke range yang sesuai (mulai dari 200mA, turunkan jika perlu)
  5. Pastikan kabel probe terpasang ke terminal COM dan mA (bukan 10A!)

6.2 Menggunakan Modul INA219

Modul INA219 adalah sensor arus/t tegangan I2C yang populer dan murah (sekitar Rp 15-25rb). Modul ini bisa mengukur tegangan bus (0-26V), arus (Β±3.2A), dan menghitung daya secara real-time β€” cocok untuk monitoring konsumsi daya proyek IoT.

Diagram: Rangkaian INA219 untuk Monitoring Daya ESP32
  Baterai         INA219 Modul              ESP32
  3.7V LiPo    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚ VIN+ ───────┼────────── VIN     β”‚
  (+) ────────── VCC  ───────┼────┬─────         β”‚
                β”‚ GND  ───────┼────┼───── GND     β”‚
  (-) ────────── SDA  ───────┼─────    β”‚         β”‚
                β”‚ SCL  β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”˜    β”‚         β”‚
                β”‚ IN-         β”‚         β”‚ GPIO 21 β”‚ (SDA)
                β”‚ IN+         β”‚         β”‚ GPIO 22 β”‚ (SCL)
                β”‚ SD0/ADR     β”‚         β”‚         β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  INA219 dihubungkan secara SERIAL pada jalur power
  untuk mengukur arus yang mengalir ke ESP32
C++ β€” baca_ina219.ino
// Membaca konsumsi daya ESP32 menggunakan INA219
// IoTHub - https://iothub.id

#include <Wire.h>
#include <Adafruit_INA219.h>

Adafruit_INA219 ina219;

void setup() {
  Serial.begin(115200);
  Serial.println("=== INA219 Power Monitor ===");

  if (!ina219.begin()) {
    Serial.println("ERROR: INA219 tidak terdeteksi!");
    while (1) { delay(1000); }
  }

  Serial.println("INA219 siap!");
  Serial.println();
}

void loop() {
  // Baca tegangan bus (tegangan baterai)
  float teganganBus = ina219.getBusVoltage_V();

  // Baca tegangan shunt (untuk hitung arus)
  float teganganShunt = ina219.getShuntVoltage_mV();

  // Baca arus dalam mA
  float arus = ina219.getCurrent_mA();

  // Hitung daya dalam mW
  float daya = ina219.getPower_mW();

  // Tampilkan hasil
  Serial.println("--- Pembacaan Daya ---");
  Serial.print("Tegangan Bus  : ");
  Serial.print(teganganBus, 3);
  Serial.println(" V");

  Serial.print("Tegangan Shunt: ");
  Serial.print(teganganShunt, 3);
  Serial.println(" mV");

  Serial.print("Arus          : ");
  Serial.print(arus, 1);
  Serial.println(" mA");

  Serial.print("Daya          : ");
  Serial.print(daya, 1);
  Serial.println(" mW");
  Serial.println();

  delay(2000);
}
πŸ’‘ Tips Pengukuran

Untuk pengukuran Deep Sleep yang akurat, pastikan modul USB-to-serial (CH340/CP2102) dilepas atau dinonaktifkan karena modul tersebut bisa menarik arus 20-30 mA. Gunakan baterai langsung untuk pengukuran yang representatif terhadap kondisi operasi nyata.

7. Mengirim Data Sebelum Tidur (WiFi Flush & MQTT Disconnect)

Salah satu kesalahan paling umum dalam proyek Deep Sleep adalah masuk sleep tanpa memastikan semua data sudah terkirim. Jika ESP32 masuk Deep Sleep saat WiFi atau MQTT masih dalam proses pengiriman, data bisa hilang atau koneksi broker menjadi ghost connection.

Urutan Shutdown yang Benar

Diagram: Urutan Shutdown WiFi & MQTT yang Benar
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  1. Pastikan semua data terkirim             β”‚
  β”‚     (MQTT publish, HTTP response, dll)        β”‚
  β”‚                     β”‚                         β”‚
  β”‚                     β–Ό                         β”‚
  β”‚  2. Tunggu WiFi TX buffer kosong             β”‚
  β”‚     (WiFi.flush() atau delay 500ms)          β”‚
  β”‚                     β”‚                         β”‚
  β”‚                     β–Ό                         β”‚
  β”‚  3. Putuskan koneksi MQTT / HTTP             β”‚
  β”‚     (client.disconnect())                    β”‚
  β”‚                     β”‚                         β”‚
  β”‚                     β–Ό                         β”‚
  β”‚  4. Matikan WiFi                             β”‚
  β”‚     (WiFi.disconnect() + WiFi.mode(WIFI_OFF))β”‚
  β”‚                     β”‚                         β”‚
  β”‚                     β–Ό                         β”‚
  β”‚  5. Putuskan WiFi radio                      β”‚
  β”‚     (esp_wifi_disconnect())                  β”‚
  β”‚                     β”‚                         β”‚
  β”‚                     β–Ό                         β”‚
  β”‚  6. Flush serial buffer                      β”‚
  β”‚     (Serial.flush())                         β”‚
  β”‚                     β”‚                         β”‚
  β”‚                     β–Ό                         β”‚
  β”‚  7. Masuk Deep Sleep                         β”‚
  β”‚     (esp_deep_sleep_start())                 β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
C++ β€” shutdown_wifi_mqtt.ino
// Fungsi shutdown yang benar untuk WiFi & MQTT
// IoTHub - https://iothub.id

#include <WiFi.h>
#include <PubSubClient.h>

// Konfigurasi WiFi
const char* ssid     = "WiFi_Indonesia";
const char* password  = "password123";

// Konfigurasi MQTT
const char* mqttServer = "broker.hivemq.com";
const int   mqttPort   = 1883;
const char* mqttTopic  = "iothub/sensor/suhu";

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

// --- Fungsi Terhubung WiFi ---
void sambungWifi() {
  Serial.print("Menghubungkan WiFi");
  WiFi.begin(ssid, password);

  int percobaan = 0;
  while (WiFi.status() != WL_CONNECTED && percobaan < 20) {
    delay(500);
    Serial.print(".");
    percobaan++;
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nWiFi terhubung!");
    Serial.print("IP: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("\nGagal terhubung WiFi!");
  }
}

// --- Fungsi Terhubung MQTT ---
void sambungMQTT() {
  mqttClient.setServer(mqttServer, mqttPort);

  int percobaan = 0;
  while (!mqttClient.connected() && percobaan < 3) {
    Serial.print("Menghubungkan MQTT...");
    if (mqttClient.connect("ESP32DeepSleep")) {
      Serial.println("OK!");
    } else {
      Serial.print("Gagal, rc=");
      Serial.println(mqttClient.state());
      delay(1000);
      percobaan++;
    }
  }
}

// --- Fungsi Kirim Data ---
bool kirimData(float suhu, float kelembaban) {
  if (!mqttClient.connected()) return false;

  // Format data sebagai JSON
  char payload[128];
  snprintf(payload, sizeof(payload),
    "{\"suhu\":%.1f,\"kelembaban\":%.1f,\"uptime\":%lu}",
    suhu, kelembaban, millis());

  // Kirim data
  bool berhasil = mqttClient.publish(mqttTopic, payload);

  if (berhasil) {
    Serial.print("Data terkirim: ");
    Serial.println(payload);
  } else {
    Serial.println("Gagal mengirim data!");
  }

  return berhasil;
}

// --- Fungsi Shutdown Aman ---
void shutdownAman() {
  Serial.println("=== Memulai Shutdown ===");

  // Langkah 1: Pastikan semua paket MQTT terkirim
  Serial.println("[1/6] Flush MQTT...");
  mqttClient.loop();  // Proses callback & pending
  delay(500);         // Tunggu TX buffer kosong

  // Langkah 2: Putuskan MQTT
  Serial.println("[2/6] Disconnect MQTT...");
  if (mqttClient.connected()) {
    mqttClient.disconnect();
    delay(100);
  }

  // Langkah 3: Disconnect WiFi
  Serial.println("[3/6] Disconnect WiFi...");
  WiFi.disconnect(true);
  delay(100);

  // Langkah 4: Matikan modul WiFi
  Serial.println("[4/6] WiFi OFF...");
  WiFi.mode(WIFI_OFF);
  delay(100);

  // Langkah 5: Putuskan radio WiFi
  Serial.println("[5/6] WiFi radio OFF...");
  esp_wifi_disconnect();
  delay(100);

  // Langkah 6: Flush serial
  Serial.println("[6/6] Serial flush...");
  Serial.flush();

  Serial.println("=== Shutdown Selesai ===");
  delay(100);
}
⚠️ Jangan Lupa!

Selalu panggil shutdownAman() sebelum esp_deep_sleep_start(). Tanpa fungsi ini, data yang dikirim via MQTT bisa hilang, atau WiFi connection bisa menjadi "ghost" yang memboroskan daya karena broker tetap mencoba mengirim data ke perangkat yang sudah tidur.

8. Proyek: Sensor Suhu Battery-Powered 1 Tahun

Sekarang kita akan menggabungkan semua konsep yang sudah dipelajari menjadi proyek nyata: sensor suhu yang bisa bertahan hampir setahun menggunakan satu baterai LiPo 18650 (3400mAh).

Spesifikasi Proyek

Parameter Nilai
SensorDHT22 / DS18B20 (akurat & hemat daya)
Interval pembacaan15 menit
Protokol kirim dataMQTT ke broker HiveMQ / Mosquitto
BateraiLiPo 18650 β€” 3.7V 3400mAh
Target umur bateraiMinimal 10 bulan
Metode hemat dayaDeep Sleep + Timer Wakeup

Kalkulasi Daya

Diagram: Kalkulasi Umur Baterai
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚           KALKULASI UMUR BATERAI            β”‚
  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
  β”‚                                             β”‚
  β”‚  Siklus satu pembacaan:                     β”‚
  β”‚  ─────────────────────                      β”‚
  β”‚  Boot + WiFi Connect    :  3 detik @ 150mA β”‚
  β”‚  MQTT Publish           :  1 detik @ 180mA β”‚
  β”‚  Total waktu aktif      :  ~5 detik        β”‚
  β”‚  Energi aktif           :  5s Γ— 150mA      β”‚
  β”‚                         =  750 mAΒ·detik     β”‚
  β”‚                                             β”‚
  β”‚  Siklus Deep Sleep:                         β”‚
  β”‚  ─────────────────                          β”‚
  β”‚  Waktu tidur            :  900 detik (15m)  β”‚
  β”‚  Arus tidur             :  0.005 mA         β”‚
  β”‚  Energi tidur           :  900 Γ— 0.005      β”‚
  β”‚                         =  4.5 mAΒ·detik     β”‚
  β”‚                                             β”‚
  β”‚  Total per siklus       :  754.5 mAΒ·detik   β”‚
  β”‚                                             β”‚
  β”‚  Siklus per hari        :  96 (15 menit)    β”‚
  β”‚  Konsumsi per hari      :  754.5 Γ— 96       β”‚
  β”‚                         =  72,432 mAΒ·detik  β”‚
  β”‚                         =  20.12 mAΒ·jam     β”‚
  β”‚                         =  20.12 mAh/hari   β”‚
  β”‚                                             β”‚
  β”‚  Umur baterai           :  3400 mAh         β”‚
  β”‚                         Γ·  20.12 mAh/hari   β”‚
  β”‚                         β‰ˆ  169 hari          β”‚
  β”‚                         β‰ˆ  5.6 bulan          β”‚
  β”‚                                             β”‚
  β”‚  Dengan self-discharge  :  ~5 bulan          β”‚
  β”‚  (baterai turun 20%/thn)                    β”‚
  β”‚                                             β”‚
  β”‚  β†’ Gunakan baterai lebih besar atau          β”‚
  β”‚    interval lebih lama untuk 1 tahun!        β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Untuk mencapai target 1 tahun, kita bisa menggunakan baterai ganda (2Γ— 18650 paralel = 6800mAh) atau interval 30 menit. Dengan 6800mAh dan interval 15 menit, baterai bertahan sekitar 338 hari β€” cukup untuk mencapai target 1 tahun.

Kode Program Lengkap

C++ β€” sensor_suhu_battery_1tahun.ino
// Sensor Suhu Battery-Powered 1 Tahun
// ESP32 Deep Sleep + MQTT + DHT22
// IoTHub - https://iothub.id

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

// ===== KONFIGURASI =====
#define SLEEP_DURATION   900LL          // 15 menit (dalam detik)
#define DHT_PIN          4              // GPIO4
#define DHT_TYPE         DHT22          // Gunakan DHT22 untuk akurasi
#define LED_INDICATOR    2              // GPIO2 (LED internal)
#define BAT_ADC_PIN      34             // GPIO34 untuk baca tegangan baterai
#define BAT_VOLT_DIV     2.0            // Rasio voltage divider

// WiFi credentials
const char* WIFI_SSID     = "WiFi_Indonesia";
const char* WIFI_PASS     = "password123";

// MQTT credentials
const char* MQTT_SERVER   = "broker.hivemq.com";
const int   MQTT_PORT     = 1883;
const char* MQTT_USER     = "";
const char* MQTT_PASS_MQTT = "";
const char* MQTT_TOPIC    = "iothub/suhu/esp32-01";
const char* MQTT_CLIENT   = "ESP32-Suhu-01";

// ===== OBJEK GLOBAL =====
DHT dht(DHT_PIN, DHT_TYPE);
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);

// ===== RTC MEMORY =====
RTC_DATA_ATTR int wakeCount     = 0;
RTC_DATA_ATTR int errConnect    = 0;
RTC_DATA_ATTR float lastSuhu    = 0.0;
RTC_DATA_ATTR float lastHumidity = 0.0;

// ===== FUNGSI SETUP =====
void setup() {
  Serial.begin(115200);
  Serial.flush();

  wakeCount++;

  // LED indikator
  pinMode(LED_INDICATOR, OUTPUT);
  digitalWrite(LED_INDICATOR, HIGH);

  Serial.println();
  Serial.println("╔══════════════════════════════════════╗");
  Serial.println("β•‘  Sensor Suhu Battery-Powered 1 Tahun β•‘");
  Serial.println("β•‘  ESP32 Deep Sleep + MQTT             β•‘");
  Serial.println("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•");
  Serial.print("Wake-up ke-: ");
  Serial.println(wakeCount);

  // Baca tegangan baterai
  float teganganBaterai = bacaTeganganBaterai();
  Serial.print("Tegangan baterai: ");
  Serial.print(teganganBaterai, 2);
  Serial.println(" V");

  // Cek apakah baterai masih cukup (minimum 3.3V)
  if (teganganBaterai < 3.3) {
    Serial.println("PERINGATAN: Baterai lemah! Interval diperpanjang.");
    // Jika baterai lemah, sleep lebih lama (30 menit)
    sleepDanBangun(SLEEP_DURATION * 2);
  }

  // Baca sensor suhu
  dht.begin();
  delay(2000);  // Tunggu sensor stabil

  float suhu     = dht.readTemperature();
  float kelembaban = dht.readHumidity();

  if (isnan(suhu) || isnan(kelembaban)) {
    Serial.println("ERROR: Gagal baca sensor DHT22!");
    // Gunakan data terakhir dari RTC memory
    suhu       = lastSuhu;
    kelembaban = lastHumidity;
    Serial.println("Menggunakan data terakhir dari RTC memory.");
  } else {
    Serial.print("Suhu      : ");
    Serial.print(suhu, 1);
    Serial.println(" Β°C");
    Serial.print("Kelembaban: ");
    Serial.print(kelembaban, 1);
    Serial.println(" %");
    lastSuhu     = suhu;
    lastHumidity = kelembaban;
  }

  // Kirim data via MQTT
  if (suhu != 0.0 || kelembaban != 0.0) {
    bool terkirim = kirimDataMQTT(suhu, kelembaban, teganganBaterai);
    if (terkirim) {
      Serial.println("Data berhasil dikirim!");
    } else {
      Serial.println("Gagal mengirim data.");
      errConnect++;
    }
  }

  // Shutdown dan masuk Deep Sleep
  shutdownAman();
  Serial.print("Tidur selama ");
  Serial.print(SLEEP_DURATION);
  Serial.println(" detik...");
  sleepDanBangun(SLEEP_DURATION);
}

// ===== FUNGSI LOOP =====
void loop() {
  // Tidak digunakan β€” ESP32 selalu bangun dari setup()
}

// ===== FUNGSI-FUNGSI PEMBANTU =====

float bacaTeganganBaterai() {
  // Baca ADC dan konversi ke tegangan
  int adcValue = analogRead(BAT_ADC_PIN);
  float tegangan = (adcValue / 4095.0) * 3.3 * BAT_VOLT_DIV;
  return tegangan;
}

bool kirimDataMQTT(float suhu, float kelembaban, float tegangan) {
  // Sambung WiFi
  Serial.print("Menghubungkan WiFi...");
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  int coba = 0;
  while (WiFi.status() != WL_CONNECTED && coba < 20) {
    delay(500);
    Serial.print(".");
    coba++;
  }

  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("\nWiFi gagal!");
    return false;
  }
  Serial.println(" OK!");

  // Sambung MQTT
  mqtt.setServer(MQTT_SERVER, MQTT_PORT);
  coba = 0;
  while (!mqtt.connected() && coba < 3) {
    Serial.print("MQTT...");
    if (mqtt.connect(MQTT_CLIENT, MQTT_USER, MQTT_PASS_MQTT)) {
      Serial.println("OK!");
    } else {
      Serial.print("Gagal (");
      Serial.print(mqtt.state());
      Serial.println(")");
      delay(1000);
      coba++;
    }
  }

  if (!mqtt.connected()) {
    Serial.println("MQTT tidak terhubung!");
    return false;
  }

  // Siapkan payload JSON
  char payload[256];
  snprintf(payload, sizeof(payload),
    "{"
    "\"device\":\"ESP32-01\","
    "\"suhu\":%.1f,"
    "\"kelembaban\":%.1f,"
    "\"baterai\":%.2f,"
    "\"wake\":%d,"
    "\"uptime\":%lu"
    "}",
    suhu, kelembaban, tegangan, wakeCount, millis()
  );

  // Publish
  bool hasil = mqtt.publish(MQTT_TOPIC, payload);
  mqtt.loop();
  delay(200);

  return hasil;
}

void shutdownAman() {
  Serial.println("Shutdown...");
  mqtt.loop();
  delay(500);
  if (mqtt.connected()) mqtt.disconnect();
  delay(100);
  WiFi.disconnect(true);
  delay(100);
  WiFi.mode(WIFI_OFF);
  delay(100);
  Serial.flush();
  digitalWrite(LED_INDICATOR, LOW);
  delay(100);
}

void sleepDanBangun(long long detikTidur) {
  esp_sleep_enable_timer_wakeup(detikTidur * 1000000ULL);
  esp_deep_sleep_start();
}

Rangkaian Fisik

Diagram: Rangkaian Lengkap Proyek Sensor Suhu Battery
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚                                                  β”‚
  β”‚   LiPo 18650          ESP32 DevKit     DHT22     β”‚
  β”‚   3.7V 3400mAh     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
  β”‚                     β”‚              β”‚  β”‚ VCC    β”‚ β”‚
  β”‚   (+)───┬──────────── VIN          β”‚  β”‚  β”œβ”€β”€β”€β”€β”€β”€ β”‚
  β”‚         β”‚           β”‚              β”‚  β”‚  [10kΞ©]β”‚ β”‚
  β”‚         β”œβ”€β”€[10kΞ©]──── GPIO34       β”‚  β”‚  β”‚    β”‚ β”‚
  β”‚         β”‚           β”‚              β”œβ”€β”€β”€ DATA   β”‚ β”‚
  β”‚   (-)───┼──────────── GPIO4 β”œβ”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚    β”‚ β”‚
  β”‚         β”‚           β”‚              β”œβ”€β”€β”€  β”‚    β”‚ β”‚
  β”‚         β”‚           β”‚ GND          β”‚  β”‚ GND   β”‚ β”‚
  β”‚         β”‚           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
  β”‚         β”‚                                        β”‚
  β”‚         β”‚    Voltage Divider                     β”‚
  β”‚         └──[10kΞ©]──┬──[10kΞ©]── GND              β”‚
  β”‚                    β”‚                             β”‚
  β”‚                    └──── GPIO34 (Baca V_batt)    β”‚
  β”‚                                                  β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
πŸ’‘ Tips Daya Tahan 1 Tahun
  • Baterai lebih besar = umur lebih lama. Gunakan 2Γ— 18650 paralel untuk 6800mAh.
  • Interval lebih lama = menghemat daya signifikan. 30 menit masih cukup untuk monitoring suhu ruangan.
  • Gunakan DS18B20 sebagai alternatif DHT22 β€” lebih hemat daya saat pembacaan.
  • Matikan semua LED pada modul selain LED indikator sesaat.
  • Hapus voltage regulator dan jalankan ESP32 langsung dari 3.7V LiPo (lihat datasheet untuk batas tegangan).

9. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang ESP32 Deep Sleep:

Pertanyaan 1: Berapa konsumsi daya ESP32 dalam mode Deep Sleep?

a) Sekitar 5-10 Β΅A (mikroampere)
b) Sekitar 0.8 mA
c) Sekitar 20 mA
d) Sekitar 150 mA

Pertanyaan 2: Komponen mana yang TETAP aktif saat ESP32 dalam Deep Sleep?

a) CPU utama Xtensa LX6
b) Modul WiFi 802.11
c) RTC (Real-Time Clock) dan RTC Memory
d) SRAM utama sebesar 520 KB

Pertanyaan 3: Apa yang harus dilakukan SEBELUM memanggil esp_deep_sleep_start()?

a) Menghapus semua data dari RTC Memory
b) Menyalakan semua LED untuk indikasi
c) Memastikan WiFi/MQTT terputus dan serial di-flush
d) Mengatur ulang semua GPIO ke mode INPUT

Pertanyaan 4: Mode mana yang paling hemat daya pada ESP32?

a) Light Sleep β€” semua RAM masih tersimpan
b) Modem Sleep β€” WiFi dimatikan, CPU tetap jalan
c) Deep Sleep β€” hanya RTC yang aktif
d) Hibernate β€” hampir semua komponen dimatikan termasuk RTC

Pertanyaan 5: Apa kegunaan atribut RTC_DATA_ATTR pada variabel ESP32?

a) Menyimpan data agar tetap tersimpan meskipun ESP32 dalam Deep Sleep
b) Membuat variabel berukuran lebih kecil di SRAM
c) Mengunci variabel agar tidak bisa diubah
d) Menyimpan variabel ke EEPROM secara otomatis
← Sebelumnya Perbandingan Protokol IoT Selanjutnya β†’ Instalasi Arduino IDE