ESP32 รีเซ็ตเองตอนมอเตอร์หมุน (Brownout) สาเหตุและวิธีแก้

ESP32 รีบูตทุกครั้งที่มอเตอร์ออกตัวและขึ้น Brownout detector was triggered เพราะไฟตก วิธีแยกไฟมอเตอร์ ใส่ตัวเก็บประจุ ใช้ buck 5 V และค่อยๆ เร่งมอเตอร์

อัปเดต 2026-11-02

ถ้า ESP32 รีสตาร์ทเองทุกครั้งที่มอเตอร์เริ่มหมุน และ Serial Monitor ขึ้นข้อความ Brownout detector was triggered แปลว่าแรงดันไฟเลี้ยงบอร์ดตกลงชั่วขณะจนต่ำกว่าเกณฑ์ ชิปจึงรีเซ็ตตัวเองเพื่อป้องกันการทำงานผิดพลาด ทางแก้คือแยกไฟของมอเตอร์ออกจากไฟของบอร์ด ให้มีไฟสำรองพอตอนกระแสกระชาก และไม่ควรปิดตัวตรวจ brownout

อาการที่เห็นใน Serial Monitor

Brownout detector was triggered

ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
...

บรรทัดแรกคือตัวบอกสาเหตุ ส่วนที่ตามมาคือข้อความตอนบูตใหม่ ถ้าเห็นวนซ้ำทุกครั้งที่สั่งมอเตอร์ หรือทุกครั้งที่ WiFi เริ่มเชื่อมต่อ ปัญหาเป็นเรื่องไฟเลี้ยงแน่นอน บางครั้งบอร์ดไม่ขึ้นข้อความนี้แต่ค้างหรือรีเซ็ตเฉยๆ ก็มาจากสาเหตุเดียวกันได้

ทำไมไฟตกตอนมอเตอร์ออกตัว

วิธีแก้ เรียงจากสำคัญที่สุด

  1. แยกไฟมอเตอร์กับไฟบอร์ด ต่อแบตเข้าขา VM ของ motor driver โดยตรง แล้วใช้ buck converter ลดแรงดันแบตลงเป็น 5 V จ่ายเข้าขา 5V (VIN) ของ ESP32 อีกทางหนึ่ง กระแสของมอเตอร์ไม่ต้องผ่านวงจรของบอร์ดเลย
  2. ต่อ GND ร่วมกันทุกส่วน แบต, motor driver, buck และ ESP32 ต้องใช้กราวด์เดียวกัน ไม่งั้นสัญญาณ PWM จะไม่มีจุดอ้างอิง ให้เดินสายกราวด์ของมอเตอร์กลับไปที่แบตโดยตรง ไม่ผ่านบอร์ด
  3. ใช้ buck ที่จ่ายได้เหลือ buck 5 V 3 A มีกำลังสำรองพอสำหรับ ESP32 กับ servo และเซนเซอร์ ตัวเล็กๆ ที่จ่ายได้ไม่ถึง 1 A จะเป็นจุดอ่อนอีกจุด
  4. ใส่ตัวเก็บประจุ
    • ตัวเก็บประจุอิเล็กโทรไลต์ 100–470 µF คร่อมขา 5V กับ GND ใกล้ ESP32 (ระวังขั้ว: ขาสั้นคือขั้วลบ) ช่วยเลี้ยงบอร์ดในจังหวะที่ไฟตก
    • ตัวเก็บประจุเซรามิก 0.1 µF (104) บัดกรีคร่อมขั้วมอเตอร์แต่ละตัว ช่วยลดสัญญาณรบกวนจากแปรงถ่านของมอเตอร์
  5. ค่อยๆ เร่งมอเตอร์ในโค้ด แทนที่จะสั่งจาก 0 ไปเต็มกำลังทันที ให้ไล่ PWM ขึ้นทีละขั้น กระแสกระชากจะลดลงมาก (ดูโค้ดด้านล่าง)
  6. ชาร์จแบตให้เต็ม แบต 18650 สองก้อนอนุกรม (2S) ควรมีแรงดันรวมไม่ต่ำกว่าราว 7 V ตอนใช้งาน ถ้าต่ำกว่านี้อาการจะกลับมาแม้วงจรถูกแล้ว อ่านเรื่องเลือกและดูแลแบตได้ใน บทความเลือกแบตเตอรี่

วงจรที่แยกไฟถูกต้อง

แผนผังวงจรในตัวจำลอง แบต 2S ต่อเข้า VM ของ TB6612FNG โดยตรง และผ่าน buck converter 5 V ไปเลี้ยง ESP32
แบต 2S (7.4 V) ──┬──▶ VM ของ TB6612FNG ──▶ มอเตอร์
                 │
                 └──▶ buck 5 V ──▶ 5V (VIN) ของ ESP32
                                        │
                                       3V3 ──▶ VCC ของ TB6612FNG (ลอจิก)
GND ของแบต, buck, TB6612FNG และ ESP32 ต่อถึงกันทั้งหมด
การต่อขาบน ESP32 DevKit V1 (จัดขาอัตโนมัติจากตัวจำลอง)
TB6612FNG
Motors
VM → แบต 7.4 V
VCC → 3V3
GND → GND
PWMA → GPIO25
AIN1 → GPIO27
AIN2 → GPIO14
PWMB → GPIO26
BIN1 → GPIO13
BIN2 → GPIO4
STBY → 3V3 (ต่อค้างไว้)
ห้ามจ่ายแบต 7.4 V เข้าขา 3V3 หรือขา 5V ของ ESP32 โดยตรง ขา 3V3 รับได้แค่ 3.3 V ส่วนขา 5V ผ่าน regulator บนบอร์ดที่ไม่ได้ออกแบบมาให้รับแรงดันสูงขนาดนั้นต่อเนื่อง ใช้ buck ลดแรงดันก่อนเสมอ

