Pin mặt trời mini cho ESP32: chọn tấm pin, mạch sạc, pin 18650, ngủ sâu và tính năng lượng mỗi ngày
ESP32 chạy bằng pin mặt trời: các khối tấm pin, mạch sạc, pin 18650, ổn áp; tính năng lượng tiêu thụ và thu được mỗi ngày; chương trình ngủ sâu đo điện áp pin, tấm pin; lắp đặt ngoài trời.
Trạm đo ngoài vườn, cảm biến mực nước ở ao, thiết bị báo trộm ở rẫy: những nơi không có ổ điện cần một nguồn tự lo được. Một tấm pin mặt trời nhỏ, một viên pin 18650 và chế độ ngủ sâu của ESP32 đủ để thiết bị chạy quanh năm, nếu tính đúng năng lượng ngay từ đầu. Bài này đi qua các khối của hệ thống, cách tính năng lượng tiêu thụ và thu được mỗi ngày, chương trình ESP32 thức dậy định kỳ đo điện áp pin và tấm pin, cách lắp đặt ngoài trời và các lỗi hay gặp.
1. Khi nào dùng pin mặt trời

Pin mặt trời hợp với thiết bị tiêu thụ ít, làm việc ngắt quãng: đo nhiệt độ, độ ẩm đất, mực nước mỗi 10–30 phút rồi gửi số liệu. Thiết bị chạy liên tục như camera, máy bơm cần tấm pin và ắc quy lớn hơn nhiều, nằm ngoài phạm vi bài này.
2. Các khối của hệ thống

- Tấm pin 5–6 V: hợp để sạc một cell Li-ion (4,2 V). Điện áp hở mạch của tấm 6 V thường khoảng 7 V; kiểm tra mạch sạc chịu được mức đó.
- Mạch sạc 1S có bảo vệ: sạc pin đúng chuẩn 4,2 V và ngắt khi pin quá cạn. Mạch sạc tuyến tính đơn giản dùng được với tấm nhỏ; mạch có dò điểm công suất cực đại (MPPT) lấy được nhiều năng lượng hơn khi trời âm u. Kiểm tra mạch sạc có chặn dòng ngược từ pin về tấm pin ban đêm không; nếu không thì thêm một diode Schottky.
- Pin 18650: 3,0–4,2 V, thường 2000–3000 mAh. Xem sạc pin Li-ion 1S an toàn.
- Ổn áp 3,3 V dòng chờ nhỏ: đây là chỗ hay bị bỏ quên. Bo DevKit V1 dùng ổn áp và chip USB tiêu thụ vài mA kể cả khi ESP32 ngủ, lớn hơn chính ESP32 hàng trăm lần.
3. Tính năng lượng trước khi lắp

Tính theo mAh mỗi ngày, với ví dụ trong hình:
- Số lần thức: 24 × 60 / 10 = 144 lần. Mỗi lần 3 giây ở khoảng 120 mA: 144 × 3 × 120 / 3600 = 14,4 mAh.
- Thời gian ngủ còn lại khoảng 23,9 giờ. Bo DevKit ngủ khoảng 8 mA: thêm 191 mAh, tổng khoảng 205 mAh/ngày. Bo tối ưu ngủ 0,05 mA: thêm 1,2 mAh, tổng khoảng 15,6 mAh/ngày.
- Tấm pin 6 V 1 W cho khoảng 167 mA khi nắng tốt. Với 3,5 giờ nắng tương đương mỗi ngày và hệ số thực tế 0,7 (góc nghiêng, bụi, nhiệt độ, tổn hao mạch sạc): khoảng 408 mAh ngày nắng; ngày mưa chỉ còn khoảng 15%, tức 61 mAh.

