บทความ › โปรเจกต์

บังคับรถหุ่นยนต์ ESP32 ด้วยจอยเกมคอนโซล ผ่าน Bluepad32

ใช้ Bluepad32 ให้ ESP32 รับจอยเกมคอนโซลผ่าน Bluetooth แล้วขับรถสองล้อด้วย TB6612FNG ESP32 รุ่นแรกรองรับจอยทุกแบบ ส่วน S3/C3/C6 ได้เฉพาะ BLE และต้องแยกไฟมอเตอร์

กลาง อ่าน 9 นาที 23 ตุลาคม 2569 ของใหม่ที่ช่างควรลอง 2026 · บทที่ 16/20

อ่านจบแล้วจะรู้
  • Bluepad32 ทำให้ ESP32 เป็นเครื่องรับจอยเกม Bluetooth ได้โดยตรง ไม่ต้องมีมือถือหรือแอปคั่นกลาง
  • ESP32 รุ่นแรกรองรับจอยทั้ง Bluetooth Classic และ BLE ส่วน S3/C3/C6 ไม่มี Bluetooth Classic จึงใช้ได้เฉพาะจอย BLE
  • สติ๊กอนาล็อกให้ค่าราว −512 ถึง 512 ผสมแกนหน้า-หลังกับซ้าย-ขวาเป็นความเร็วล้อซ้ายและขวา แล้วตัดค่าเกินทิ้ง
  • แยกแบตมอเตอร์ออกจากไฟเลี้ยง ESP32 แต่ต่อกราวด์ร่วมกัน และหยุดมอเตอร์ทันทีเมื่อจอยหลุด

จอยเกมคอนโซลที่วางอยู่บ้านใช้บังคับรถหุ่นยนต์ ESP32 ได้โดยตรง ด้วยไลบรารี Bluepad32 ที่ทำให้ ESP32 รับจอย Bluetooth ได้เหมือนเครื่องเกม เงื่อนไขสำคัญมีสองข้อ: ESP32 รุ่นแรกเท่านั้นที่รองรับจอยทุกแบบ (รุ่น S3/C3/C6 ได้เฉพาะจอย BLE) และไฟมอเตอร์ต้องแยกจากไฟเลี้ยงบอร์ด

บทนี้เป็นคู่มือวิธีสร้าง ยังไม่ใช่บันทึกงานที่ทำเสร็จแล้ว ตัวเลขในตัวอย่างใช้แสดงวิธีคำนวณ เช็กสเปกมอเตอร์และแบตของคุณเองทุกครั้ง

เลือกบอร์ดให้ตรงกับจอย

จอยแต่ละแบบคุยกับเครื่องรับคนละโปรโตคอล บางแบบใช้ Bluetooth Classic (BR/EDR) บางแบบใช้ BLE เอกสาร Bluepad32 ระบุว่า ESP32 รุ่นแรก, Pico W และ Pico 2 W รองรับ BR/EDR ส่วน ESP32-S3, C3, C5, C6 และ H2 ไม่รองรับ

ESP32 รุ่นแรกESP32-S3 / C3 / C6
Bluetooth Classic (BR/EDR)มีไม่มี
BLEมีมี
จอย PS3 / PS4 / PS5ได้ไม่ได้
Switch Pro, Joy-Con, Wii Remoteได้ไม่ได้
จอยตระกูล 8BitDoได้ไม่ได้
Xbox Wireless รุ่น 1914 (เฟิร์มแวร์ v5.15 ขึ้นไป)ได้ได้
Switch 2 Pro, Switch 2 Joy-Conได้ได้
Steam Controller, Stadia (เฟิร์มแวร์ Bluetooth)ได้ได้

ถ้ายังไม่มีบอร์ด เลือก ESP32 รุ่นแรก จอยไหนในบ้านก็ใช้ได้ ดูความต่างอื่นของแต่ละรุ่นได้ในเทียบรุ่น ESP32

ตั้งค่า Arduino IDE

Bluepad32 แจกเป็น board package แยก ไม่ใช่ไลบรารีธรรมดา

  1. ใน Preferences เพิ่ม URL ของ board index สองอัน: ของ ESP32 ทางการ และ package_esp32_bluepad32_index.json จาก repo ricardoquesada/esp32-arduino-lib-builder (ลิงก์เต็มอยู่ในหน้าเอกสาร Arduino ของ Bluepad32)
  2. Tools → Board → Boards Manager ติดตั้ง esp32 และ esp32_bluepad32
  3. เลือกบอร์ดจาก Tools → Board → ESP32 + Bluepad32 Arduino
  4. เปิดตัวอย่าง File → Examples → Bluepad32_ESP32 → Controller อัปโหลด แล้วกดปุ่มจับคู่บนจอย ดูค่าที่พิมพ์ออก Serial Monitor