โค้ดเร่งมอเตอร์แบบค่อยเป็นค่อยไป

ต่อยอดจากฟังก์ชัน motor() ใน บทความ TB6612FNG เก็บความเร็วปัจจุบันไว้ แล้วขยับเข้าหาความเร็วเป้าหมายทีละไม่เกิน STEP ทุก 10 มิลลิวินาที

const int PWMA = 25, AIN1 = 27, AIN2 = 14;   // ล้อซ้าย
const int PWMB = 26, BIN1 = 13, BIN2 = 4;    // ล้อขวา
const int STEP = 8;                          // เปลี่ยนได้ไม่เกินเท่านี้ต่อ 10 ms (0 → 200 ใช้ราว 0.25 วินาที)

int targetL = 0, targetR = 0;   // ความเร็วที่อยากได้ -255..255
int nowL = 0, nowR = 0;         // ความเร็วที่สั่งอยู่จริง

void motor(int pwm, int in1, int in2, int speed) {
  digitalWrite(in1, speed > 0);
  digitalWrite(in2, speed < 0);
  analogWrite(pwm, abs(speed));
}

int approach(int now, int target) {
  if (now < target) return min(now + STEP, target);
  if (now > target) return max(now - STEP, target);
  return now;
}

void updateMotors() {
  static unsigned long last = 0;
  if (millis() - last < 10) return;
  last = millis();
  nowL = approach(nowL, targetL);
  nowR = approach(nowR, targetR);
  motor(PWMA, AIN1, AIN2, nowL);
  motor(PWMB, BIN1, BIN2, nowR);
}

void setup() {
  Serial.begin(115200);
  int pins[] = { PWMA, AIN1, AIN2, PWMB, BIN1, BIN2 };
  for (int p : pins) pinMode(p, OUTPUT);
}

void loop() {
  updateMotors();                       // เรียกทุกรอบ ห้ามใช้ delay() ยาวๆ
  if (millis() % 4000 < 2000) { targetL = 200; targetR = 200; }
  else                         { targetL = -150; targetR = -150; }
}

การกลับทิศจากเดินหน้าเป็นถอยหลังจะค่อยๆ ผ่าน 0 ไปเอง ซึ่งเป็นจังหวะที่มอเตอร์ดึงกระแสสูงที่สุด

ทำไมไม่ควรปิด brownout detector

ในเว็บบอร์ดมักแนะนำให้ใส่ WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) เพื่อปิดตัวตรวจ ซึ่งทำให้ข้อความหายไปจริง แต่ไฟยังตกเหมือนเดิม สิ่งที่ตามมาคือ

brownout detector เป็นสัญญาณเตือนที่มีประโยชน์ ใช้เป็นตัวทดสอบได้ด้วย: แก้วงจรแล้วสั่งมอเตอร์ออกตัวเต็มกำลังซ้ำๆ ถ้าไม่รีเซ็ตเลยแปลว่าไฟเลี้ยงพอแล้ว

ชิ้นส่วน

ชิ้นส่วนสำหรับ ESP32 DevKit V1
ชิ้นส่วนจำนวนราคาประมาณร้าน
ESP32 DevKit V1 (30 ขา)1฿130–฿250Shopee
TB6612FNG motor driver1฿50–฿120Shopee
ชุดแชสซี 2WD
มีมอเตอร์ TT 2 ตัว ล้อ 2 ล้อ และล้อ caster
1฿150–฿300Shopee
ถ่าน Li-ion 186502฿60–฿150Shopee
รางถ่าน 18650 แบบ 2 ก้อน (2S)1฿20–฿60Shopee
Buck converter 7.4 V → 5 V 3 A1฿30–฿90Shopee
สวิตช์เปิด-ปิด1฿5–฿20Shopee
สายจัมเปอร์ ผู้-ผู้ / ผู้-เมีย ชุด 40 เส้น1฿30–฿60Shopee
แนะนำเพิ่ม
ที่ชาร์จถ่าน 186501฿100–฿250Shopee
รวมโดยประมาณ฿535–฿1,200

ราคาประมาณการ ณ 2026-10-31 ยังไม่ได้ตรวจกับร้าน · บางลิงก์เป็นลิงก์ affiliate (อ่านเพิ่ม)

ตัวเก็บประจุ 100–470 µF และ 0.1 µF หาซื้อได้ตามร้านอะไหล่อิเล็กทรอนิกส์ทั่วไป ชิ้นละไม่กี่บาท

ลองในตัวจำลอง

หุ่นในตัวจำลองต่อไฟแบบแยกตามบทความนี้ไว้แล้ว เปิดหน้า Wiring เพื่อดูว่าไฟแต่ละเส้นไปที่ไหน และดูตารางกำลังไฟว่าราง 5 V กับ 3.3 V ใช้กระแสไปเท่าไร ตัวตรวจวงจรจะเตือนถ้าใช้เกินกำลังของรางนั้น

เปิดวงจรหุ่น 2 ล้อในตัวจำลอง →