คู่มือสมบูรณ์ ESP32 Deep Sleep: ยืดอายุแบตเตอรี่จากวันเป็นเดือน

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

8 มีนาคม 2026 15 นาที ระดับกลาง
ESP32Deep SleepLow PowerBattery

ทำไมต้อง Deep Sleep?

เคยเจอปัญหาโปรเจกต์ IoT ที่ใช้แบตเตอรี่หมดภายในวันเดียวไหม? ESP32 ที่ทำงานปกติใช้กระแสไฟ ~240mA เมื่อเปิด WiFi แบบเต็มสูบ แบตเตอรี่ 2000mAh จะหมดภายใน ~8 ชั่วโมง เท่านั้น!

แต่ด้วย Deep Sleep Mode กระแสไฟจะลดลงเหลือเพียง ~10µA (0.01mA) ทำให้แบตเตอรี่เดิมใช้งานได้ 6-12 เดือน หรือมากกว่านั้น!

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

Active Mode (WiFi เปิด)

~240mA

แบต 2000mAh = 8 ชม.

Deep Sleep Mode

~10µA (0.01mA)

แบต 2000mAh = 6-12 เดือน

โหมดประหยัดไฟของ ESP32

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

1. Modem Sleep

ปิด WiFi แต่ CPU ยังทำงาน

  • • กระแส: ~20-70mA
  • • ใช้เมื่อ: ไม่ต้องใช้ WiFi ต่อเนื่อง
  • • Wake-up: ทันที

2. Light Sleep

CPU หยุดทำงาน แต่ RAM ยังเก็บข้อมูล

  • • กระแส: ~0.8-15mA
  • • ใช้เมื่อ: ต้องการตื่นเร็วๆ
  • • Wake-up: ไม่กี่มิลลิวินาที

3. Deep Sleep ⭐

แนะนำ

CPU และ WiFi ปิดทั้งหมด เก็บข้อมูลเฉพาะ RTC Memory

  • • กระแส: ~10µA (0.01mA)
  • • ใช้เมื่อ: ต้องการประหยัดพลังงานสูงสุด
  • • Wake-up: ต้อง Restart โปรแกรมใหม่

4. Hibernation

ปิดทุกอย่าง รวมถึง RTC Memory

  • • กระแส: ~2.5µA
  • • ใช้เมื่อ: ประหยัดพลังงานสูงสุด ไม่สนข้อมูล
  • • Wake-up: ต้องเริ่มต้นใหม่ทั้งหมด

เริ่มต้น Deep Sleep ง่ายๆ

มาเริ่มต้นด้วยตัวอย่างพื้นฐาน: ให้ ESP32 นอน Deep Sleep เป็นเวลา 30 วินาที แล้วตื่นมาทำงานอีกครั้ง

ESP32_DeepSleep_Basic.ino
/*
 * ESP32 Deep Sleep Basic Example
 * ตัวอย่างการใช้งาน Deep Sleep Mode เบื้องต้น
 * โดยให้ ESP32 นอน 30 วินาที แล้วตื่นมาทำงานอีกครั้ง
 */

#define uS_TO_S_FACTOR 1000000  // แปลงไมโครวินาทีเป็นวินาที
#define TIME_TO_SLEEP  30        // เวลานอน (วินาที)

void setup() {
  Serial.begin(115200);
  
  // รอเวลาสักครู่เพื่อให้ Serial เตรียมพร้อม
  delay(1000);
  
  // พิมพ์ข้อความเริ่มต้น
  Serial.println("ESP32 เริ่มต้นทำงาน!");
  Serial.print("จะเข้า Deep Sleep เป็นเวลา ");
  Serial.print(TIME_TO_SLEEP);
  Serial.println(" วินาที");
  
  // ตั้งค่าเวลานอน
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  
  // เข้าสู่ Deep Sleep Mode
  Serial.println("กำลังเข้า Deep Sleep Mode...");
  esp_deep_sleep_start();
}

void loop() {
  // ใน Deep Sleep Mode จะไม่มีการทำงานใน loop()
  // เพราะโปรแกรมจะเริ่มใหม่ที่ setup() เสมอเมื่อตื่น
}

