บทความ: ESP32 Deep Sleep ประหยัดแบตเตอรี่ IoT ฉบับสมบูรณ์

เรียนรู้วิธีการใช้งาน Deep Sleep Mode บน ESP32 เพื่อสร้างอุปกรณ์ IoT ที่ทำงานด้วยแบตเตอรี่ได้นานเป็นเดือนหรือเป็นปี พร้อมตัวอย่างโค้ดและคำนวณพลังงาน

📅 26 มีนาคม 2026⏱️ 20 นาที🎯 ระดับกลาง

ทำไมต้อง Deep Sleep Mode?

เมื่อสร้างอุปกรณ์ IoT ที่ทำงานด้วยแบตเตอรี่ การประหยัดพลังงานเป็นสิ่งสำคัญที่สุด ESP32 ในโหมดปกติใช้กระแสไฟประมาณ 80-240 mA ซึ่งทำให้แบตเตอรี่หมดภายในไม่กี่ชั่วโมง แต่ด้วย Deep Sleep Mode คุณสามารถลดการใช้พลังงานลงเหลือเพียง 10-100 µA ทำให้อุปกรณ์ทำงานได้นานเป็นเดือนหรือเป็นปี!

💡 เปรียบเทียบการใช้พลังงาน

  • Active Mode: ~240 mA (100% ใช้งาน)
  • Light Sleep: ~0.8 mA (WiFi เปิดอยู่)
  • Deep Sleep: ~10-100 µA (เกือบปิดทั้งหมด)
  • Hibernation: ~2.5 µA (ปิดสนิท)

ใครควรใช้ Deep Sleep?

  • ✅ เซ็นเซอร์วัดอุณหภูมิ/ความชื้นที่ส่งข้อมูลทุก 10-15 นาที
  • ✅ โปรเจกต์ติดตามสัตว์เลี้ยง (Pet Tracker)
  • ✅ ระบบเตือนภัยไฟไหม้/แก๊สรั่ว
  • ✅ เครื่องวัดปริมาณน้ำฝน/ระดับน้ำ
  • ✅ Remote control ที่ใช้แบตเตอรี่

โหมดประหยัดพลังงานของ ESP32

ESP32 มีหลายโหมดสำหรับประหยัดพลังงาน เลือกใช้ตามความเหมาะสมของโปรเจกต์

1. Modem Sleep

WiFi ยังเชื่อมต่ออยู่ แต่ CPU ลดการทำงาน ใช้ ~15 mA

2. Light Sleep

CPU หยุดทำงาน แต่ WiFi/Bluetooth พร้อมปลุกได้ทันที ใช้ ~0.8 mA

3. Deep Sleep ⭐

CPU, WiFi, Bluetooth ปิดหมด เหลือแต่ RTC memory ใช้ ~10-100 µA

4. Hibernation

ปิดทุกอย่างรวม RTC memory ใช้ ~2.5 µA (ต้อง reboot ใหม่)

พื้นฐานของ Deep Sleep Mode

เมื่อ ESP32 เข้าสู่ Deep Sleep Mode สิ่งที่เกิดขึ้นมีดังนี้:

❌ สิ่งที่หยุดทำงาน

  • • CPU cores ทั้ง 2 cores
  • • WiFi และ Bluetooth
  • • ส่วนใหญ่ของ peripherals
  • • RAM ส่วนใหญ่จะหายไป

✅ สิ่งที่ยังทำงาน

  • • RTC (Real-Time Clock)
  • • RTC Memory (8 KB)
  • • RTC GPIO pins (บาง pins)
  • • ULP Coprocessor (ถ้าใช้)

⚠️ ข้อควรระวังสำคัญ

  • • ตัวแปรใน RAM ทั่วไปจะหายไปหมด (ต้องเก็บใน RTC memory)
  • • WiFi connection จะหลุด ต้องเชื่อมต่อใหม่เมื่อตื่น
  • • โค้ดจะเริ่มทำงานใหม่จาก setup() เสมอ
  • • ต้องเลือก wake source ก่อนเข้า deep sleep

วิธีการปลุก ESP32 จาก Deep Sleep

ESP32 สามารถตื่นจาก Deep Sleep ได้หลายวิธี ขึ้นอยู่กับ application ของคุณ

1. Timer (ตั้งเวลา)

ตื่นเมื่อครบเวลาที่กำหนด เหมาะกับเซ็นเซอร์ที่ส่งข้อมูลเป็นระยะ

