เนื้อหาในบทความ
📋 ทำไมต้อง Deep Sleep?
Deep Sleep Mode เป็นเทคนิคสำคัญที่ทำให้ ESP32 สามารถลดการใช้พลังงานลงเหลือเพียง 5-10 µA (ไมโครแอมป์) เทียบกับโหมดปกติที่ใช้ 150-240 mA (มิลลิแอมป์) — ลดลงมากกว่า 15,000 เท่า!
ด้วยการใช้ Deep Sleep อย่างเหมาะสม โปรเจกต์ IoT ของคุณสามารถทำงานได้:
- 🔋 เดือน ถึง ปี บนแบตเตอรี่เพียงก้อนเดียว
- 📡 ส่งข้อมูลเซ็นเซอร์เป็นระยะ (เช่น ทุก 5-15 นาที)
- 🌱 ลดต้นทุนพลังงานและการบำรุงรักษา
- 🌍 เหมาะสำหรับโปรเจกต์ตรวจวัดระยะไกล, สถานที่ไม่มีไฟฟ้า
💡 ตัวอย่างจริง: โหนดเซ็นเซอร์ ESP32 ที่ตื่นทุก 10 นาที (5 วินาทีต่อครั้ง) สามารถทำงานได้ 8-12 เดือน บนแบตเตอรี่ LiPo 2000mAh
⚡ โหมดพลังงานของ ESP32
ESP32 มีหลายโหมดพลังงานให้เลือกใช้ตามความเหมาะสมของแต่ละโปรเจกต์:
| โหมด | กระแสไฟ | การตื่น | ใช้เมื่อ |
|---|---|---|---|
| Active (WiFi/BT) | 150-240 mA | - | กำลังส่งข้อมูล |
| Modem Sleep | ~20 mA | ทันที | ประมวลผลแต่ไม่สื่อสาร |
| Light Sleep | ~0.8 mA | ~2 ms | ต้องการตื่นเร็ว |
| Deep Sleep | 5-10 µA | ~100 ms | โปรเจกต์ประหยัดพลังงาน ⭐ |
| Hibernation | ~2.5 µA | ~250 ms | ปิดเกือบสิ้นเชิง |
⚠️ ข้อควรระวัง: Deep Sleep จะรีเซ็ต CPU และหยุดการทำงานของโปรแกรม ข้อมูลใน RAM จะหายไป ยกเว้นตัวแปรที่เก็บใน RTC Memory (8KB)
😴 พื้นฐาน Deep Sleep
การตื่นจาก Deep Sleep (Wake-up Sources)
ESP32 สามารถตื่นจาก Deep Sleep ได้หลายวิธี:
- Timer - ตั้งเวลาตื่นเอง (เช่น ทุก 10 นาที)
- Touch - สัมผัสที่ขา Touch Pin
- EXT0 / EXT1 - การเปลี่ยนสถานะขา GPIO
- ULP - โปรแกรม ULP ปลุกเมื่อเงื่อนไขตรง
- Timer + ULP - ผสมผสานเพื่อประหยัดพลังงานสูงสุด
โค้ดพื้นฐาน Deep Sleep
#include <esp_sleep.h>
// ตั้งเวลานอน (หน่วย: ไมโครวินาที)
#define SLEEP_DURATION_US 10 * 60 * 1000000 // 10 นาที
// ตัวแปรที่เก็บใน RTC Memory (จะไม่หายเมื่อนอน)
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR float lastSensorValue = 0.0;
void setup() {
Serial.begin(115200);
// นับจำนวนครั้งที่บูต
bootCount++;
Serial.println("Boot count: " + String(bootCount));
// --- โค้ดของคุณที่นี่ ---
// 1. อ่านเซ็นเซอร์
// 2. เชื่อมต่อ WiFi
// 3. ส่งข้อมูลไป CynoIoT
// -----------------------
Serial.println("เข้าสู่ Deep Sleep 10 นาที...");
Serial.println("แล้วเจอกันใหม่! zZZ");
// เข้าสู่ Deep Sleep
esp_deep_sleep(SLEEP_DURATION_US);
}
void loop() {
// ไม่มีอะไรทำที่นี่ เพราะ Deep Sleep จะรีเซ็ต
} 💡 เคล็ดลับ: ใช้ RTC_DATA_ATTR สำหรับตัวแปรที่ต้องการเก็บค่าระหว่างการนอน เช่น boot counter, ค่าเซ็นเซอร์ล่าสุด, หรือสถานะของระบบ
🔄 ULP Coprocessor: ตัวช่วยประหยัดพลังงาน
ULP (Ultra Low Power) Coprocessor เป็นโปรเซสเซอร์เล็กๆ ที่ทำงานแยกจาก CPU หลัก สามารถอ่านเซ็นเซอร์ได้ขณะที่ ESP32 กำลังนอนอยู่ โดยใช้กระแสเพียง ~5 µA
ข้อดีของ ULP
- 📊 อ่านเซ็นเซอร์ ADC ได้โดยไม่ต้องปลุก CPU
- 💾 เก็บข้อมูลไว้ใน RTC memory
- ⏰ ปลุก CPU เมื่อค่าเซ็นเซอร์ผิดปกติ
- 🔋 ประหยัดแบตเตอรี่มากกว่าการตื่นเอง
ตัวอย่าง: ใช้ ULP อ่านเซ็นเซอร์อุณหภูมิ
#include <esp_sleep.h>
#include <ulp.h>
#include <ulp_common.h>
// ตัวแปรที่ ULP เข้าถึงได้
RTC_DATA_ATTR float ulpTemperature;
// โค้ด ULP Assembly (ตัวอย่างง่าย)
const ulp_insn_t program[] = {
// อ่านค่า ADC ที่ขา GPIO36
I_ADC(0, 0, 0, 36), // ADC ช่อง 0
M_BL(3, 1), // Branch if less than threshold
I_WAKE(), // Wake CPU if threshold exceeded
I_HALT() // Stop ULP
};
void setup() {
Serial.begin(115200);
// ตั้งค่า ULP
ulp_set_wakeup_period(0, 60 * 1000000); // ทำงานทุก 60 วินาที
// โหลดและเริ่ม ULP program
ulp_load_binary_program(0, program, sizeof(program) / sizeof(ulp_insn_t));
ulp_run();
// เข้าสู่ Deep Sleep
esp_deep_sleep_start();
}
void loop() {
// ULP จะทำงานอัตโนมัติ
}🚀 Tip: การใช้ ULP ช่วยให้โปรเจกต์ของคุณทำงานได้ 2-5 เท่านานกว่า เดิม เพราะ CPU ไม่ต้องตื่นทุกครั้งที่อ่านเซ็นเซอร์
🔧 เทคนิค Hardware สำคัญ
1. ตัดไฟเซ็นเซอร์ด้วย MOSFET
เซ็นเซอร์บางตัว (เช่น DHT22, BME280) กินไฟมาก ควรตัดไฟเวลานอน:
// ขา GPIO ควบคุม MOSFET (เช่น GPIO4)
#define SENSOR_POWER_PIN 4
void setup() {
pinMode(SENSOR_POWER_PIN, OUTPUT);
// เปิดไฟเซ็นเซอร์
digitalWrite(SENSOR_POWER_PIN, HIGH);
delay(100); // รอให้เซ็นเซอร์พร้อม
// อ่านค่าเซ็นเซอร์
float temp = readTemperature();
// ปิดไฟเซ็นเซอร์
digitalWrite(SENSOR_POWER_PIN, LOW);
// ส่งข้อมูลและนอน
sendData(temp);
esp_deep_sleep_start();
}2. เลือก Voltage Regulator ที่เหมาะสม
บอร์ด ESP32 บางบอร์ดใช้ LDO ที่กินไฟมาก (10-20 mA) ควร:
- ใช้ HT7333, MCP1700 (2-6 µA quiescent current)
- หรือจ่ายไฟ 3.3V โดยตรง (ข้าม LDO บนบอร์ด)
- หลีกเลี่ยงบอร์ดที่มี LED ติดอยู่ตลอดเวลา
3. ปิดทุกอย่างที่ไม่จำเป็น
- ปิด LED บนบอร์ด (ถอนหลอดไฟ)
- ปิด USB-to-UART chip ด้วยการต่อขา EN เป็น LOW
- ใช้เซ็นเซอร์ที่รองรับ Single-ended measurement
- หลีกเลี่ยง Shield หรือ HAT ที่ไม่จำเป็น
⚠️ จุดผิดพลาดทั่วไป: ESP32 บน breadboard ที่มี LED ติดอยู่อาจกินไฟ 10 mA ตลอดเวลา ทำให้แบตเตอรี่หมดภายในไม่กี่วัน!
💻 รูปแบบ Firmware ที่ดี
Pattern 1: Wake, Read, Sleep
รูปแบบง่ายที่สุด: ตื่น → อ่านเซ็นเซอร์ → ส่งข้อมูล → นอน
void setup() {
// 1. เชื่อมต่อ WiFi (เวลา: ~2 วินาที)
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(10);
}
// 2. อ่านเซ็นเซอร์ (เวลา: ~100 ms)
float temp = readTemperature();
float hum = readHumidity();
// 3. ส่งข้อมูลไป CynoIoT (เวลา: ~2 วินาที)
sendToCynoIoT(temp, hum);
// 4. ตัด WiFi และนอน
WiFi.disconnect(true);
esp_deep_sleep(10 * 60 * 1000000); // 10 นาที
}Pattern 2: Smart Wake (ULP + WiFi)
ใช้ ULP ตรวจสอบค่าเซ็นเซอร์ และปลุก CPU เมื่อจำเป็น:
RTC_DATA_ATTR bool urgentWakeup = false;
void setup() {
if (urgentWakeup) {
// อ่านค่าเซ็นเซอร์และส่งแบบด่วน
sendUrgentAlert();
} else {
// ตื่นตามปกติ (ทุก 10 นาที)
sendRegularUpdate();
}
esp_deep_sleep_start();
}✅ ผลลัพธ์: รูปแบบที่ 2 สามารถลดการใช้พลังงานลงได้อีก 50-70% เพราะ WiFi ไม่ต้องทำงานทุกครั้ง
🔋 คำนวณแบตเตอรี่
สูตรคำนวณ
1. คำนวณกระแสเฉลี่ย:
Avg_Current = (Active_Current × Active_Time) + (Sleep_Current × Sleep_Time)
2. คำนวณอายุการใช้งาน:
Battery_Life (hours) = Battery_Capacity (mAh) / Avg_Current (mA)
3. แปลงเป็นวัน:
Battery_Life (days) = Battery_Life (hours) / 24ตัวอย่าง: โปรเจกต์จริง
| พารามิเตอร์ | ค่า |
|---|---|
| แบตเตอรี่ | 2000 mAh (LiPo) |
| กระแสตื่น (Active) | 120 mA ใช้ 5 วินาที |
| กระแสนอน (Deep Sleep) | 10 µA ใช้ 595 วินาที |
| กระแสเฉลี่ย | ≈ 0.03 mA |
| อายุการใช้งาน | ≈ 2,700 ชั่วโมง (≈ 112 วัน) |
เคล็ดลับเพิ่มอายุแบตเตอรี่
- ลดเวลาตื่น (Active Time) ให้น้อยที่สุด
- เพิ่มระยะห่างระหว่างการตื่น (Sleep Time)
- ใช้ ULP อ่านเซ็นเซอร์แทน CPU
- เลือกแบตเตอรี่ขนาดใหญ่ขึ้น (เช่น 18650 3000-3500 mAh)
- พิจารณาใช้พลังงานแสงอาทิตย์ + Solar Charger
🔨 ปัญหาที่พบบ่อยและวิธีแก้ไข
❌ ปัญหา: ESP32 กินไฟ 10 mA ใน Deep Sleep
สาเหตุ: บอร์ดบางรุ่นมี LDO หรือ LED ที่กินไฟ
วิธีแก้: ถอน LED, ใช้ LDO ที่ดีกว่า (HT7333), หรือจ่ายไฟ 3.3V โดยตรง
❌ ปัญหา: WiFi เชื่อมต่อไม่ได้หลังจากตื่น
สาเหตุ: WiFi เริ่มต้นช้าเกินไป
วิธีแก้: ใช้ WiFi.setSleep(false) หรือเพิ่ม retry loop
❌ ปัญหา: ข้อมูล RTC_DATA_ATTR หาย
สาเหตุ: เก็บข้อมูลเกิน 8KB
วิธีแก้: ลดจำนวนตัวแปร RTC_DATA_ATTR หรือใช้ SPIFFS/NVS
❌ ปัญหา: ESP32 ไม่ยอมนอน
สาเหตุ: ยังมี Serial Monitor หรือ USB เชื่อมต่ออยู่
วิธีแก้: ตัด USB, ใช้แหล่งจ่ายไซ์ภายนอก, หรือต่อขา EN เป็น LOW
✅ สรุป
การใช้ Deep Sleep อย่างเหมาะสมสามารถทำให้โปรเจกต์ ESP32 IoT ของคุณทำงานได้นานเป็นเดือนหรือหลายปีบนแบตเตอรี่เพียงก้อนเดียว:
- ✅ Deep Sleep ลดกระแสจาก 150 mA เหลือ 5-10 µA
- ✅ ใช้ ULP Coprocessor อ่านเซ็นเซอร์โดยไม่ต้องปลุก CPU
- ✅ ตัดไฟเซ็นเซอร์ด้วย MOSFET เวลานอน
- ✅ เลือกบอร์ดและ Voltage Regulator ที่เหมาะสม
- ✅ คำนวณและทดสอบกระแสไฟจริง