Kết luận từ ví dụ: ngày nắng thì cả hai cách đều đủ điện, nhưng một tuần mưa liền bo DevKit sẽ cạn pin (ngày mưa chỉ thu 61 mAh, tiêu tới 205 mAh). Bo tối ưu chạy hơn 4 tháng không cần nắng. Hai quy tắc chọn:
- Năng lượng thu được ngày nắng nên gấp 3–5 lần năng lượng tiêu thụ.
- Pin đủ cho số ngày mưa liên tiếp dài nhất ở nơi lắp (ví dụ 7 ngày), cộng thêm phần dự phòng.
Giảm tiêu thụ thường rẻ hơn tăng tấm pin: thức thưa hơn, bật Wi-Fi ngắn hơn (gửi gộp nhiều số đo một lần), dùng bo không có chip USB và đèn nguồn, hoặc tháo đèn nguồn.
4. Chương trình: thức, đo, ngủ
Chương trình chỉ dùng gói ESP32 cho Arduino IDE. Mỗi lần thức, ESP32 đo điện áp pin (GPIO34) và tấm pin (GPIO35) qua cầu phân áp, nhớ số lần thức và điện áp thấp nhất trong bộ nhớ RTC (vẫn giữ khi ngủ sâu), làm việc chính nếu pin đủ, rồi ngủ 10 phút; pin dưới 3,5 V thì ngủ 1 giờ để tiết kiệm.
// PYWORLD.VN - ESP32 chạy pin 18650 sạc bằng pin mặt trời: thức dậy định kỳ, đo điện áp pin và tấm pin, rồi ngủ sâu
// PYWORLD.VN - Pin yếu thì ngủ lâu hơn và bỏ qua việc tốn điện; số lần thức, điện áp thấp nhất giữ trong bộ nhớ RTC
// PYWORLD.VN - Cầu phân áp: pin -> 100k -> GPIO34 -> 100k -> GND; tấm pin -> 200k -> GPIO35 -> 100k -> GND (thêm tụ 100 nF ở mỗi chân ADC)
const int CHAN_DO_PIN = 34; // ADC1, dùng được khi bật Wi-Fi
const int CHAN_DO_TAM_PIN = 35; // ADC1
const float HE_SO_PIN = 2.0f; // (100k + 100k) / 100k
const float HE_SO_TAM_PIN = 3.0f; // (200k + 100k) / 100k
const int SO_LAN_DO = 16;
const uint32_t NGU_BINH_THUONG_S = 600; // 10 phút
const uint32_t NGU_PIN_YEU_S = 3600; // 1 giờ
const uint32_t NGUONG_PIN_YEU_MV = 3500; // dưới mức này ngủ lâu hơn
const uint32_t NGUONG_BO_VIEC_MV = 3300; // dưới mức này chỉ đo rồi ngủ, không làm việc tốn điện
const uint32_t CHENH_DANG_SAC_MV = 300; // tấm pin cao hơn pin chừng này thì coi như đang có nắng
RTC_DATA_ATTR uint32_t soLanThuc = 0; // bộ nhớ RTC còn giữ khi ngủ sâu
RTC_DATA_ATTR uint32_t pinThapNhatMv = 9999;
uint32_t doTrungBinhMv(int chan) {
uint32_t tong = 0;
for (int i = 0; i < SO_LAN_DO; i++) {
tong += analogReadMilliVolts(chan);
}
return tong / SO_LAN_DO;
}
void lamViecChinh() {
// Việc chính của thiết bị đặt ở đây: đọc cảm biến, bật Wi-Fi gửi số liệu...
delay(50);
}
void setup() {
Serial.begin(115200);
delay(20);
soLanThuc = soLanThuc + 1;
uint32_t pinMv = (uint32_t)(doTrungBinhMv(CHAN_DO_PIN) * HE_SO_PIN);
uint32_t tamPinMv = (uint32_t)(doTrungBinhMv(CHAN_DO_TAM_PIN) * HE_SO_TAM_PIN);
if (pinMv < pinThapNhatMv) pinThapNhatMv = pinMv;
bool coNang = tamPinMv > pinMv + CHENH_DANG_SAC_MV;
Serial.printf("Lan thuc %u: pin %u mV (thap nhat %u mV), tam pin %u mV, %s\n", (unsigned)soLanThuc, (unsigned)pinMv,
(unsigned)pinThapNhatMv, (unsigned)tamPinMv, coNang ? "co nang" : "khong nang");
if (pinMv >= NGUONG_BO_VIEC_MV) {
lamViecChinh();
} else {
Serial.println("Pin qua yeu: bo qua viec chinh");
}
uint32_t thoiGianNgu = (pinMv < NGUONG_PIN_YEU_MV) ? NGU_PIN_YEU_S : NGU_BINH_THUONG_S;
Serial.printf("Ngu %u giay\n", (unsigned)thoiGianNgu);
Serial.flush();
esp_sleep_enable_timer_wakeup((uint64_t)thoiGianNgu * 1000000ULL);
esp_deep_sleep_start();
}
void loop() {
// Không dùng: mỗi lần thức chương trình chạy lại từ setup()
}
RTC_DATA_ATTR: biến nằm trong bộ nhớ RTC, không bị xóa khi ngủ sâu (nhưng mất khi mất điện hẳn).analogReadMilliVolts()đã hiệu chỉnh theo từng chip, nhưng vẫn có thể lệch vài chục mV: đo pin bằng đồng hồ vạn năng rồi chỉnhHE_SO_PINcho khớp. Xem đọc ADC và đo điện áp pin 18650.- "co nang" chỉ là ước đoán: tấm pin cao hơn pin từ 300 mV trở lên.
- Cầu phân áp 100k + 100k vẫn tiêu thụ khoảng 20 µA liên tục từ pin; với bo thật tối ưu, có thể dùng điện trở lớn hơn hoặc một MOSFET ngắt cầu khi ngủ.