esp_sleep_enable_timer_wakeup(60 * 1000000); // 60 วินาที

2. Touch Pad (สัมผัส)

ตื่นเมื่อมีการสัมผัสที่ pin ที่กำหนด เหมาะกับปุ่มกด

esp_sleep_enable_touchpad_wakeup();

3. Ext0 (External Wakeup)

ตื่นเมื่อ GPIO pin เปลี่ยนสถานะ เหมาะกับเซ็นเซอร์หรือปุ่ม

esp_sleep_enable_ext0_wakeup(GPIO_NUM_4, 0); // Pin 4, LOW

4. Ext1 (Multiple GPIOs)

ตื่นเมื่อ GPIO pins ใดก็ได้เปลี่ยนสถานะ (สูงสุด 6 pins)

esp_sleep_enable_ext1_wakeup(GPIO_SEL_4 | GPIO_SEL_5, ESP_EXT1_WAKEUP_ANY_HIGH);

5. ULP Coprocessor

ใช้ ULP ประมวลผลข้อมูลเซ็นเซอร์ขณะหลับ ตื่นเมื่อเงื่อนไขตรง

esp_sleep_enable_ulp_wakeup();

ตัวอย่างการใช้งาน Deep Sleep แบบพื้นฐาน

มาเริ่มต้นด้วยตัวอย่างง่ายๆ ที่ใช้ Timer Wakeup เพื่อให้ ESP32 ตื่นทุกๆ 30 วินาที

Arduino/C++
#include <WiFi.h>
#include <esp_sleep.h>

// กำหนดค่า WiFi
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

// ตั้งค่าเวลาหลับ (เป็นไมโครวินาที)
#define uS_TO_S_FACTOR 1000000  /* แปลงไมโครวินาทีเป็นวินาที */
#define TIME_TO_SLEEP  30        /* หลับ 30 วินาที */

// ตัวแปร RTC memory (จะไม่หายเมื่อหลับ)
RTC_DATA_ATTR int bootCount = 0;

void setup() {
  Serial.begin(115200);
  
  // นับจำนวนครั้งที่ boot
  bootCount++;
  Serial.println("Boot number: " + String(bootCount));

  // พิมพ์สาเหตุที่ตื่น
  print_wakeup_reason();

  // เชื่อมต่อ WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWiFi connected!");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // ====== ทำงานของคุณที่นี่ ======
  // อ่านเซ็นเซอร์ ส่งข้อมูล ฯลฯ
  Serial.println("Doing work...");
  
  // ตัดการเชื่อมต่อ WiFi
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  
  // ====== เข้าสู่ Deep Sleep ======
  Serial.println("Going to sleep now");
  Serial.flush(); 
  
  // ตั้งเวลาปลุก
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  
  // เข้าสู่ deep sleep
  esp_deep_sleep_start();
}

void loop() {
  // ไม่มีอะไรที่นี่ เพราะ deep sleep จะรีเซ็ตตัวเอง
}

// ฟังก์ชันตรวจสอบสาเหตุที่ตื่น
void print_wakeup_reason() {
  esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason) {
    case ESP_SLEEP_WAKEUP_EXT0:
      Serial.println("Wakeup caused by external signal using RTC_IO");
      break;
    case ESP_SLEEP_WAKEUP_EXT1:
      Serial.println("Wakeup caused by external signal using RTC_CNTL");
      break;
    case ESP_SLEEP_WAKEUP_TIMER:
      Serial.println("Wakeup caused by timer");
      break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD:
      Serial.println("Wakeup caused by touchpad");
      break;
    case ESP_SLEEP_WAKEUP_ULP:
      Serial.println("Wakeup caused by ULP program");
      break;
    default:
      Serial.println("Wakeup was not caused by deep sleep");
      break;
  }
}

✅ จุดสำคัญของโค้ดนี้

  • RTC_DATA_ATTR ใช้เก็บตัวแปรที่ไม่หายเมื่อหลับ
  • esp_sleep_enable_timer_wakeup() ตั้งเวลาปลุก
  • esp_deep_sleep_start() เริ่มเข้าสู่ deep sleep
  • loop() จะไม่ถูกเรียก เพราะโค้ดรีเซ็ตใหม่เสมอ

เทคนิคขั้นสูง: ประหยัดพลังงานสูงสุด

1. ปิด WiFi และ Bluetooth ทันทีที่ใช้เสร็จ

// เปิด WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);

// ทำงานที่ต้องใช้ WiFi...