ทำข้อ 4 ให้ผ่านก่อนต่อมอเตอร์ จะได้รู้ว่าดันสติ๊กขึ้นแล้วค่า axisY() ออกบวกหรือลบ

ต่อวงจร: แยกไฟมอเตอร์

ใช้ไดรเวอร์มอเตอร์ TB6612FNG คุมมอเตอร์ DC สองตัว ข้อมูลจาก datasheet ของ Toshiba

  • VM (ไฟมอเตอร์) ใช้งานจริง 2.5–13.5 V สูงสุดห้ามเกิน 15 V
  • VCC (ไฟลอจิก) 2.7–5.5 V ต่อ 3V3 ของ ESP32 ได้
  • กระแสต่อช่อง 1.2 A เฉลี่ย 3.2 A ช่วงสั้น (พัลส์ 10 ms) และในตารางช่วงใช้งานระบุ 1.0 A ที่ VM ≥ 4.5 V
  • PWM ได้ถึง 100 kHz มีวงจรตัดเมื่อร้อนเกิน
  • ขา STBY ต้องดึงเป็น HIGH มอเตอร์ถึงจะหมุน
TB6612FNGต่อกับ
VMขั้วบวกแบตมอเตอร์
VCCESP32 3V3
GNDกราวด์แบตมอเตอร์ และ GND ของ ESP32
AIN1 / AIN2 / PWMAGPIO25 / 26 / 27 (ล้อซ้าย)
BIN1 / BIN2 / PWMBGPIO32 / 33 / 4 (ล้อขวา)
STBYGPIO21
AO1-AO2 / BO1-BO2มอเตอร์ซ้าย / ขวา

ทำไมต้องแยกไฟ: ตอนมอเตอร์ออกตัวหรือติดขัด กระแสพุ่งสูงและแรงดันตก ถ้าบอร์ดใช้ไฟเส้นเดียวกัน ESP32 อาจรีเซ็ตกลางทาง ให้ ESP32 ใช้ไฟจาก USB power bank หรือวงจรแปลงไฟแยก (วิธีจ่ายไฟ ESP32) ส่วนมอเตอร์ใช้แบตของมันเอง แล้วต่อกราวด์สองฝั่งเข้าด้วยกัน ถ้าลืมกราวด์ร่วม สัญญาณจาก ESP32 จะไม่มีจุดอ้างอิง มอเตอร์จะไม่ตอบสนองหรือกระตุก

ตัวอย่างเช็กแบตกับไดรเวอร์ แบตลิเธียมสองเซลล์อนุกรมเต็มที่ 2 × 4.2 = 8.4 V อยู่ในช่วง 2.5–13.5 V แต่ต้องเช็กว่ามอเตอร์ทนแรงดันนี้ได้ด้วย และกระแสตอนล้อติด (stall current) ของมอเตอร์แต่ละตัวต้องไม่เกินราว 1 A ต่อช่อง ถ้าสเปกมอเตอร์บอกสูงกว่านี้ ต้องใช้ไดรเวอร์ที่รับกระแสได้มากกว่า ก่อนใช้แบตลิเธียมอ่านความปลอดภัยของแบต LiPo และ Li-ion

ผสมสติ๊กเป็นความเร็วล้อ

เอกสาร Bluepad32 ระบุว่าสติ๊กอนาล็อกถูกปรับให้อยู่ในช่วงราว −512 ถึง 512 ส่วนไกปืนอยู่ที่ 0–1023 รถสองล้อขับแบบรถถัง (differential drive) ใช้สติ๊กซ้ายอันเดียว: แกน Y คือเดินหน้า-ถอยหลัง แกน X คือเลี้ยว

  • ล้อซ้าย = เดินหน้า + เลี้ยว
  • ล้อขวา = เดินหน้า − เลี้ยว