Để xem dòng in, cắm USB và mở Serial Monitor trước khi ESP32 thức dậy. Khi cắm USB, bo được cấp điện từ máy tính nên đo dòng tiêu thụ phải làm lúc rút USB.
5. Lắp đặt ngoài trời
- Hướng và góc: ở Việt Nam, đặt tấm pin hướng về phía nam, nghiêng khoảng 10–20°; nghiêng còn giúp nước mưa cuốn bụi.
- Không che bóng: một vệt bóng cây nhỏ cũng làm dòng của tấm pin giảm mạnh.
- Nhiệt độ: hộp kín phơi nắng có thể nóng trên 60 °C; pin Li-ion không nên sạc khi quá 45 °C. Đặt hộp pin trong bóng râm (phía sau tấm pin), sơn màu sáng, có lỗ thông hơi chống côn trùng.
- Chống nước: hộp có gioăng, đầu dây đi từ dưới lên, dùng đầu nối chống nước.
6. Lỗi hay gặp
| Hiện tượng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
| Có nắng nhưng pin vẫn cạn dần | Bo ngủ tốn vài mA; tấm pin bị che; mạch sạc không nhận nguồn từ tấm pin | Đo dòng khi ngủ; đổi bo tối ưu; đo điện áp tấm pin lúc nắng |
| ESP32 khởi động lại khi bật Wi-Fi | Pin yếu, ổn áp không đủ dòng đỉnh | Thêm tụ 470 µF gần chân 3,3 V; chặn việc chính khi pin dưới ngưỡng |
| Điện áp đo lệch đồng hồ | Sai số điện trở, ADC | Hiệu chỉnh hệ số; thêm tụ 100 nF ở chân ADC |
| Pin phồng, nóng | Sạc ở nhiệt độ cao, mạch sạc kém | Che nắng cho hộp pin; dùng mạch sạc có bảo vệ |
| Đêm pin tụt nhanh hơn tính toán | Dòng ngược qua tấm pin, dòng của cầu phân áp | Kiểm tra chặn dòng ngược; dùng điện trở phân áp lớn hơn |
7. Xem thêm
- Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn
- Cấp nguồn ESP32 bằng pin 18650 sạc qua jack Type-C
- Mạch có sẵn pin và mạch sạc: mô-đun ESP32 tích hợp pin 18650 và mạch quản lý pin, mô-đun pin 18650, khay pin 18650.
- Các bài cùng loạt năng lượng: sạc pin 18650 đúng cách, đo dung lượng pin 18650.
Xem thêm