// ปิด WiFi ทันที
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
btStop(); // ปิด Bluetooth ถ้ามี

2. ลด CPU Frequency

#include <esp_wifi.h>

// ลดความเร็ว CPU จาก 240 MHz เป็น 80 MHz
setCpuFrequencyMhz(80);

// ลดความเร็ว WiFi กินกระแสน้อยลง
esp_wifi_set_ps(WIFI_PS_MAX_MODEM);

3. ใช้ RTC Memory อย่างมีประสิทธิภาพ

// ตัวแปรใน RTC memory (8 KB)
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float lastTemperature = 0;
RTC_DATA_ATTR char deviceID[16] = "ESP32_001";

// struct ซับซ้อนก็ได้
struct SensorData {
  float temp;
  float humidity;
  int batteryLevel;
};

RTC_DATA_ATTR SensorData lastReading;

4. External Wakeup กับเซ็นเซอร์

// ตื่นเมื่อมี motion จาก PIR sensor
#define PIR_SENSOR_PIN 4

void setup() {
  pinMode(PIR_SENSOR_PIN, INPUT_PULLUP);
  
  // ตั้งค่าให้ตื่นเมื่อ PIR เป็น HIGH
  esp_sleep_enable_ext0_wakeup(
    (gpio_num_t)PIR_SENSOR_PIN, 
    1  // 1 = HIGH, 0 = LOW
  );
  
  // ทำงาน...
  
  esp_deep_sleep_start();
}

5. ใช้ ULP Coprocessor (ขั้นสูง)

ULP สามารถอ่านเซ็นเซอร์และประมวลผลขณะที่ main CPU หลับอยู่ ประหยัดพลังงานสูงสุด

Note: การเขียน ULP code ต้องใช้ Assembly พิเศษ และมีความซับซ้อนสูง แนะนำให้ศึกษาจาก Espressif ULP Documentation

คำนวณอายุแบตเตอรี่

มาคำนวณกันว่าโปรเจกต์ของคุณทำงานได้นานแค่ไหน

📊 สูตรคำนวณ

กระแสเฉลี่ย (mA) = (ActiveCurrent × ActiveTime + SleepCurrent × SleepTime) / TotalCycle

อายุแบตเตอรี่ (ชั่วโมง) = BatteryCapacity / AverageCurrent

อายุแบตเตอรี่ (วัน) = BatteryHours / 24

ตัวอย่างการคำนวณ

สถานการณ์: เซ็นเซอร์อุณหภูมิ

  • • แบตเตอรี่: 2000 mAh (Li-ion 18650)
  • • Active time: 5 วินาที (connect WiFi + send data)
  • • Sleep time: 300 วินาที (5 นาที)
  • • Active current: 150 mA (เฉลี่ย)
  • • Sleep current: 20 µA = 0.02 mA
// กระแสเฉลี่ยต่อรอบ (305 วินาที)
= (150 mA × 5s + 0.02 mA × 300s) / 305s
= (750 + 6) / 305
= 2.48 mA

// อายุแบตเตอรี่
= 2000 mAh / 2.48 mA
= 806 ชั่วโมง
= 33.6 วัน ≈ 1 เดือน

✨ เคล็ดลับ: ยืดอายุแบตเตอรี่

  • • เพิ่มระยะเวลาหลับ (จาก 5 นาที → 15 นาที = 3 เท่ายิ่งดี)
  • • ลด Active time (disconnect WiFi ไวๆ)
  • • เลือกบอร์ดที่มี sleep current ต่ำ (ESP32-S2, S3, C3)
  • • ใช้แบตเตอรี่ขนาดใหญ่ขึ้น
  • • เพิ่ม solar panel เพื่อ charge

เปรียบเทียบอายุแบตเตอรี่ (2000 mAh)

รอบการส่งข้อมูลกระแสเฉลี่ยอายุแบตเตอรี่
ทุก 1 นาที~5 mA~16 วัน
ทุก 5 นาที~2.5 mA~33 วัน
ทุก 15 นาที~0.8 mA~104 วัน (3.5 เดือน)
ทุก 1 ชั่วโมง~0.2 mA~416 วัน (13.8 เดือน)

เฮาร์ดแวร์ Tips เพื่อประหยัดพลังงาน

1. เลือกบอร์ดที่เหมาะสม

  • • ESP32-S2, S3: Sleep current ต่ำกว่า
  • • ESP32-C3: ราคาถูก, กินไฟน้อย
  • • หลีกเลี่ยงบอร์ดที่มี LED ติดอยู่
  • • เลือกบอร์ดที่มี voltage regulator ดี

