Cấp nguồn cho ESP32 đúng cách: cổng USB, chân VIN, 3V3, pin 18650 và lỗi brownout khi bật Wi-Fi

Cấp nguồn cho ESP32 qua cổng USB, chân VIN, 3V3, từ adapter hay pin 18650; vì sao ESP32 tự khởi động lại khi bật Wi-Fi (brownout) và chương trình đo sụt áp nguồn.

ESP32 chạy được hay không, chạy có ổn định hay không, phần lớn phụ thuộc vào nguồn cấp. Lỗi hay gặp nhất là mạch tự khởi động lại mỗi khi bật Wi-Fi, Serial Monitor hiện dòng Brownout detector was triggered. Bài này tổng hợp các cách cấp nguồn cho mạch ESP32 DevKit: qua cổng USB, chân VIN (bản 38 chân là chân 5V), chân 3V3, từ adapter, từ pin 18650; giải thích lỗi sụt áp (brownout) và kèm một chương trình để tự đo xem nguồn đang dùng có đủ khỏe hay không.

1. Đường nguồn trên mạch ESP32 DevKit

Sơ đồ đường nguồn trên mạch ESP32 DevKit: cổng USB 5 V qua diode tới chân VIN, IC ổn áp tuyến tính hạ xuống 3,3 V ở chân 3V3 rồi cấp cho module ESP32-WROOM
Ba chỗ có thể đưa nguồn vào mạch ESP32 DevKit (hình minh họa).

Chip ESP32 chạy ở 3,3 V. Trên mạch DevKit, 5 V từ cổng USB đi qua một diode tới đường 5 V (nối ra chân VIN), rồi qua IC ổn áp tuyến tính (thường là loại AMS1117-3.3) hạ xuống 3,3 V nối ra chân 3V3. Như vậy có ba chỗ đưa nguồn vào:

  • Cổng USB: cách tiện nhất. Dùng củ sạc 5 V từ 1 A trở lên và cáp ngắn, dây to. Cổng USB 2.0 của máy tính chỉ đảm bảo 500 mA, đủ để nạp code và chạy thử, có thể thiếu khi bật Wi-Fi kèm cảm biến, màn hình.
  • Chân VIN (bản 38 chân là chân 5V): cấp 5 V ổn định. IC ổn áp tuyến tính cần điện áp vào cao hơn 3,3 V khoảng 1–1,3 V, nên dưới khoảng 4,5 V là bắt đầu thiếu áp. Cao hơn 5 V thì phần dư biến thành nhiệt trên IC: công suất tỏa nhiệt bằng (điện áp vào − 3,3 V) × dòng. Ví dụ 12 V, 250 mA tỏa khoảng 2,2 W, quá nhiều cho IC dán nhỏ trên mạch.
  • Chân 3V3: chỉ dùng khi đã có nguồn 3,3 V ổn định (3,0–3,6 V) từ một IC ổn áp bên ngoài. Cách này bỏ qua IC ổn áp trên mạch. Khi cấp vào 3V3, không nối gì vào VIN; cắm cáp USB để nạp code thì tháo nguồn 3,3 V ngoài ra.

Hai cách sai hay gặp: đưa 12 V thẳng vào VIN, và nối pin 18650 thẳng vào 3V3 (pin đầy 4,2 V, vượt mức chip chịu được) hoặc vào VIN (pin 3,0–4,2 V, không đủ cho IC ổn áp tạo ra 3,3 V).

2. Chọn nguồn theo từng trường hợp

Bảng chọn nguồn cho ESP32: cáp USB máy tính, củ sạc 5 V, adapter 9–24 V qua mạch hạ áp, pin 18650 qua mạch tăng áp, khối pin 2S 3S, đế ra chân ESP32
Mỗi loại nguồn nối vào đâu (hình minh họa).
  • Adapter 9 V, 12 V, 24 V: qua mạch hạ áp DC-DC chỉnh 5 V rồi vào VIN. Mạch hạ áp gần như không nóng như IC ổn áp tuyến tính. Cách chọn và chỉnh mạch hạ áp xem bài chọn mạch hạ áp, tăng áp DC-DC và LM2596: cách chỉnh 5 V.
  • Pin 18650 một cell: tăng áp lên 5 V rồi vào VIN, hoặc dùng IC ổn áp 3,3 V loại sụt áp thấp rồi vào 3V3. Hai cách được so sánh chi tiết trong bài cấp nguồn ESP32 bằng pin 18650 sạc qua jack Type-C. Hoặc dùng luôn mạch ESP32 tích hợp đế pin 18650 và mạch quản lý pin.
  • Khối pin 2S, 3S: điện áp thay đổi từ khoảng 6 V tới 12,6 V theo mức pin, nên dùng mạch hạ áp DC-DC xuống 5 V.
  • Đế ra chân ESP32 30 chân: cắm adapter 6,5–16 V vào jack DC trên đế, IC ổn áp trên đế hạ xuống 5 V cho ESP32. Xem bài đế ra chân ESP32 30 chân.