💡 สิ่งสำคัญที่ต้องรู้

  • • เมื่อ ESP32 ตื่นจาก Deep Sleep โปรแกรมจะเริ่มใหม่ที่ setup() เสมอ
  • • ข้อมูลในตัวแปรปกติจะหายไป ต้องใช้ RTC Memory ถ้าต้องการเก็บข้อมูล
  • • Deep Sleep ใช้กระแสไฟเพียง ~10µA ประหยัดมาก!
  • • สามารถตั้งเวลานอนได้นานสุด ~58 ปี (ในทางทฤษฎี)

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

ESP32 สามารถตื่นจาก Deep Sleep ได้หลายวิธี เลือกใช้ตามความเหมาะสมกับโปรเจกต์:

⏰ Timer Wake-up

ตั้งเวลาปลุก เช่น ทุกๆ 10 นาที

เหมาะกับ: เซ็นเซอร์ที่วัดค่าเป็นระยะ

👆 Touch Wake-up

สัมผัสที่ขา Touch Pin

เหมาะกับ: ปุ่มสัมผัสแบบประหยัดไฟ

⚡ External Wake-up

สัญญาณจากภายนอก เช่น PIR Sensor

เหมาะกับ: ตรวจจับความเคลื่อนไหว

🌐 ULP Co-processor

ใช้ ULP ตรวจสอบเซ็นเซอร์ขณะนอน

เหมาะกับ: ตรวจสอบเซ็นเซอร์แบบละเอียด

ตัวอย่าง: External Wake-up ด้วย PIR Sensor

ตัวอย่างนี้ใช้ PIR Motion Sensor เพื่อปลุก ESP32 เมื่อตรวจจับความเคลื่อนไหว

ESP32_PIR_Wakeup.ino
/*
 * ESP32 PIR Motion Sensor Wake-up
 * ปลุก ESP32 เมื่อตรวจจับความเคลื่อนไหวด้วย PIR Sensor
 * 
 * วิธีต่อสาย:
 * PIR VCC  -> 3.3V
 * PIR GND  -> GND
 * PIR OUT  -> GPIO 4
 */

#define RTC_DATA_ATTR  // บันทึกข้อมูลใน RTC Memory (ไม่หายเมื่อ Deep Sleep)
RTC_DATA_ATTR int bootCount = 0;  // นับจำนวนครั้งที่ Boot

const int PIR_SENSOR_PIN = 4;  // ขาที่ต่อกับ PIR Sensor

void setup() {
  Serial.begin(115200);
  delay(1000);
  
  // เพิ่มจำนวนครั้งที่ Boot
  bootCount++;
  Serial.println("Boot number: " + String(bootCount));
  
  // ตรวจสอบสาเหตุที่ตื่น
  esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();
  
  switch(wakeup_reason) {
    case ESP_SLEEP_WAKEUP_EXT0:
      Serial.println("ตื่นเพราะตรวจจับความเคลื่อนไหว (PIR Sensor)!");
      break;
    case ESP_SLEEP_WAKEUP_TIMER:
      Serial.println("ตื่นเพราะหมดเวลา Timer");
      break;
    default:
      Serial.println("ตื่นเพราะสาเหตุอื่น");
      break;
  }
  
  // ทำงานที่ต้องการ เช่น ส่งข้อมูลไป Server
  doSomething();
  
  // ตั้งค่าให้ตื่นเมื่อมีสัญญาณจาก PIR Sensor (EXT0)
  esp_sleep_enable_ext0_wakeup(
    GPIO_NUM_4,    // ขาที่ต่อกับ PIR Sensor
    1              // 1 = HIGH, 0 = LOW
  );
  
  Serial.println("กำลังเข้า Deep Sleep Mode...");
  Serial.println("รอจนกว่าจะตรวจจับความเคลื่อนไหว...");
  esp_deep_sleep_start();
}

void loop() {
  // ไม่มีการทำงานใน loop เมื่อใช้ Deep Sleep
}

