ภาพรวมระบบ
UNO Q มีสมองสองส่วนบนบอร์ดเดียว ฝั่ง MPU (Qualcomm, Linux) รันโมเดลตรวจจับใบหน้าและโปรแกรม Python ฝั่ง MCU (STM32, Zephyr RTOS) สร้างสัญญาณ PWM ให้ servo อย่างแม่นยำ ทั้งสองฝั่งคุยกันผ่าน Bridge RPC ระบบประมวลผลได้ประมาณ 10–15 เฟรมต่อวินาที
หุ่นฐานเดียวกันรองรับทุกภารกิจ สิ่งที่เปลี่ยนตามภารกิจคือโปรแกรมฝั่ง Python
| หัวข้อ | ภารกิจ 1–6 และภารกิจที่เสนอเอง | ภารกิจ 7 หันหาใบหน้า |
|---|---|---|
| การขับล้อ | เซอร์โว FS5103R สองตัวต่อตรงกับขา D9/D10 ไฟเลี้ยงจากตัวแปลงไฟ 5 V แยกจากบอร์ด | |
| AI ฝั่ง Linux | vision_bridge.py (OpenCV / Teachable Machine / โมเดลใน App Lab) | brick video_object_detection โมเดล face-detection |
| คำสั่งที่ส่งผ่าน Bridge | drive("F"), drive("L") … ทีละตัวอักษร | set_wheel_pwm(left_us, right_us) |
| โปรแกรมฝั่ง MCU | robot_base_servo.ino ไฟล์เดียวกัน (หยุดเองเมื่อเจอสิ่งกีดขวาง < 15 cm) | |
| ตรรกะการตัดสินใจ | decide() ตามตารางการตัดสินใจ | ตัวควบคุมแบบสัดส่วน: heading error → turn |
| การตรวจสอบ/ปรับค่า | log ใน App Lab · แท็บ "ขับด้วยคำสั่ง" ในแบบ 3 มิติ | แท็บ "หันหาใบหน้า" ในแบบ 3 มิติ · Web UI พอร์ต 7000 (ฉบับเต็ม) |
รายการอุปกรณ์ (ต่อ 1 กลุ่ม)
| อุปกรณ์ | จำนวน | หมายเหตุ |
|---|---|---|
| Arduino UNO Q | 1 | รุ่น 2 GB หรือ 4 GB |
| เซอร์โว Feetech FS5103R (หมุนต่อเนื่อง) | 2 | 4–8.4 V · 2.6 kg·cm ที่ 4.8 V |
| กล้อง Logitech C270 | 1 | มีไมค์ในตัว ใช้กับภารกิจสั่งด้วยเสียงได้ · กล้อง UVC ทั่วไปใช้แทนได้ |
| อัลตราโซนิก HC-SR04 | 1 | เสียบรางด้านในผนังหน้า |
| รางถ่าน 2 × 18650 + ถ่าน 2 ก้อน | 1 | 7.4 V เข้า VIN ของบอร์ด |
| ตัวแปลงไฟ DC-DC step-down 5 V 3 A | 1 | เลี้ยงเซอร์โวและอัลตราโซนิก |
| สวิตช์ไฟ Ø12 mm | 1 | ติดผนังหลัง |
| ตัวเก็บประจุ 470 µF 16 V | 1 | คร่อมราง 5V–GND ของเซอร์โว |
| เบรดบอร์ดเล็กและสาย jumper | 1 / ~16 | ผู้–ผู้ และ ผู้–เมีย |
| USB-C hub หรือ OTG | 1 | สำหรับเสียบกล้อง |
| ชิ้นงานพิมพ์ 3D | 1 ชุด | body, lid, wheel ×2, caster, cam_mount (ชุดไฟล์ หุ่นเซอร์โวแบบกล่อง_ว32210) |
| ลูกแก้วหรือลูกเหล็ก Ø16 mm | 1 | กดเข้าลูกล้อประคอง |
| ยางโอริงหรือยางรัดของ | 2 | คาดร่องล้อ |
| น็อต M3 × 10 (8), M3 × 8 (10), หัวน็อต M3, เสารอง M3 (4) | 1 ชุด | พร้อมไขควง |
| มัลติมิเตอร์ | 1 ต่อห้อง | ปรับตัวแปลงไฟให้ได้ 5.0–5.2 V |
การแบ่งหน้าที่ในกลุ่ม 4–5 คน
ประกอบตัวหุ่น
ทุกขั้นมีลิงก์ไปยังแบบ 3 มิติที่แสดงชิ้นส่วนของขั้นนั้นเลื่อนเข้าที่ หมุนดูได้รอบทิศ
-
1
เตรียมตัวถังและติดลูกล้อประคอง
แคะเศษพลาสติกออกจากรูสกรูและช่องเซอร์โว กดลูกแก้ว Ø16 mm เข้าปลายลูกล้อ แล้วยึดใต้พื้นกล่องด้านหน้าด้วย M3 × 8 สองตัว
ตรวจ: ลูกแก้วหมุนได้คล่อง ไม่หลุดเมื่อคว่ำ
ดูแบบ 3 มิติ ขั้นที่ 1 -
2
ยึดเซอร์โวซ้ายและขวา
สอดเซอร์โวจากด้านในกล่องให้หัวเพลาโผล่ออกช่องข้าง ยึดหูเซอร์โวกับผนังด้วย M3 × 10 และหัวน็อตข้างละ 4 ตัว ตัวขวาหันกลับด้านกับตัวซ้าย ซึ่งเป็นเรื่องปกติ
ตรวจ: แกนเพลาสองข้างอยู่แนวเดียวกัน ทำเครื่องหมายว่าตัวไหนซ้าย ตัวไหนขวา
ดูแบบ 3 มิติ ขั้นที่ 2 -
3
ใส่ล้อ
ยึดแป้นกลมของเซอร์โวในหลุมกลางล้อ สวมเข้ากับเพลาแล้วขันสกรูกลางล้อ คาดยางโอริงที่ร่องล้อ
ตรวจ: หมุนล้อด้วยมือแล้วไม่แกว่งและไม่เสียดสีตัวถัง
ดูแบบ 3 มิติ ขั้นที่ 3 -
4
ใส่อัลตราโซนิก
เสียบบอร์ด HC-SR04 ลงรางด้านในผนังหน้า ให้ตัวรับ-ส่งคลื่นทั้งสองโผล่ออกรูหน้ารถ ขาต่อสายหันลง
ตรวจ: บอร์ดตั้งตรง ไม่เอียง และตัวรับ-ส่งคลื่นไม่ถูกผนังบัง
ดูแบบ 3 มิติ ขั้นที่ 4 -
5
วางรางถ่าน ตัวแปลงไฟ และสวิตช์
วางรางถ่าน 2 × 18650 กลางพื้นระหว่างเซอร์โว รัดด้วยสายตีนตุ๊กแก ยึดตัวแปลงไฟ 5 V ที่รูพื้นด้านหน้าขวา ใส่สวิตช์ที่ผนังหลัง ปรับตัวแปลงไฟให้ได้ 5.0–5.2 V ด้วยมัลติมิเตอร์ก่อนต่อเซอร์โว
ตรวจ: ยังไม่ใส่ถ่าน สวิตช์อยู่ตำแหน่งปิด
ดูแบบ 3 มิติ ขั้นที่ 5 -
6
ร้อยสายและปิดฝาบน
ร้อยสายเซอร์โวและสายไฟจากตัวแปลงไฟขึ้นทางช่องกลางฝา ร้อยสายอัลตราโซนิกขึ้นทางช่องหน้า แล้วสวมฝาและขันสกรูมุม 4 ตัว
ตรวจ: สายไม่ถูกหนีบระหว่างฝากับตัวถัง
ดูแบบ 3 มิติ ขั้นที่ 6 -
7
ติดตั้ง Arduino UNO Q
ยึดบอร์ดบนเสารอง M3 ที่ฝาด้านหลัง ให้พอร์ต USB-C หันไปด้านหลัง
ตรวจ: ใต้บอร์ดไม่มีโลหะหรือสายเปลือยแตะ
ดูแบบ 3 มิติ ขั้นที่ 7 -
8
ติดเบรดบอร์ดและตัวเก็บประจุ
ติดเบรดบอร์ดด้านหน้าฝา เสียบตัวเก็บประจุ 470 µF คร่อมราง 5V กับ GND โดยขายาว (+) อยู่ราง 5V
ตรวจ: ขั้วตัวเก็บประจุถูกต้อง เพราะถ้ากลับขั้วอาจบวมหรือแตก
ดูแบบ 3 มิติ ขั้นที่ 8 -
9
ติดแผ่นยึดกล้องและกล้อง
ขันแผ่นยึดกล้องกับผนังหน้าด้วย M3 × 8 สี่ตัว หนีบกล้อง C270 ที่ขอบบนแผ่น หันเลนส์ตรงไปด้านหน้า ร้อยสาย USB ผ่านช่องหน้าฝาไปที่ hub ของบอร์ด
ตรวจ: กล้องไม่เอียงซ้าย-ขวา เพราะจะทำให้ค่าตำแหน่งในภาพเพี้ยน
ดูแบบ 3 มิติ ขั้นที่ 9 -
10
ต่อสายทั้งหมด
ต่อตามผังในหัวข้อที่ 4 แล้วให้ครูเซ็นเช็กลิสต์ก่อนใส่ถ่านและเปิดสวิตช์
ทดสอบ: ส่งคำสั่ง T ล้อต้องเดินหน้า ถอย หมุนซ้าย หมุนขวา แล้วหยุด
ดูแบบ 3 มิติ ขั้นที่ 10
ผังต่อสาย
| อุปกรณ์ | สาย / ขา | ต่อที่ |
|---|---|---|
| เซอร์โวซ้าย | สัญญาณ (เหลือง/ขาว) | D9 |
| แดง · น้ำตาล/ดำ | ราง 5V · ราง GND | |
| เซอร์โวขวา | สัญญาณ (เหลือง/ขาว) | D10 |
| แดง · น้ำตาล/ดำ | ราง 5V · ราง GND | |
| อัลตราโซนิก HC-SR04 | TRIG · ECHO | D12 · D13 |
| VCC · GND | ราง 5V · ราง GND | |
| รางถ่าน 18650 (+) | ผ่านสวิตช์ | ขา VIN ของ UNO Q และขา IN+ ของตัวแปลงไฟ |
| รางถ่าน 18650 (−) | GND | ขา GND ของ UNO Q และขา IN− ของตัวแปลงไฟ |
| ตัวแปลงไฟ 5 V | OUT+ · OUT− | ราง 5V · ราง GND |
| UNO Q | GND | ราง GND (GND ร่วม) · ห้ามต่อขา 5V ของบอร์ดเข้าราง |
| ตัวเก็บประจุ 470 µF | ขายาว (+) · ขาสั้น (−) | ราง 5V · ราง GND |
| กล้อง C270 | USB-A | USB-C hub/OTG → พอร์ต USB-C ของ UNO Q |
เซอร์โวขวาติดตั้งกลับด้านกับตัวซ้าย ไม่ต้องสลับสาย robot_base_servo.ino ตั้ง INVERT_R = true และกลับทิศให้ ส่วนไฟเซอร์โวมาจากตัวแปลงไฟ 5 V ไม่ใช่ขา 5V ของบอร์ด เพราะกระแสกระชากของเซอร์โวสองตัวรวมกันได้ถึงราว 1.8 A
ติดตั้งซอฟต์แวร์ App Lab
- เปิด Arduino App Lab เวอร์ชัน 0.6 ขึ้นไป และเชื่อมต่อ UNO Q
- สร้างแอปใหม่ หรือนำเข้าไฟล์จาก GitHub ของโปรเจกต์
- ตรวจไฟล์
app.yamlว่าเลือก brick และโมเดลถูกต้อง - ตรวจไลบรารีใน
sketch/sketch.yaml: Arduino_RouterBridge, Servo, MsgPack - กด Run: App Lab จะคอมไพล์ sketch แฟลชลง MCU แล้วเริ่ม main.py
- ดู log บรรทัด
sample_detectionsต้องเห็น label"face"และค่า bounding box ที่สมเหตุสมผล - เปิด Web UI ที่
http://<IP ของ UNO Q>:7000ต้องเห็นภาพจากกล้องและรายการ detection
name: Detect and follow robocar
bricks:
- arduino:video_object_detection:
model: face-detection
- arduino:web_ui: {}
detect-and-follow-robocar/ ├── app.yaml # เลือก brick และโมเดล ├── python/main.py # MPU: ตรวจจับ + ตัวควบคุมการเลี้ยว ├── sketch/sketch.ino # MCU: PWM ให้ servo └── assets/ # Web UI
ทดสอบมอเตอร์
- วางหุ่นบนกล่องให้ล้อลอยพ้นโต๊ะ
- ส่งคำสั่ง drive("T") จาก Python (หรือกด Motor Test ใน Web UI ของภารกิจใบหน้า): ล้อต้องเดินหน้า ถอย หมุนซ้าย หมุนขวา แล้วหยุด
- หากล้อยังหมุนช้าๆ ตอนสั่ง S ให้ปรับค่า TRIM_L / TRIM_R ใน robot_base_servo.ino (หรือหมุนสกรูปรับบนตัวเซอร์โว ถ้ามี) จนล้อหยุดสนิท ทดลองหาค่าก่อนได้ในแท็บ "ขับด้วยคำสั่ง" ของแบบ 3 มิติ
- หากไม่หมุนเลย ตรวจแรงดันขาออกตัวแปลงไฟ (5.0–5.2 V) ราง 5V/GND สาย GND ร่วม และสายสัญญาณที่ D9/D10
| พัลส์ (µs) | การทำงานของ servo หมุนต่อเนื่อง |
|---|---|
| 1500 | หยุด |
| 1000 | เร็วสุด ทิศทางหนึ่ง |
| 2000 | เร็วสุด อีกทิศทาง |
| 1500 ± 125 | ช่วงที่โปรเจกต์ใช้ (MAX_TURN_SPEED = 0.25) |
ปรับจูนค่า
main.py แปลงตำแหน่งกลางกรอบใบหน้าเป็นคำสั่งเลี้ยวตามลำดับนี้
heading_error = (target_cx - 0.5) * 2.0 # −1 (ซ้ายสุด) … +1 (ขวาสุด) if abs(heading_error) < CENTER_DEADBAND: heading_error = 0 shaped = copysign(abs(heading_error) ** STEER_CURVE, heading_error) turn = clamp(STEER_SIGN * STEER_GAIN * shaped, -MAX_TURN_SPEED, MAX_TURN_SPEED) left_us = 1500 + turn * 500 right_us = 1500 - turn * 500
| ค่า | ค่าเริ่มต้น | ผลเมื่อปรับ |
|---|---|---|
STEER_GAIN | 0.15 | มากขึ้น = เลี้ยวเร็วขึ้น แต่เสี่ยงส่ายเลยเป้า |
MAX_TURN_SPEED | 0.25 | เพดานความเร็วล้อ (~±125 µs) ต้องมากกว่าช่วงตายของ servo |
CENTER_DEADBAND | 0.05 | มากขึ้น = ยอมให้ใบหน้าเยื้องกลางได้มากขึ้นก่อนเลี้ยว ลดการสั่น |
STEER_CURVE | 0.4 | ตอบสนองแรงขึ้นเมื่อ error น้อย และนุ่มลงใกล้ขอบภาพ |
STEER_SIGN | 1.0 | ใช้ −1.0 ถ้าหุ่นหันหนีใบหน้า |
DRIVE_BIAS | 0.0 | บวก = ค่อยๆ เดินหน้า ลบ = ถอย |
TRACKING_TIMEOUT | 0.5 s | เวลาที่ยังเลี้ยวต่อด้วยคำสั่งเดิมเมื่อใบหน้าหายชั่วคราว |
FRAME_WIDTH_FALLBACK | 640 | ต้องตรงกับความกว้างภาพจริง ไม่อย่างนั้นการเลี้ยวจะเอียงข้าง |
ขั้นตอน: เริ่มจากค่าเริ่มต้น เพิ่ม STEER_GAIN ใน Web UI จนหุ่นหันเข้ากลางได้นุ่มนวล ถ้าส่ายซ้าย-ขวาให้ลดลง ได้ค่าที่ดีแล้วจึงแก้ค่าเริ่มต้นใน main.py
ทดลองปรับค่าในแบบจำลอง 3 มิติแก้ปัญหาเบื้องต้น
| อาการ | สาเหตุที่เป็นไปได้ | วิธีแก้ |
|---|---|---|
| Web UI เห็น detection แต่ขึ้น “lost target – stopped” | TARGET_CLASS ไม่ตรงกับ label ของโมเดล | ดู log sample_detections แล้วตั้งให้ตรงทุกตัวอักษร |
| ล้อไม่หมุนเลย | ไฟ servo สายสัญญาณ หรือ Bridge | ส่ง drive("T") เพื่อแยกปัญหา ตรวจตัวแปลงไฟ ราง 5V/GND และ D9/D10 |
| หุ่นหันหนีใบหน้า | ทิศการเลี้ยวกลับด้าน | ตั้ง STEER_SIGN = -1.0 หรือสลับค่า invert ของล้อ |
| ส่ายไปมา ไม่นิ่ง | gain สูงเกินหรือ deadband น้อยเกิน | ลด STEER_GAIN เพิ่ม CENTER_DEADBAND |
| บอร์ดรีเซ็ตหรือกล้องหลุดตอนล้อเริ่มหมุน | กระแสกระชากจาก servo | ตรวจว่าไฟเซอร์โวมาจากตัวแปลงไฟ ไม่ใช่ขา 5V ของบอร์ด ตรวจตัวเก็บประจุ 470 µF และชาร์จถ่าน 18650 ให้เต็ม |
| ไม่มีภาพจากกล้อง | บอร์ดไม่พบกล้อง | ตรวจการเสียบ USB หรือใช้ hub ที่มีไฟเลี้ยง |
| หยุดฉุกเฉินไม่ทำงาน | Socket.IO หลุด | ดูแถบแจ้งข้อผิดพลาดใน Web UI แล้วโหลดหน้าใหม่ |
โค้ดตัวอย่าง
ไฟล์อยู่ในโฟลเดอร์ code-examples-face ตรวจโค้ดตามเอกสารแล้ว แต่ยังไม่ได้รันบนบอร์ด UNO Q จริง ไฟล์ .py ที่เป็นตรรกะจำลองรันบนคอมพิวเตอร์ได้
| ไฟล์ | วางที่ | ใช้กับ |
|---|---|---|
| robot_base_servo.ino | sketch/sketch.ino | ใช้กับทุกภารกิจ · drive F/B/L/R/S/T · set_wheel_pwm · get_distance · เซอร์โว D9/D10 อัลตราโซนิก D12/D13 · ใบงาน 2.1F, 3.1F |
| face_follow_sketch.ino | sketch/sketch.ino | ไฟล์ต้นฉบับ (D3/D6) เก็บไว้เทียบ · หุ่นฐานใช้ robot_base_servo.ino แทน ซึ่งรับ set_wheel_pwm เหมือนกันที่ D9/D10 |
| face_follow_main.py | python/main.py | ฉบับย่อไม่มี Web UI: ตรวจจับ เลี้ยว จำกัดความถี่ watchdog · ใบงาน 3.1F, 4.2F |
| servo_pulse_test.ino | sketch/sketch.ino | ส่งพัลส์ 1300–1700 µs ทีละค่า · ใบงาน 2.2F ตอนที่ 1 |
| steer_calc.py | คอมพิวเตอร์ | ตรวจผลคำนวณคำสั่งล้อ · ใบงาน 2.2F ตอนที่ 2 |
| decide_distance.py | คอมพิวเตอร์ → main.py | รักษาระยะห่างด้วยขนาดกรอบ · ใบงาน 4.3F |
| decide_search.py | คอมพิวเตอร์ → main.py | state machine หมุนค้นหา · ใบงาน 4.3F |
ฉบับเต็มที่มี Web UI ปรับค่าได้ ใช้ python/main.py จาก GitHub ของโปรเจกต์ต้นฉบับ ซึ่งใช้ sketch เดียวกันนี้ได้