Tải lớn lấy nguồn riêng. Relay, động cơ, servo, dải LED không lấy nguồn từ chân 3V3 hay VIN của ESP32; cấp từ nguồn riêng, chỉ nối chung GND với ESP32.

3. Lỗi brownout: ESP32 tự khởi động lại khi bật Wi-Fi

ESP32 có bộ phát hiện sụt áp (brownout detector). Khi điện áp nguồn của chip tụt xuống dưới một ngưỡng (với cấu hình mặc định của gói esp32 cho Arduino, khoảng 2,43 V theo tài liệu của Espressif), chip tự reset để tránh chạy sai hoặc ghi hỏng bộ nhớ flash. Serial Monitor hiện:

Brownout detector was triggered
Dạng điện áp 3,3 V của ESP32 khi phát Wi-Fi: nguồn tốt chỉ sụt nhẹ, nguồn yếu sụt dưới ngưỡng brownout và ESP32 khởi động lại
Sụt áp khi ESP32 phát Wi-Fi với nguồn tốt và nguồn yếu (hình minh họa, số liệu chọn để giải thích).

Nguyên nhân là mỗi lần phát sóng Wi-Fi, ESP32 kéo dòng vài trăm mA trong thời gian rất ngắn. Nguồn yếu, cáp dài và mảnh, mối nối lỏng làm điện áp tụt theo từng xung dòng. Ví dụ cáp USB dây mảnh có điện trở tổng khoảng 0,5 Ω, xung 0,4 A làm sụt 0,2 V ngay trên dây cáp.

Cách khắc phục, làm lần lượt:

  1. Đổi nguồn và cáp: củ sạc 5 V từ 1 A trở lên, cáp ngắn và dày. Đây là nguyên nhân của phần lớn trường hợp.
  2. Thêm tụ: tụ hóa 470–1000 µF song song với tụ gốm 100 nF, đặt sát giữa chân VIN và GND.
  3. Tách nguồn tải: relay, servo, động cơ lấy nguồn riêng, không dùng chung với ESP32.
  4. Dùng mạch hạ áp đủ dòng khi cấp từ adapter hay pin, không dùng IC ổn áp tuyến tính nhỏ cho điện áp vào cao.
  5. Giảm công suất phát nếu thiết bị đặt gần bộ phát Wi-Fi: gọi WiFi.setTxPower(WIFI_POWER_15dBm) sau khi bật Wi-Fi. Đây là cách chữa cháy, không thay được việc sửa nguồn.

Không nên tắt bộ phát hiện sụt áp như một số hướng dẫn trên mạng: lỗi vẫn còn, chỉ là chip chạy tiếp khi điện áp không đủ, dễ treo, chạy sai hoặc hỏng dữ liệu trong flash.

4. Chương trình kiểm tra nguồn

Chương trình dưới đây giúp biết nguồn đang dùng có đủ khỏe hay không:

  • in lý do lần khởi động gần nhất, và đếm số lần reset do sụt áp kể từ lúc cấp nguồn;
  • đo điện áp chân VIN qua cầu phân áp hai điện trở 100 kΩ nối vào chân D34 (GPIO34);
  • cứ 5 giây quét Wi-Fi một lần (lúc ESP32 phát sóng nhiều nhất) và ghi lại mức VIN thấp nhất trong lúc quét.

Nối dây

Sơ đồ nối cầu phân áp hai điện trở 100 kΩ từ chân VIN xuống GND, điểm giữa vào chân D34 của ESP32 DevKit, tụ hóa 1000 µF giữa VIN và GND
Cầu phân áp đo VIN và tụ chống sụt áp (hình minh họa).
Linh kiệnNối
Điện trở R1 100 kΩtừ chân VIN tới điểm giữa
Điện trở R2 100 kΩtừ điểm giữa tới GND
Điểm giữachân D34 (GPIO34)
Tụ hóa 470–1000 µF (tùy chọn, để so sánh)cực + vào VIN, cực − vào GND, đặt sát mạch