void doSomething() {
  Serial.println("กำลังทำงาน...");
  // เพิ่มโค้ดของคุณที่นี่ เช่น:
  // - อ่านค่าเซ็นเซอร์
  // - ส่งข้อมูลผ่าน WiFi
  // - บันทึกข้อมูล
  delay(2000);
  Serial.println("ทำงานเสร็จสิ้น");
}

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

เพื่อคำนวณอายุแบตเตอรี่ที่แม่นยำ ต้องวัดกระแสไฟจริงของโปรเจกต์คุณเอง

วิธีวัดกระแสไฟ

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

  • • Multimeter ที่วัดกระแสไฟ µA ได้
  • • แหล่งจ่ายไฟ เช่น แบตเตอรี่หรือ Power Supply
  • • ตัวต้านทาน 10Ω (สำหรับวัดกระแส Active Mode)

ขั้นตอนการวัด

  1. 1ต่อ Multimeter แบบ Series (ต่อเรียง) ระหว่างแบตเตอรี่และ ESP32
  2. 2ตั้งค่า Multimeter ที่ 200µA DC หรือ 200mA DC (ขึ้นกับโหมด)
  3. 3วัดกระแสในแต่ละโหมด: Active, Light Sleep, Deep Sleep
  4. 4บันทึกค่าและคำนวณอายุแบตเตอรี่

⚠️ ข้อควรระวัง

  • • อย่าวัดกระแส Active Mode โดยตรง (อาจเกินขอบเขตของ Multimeter)
  • • ใช้ตัวต้านทาน 10Ω และวัดแรงดันข้ามตัวต้านทานแทน
  • • ระวังอย่าให้ขาสั้น (Short Circuit)
  • • USB Programmer บางตัวมีผลต่อการวัดกระแส Deep Sleep

เทคนิคขั้นสูง

นอกจาก Deep Sleep แล้ว ยังมีเทคนิคอื่นๆ เพื่อประหยัดพลังงานเพิ่มเติม:

1. ปิด WiFi และ Bluetooth เมื่อไม่ได้ใช้

WiFi และ Bluetooth ใช้พลังงานมาก ปิดทันทีที่ไม่ได้ใช้

// ปิด WiFi
WiFi.mode(WIFI_OFF);

// ปิด Bluetooth
btStop();

// เปิดใหม่เมื่อต้องใช้
WiFi.begin(ssid, password);

2. ลดความเร็ว CPU

ลดความเร็ว CPU เมื่อไม่ต้องการประมวลผลเยอะ

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

// กลับสู่ความเร็วปกติ
setCpuFrequencyMhz(240);

ประหยัด ~20-30% พลังงาน แต่ทำงานช้าลง

3. ใช้ RTC Memory เก็บข้อมูล

ข้อมูลใน RTC Memory จะไม่หายเมื่อ Deep Sleep

// ประกาศตัวแปรใน RTC Memory
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float sensorData[10];

// ข้อมูลจะยังอยู่หลังจากตื่นจาก Deep Sleep

4. ใช้ ULP Co-processor

ULP สามารถอ่านเซ็นเซอร์ได้ขณะที่ ESP32 นอน Deep Sleep

เหมาะสำหรับ: ตรวจสอบเซ็นเซอร์ที่ต้องการความแม่นยำสูง

5. เลือกใช้บอร์ดที่ประหยัดไฟ

บอร์ด ESP32 บางรุ่นมีวงจรประหยัดไฟในตัว

  • • ESP32-WROOM-32 มี LDO ในตัว (กระแส Deep Sleep ~10µA)
  • • ESP32-WROVER มี PSRAM (กระแส Deep Sleep ~20µA)
  • • บอร์ดบางรุ่นมี LED ที่ติดอยู่ ทำให้ใช้ไฟมากขึ้น

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

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

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

ความจุแบต (mAh) ÷ กระแสเฉลี่ย (mA)

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

โปรเจกต์: เซ็นเซอร์วัดอุณหภูมิทุก 10 นาที

  • แบตเตอรี่: 2000mAh (พวง AA 2 ก้อน)
  • Active Mode: 200mA นาน 5 วินาที (เชื่อมต่อ WiFi ส่งข้อมูล)
  • Deep Sleep: 0.01mA นาน 595 วินาที (รอ 10 นาที)