2. ตัดอุปกรณ์ที่ไม่ใช้

  • • ถอด USB-to-UART chip ออก (ถ้าได้)
  • • ต่อเซ็นเซอร์ผ่าน MOSFET เพื่อตัดไฟ
  • • ใช้ pull-up/pull-down แทนการเปิด IO
  • • เลือกเซ็นเซอร์ที่กินไฟน้อย

3. จ่ายไฟอย่างมีประสิทธิภาพ

  • • ใช้ LDO ที่มี quiescent current ต่ำ
  • • หลีกเลี่ยง linear regulator เมื่อต่างศักย์มาก
  • • ใช้ buck converter เมื่อเหมาะสม
  • • ตัด LED บนบอร์ดออก (ถ้าได้)

4. เลือกแบตเตอรี่ที่เหมาะสม

  • • Li-ion/LiPo: 3.7V, high capacity
  • • LiFePO4: 3.2V, 3000+ cycles
  • • AA Alkaline: ต่อกัน series
  • • พิจารณาใช้ solar + supercap

⚡ วัดกระแสไฟจริง

ใช้ multimeter หรือ power monitor เพื่อวัดกระแสจริงของโปรเจกต์คุณ เพราะค่าที่คำนวณอาจต่างจากจริงมาก

ปัญหาที่พบบ่อยและวิธีแก้ไข

❌ ปัญหา: ตื่นแล้ว WiFi เชื่อมต่อไม่ได้

สาเหตุ: WiFi ยังเปิดอยู่ขณะเข้า deep sleep ทำให้ state ผิดพลาด

วิธีแก้: ต้อง WiFi.disconnect(true) และ WiFi.mode(WIFI_OFF) ก่อนเข้า deep sleep เสมอ

❌ ปัญหา: ตัวแปรหายหมดเมื่อตื่น

สาเหตุ: เก็บตัวแปรใน RAM ปกติ ซึ่งจะหายเมื่อ deep sleep

วิธีแก้: ใช้ RTC_DATA_ATTR สำหรับตัวแปรที่ต้องเก็บไว้

❌ ปัญหา: ตื่นแล้ว setup() ไม่ทำงาน

สาเหตุ: ผิด ในความเป็นจริง setup() จะถูกเรียกทุกครั้งที่ตื่น

วิธีแก้: ตรวจสอบ Serial Monitor และเพิ่ม Serial.flush() ก่อน sleep

❌ ปัญหา: แบตเตอรี่หมดเร็วมาก

สาเหตุ: อาจมีอุปกรณ์อื่นกินไฟ เช่น LED, regulator, หรือเซ็นเซอร์

วิธีแก้: วัดกระแสไฟแต่ละส่วน และตัดสิ่งที่ไม่จำเป็นออก

❌ ปัญหา: Ext0 wakeup ไม่ทำงาน

สาเหตุ: ใช้ GPIO pin ที่ไม่รองรับ RTC wakeup

วิธีแก้: ต้องใช้ RTC_GPIO pins ดูรายการจาก datasheet ESP32

❌ ปัญหา: หลับแล้วไม่ยอมตื่น

สาเหตุ: ไม่ได้ตั้งค่า wake source ก่อนเข้า deep sleep

วิธีแก้: ต้องเรียก esp_sleep_enable_xxx_wakeup() ก่อน esp_deep_sleep_start() เสมอ

สรุป

Deep Sleep Mode เป็นเครื่องมือที่ทรงพลังสำหรับสร้าง IoT device ที่ทำงานด้วยแบตเตอรี่ได้นาน ด้วยการลดการใช้พลังงานจาก 240 mA เหลือเพียง 10-100 µA คุณสามารถสร้างอุปกรณ์ที่ทำงานได้เป็นเดือนหรือเป็นปี!

สิ่งที่คุณได้เรียนรู้:

  • ✅ ความแตกต่างระหว่างโหมดประหยัดพลังงานต่างๆ
  • ✅ วิธีการตั้งค่า Deep Sleep และ Wake sources
  • ✅ การใช้ RTC Memory เพื่อเก็บข้อมูลข้ามรอบ sleep
  • ✅ เทคนิคขั้นสูงเพื่อลดการใช้พลังงาน
  • ✅ การคำนวณอายุแบตเตอรี่
  • ✅ การแก้ปัญหาที่พบบ่อย

🎯 ถัดไป