คู่มือ ESP32 Deep Sleep: ประหยัดพลังงานสำหรับโปรเจกต์ IoT แบตเตอรี่

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

📅 5 มีนาคม 2026⏱️ 12 นาที🎯 ระดับกลาง-สูง

Deep Sleep คืออะไร?

Deep Sleep Mode คือโหมดพลังงานต่ำสุดของ ESP32 ที่ปิดการทำงานของ CPU, WiFi, Bluetooth และอุปกรณ์ส่วนใหญ่ โดยเหลือไว้เฉพาะ RTC Memory และ Real Time Clock (RTC) เพื่อรักษาข้อมูลและตั้งเวลาการตื่น

💡 ทำไมต้อง Deep Sleep? ESP32 ในโหมดปกติใช้กระแส ~80-240mA แต่ใน Deep Sleep ใช้เพียง ~10-150µA เท่านั้น! นั่นหมายถึงประหยัดพลังงานได้ 1,000-10,000 เท่า

เหมาะสำหรับโปรเจกต์ประเภทใด?

  • 🌡️ เซ็นเซอร์วัดอุณหภูมิ/ความชื้น ส่งข้อมูลทุก 5-15 นาที
  • 💧 ระบบรดน้ำอัตโนมัติ ตรวจสอบความชื้นดินทุกชั่วโมง
  • 📍 Tracking devices ส่งพิกัดทุก 10-30 นาที
  • 🔔 Remote alerts ส่งข้อมูลเฉพาะเมื่อมีเหตุการณ์
  • 📊 Data loggers บันทึกข้อมูลเป็นระยะ

โหมดพลังงานของ ESP32

โหมดกระแสไฟWiFi/BTการใช้งาน
Active80-240 mAเปิดปกติ
Modem Sleep15-30 mAปิดชั่วคราวCPU ทำงาน
Light Sleep0.8-15 mAปิดตื่นได้เร็ว
Deep Sleep10-150 µAปิดประหยัดสุด
Hibernation2.5-5 µAปิดทั้งหมดRTC เท่านั้น

* ค่ากระแสขึ้นอยู่กับบอร์ดและอุปกรณ์ที่ต่ออยู่ บอร์ดบางรุ่นอาจใช้ไฟมากกว่าใน Deep Sleep

การเตรียมอุปกรณ์

อุปกรณ์ที่ต้องการ

  • ESP32 Development Board (NodeMCU, Wemos, หรือ Generic)
  • USB Cable สำหรับ programming
  • Arduino IDE หรือ PlatformIO
  • แหล่งจ่ายไฟแบตเตอรี่ (ถ้าทดสอบจริง)
  • (Optional) Multimeter สำหรับวัดกระแส

ข้อควรระวังเรื่อง Hardware

⚠️ บอร์ด ESP32 บางรุ่นมีอุปกรณ์เสริมที่ใช้ไฟเสมอ!

  • Power LED (สีแดง/ฟ้า) ใช้ ~2-10 mA - ตัดถ้าต้องการประหยัดสุด
  • Voltage Regulator บางรุ่นใช้ไฟมาก
  • USB-to-UART Chip ใช้ ~2-5 mA - ต้องตัดถ้าใช้แบตเตอรี่

Tip: สำหรับโปรเจกต์แบตเตอรี่จริง ใช้บอร์ดที่ออกแบบมาสำหรับ Low Power เช่น ESP32-WROOM-32, ESP32-C3, หรือ FireBeetle

Deep Sleep พื้นฐาน

ตัวอย่างที่ 1: Deep Sleep เป็นเวลา N วินาที

นี่คือตัวอย่างพื้นฐานที่สุด - ให้ ESP32 นอน Deep Sleep 30 วินาที แล้วตื่นขึ้นมาทำงาน

#include <WiFi.h>

// ตั้งค่าเวลานอน (เป็นวินาที)
#define uS_TO_S_FACTOR 1000000  /* ปัจจัยแปลงไมโครวินาทีเป็นวินาที */
#define TIME_TO_SLEEP  30        /* เวลาที่จะนอน Deep Sleep (วินาที) */