ตัวอย่างทีละขั้น ดันสติ๊กขึ้นค่อนไปทางขวา Serial อ่านได้ axisY = −400, axisX = 150 (บนจอยส่วนใหญ่ดันขึ้นค่าเป็นลบ ให้เช็กกับจอยของคุณ)

  1. เดินหน้า = −(−400) = 400, เลี้ยว = 150
  2. ล้อซ้าย = 400 + 150 = 550 → ตัดให้เหลือ 512
  3. ล้อขวา = 400 − 150 = 250
  4. แปลงเป็น PWM 8 บิต (0–255): ซ้าย 512 × 255 ÷ 512 = 255, ขวา 250 × 255 ÷ 512 ≈ 124
  5. ผล: ล้อซ้ายหมุนเต็มที่ ล้อขวาราวครึ่งเดียว รถโค้งไปทางขวา

สติ๊กไม่เคยคืนศูนย์พอดี ค่าจะค้างอยู่หลักสิบ ตั้ง dead zone เช่น ±40 ให้ค่าที่เล็กกว่านี้นับเป็นศูนย์ รถจะไม่คลานเองตอนปล่อยมือ

สติ๊กเดินหน้า400สติ๊กเลี้ยว150ล้อซ้าย = 400 + 150512 (ตัดที่เพดาน)ล้อขวา = 400 - 150250ค่าสติ๊กประมาณ -512 ถึง 512
ดันสติ๊กขึ้นเยื้องขวา ล้อซ้ายเร็วกว่า รถโค้งขวา

โค้ด

#include <Bluepad32.h>

const int AIN1 = 25, AIN2 = 26, PWMA = 27;   // ล้อซ้าย
const int BIN1 = 32, BIN2 = 33, PWMB = 4;    // ล้อขวา
const int STBY = 21;
const int DEAD = 40;

ControllerPtr pad = nullptr;

void onConnected(ControllerPtr c)    { if (!pad) pad = c; }
void onDisconnected(ControllerPtr c) { if (pad == c) pad = nullptr; }

void drive(int in1, int in2, int pwm, int v) {     // v: -512..512
  v = constrain(v, -512, 512);
  digitalWrite(in1, v > 0);
  digitalWrite(in2, v < 0);
  ledcWrite(pwm, abs(v) * 255 / 512);
}

void stopAll() { drive(AIN1, AIN2, PWMA, 0); drive(BIN1, BIN2, PWMB, 0); }

void setup() {
  for (int p : {AIN1, AIN2, BIN1, BIN2, STBY}) pinMode(p, OUTPUT);
  ledcAttach(PWMA, 20000, 8);    // 20 kHz พ้นช่วงที่หูได้ยิน
  ledcAttach(PWMB, 20000, 8);
  digitalWrite(STBY, HIGH);
  BP32.setup(&onConnected, &onDisconnected);
}

void loop() {
  BP32.update();
  if (!pad || !pad->isConnected()) { stopAll(); delay(10); return; }  // จอยหลุด = หยุด
  if (pad->hasData()) {
    int fwd = -pad->axisY(), turn = pad->axisX();
    if (abs(fwd) < DEAD) fwd = 0;
    if (abs(turn) < DEAD) turn = 0;
    drive(AIN1, AIN2, PWMA, fwd + turn);
    drive(BIN1, BIN2, PWMB, fwd - turn);
  }
  delay(10);
}

ledcAttach(pin, freq, resolution) เป็น API ของ Arduino-ESP32 รุ่น 3.x ถ้าคอมไพล์แล้วไม่รู้จักฟังก์ชันนี้ แปลว่า core เป็นรุ่นเก่า ให้ใช้ ledcSetup กับ ledcAttachPin แทน ถ้าดันขึ้นแล้วรถถอย ลบเครื่องหมายลบหน้า axisY() ออก ถ้าเลี้ยวกลับด้าน สลับสายมอเตอร์ข้างนั้น

หยุดมอเตอร์ทุกครั้งที่จอยหลุด รถที่วิ่งค้างตามคำสั่งสุดท้ายจะชนของหรือตกโต๊ะ ทดสอบครั้งแรกโดยยกล้อให้ลอยจากพื้น

ตัวถังพิมพ์ 3 มิติ

พิมพ์แผ่นฐานที่มีรูยึดมอเตอร์ ช่องใส่แบตที่ถอดชาร์จได้ และกล่องบอร์ดแยกจากแบต ใช้ heat-set insert ที่จุดที่ต้องขันสกรูซ้ำ (วิธีใส่ insert) วางแบตไว้ต่ำและกลางรถ รถจะไม่หงายตอนออกตัวแรง

