เนื้อหาในบทความ
Deep Sleep คืออะไร?
💤 โหมดพักเครื่องสุดคุ้ม
Deep Sleep เป็นโหมดประหยัดพลังงานระดับสูงสุดของ ESP32 โดยจะ:
- ปิด CPU และหน่วยความจำส่วนใหญ่
- ปิด WiFi และ Bluetooth
- ปิดพอร์ตต่างๆ (GPIO) ยกเว้นที่ตั้งค่าไว้
- เหลือเพียง RTC Memory และ RTC Timer ทำงาน
- ลดการใช้กระแสไฟลงเหลือเพียง ไม่กี่ไมโครแอมป์
ข้อควรระวัง: เมื่อ ESP32 ตื่นจาก Deep Sleep โปรแกรมจะเริ่มต้นใหม่จาก setup() เหมือนกับการรีสตาร์ท แต่ตัวแปรใน RTC Memory จะยังคงค่าอยู่
ทำไมต้องใช้ Deep Sleep?
🌡️ เซ็นเซอร์วัดอุณหภูมิ
วัดค่าทุก 5 นาที ใช้แบต 2000mAh ได้ >6 เดือน
💧 รดน้ำอัตโนมัติ
ตรวจความชื้นดินรายวัน แบตอยู่ได้ทั้งฤดูกาล
📦 ติดตามพัสดุ
ส่งพิกัดเมื่อมีการเคลื่อนไหว ใช้งานได้เป็นเดือน
🏠 สวิตช์ไฟอัจฉริยะ
รอสั่งงานผ่าน MQTT แบตอึดถึง 1 ปี
เปรียบเทียบการใช้พลังงาน
| โหมด | กระแสไฟ | แบต 2000mAh ใช้ได้นาน |
|---|---|---|
| Active (WiFi เปิด) | ~150 mA | ⚠️ ~13 ชั่วโมง |
| Modem Sleep | ~15 mA | ⏱️ ~5 วัน |
| Deep Sleep | ~10 µA | ✅ >6 เดือน |
| Hibernate | ~2.5 µA | ✅ >2 ปี |
💡 เคล็ดลับ: หากตื่นทุกๆ 5 นาทีเพื่อวัดค่าเซ็นเซอร์ 3 วินาที แล้วกลับเข้า Deep Sleep อีก แบต 2000mAh สามารถใช้งานได้นานถึง 6-8 เดือน!
วิธีการตื่นจาก Deep Sleep
ESP32 สามารถตื่นจาก Deep Sleep ได้หลายวิธี:
1️⃣ ตั้งเวลา (Timer Wakeup)
ตั้งเวลาให้ตื่นทุกๆ X วินาที/นาที/ชั่วโมง - เหมาะสำหรับเซ็นเซอร์ที่ต้องวัดค่าเป็นระยะ
esp_sleep_enable_timer_wakeup(ติดต่อกันเป็นไมโครวินาที) 2️⃣ Touch Pin (Touch Wakeup)
ตื่นเมื่อมีการสัมผัสขา Touch (T0-T9) - เหมาะสำหรับปุ่มกด
esp_sleep_enable_touchpad_wakeup() 3️⃣ External Wakeup (EXT0/EXT1)
ตื่นเมื่อสัญญาณดิจิตอลจากภายนอกเปลี่ยน - เหมาะสำหรับเซ็นเซอร์
esp_sleep_enable_ext0_wakeup(GPIO_PIN, ระดับสัญญาณ) 4️⃣ ULP Co-Processor
ใช้ ULP ประมวลผลขณะหลับ - เหมาะสำหรับเซ็นเซอร์ที่ต้องการความแม่นยำสูง
ต้องเขียนโค้ด ULP แยก ตัวอย่างพื้นฐาน: วัดอุณหภูมิทุก 5 นาที
โค้ดตัวอย่างนี้แสดงวิธีใช้ Deep Sleep เพื่อวัดค่าอุณหภูมิทุกๆ 5 นาที แล้วกลับเข้าโหมดพักเครื่องอีกครั้ง
/*
* ESP32 Deep Sleep: วัดอุณหภูมิทุก 5 นาที
* เหมาะสำหรับโปรเจกต์เซ็นเซอร์ที่ต้องการประหยัดแบตเตอรี่
*
* Hardware: ESP32 + DHT22 (หรือเซ็นเซอร์อื่นๆ)
* Author: CynoIoT
* Date: April 2026
*/
#include <WiFi.h>
#include <DHT.h>
// ตั้งค่าเซ็นเซอร์ DHT22
#define DHTPIN 4 // GPIO 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// ตั้งค่า WiFi
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
// ตั้งค่าเวลานอน (5 นาที = 300,000,000 ไมโครวินาที)
#define uS_TO_S_FACTOR 1000000 /* แปลงไมโครวินาทีเป็นวินาที */
#define TIME_TO_SLEEP 300 /* เวลานอน (วินาที) */
// ตัวแปรเก็บจำนวนครั้งที่ตื่น (อยู่ใน RTC Memory)
RTC_DATA_ATTR int bootCount = 0;
// ฟังก์ชันตั้งค่าเริ่มต้น
void setup() {
Serial.begin(115200);
// เพิ่มจำนวนครั้งที่บูต
bootCount++;
Serial.println("Boot count: " + String(bootCount));
// ตื่นจากอะไร?
print_wakeup_reason();
// เริ่มใช้งานเซ็นเซอร์
dht.begin();
// เชื่อมต่อ WiFi
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
// รอเชื่อมต่อ (แต่ตั้ง timeout ไว้ 10 วินาที)
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected!");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// วัดค่าเซ็นเซอร์
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (!isnan(temperature) && !isnan(humidity)) {
Serial.println("Temperature: " + String(temperature) + "°C");
Serial.println("Humidity: " + String(humidity) + "%");
// ส่งข้อมูลไปยังเซิร์ฟเวอร์ (CynoIoT, MQTT, ฯลฯ)
// send_data_to_server(temperature, humidity);
} else {
Serial.println("Failed to read from DHT sensor!");
}
// ตัดการเชื่อมต่อ WiFi
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
} else {
Serial.println("\nWiFi connection failed!");
}
// ตั้งค่า Deep Sleep
Serial.println("Going to sleep now...");
Serial.flush();
// ตื่นทุกๆ 5 นาที
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
// เข้าโหมด Deep Sleep
esp_deep_sleep_start();
}
// ลูปหลัก (จะไม่ถูกเรียกใช้เมื่อใช้ Deep Sleep)
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;
}
}✅ ผลลัพธ์: ด้วยโค้ดนี้ ESP32 จะตื่นทุกๆ 5 นาที เชื่อมต่อ WiFi วัดค่าเซ็นเซอร์ ส่งข้อมูล แล้วกลับเข้า Deep Sleep อีกครั้ง แบต 2000mAh สามารถใช้งานได้นาน 6-8 เดือน!
ใช้ RTC Memory เก็บข้อมูลระหว่าง Sleep
RTC Memory เป็นหน่วยความจำพิเศษที่ข้อมูลจะไม่หายเมื่อ ESP32 เข้า Deep Sleep เหมาะสำหรับเก็บ:
- ตัวนับ (counter) จำนวนครั้งที่ตื่น
- ข้อมูลเซ็นเซอร์สะสม
- การตั้งค่าต่างๆ
- ข้อมูลที่ต้องนำไปใช้ต่อในครั้งต่อไป
// ตัวแปรใน RTC Memory - จะไม่หายเมื่อ Deep Sleep
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float totalTemperature = 0;
RTC_DATA_ATTR int readingsCount = 0;
void setup() {
bootCount++;
// วัดอุณหภูมิ
float temp = readTemperature();
totalTemperature += temp;
readingsCount++;
// คำนวณค่าเฉลี่ย
float avgTemp = totalTemperature / readingsCount;
Serial.println("Boot #" + String(bootCount));
Serial.println("Avg Temperature: " + String(avgTemp) + "°C");
// ทำงานอื่นๆ...
// เข้า Deep Sleep
esp_deep_sleep_start();
}💡 หมายเหตุ: RTC Memory มีขนาดจำกัด (~8KB) ใช้เฉพาะข้อมูลสำคัญเท่านั้น หากต้องการเก็บข้อมูลมากๆ ให้ใช้ SPIFFS หรือส่งไปเซิร์ฟเวอร์
Ultra Deep Sleep: ประหยัดพลังงานสูงสุด
นอกจาก Deep Sleep แล้ว ESP32 ยังมี Hibernate Mode ที่ประหยัดพลังงานมากกว่า โดยจะปิดทุกอย่างรวมถึง RTC Memory:
🔋 เปรียบเทียบ Deep Sleep vs Hibernate
| คุณสมบัติ | Deep Sleep | Hibernate |
|---|---|---|
| กระแสไฟ | ~10 µA | ~2.5 µA |
| RTC Memory | ✅ ใช้ได้ | ❌ หาย |
| ตื่นด้วย Timer | ✅ ได้ | ✅ ได้ |
| แบต 2000mAh | ~6 เดือน | >2 ปี |
// เปิดใช้ Hibernate Mode
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);
// เข้า Hibernate
esp_deep_sleep_start();เทคนิคเพิ่มเติม: ให้ใช้แบตนานขึ้น
1️⃣ ปิด WiFi/Bluetooth ทันทีที่ใช้เสร็จ
WiFi ใช้พลังงานมาก ปิดทันทีด้วย WiFi.mode(WIFI_OFF) และ btStop()
2️⃣ ลดความสว่าง LED
ปิด LED บนบอร์ดด้วย btStop() หรือตั้งค่าใน preferences.txt
3️⃣ ลด Clock Speed
ลดความเร็ว CPU เหลือ 80MHz ด้วย setCpuFrequencyMhz(80) ประหยัดไฟ ~20%
4️⃣ ใช้แบต Lipo พร้อมโมดูลชาร์จ
ใช้ TP4056 หรือ DW01+ เพื่อป้องกันแบตเสีย และรองรับการชาร์จ
5️⃣ ตั้งเวลาตื่นให้เหมาะสม
ตื่นน้อยครั้ง = ใช้แบตนานขึ้น เช่น ทุก 10 นาทีแทนทุก 5 นาที
แก้ปัญหาที่พบบ่อย
❌ ปัญหา: ESP32 ไม่ยอมเข้า Deep Sleep
สาเหตุ: ยังมี WiFi/Bluetooth เปิดอยู่
วิธีแก้: ปิด WiFi ก่อนด้วย WiFi.mode(WIFI_OFF) และ btStop()
❌ ปัญหา: ข้อมูลในตัวแปรหาย
สาเหตุ: ไม่ได้ใช้ RTC Memory
วิธีแก้: ใช้ RTC_DATA_ATTR นำหน้าตัวแปร
❌ ปัญหา: ใช้แบตเร็วเกินไป
สาเหตุ: ตื่นบ่อยเกินไปหรือใช้ WiFi นานเกินไป
วิธีแก้: เพิ่มเวลานอน หรือใช้ WiFi.setSleep(true)
❌ ปัญหา: ตรวจสอบไม่ได้ว่าตื่นจากอะไร
สาเหตุ: ไม่ได้เรียกฟังก์ชันตรวจสอบ
วิธีแก้: ใช้ esp_sleep_get_wakeup_cause() เหมือนในตัวอย่าง
สรุป
Deep Sleep Mode เป็นเทคนิคสำคัญที่ทำให้โปรเจกต์ IoT ของคุณใช้งานได้นานเป็นเดือนหรือเป็นปี ด้วยแบตเตอรี่เพียงก้อนเดียว
สิ่งสำคัญที่ต้องจำ:
- Deep Sleep ลดการใช้พลังงานลงเหลือ ~10 µA
- ใช้
RTC_DATA_ATTRเก็บข้อมูลระหว่าง Sleep - ปิด WiFi/Bluetooth ทันทีที่ใช้เสร็จ
- ตั้งเวลาตื่นให้เหมาะกับการใช้งาน
- ทดสอบอย่างละเอียดก่อนนำไปใช้งานจริง
🎯 โปรเจกต์ถัดไปที่แนะนำ
- • ระบบรดน้ำอัตโนมัติ: ใช้ Deep Sleep + เซ็นเซอร์ความชื้นดิน
- • เครื่องวัด Air Quality: วัดค่าทุกๆ 15 นาที ส่งข้อมูลไป CynoIoT
- • ติดตามพัสดุ: ใช้ GPS + Deep Sleep ส่งพิกัดเมื่อมีการเคลื่อนไหว