void setup() {
  Serial.begin(115200);
  
  // รอให้ Serial เปิด (สำหรับ debugging)
  delay(1000);
  
  // พิมพ์ข้อความต้อนรับ
  Serial.println("ESP32 ตื่นขึ้นมาแล้ว!");
  Serial.println("กำลังทำงาน...");
  
  // --- ใส่โค้ดของคุณที่นี่ ---
  // อ่านเซ็นเซอร์, ส่งข้อมูล, ทำสิ่งที่ต้องการ
  
  Serial.println("เสร็จสิ้น! กำลังเข้าสู่ Deep Sleep...");
  Serial.println("--------------------------------");
  
  // เข้าสู่ Deep Sleep เป็นเวลาที่กำหนด
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("ตั้งเวลาตื่น: " + String(TIME_TO_SLEEP) + " วินาที");
  
  Serial.println("กำลังเข้า Deep Sleep ตอนนี้...");
  esp_deep_sleep_start();
  
  // โค้ดบรรทัดนี้จะไม่ถูก executed เพราะ ESP32 จะหลับ
  Serial.println("นี่คือข้อความที่คุณจะไม่เห็น");
}

void loop() {
  // ใน Deep Sleep mode, loop() จะไม่ถูกเรียกใช้
  // เพราะ ESP32 จะรีสตาร์ททุกครั้งที่ตื่นจาก Deep Sleep
}

💡 สังเกต: เมื่อ ESP32 ตื่นจาก Deep Sleep มันจะเริ่มทำงานใหม่จาก setup() ไม่ใช่ loop() นั่นเป็นเพราะ Deep Sleep ทำการรีสตาร์ทชิป

ตัวอย่างที่ 2: ตรวจสอบว่าตื่นจากอะไร

ESP32 สามารถตื่นจาก Deep Sleep ได้หลายวิธี ตัวอย่างนี้ตรวจสอบว่าตื่นจากอะไร

#include <WiFi.h>
#include <esp_wifi.h>

#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP  30

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("ตื่นจากสัญญาณภายนอก (RTC_IO)"); 
      break;
    case ESP_SLEEP_WAKEUP_EXT1: 
      Serial.println("ตื่นจากสัญญาณภายนอก (RTC_CNTL)"); 
      break;
    case ESP_SLEEP_WAKEUP_TIMER: 
      Serial.println("ตื่นจาก Timer"); 
      break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD: 
      Serial.println("ตื่นจาก Touchpad"); 
      break;
    case ESP_SLEEP_WAKEUP_ULP: 
      Serial.println("ตื่นจาก ULP Coprocessor"); 
      break;
    default: 
      Serial.printf("ตื่นจากสาเหตุอื่น: %d\n", wakeup_reason); 
      break;
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  // ตรวจสอบสาเหตุที่ตื่น
  print_wakeup_reason();
  
  // ทำงานของคุณ...
  Serial.println("ทำงานเสร็จแล้ว กลับไปนอนต่อ...");
  
  // ตั้งเวลา Deep Sleep
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  esp_deep_sleep_start();
}

void loop() {
  // ไม่ได้ใช้ใน Deep Sleep
}

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

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

วิธีที่ง่ายที่สุด - ตั้งเวลาให้ตื่นเป็นระยะ

// ตื่นทุก 5 นาที
esp_sleep_enable_timer_wakeup(5 * 60 * 1000000);  // ไมโครวินาที

// ตื่นทุก 1 ชั่วโมง
esp_sleep_enable_timer_wakeup(60 * 60 * 1000000);

2. External Wake-up (EXT0/EXT1)

ตื่นเมื่อมีสัญญาณจากขา GPIO เช่น ปุ่มกด หรือเซ็นเซอร์

#define BUTTON_PIN  0  // GPIO 0 (Boot button)

// EXT0: ใช้ GPIO ตัวเดียว
esp_sleep_enable_ext0_wakeup(
  (gpio_num_t)BUTTON_PIN,   // ขา GPIO
  0                         // 0 = Low, 1 = High (level ที่ตื่น)
);