กระแสเฉลี่ยต่อรอบ (10 นาที):

(200mA × 5s + 0.01mA × 595s) ÷ 600s
= (1000 + 5.95) ÷ 600
= 1.67mA

อายุแบตเตอรี่:

2000mAh ÷ 1.67mA = 1197 ชั่วโมง ≈ 50 วัน

💡 เคล็ดลับเพิ่มอายุแบตเตอรี่

  • • เพิ่มระยะห่างระหว่างการอ่านเซ็นเซอร์ (เช่น ทุก 30 นาที แทน 10 นาที)
  • • ลดเวลาที่ใช้ WiFi (ส่งข้อมูลเร็วๆ แล้วปิดทันที)
  • • ใช้แบตเตอรี่ Li-Ion 18650 (2000-3500mAh) แทน AA
  • • เพิ่มแผงโซลาร์เซลล์ชาร์จแบตเตอรี่
  • • ใช้ LDO ที่มีประสิทธิภาพสูง (เช่น HT7333, ME6211)

ตัวอย่างจริง: เซ็นเซอร์โหนดวัดอุณหภูมิและความชื้น

มาดูตัวอย่างเต็มๆ ของเซ็นเซอร์โหนดที่ใช้ DHT22 วัดอุณหภูมิและความชื้น และส่งข้อมูลไปยัง CynoIoT Platform ทุกๆ 15 นาที

ESP32_SensorNode_DHT22.ino
/*
 * ESP32 Low Power Sensor Node with DHT22
 * เซ็นเซอร์โหนดวัดอุณหภูมิและความชื้น ประหยัดไฟ
 * ส่งข้อมูลไป CynoIoT ทุกๆ 15 นาที
 * 
 * อุปกรณ์:
 * - ESP32 Board
 * - DHT22 Sensor (ต่อที่ GPIO 4)
 * - แบตเตอรี่ Li-Ion 18650
 * 
 * คาดว่าอายุแบตเตอรี่: 6-12 เดือน
 */

#include "DHT.h"
#include <WiFi.h>
#include <HTTPClient.h>

// ===== WiFi Credentials =====
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

// ===== CynoIoT Settings =====
const char* cynoiot_server = "api.cynoiot.com";
const char* device_id = "YOUR_DEVICE_ID";
const char* api_key = "YOUR_API_KEY";

// ===== Sensor Settings =====
#define DHTPIN 4     // ขาที่ต่อกับ DHT22
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// ===== Sleep Settings =====
#define uS_TO_S_FACTOR 1000000  // แปลงไมโครวินาทีเป็นวินาที
#define TIME_TO_SLEEP  900      // เวลานอน (15 นาที = 900 วินาที)

// ===== RTC Memory (เก็บข้อมูลขณะ Deep Sleep) =====
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float avgTemp = 0;
RTC_DATA_ATTR float avgHum = 0;
RTC_DATA_ATTR int readingsCount = 0;

// ===== Function Prototypes =====
void readSensor();
void sendData(float temp, float hum);
void enterDeepSleep();

void setup() {
  // เพิ่มจำนวนครั้งที่ Boot
  bootCount++;
  
  Serial.begin(115200);
  delay(1000);
  
  Serial.println("=================================");
  Serial.println("ESP32 Sensor Node - Boot #" + String(bootCount));
  Serial.println("=================================");
  
  // เริ่มต้นใช้งานเซ็นเซอร์
  dht.begin();
  
  // อ่านค่าเซ็นเซอร์
  readSensor();
  
  // เข้าสู่ Deep Sleep Mode
  enterDeepSleep();
}

void loop() {
  // ไม่มีการทำงานใน loop เมื่อใช้ Deep Sleep
}