GPIO34 thuộc bộ ADC1 nên vẫn đo được khi Wi-Fi đang bật (các chân ADC2 thì không). Điểm đo không gắn tụ, để bắt được những lần sụt áp ngắn.

Chương trình

Bài dùng gói esp32 phiên bản 3.3.10 trên Arduino IDE 2, không cần thư viện ngoài. Chọn bo mạch ESP32 Dev Module.

// PYWORLD.VN - Kiểm tra nguồn cấp cho ESP32: lý do khởi động lại và số lần reset do sụt áp (brownout)
// PYWORLD.VN - Đo điện áp chân VIN qua cầu phân áp 100 kΩ / 100 kΩ nối vào GPIO34
// PYWORLD.VN - Ghi mức VIN thấp nhất trong lúc ESP32 quét Wi-Fi, lúc phát sóng tốn dòng nhất

#include <WiFi.h>
#include "esp_system.h"
#include "esp_attr.h"

// Cầu phân áp hai điện trở 100 kΩ: VIN — 100 kΩ — GPIO34 — 100 kΩ — GND.
// Điện áp tại GPIO34 bằng một nửa VIN. GPIO34 thuộc ADC1 nên vẫn đo được khi bật Wi-Fi.
// Không gắn tụ ở điểm đo: tụ sẽ làm phẳng các lần sụt áp ngắn mà bài muốn bắt.
const int CHAN_DO_VIN = 34;
const uint32_t HE_SO_CAU = 2;               // VIN = điện áp tại chân đo × (100k + 100k) / 100k
const uint32_t NGUONG_CANH_BAO_MV = 4500;   // VIN dưới mức này là nguồn đã yếu

// Biến đặt trong vùng nhớ RTC không khởi tạo: giữ giá trị qua reset mềm và reset do sụt áp,
// mất khi rút nguồn. Dùng một số đánh dấu để biết giá trị đang giữ có hợp lệ hay không.
RTC_NOINIT_ATTR uint32_t danhDau;
RTC_NOINIT_ATTR uint32_t soLanBrownout;
const uint32_t DANH_DAU_HOP_LE = 0x50595744;

const char *tenLyDo(esp_reset_reason_t lyDo) {
  switch (lyDo) {
    case ESP_RST_POWERON:   return "cap nguon lan dau";
    case ESP_RST_SW:        return "khoi dong lai bang phan mem";
    case ESP_RST_PANIC:     return "loi chuong trinh (panic)";
    case ESP_RST_INT_WDT:
    case ESP_RST_TASK_WDT:
    case ESP_RST_WDT:       return "watchdog";
    case ESP_RST_DEEPSLEEP: return "thuc day tu ngu sau";
    case ESP_RST_BROWNOUT:  return "SUT AP (brownout)";
    default:                return "khac";
  }
}

// Đo VIN (mV): lấy trung bình 16 lần đo cho số ổn định
uint32_t doVinTrungBinh() {
  uint32_t tong = 0;
  for (int i = 0; i < 16; i++) {
    tong += analogReadMilliVolts(CHAN_DO_VIN);
  }
  return tong / 16 * HE_SO_CAU;
}

void setup() {
  Serial.begin(115200);
  delay(300);

  esp_reset_reason_t lyDo = esp_reset_reason();
  if (danhDau != DANH_DAU_HOP_LE || lyDo == ESP_RST_POWERON) {
    danhDau = DANH_DAU_HOP_LE;
    soLanBrownout = 0;
  }
  if (lyDo == ESP_RST_BROWNOUT) {
    soLanBrownout++;
  }

  Serial.println();
  Serial.printf("Ly do khoi dong: %s\n", tenLyDo(lyDo));
  Serial.printf("So lan sut ap tu luc cap nguon: %u\n", (unsigned)soLanBrownout);
  Serial.printf("VIN luc chua bat Wi-Fi: %u mV\n", (unsigned)doVinTrungBinh());
}