ข้อผิดพลาดที่เจอบ่อย

  • ใช้บอร์ด S3/C3/C6 กับจอย PlayStation หรือ Switch Pro จับคู่ไม่ได้เพราะไม่มี Bluetooth Classic
  • ไฟมอเตอร์กับบอร์ดใช้เส้นเดียว ESP32 รีเซ็ตตอนมอเตอร์ออกตัว จอยหลุดกลางทาง
  • ลืมต่อกราวด์ร่วม มอเตอร์ไม่หมุนหรือกระตุก
  • ลืมดึง STBY เป็น HIGH ทุกอย่างต่อถูกแต่ล้อไม่หมุน
  • ไม่มี dead zone รถคลานเองตอนปล่อยสติ๊ก
  • ไม่ตัดค่าเกิน 512 ค่าล้นแล้วความเร็วกระโดด
  • มอเตอร์กินกระแสเกินไดรเวอร์ ชิปร้อนและตัดการทำงานเป็นช่วง ๆ

แหล่งข้อมูล

คำถามที่พบบ่อย

ทำไมจอย PS4 ต่อกับบอร์ด ESP32-S3 ไม่ได้

จอย PlayStation ทุกรุ่นที่ Bluepad32 รองรับใช้ Bluetooth Classic (BR/EDR) แต่ ESP32-S3, C3 และ C6 ไม่มี BR/EDR ต้องใช้ ESP32 รุ่นแรก หรือเปลี่ยนเป็นจอยที่อยู่ในรายการ BLE

ใช้แบตก้อนเดียวเลี้ยงทั้งมอเตอร์และบอร์ดได้ไหม

ได้ถ้ามีวงจรแปลงไฟแยกให้บอร์ดและตัวเก็บประจุพอ แต่สำหรับรถคันแรก แยกแหล่งไฟง่ายกว่าและตัดปัญหาบอร์ดรีเซ็ตตอนมอเตอร์ออกตัว ไม่ว่าแบบไหนต้องต่อกราวด์ร่วมกัน

ใช้ Bluepad32 ในงานขายได้ไหม

ตัว Bluepad32 เป็น Apache 2.0 แต่ใช้ BTstack ซึ่งฟรีเฉพาะโปรเจกต์โอเพนซอร์ส งานปิดซอร์สเชิงพาณิชย์บน ESP32 ต้องติดต่อ BTstack เรื่องสัญญาอนุญาต

วงจรและโค้ดในบทความทดสอบกับบอร์ดตัวอย่าง บอร์ดต่างรุ่นอาจใช้ขาต่างกัน ตรวจ pinout ของบอร์ดที่ใช้ก่อนต่อไฟเสมอ

อ่านต่อ

#โปรเจกต์กลาง

กล่องดนตรี NFC ฝังแท็ก NTAG215 ในตัวหมากพิมพ์ 3 มิติ อ่านด้วย ESP32 กับ PN532

ฝังแท็ก NTAG215 ในตัวหมากด้วยการหยุดพิมพ์กลางงาน แล้วให้ ESP32 กับเครื่องอ่าน PN532 อ่าน UID ของแท็ก วางตัวไหนเล่นเพลงนั้น พร้อมคำนวณความลึกช่องและจุดหยุดพิมพ์

อ่าน 9 นาที
#โปรเจกต์กลาง

ของเล่น AI พูดได้ ด้วย ESP32-S3 และ xiaozhi-esp32 คำปลุกบนบอร์ด สมองบนคลาวด์

ทำของเล่นคุยได้ด้วยโปรเจกต์โอเพนซอร์ส xiaozhi-esp32 บอร์ดฟังคำปลุกเอง ส่วน LLM อยู่บนคลาวด์ พร้อมเรื่องที่ต้องคิดก่อนให้เด็กเล่น ทั้งความเป็นส่วนตัวและไฟบอกไมค์

อ่าน 7 นาที
#โปรเจกต์เริ่มต้น

พิมพ์ 3 มิติ ลงบน ผ้าตาข่าย tulle ทำของเล่นที่งอได้ ด้วยการหยุดพิมพ์กลางงาน

หยุดพิมพ์หลังชั้นแรก ๆ วางผ้า tulle ให้ตึง แล้วพิมพ์ต่อทับ พลาสติกจะไหลผ่านรูตาข่ายยึดผ้าไว้ในเนื้อ ได้ของเล่นแบ่งเป็นปล้องที่งอได้ พร้อมค่าตั้งต้นและการคำนวณชั้น

อ่าน 6 นาที