// EXT1: ใช้หลายขาพร้อมกัน
#define BUTTON1_PIN  0
#define BUTTON2_PIN  35

uint64_t mask = (1ULL << BUTTON1_PIN) | (1ULL << BUTTON2_PIN);
esp_sleep_enable_ext1_wakeup(
  mask,      // bitmask ของ GPIO
  ESP_EXT1_WAKEUP_ANY_HIGH  // ANY_HIGH หรือ ALL_LOW
);

⚠️ ข้อจำกัด EXT0: ใช้ได้กับ RTC GPIO เท่านั้น (GPIO: 0, 2, 4, 12-15, 25-27, 32-39)
⚠️ ข้อจำกัด EXT1: ใช้ได้กับ RTC GPIO เหมือนกัน

3. Touch Wake-up (Touchpad)

ตื่นเมื่อมีการสัมผัสที่ Touchpad

// ตั้งค่า threshold สำหรับ touch
int threshold = 40;
touchAttachInterrupt(
  T2,                           // Touch pin 2 (GPIO 2)
  NULL,                         // callback function (NULL = ไม่ใช้)
  threshold
);

// เปิดใช้งาน touch wake-up
esp_sleep_enable_touchpad_wakeup();

4. ULP Coprocessor Wake-up

ให้ ULP Coprocessor ทำงานขณะนอน และตื่นเมื่อตรงตามเงื่อนไข (Advanced)

ULP คือ coprocessor ขนาดเล็กที่ทำงานขณะ ESP32 นอน Deep Sleep ได้ ใช้สำหรับ:

  • อ่านเซ็นเซอร์ ADC ต่อเนื่อง
  • ตรวจสอบค่าและตื่นเมื่อเกิน threshold
  • นับเวลาแบบกำหนดเอง

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

1. WiFi Optimization

WiFi ใช้พลังงานมากที่สุด ให้ใช้งานน้อยที่สุด

#include <WiFi.h>

void connectWiFi() {
  // ตั้งค่า WiFi mode เป็น STA (Station)
  WiFi.mode(WIFI_STA);
  
  // ลดกำลังส่ง (TX power) ลง
  WiFi.setTxPower(WIFI_POWER_8_5dBm);  // ต่ำสุด
  
  // เชื่อมต่อ WiFi
  WiFi.begin("your_SSID", "your_PASSWORD");
  
  // รอการเชื่อมต่อ (timeout 10 วินาที)
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    attempts++;
  }
  
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("WiFi เชื่อมต่อสำเร็จ!");
    Serial.println("IP: " + WiFi.localIP().toString());
  } else {
    Serial.println("WiFi เชื่อมต่อไม่สำเร็จ");
  }
  
  // --- ส่งข้อมูล ---
  // ทำ HTTP Request, MQTT, etc.
  
  // --- ปิด WiFi ---
  WiFi.disconnect(true);  // true = ปิด WiFi และลบการเชื่อมต่อ
  WiFi.mode(WIFI_OFF);    // ปิด WiFi mode
  Serial.println("WiFi ปิดแล้ว");
}

2. ปิด Peripherals ที่ไม่ใช้

// ปิด peripherals ที่ไม่ใช้
COST_BEGIN {
  // ปิด ADC
  adc_power_off();
  
  // ปิด Bluetooth
  btStop();
  
  // ปิด I2C, SPI, Serial ถ้าไม่ใช้
  // Serial.end();
  
  // ลด clock speed (optional)
  setCpuFrequencyMhz(80);  // ปกติ 240MHz, ลดเหลือ 80MHz
}
COST_END

3. ใช้ RTC Memory อย่างชาญฉลาด

RTC Memory เก็บข้อมูลได้แม้ ESP32 จะ Deep Sleep

// ตัวแปรใน RTC Memory (เก็บไว้ข้าม Deep Sleep)
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float sensorReadings[10];

void setup() {
  Serial.begin(115200);
  
  // นับจำนวนครั้งที่บูต
  bootCount++;
  Serial.println("บูตครั้งที่: " + String(bootCount));
  
  // เขียน/อ่านข้อมูลใน RTC Memory
  sensorReadings[0] = 25.5;  // เก็บค่าเซ็นเซอร์
  
  // ... ทำงานอื่นๆ ...
  
  // เข้า Deep Sleep
  esp_deep_sleep_start();
}

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