void loop() {
  WiFi.mode(WIFI_STA);
  uint32_t vinTruoc = doVinTrungBinh();
  uint32_t thapNhat = vinTruoc;

  // Quét Wi-Fi ở chế độ không chặn; trong lúc quét, đo VIN liên tục để bắt mức thấp nhất
  WiFi.scanNetworks(true);
  uint32_t dem = 0;
  while (WiFi.scanComplete() == WIFI_SCAN_RUNNING) {
    uint32_t v = analogReadMilliVolts(CHAN_DO_VIN) * HE_SO_CAU;
    if (v < thapNhat) {
      thapNhat = v;
    }
    if (++dem % 50 == 0) {
      delay(1);  // nhường CPU cho các tác vụ khác
    }
  }
  int soMang = WiFi.scanComplete();
  WiFi.scanDelete();
  WiFi.mode(WIFI_OFF);

  Serial.printf("Quet Wi-Fi: %d mang | VIN truoc %u mV, thap nhat %u mV, sut %u mV (%u lan do)\n",
                soMang, (unsigned)vinTruoc, (unsigned)thapNhat, (unsigned)(vinTruoc - thapNhat), (unsigned)dem);
  if (thapNhat < NGUONG_CANH_BAO_MV) {
    Serial.println("Canh bao: VIN xuong duoi 4,5 V khi phat Wi-Fi: nguon yeu, day dai hoac nho");
  }
  delay(5000);
}

Kết quả

Serial Monitor của chương trình kiểm tra nguồn ESP32: lý do khởi động là sụt áp, số lần brownout, điện áp VIN trước và trong khi quét Wi-Fi, cảnh báo nguồn yếu
Ví dụ kết quả với một nguồn yếu (hình minh họa, số liệu ví dụ).

Cách đọc kết quả:

  • Dòng "Ly do khoi dong" hiện "SUT AP (brownout)" nghĩa là lần khởi động vừa rồi do sụt áp. Số lần sụt áp tăng dần sau mỗi lần quét là nguồn đang không đủ.
  • Khi cấp qua cổng USB, VIN thường thấp hơn 5 V khoảng 0,2–0,4 V vì sụt áp trên diode và cáp.
  • Mức "sut" là độ sụt khi phát Wi-Fi. Nguồn tốt, cáp ngắn thường chỉ sụt vài chục tới khoảng 100 mV. Sụt vài trăm mV, hoặc VIN xuống dưới 4,5 V, là nguồn hay cáp đang yếu.
  • Thử lần lượt: đổi cáp, đổi củ sạc, thêm tụ 1000 µF, rồi so sánh mức sụt giữa các lần.

Giải thích các phần chính

  • esp_reset_reason() trả về lý do lần khởi động gần nhất; ESP_RST_BROWNOUT là reset do sụt áp.
  • RTC_NOINIT_ATTR đặt biến đếm vào vùng nhớ RTC không bị xóa khi reset mềm hay reset do sụt áp, chỉ mất khi rút nguồn. Số đánh dấu DANH_DAU_HOP_LE giúp nhận ra giá trị rác lúc mới cấp nguồn.
  • analogReadMilliVolts() đọc điện áp chân ADC đã hiệu chuẩn, đơn vị mV; nhân 2 để ra VIN vì cầu phân áp chia đôi.
  • WiFi.scanNetworks(true) quét Wi-Fi ở chế độ không chặn, nên vòng lặp vẫn đo được VIN liên tục trong lúc quét; delay(1) sau mỗi 50 lần đo để nhường CPU cho các tác vụ khác.

5. Lỗi thường gặp

Hiện tượngNguyên nhân hay gặpCách xử lý
Khởi động lại khi bật Wi-Fi, báo BrownoutNguồn yếu, cáp dài mảnhCủ sạc 1 A trở lên, cáp ngắn, thêm tụ 1000 µF
Khởi động lại khi relay hoặc động cơ chạyTải dùng chung nguồn với ESP32Cấp nguồn riêng cho tải, chỉ nối chung GND
IC ổn áp trên mạch rất nóngCấp 9–12 V vào VINDùng mạch hạ áp DC-DC xuống 5 V
Chạy pin 18650 được một lúc thì tắtNối pin vào VIN không qua tăng áp, pin xuống dưới khoảng 4,5 V là thiếuThêm mạch tăng áp 5 V hoặc ổn áp 3,3 V sụt áp thấp
Mạch nóng ran, chip hỏngNối 5 V hoặc pin 4,2 V vào chân 3V3Chân 3V3 chỉ nhận 3,0–3,6 V
Chạy bằng máy tính được, bằng củ sạc thì khôngCủ sạc kém, điện áp dao độngĐo bằng chương trình ở mục 4, thay củ sạc

