คู่มือ ESP32 Deep Sleep: ทำโปรเจกต์ IoT ใช้แบตเตอรี่นานเป็นปี

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

📅 22 มีนาคม 2026⏱️ 15 นาที🎯 Intermediate

📋 ทำไมต้อง 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 Sleep5-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 ที่เหมาะสม
  • ✅ คำนวณและทดสอบกระแสไฟจริง

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