void readSensor() {
  Serial.println("กำลังอ่านค่าเซ็นเซอร์ DHT22...");
  
  // อ่านค่าอุณหภูมิและความชื้น
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  // ตรวจสอบว่าอ่านค่าสำเร็จหรือไม่
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  
  Serial.print("อุณหภูมิ: ");
  Serial.print(t);
  Serial.print("°C | ความชื้น: ");
  Serial.print(h);
  Serial.println("%");
  
  // คำนวณค่าเฉลี่ย
  if (readingsCount == 0) {
    avgTemp = t;
    avgHum = h;
  } else {
    avgTemp = (avgTemp * readingsCount + t) / (readingsCount + 1);
    avgHum = (avgHum * readingsCount + h) / (readingsCount + 1);
  }
  readingsCount++;
  
  // ส่งข้อมูลไป CynoIoT (เฉพาะครั้งที่ 5 เพื่อประหยัดแบต)
  if (bootCount % 5 == 0) {
    sendData(avgTemp, avgHum);
    // Reset averages
    avgTemp = 0;
    avgHum = 0;
    readingsCount = 0;
  }
}

void sendData(float temp, float hum) {
  Serial.println("กำลังเชื่อมต่อ WiFi...");
  
  // เชื่อมต่อ WiFi
  WiFi.begin(ssid, password);
  unsigned long startTime = millis();
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    
    // Timeout หลังจาก 10 วินาที
    if (millis() - startTime > 10000) {
      Serial.println("\nเชื่อมต่อ WiFi ไม่สำเร็จ!");
      return;
    }
  }
  
  Serial.println("\nWiFi เชื่อมต่อสำเร็จ!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  // ส่งข้อมูลไป CynoIoT
  HTTPClient http;
  String url = "https://" + String(cynoiot_server) + "/api/v1/data";
  
  http.begin(url);
  http.addHeader("Content-Type", "application/json");
  http.addHeader("X-API-Key", api_key);
  
  // สร้าง JSON payload
  String payload = "{\"device_id\":\"" + String(device_id) + 
                    "\",\"temperature\":" + String(temp) + 
                    ",\"humidity\":" + String(hum) + "}";
  
  Serial.println("กำลังส่งข้อมูล...");
  int httpResponseCode = http.POST(payload);
  
  if (httpResponseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    String response = http.getString();
    Serial.println("Response: " + response);
  } else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  
  http.end();
  
  // ปิด WiFi เพื่อประหยัดพลังงาน
  WiFi.mode(WIFI_OFF);
  Serial.println("ปิด WiFi เรียบร้อย");
}

void enterDeepSleep() {
  Serial.println("=================================");
  Serial.print("Boot count: ");
  Serial.println(bootCount);
  Serial.print("เฉลี่ยอุณหภูมิ: ");
  Serial.print(avgTemp);
  Serial.println("°C");
  Serial.print("เฉลี่ยความชื้น: ");
  Serial.print(avgHum);
  Serial.println("%");
  
  // ตั้งค่าเวลานอน
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  
  Serial.println("กำลังเข้า Deep Sleep Mode...");
  Serial.print("จะตื่นอีกครั้งใน ");
  Serial.print(TIME_TO_SLEEP / 60);
  Serial.println(" นาที");
  Serial.println("=================================\n");
  
  // เข้าสู่ Deep Sleep Mode
  esp_deep_sleep_start();
}

📊 สรุปสมรรถนะ

อายุแบตเตอรี่โดยประมาณ

6-12 เดือน

ระยะห่างการส่งข้อมูล

ทุก 75 นาที

กระแสไฟเฉลี่ย

~0.5mA

ค่าใช้จ่ายต่อเดือน

~0.05 บาท

สรุป

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

ในบทความนี้เราได้เรียนรู้:

  • • โหมดประหยัดไฟของ ESP32 ทั้งหมด 4 โหมด
  • • วิธีใช้งาน Deep Sleep พื้นฐานและขั้นสูง
  • • วิธีปลุก ESP32 จาก Deep Sleep (Timer, Touch, External)
  • • เทคนิคขั้นสูงในการประหยัดพลังงานเพิ่มเติม
  • • การคำนวณอายุแบตเตอรี่ที่แม่นยำ
  • • ตัวอย่างเซ็นเซอร์โหนดจริงที่ใช้งานได้

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

บทความที่เกี่ยวข้อง