6. Xem thêm

Cần tư vấn chọn nguồn cho thiết bị ESP32, liên hệ PYWORLD qua số 0915703319.


Tin tức liên quan

Cấu hình LoRa trên ESP32: SF, băng thông, tỉ lệ mã, công suất và cách thử tầm xa
Cấu hình LoRa trên ESP32: SF, băng thông, tỉ lệ mã, công suất và cách thử tầm xa

Giải thích bốn tham số cấu hình LoRa (SF, băng thông, tỉ lệ mã, công suất), cách tính thời gian phát một gói và hướng dẫn làm bộ thử tầm xa bằng ESP32, SX1278 và màn hình OLED.

Điều khiển relay từ xa bằng ESP-NOW: remote ESP32 một nút nhấn có phản hồi trạng thái
Điều khiển relay từ xa bằng ESP-NOW: remote ESP32 một nút nhấn có phản hồi trạng thái

Hướng dẫn làm bộ điều khiển relay từ xa bằng hai mạch ESP32 và ESP-NOW hai chiều: remote gửi lệnh, mạch relay báo lại trạng thái, lọc theo địa chỉ MAC và bật mã hóa.

Tự làm máy vẽ (pen plotter) 2 trục bằng ESP32 và động cơ bước, tự viết bộ đọc G-code
Tự làm máy vẽ (pen plotter) 2 trục bằng ESP32 và động cơ bước, tự viết bộ đọc G-code

Tự làm máy vẽ 2 trục với ESP32, hai A4988, NEMA 17 và servo nhấc bút; chương trình tự đọc G-code G0 G1 G2 G3, nội suy Bresenham có tăng tốc, script Python gửi file G-code.

Đóng relay làm ESP32, Arduino bị reset hoặc treo: nguyên nhân và cách khắc phục
Đóng relay làm ESP32, Arduino bị reset hoặc treo: nguyên nhân và cách khắc phục

Vì sao đóng relay làm ESP32, Arduino tự khởi động lại hoặc treo: sụt áp nguồn, xung cuộn dây, hồ quang tiếp điểm, chân khởi động; cách khắc phục và chương trình đo sụt áp.

Hướng dẫn dùng màn hình OLED 0.96 inch SSD1306 với Arduino Nano
Hướng dẫn dùng màn hình OLED 0.96 inch SSD1306 với Arduino Nano

Hướng dẫn nối màn hình OLED 0.96 inch SSD1306 (I2C) với Arduino Nano, cài thư viện Adafruit, hiện chữ nhiều cỡ, vẽ thanh mức theo điện áp và lưu ý về bộ nhớ RAM.

Cánh tay robot 4 servo với ESP32: điều khiển bằng biến trở, ghi nhớ và phát lại động tác
Cánh tay robot 4 servo với ESP32: điều khiển bằng biến trở, ghi nhớ và phát lại động tác

Làm cánh tay robot 4 servo với ESP32: điều khiển từng khớp bằng biến trở, nhấn nút ghi tư thế, phát lại chuỗi động tác mượt, lưu vào flash khi mất điện và gợi ý STEM.

Hướng dẫn bắt đầu với Arduino Nano CH340: sơ đồ chân, driver và nạp code
Hướng dẫn bắt đầu với Arduino Nano CH340: sơ đồ chân, driver và nạp code

Hướng dẫn bắt đầu với Arduino Nano CH340: sơ đồ chân, cài driver, chọn Board và Processor, nạp Blink, in ra Serial Monitor, quét I2C trên A4/A5, cấp nguồn và xử lý lỗi thường gặp.

Tưới cây tự động với ESP32: cảm biến độ ẩm đất, relay và bơm mini, ngưỡng có trễ
Tưới cây tự động với ESP32: cảm biến độ ẩm đất, relay và bơm mini, ngưỡng có trễ

Làm hệ thống tưới cây tự động với ESP32: cảm biến độ ẩm đất điện dung, hiệu chỉnh khô ướt, relay điều khiển bơm mini, ngưỡng có trễ, giới hạn thời gian bơm và thí nghiệm STEM.


Bình luận
Đã thêm vào giỏ hàng