สูตรคำนวณ

อายุแบตเตอรี่ (ชั่วโมง) = ความจุแบตเตอรี่ (mAh) / กระแสเฉลี่ย (mA)

โดยกระแสเฉลี่ยคำนวณจาก:

Avg Current = (I_sleep × T_sleep + I_active × T_active) / (T_sleep + T_active)

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

พารามิเตอร์ค่า
ความจุแบตเตอรี่2000 mAh (2x AA)
กระแส Deep Sleep0.02 mA (20µA)
กระแส Active150 mA (avg)
เวลา Active5 วินาที
เวลา Sleep295 วินาที (5 นาที)

📊 ผลลัพธ์:

  • กระแสเฉลี่ย = (0.02 × 295 + 150 × 5) / 300 = 2.52 mA
  • อายุแบตเตอรี่ = 2000 mAh / 2.52 mA = 793 ชั่วโมง ≈ 33 วัน

เปรียบเทียบ: ถ้าไม่ใช้ Deep Sleep (คงที่ 150mA) → 2000/150 = 13.3 ชั่วโมง เท่านั้น!

แก้ปัญหาที่พบบ่อย

❓ ปัญหา: ESP32 กินแบตเตอรี่เร็วมาก

สาเหตุที่เป็นไปได้:

  • ไม่ได้ปิด WiFi ก่อนเข้า Deep Sleep
  • มี LED บนบอร์ดสว่างอยู่
  • ใช้บอร์ดที่มี power regulator ที่กินไฟมาก
  • เซ็นเซอร์ที่ต่ออยู่ใช้ไฟเอง

วิธีแก้: วัดกระแสด้วย Multimeter ตรวจสอบว่า WiFi ปิดแล้ว, ตัด LED, ใช้บอร์ด low-power

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

สาเหตุ: การเชื่อมต่อ WiFi ต้องการเวลา และบางครั้งล้มเหลว

วิธีแก้: เพิ่ม retry logic, ใช้ WiFi.setAutoReconnect(true), หรือลองเชื่อมต่อใหม่หลายครั้ง

❓ ปัญหา: RTC Memory ไม่เก็บข้อมูล

สาเหตุ: ใช้ตัวแปรธรรมดาแทน RTC_DATA_ATTR

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

❓ ปัญหา: External wakeup ไม่ทำงาน

สาเหตุ: ใช้ GPIO ที่ไม่ใช่ RTC GPIO

วิธีแก้: ตรวจสอบว่าใช้ RTC GPIO เท่านั้น (0, 2, 4, 12-15, 25-27, 32-39)

สรุป

Deep Sleep Mode เป็นเทคนิคสำคัญที่ทำให้โปรเจกต์ IoT ของคุณทำงานด้วยแบตเตอรี่ได้นานเป็นเดือนหรือปี โดยไม่ต้องเปลี่ยนถ่านบ่อยๆ

สิ่งสำคัญที่ต้องจำ:

  • ✅ Deep Sleep ใช้กระแสเพียง 10-150µA เทียบกับ 80-240mA ในโหมดปกติ
  • ✅ WiFi คือศัตรูหมายเลข 1 ของพลังงาน ให้ใช้น้อยที่สุด
  • ✅ ตั้งค่า wakeup source ให้เหมาะสมกับการใช้งาน
  • ✅ ใช้ RTC_DATA_ATTR เพื่อเก็บข้อมูลข้าม Deep Sleep
  • ✅ วัดกระแสจริงเพื่อคำนวณอายุแบตเตอรี่ที่แม่นยำ

🚀 ถัดไป

CynoIoT LogoCynoIoT

แพลตฟอร์ม IoT ที่ช่วยให้คุณเชื่อมต่อและจัดการอุปกรณ์ IoT ได้ง่ายๆ
พัฒนาโปรเจกต์ IoT ของคุณกับเราวันนี้

© 2026 CynoIoT. All rights reserved.