โปรเจคนี้มันเกี่ยวกับอะไร?
นี่คือหุ่นยนต์ทรงตัวลูกบอล มันจะพยายามทรงตัวลูกบอลให้อยู่ตรงกลางด้วย Object Detection & Image Recognition ผ่าน Arduino กับ Python เราใช้เซ็นเซอร์วัดระยะและเทคนิคการจดจำภาพเพื่อให้มันทรงตัวได้
ทำไมถึงอยากทำมันขึ้นมา?
พี่อยากทรงตัวลูกปิงปองให้อยู่กลางแผ่นไง เลยทำหุ่นยนต์ตัวนี้ขึ้นมาจัดไปวัยรุ่น
มันทำงานยังไง?
คอนเซปต์ของหุ่นยนต์ทรงตัวลูกบอลมันง่ายๆเลย น้อง ลูกบอลต้องอยู่กลางกล่อง ถ้ามันกลิ้งไปทางซ้าย กล่องก็จะยกขึ้นจากฝั่งซ้าย เพื่อให้มันกลิ้งลงไปอีกฝั่งหนึ่ง กระบวนการนี้จะซ้ำไปเรื่อยๆจนกว่าลูกบอลจะมาอยู่ตรงกลางพอดี
Image Recognition (การจดจำภาพ)
โปรเจคนี้ทิ้งเซ็นเซอร์ฮาร์ดแวร์ไปเลย แล้วหันมาใช้การวัดระยะทางด้วยภาพแทน กล้อง USB ความเร็วสูงจะจับภาพแผ่น แล้ววิเคราะห์สีของลูกบอลด้วย **OpenCV** บน Python โดยตรงเลย มันจะหาแกน X/Y ที่แม่นยำ คำนวณมุม Tilt/Pan ที่ต้องการแบบเรียลไทม์ แล้วส่งคำสั่ง Serial ไปให้ Arduino เพื่อควบคุม Servo Motor สองตัวให้ทรงตัวได้!
เราใช้เทคนิคการจดจำภาพ OpenCV บนภาษา Python โดยตั้งค่า threshold สำหรับสีส้มไว้ มันจะวงกลมล้อมรอบวัตถุสีส้มใดๆที่กล้องเห็น งานหนักๆทั้งหมดจะทำบน Python ใน PC หรือ Raspberry Pi เพราะตัวประมวลผลของ Arduino มันอ่อนเกินไปสำหรับการวิเคราะห์วิดีโอ ห้ามช็อตนะตัวนี้
Python OpenCV Image Thresholding (The Vision Engine)
- OpenCV จับภาพจากเว็บแคม USB!
- แปลงภาพไปยังพื้นที่สี **HSV (Hue, Saturation, Value)**
- "Mask" ภาพเพื่อแยกเฉพาะพิกเซลสีส้มของลูกปิงปองออกมา ทุกอย่างที่เหลือจะกลายเป็นสีดำสนิท!
- เรียกใช้ `cv2.moments()` เพื่อคำนวณจุดศูนย์กลางมวล 2D ที่แม่นยำของก้อนสีส้มนั้นทางคณิตศาสตร์!
# The Python OpenCV Center-Finding Algorithm!
mask = cv2.inRange(hsv_frame, orange_lower, orange_upper)
M = cv2.moments(mask)
if M["m00"] != 0:
cX = int(M["m10"] / M["m00"]) # Calculate absolute X Coordinate
cY = int(M["m01"] / M["m00"]) # Calculate absolute Y Coordinate
# Calculate the PID Error from the exact Center of the physical glass!
errorX = CenterX - cX
# Run PID Math and send exact Servo Angle to Arduino via Serial!
ser.write(f"X{servoAngleX}Y{servoAngleY}\n".encode())
เรามีเส้นสมมติแบ่งวิดีโอออกเป็นซ้ายขวา ดังนั้นเมื่อใดก็ตามที่มันตรวจจับวัตถุทางซ้าย มันจะแสดงคำว่า "left" เป็นสีน้ำเงิน และเมื่อใดก็ตามที่มันตรวจจับวัตถุทางขวา มันจะแสดงคำว่า "right" เป็นสีแดง
The Proportional-Integral-Derivative (PID) Struggle
ถ้า Arduino แค่สั่งให้เซอร์โวหมุนสุดไปทางซ้ายตอนลูกบอลกลิ้งไปขวา ลูกบอลจะกระเด็นออกจากโต๊ะทันทีเลย! น้องต้องปรับแต่ง **PID Controller** ให้ดี:
- Proportional (P): เอียงแผ่นตามระยะห่างของลูกบอลจากจุดศูนย์กลางเป๊ะๆ
- Derivative (D): ถ้าลูกบอลกำลังวิ่งเร็วมากไปทางขอบ ให้เอียงแผ่นแบบดุดันแต่เนิ่นๆ เพื่อทำหน้าที่เป็นเบรกทางกายภาพ!
- Integral (I): ถ้าลูกบอลค่อยๆ เฉไปจากศูนย์กลางเรื่อยๆ เพราะโต๊ะเอียง ให้ค่อยๆ เพิ่มมุมเอียงเพื่อดันมันกลับมาที่ศูนย์กลางจริงๆ!
หลังจากตรวจจับแล้ว Python จะส่งข้อมูลไปยังไมโครคอนโทรลเลอร์ผ่าน Serial และไมโครคอนโทรลเลอร์ก็จะขยับมอเตอร์ตามข้อมูลที่ได้รับ ในช่วงนี้เซ็นเซอร์อัลตราโซนิกจะถูกตัดออก และงานทรงตัวทั้งหมดจะทำโดยกล้องกับเซอร์โว สู้งานนะน้อง
ฮาร์ดแวร์สำหรับควบคุมหุ่นยนต์
- แล็ปท็อป หรือ Raspberry Pi 4 (ต้องมีนะตัวนี้! ไม่งั้นจะรันโค้ด Python OpenCV ที่เล่นกับเมทริกซ์ภาพซับซ้อนๆ ตรงๆ ไม่ได้เลย)
- เว็บแคม USB (ต้องติดตั้งแบบจ้องก้มลงมาที่พื้นงานเลยนะ ควรได้ 60FPS จะได้ดีเลย์น้อยๆ ติดตามวัตถุได้ทันใจ)
- Arduino Uno / Nano (เจ้านี่ทำหน้าที่เป็นทาสรับคำสั่งผ่านสาย Serial อย่างเดียว ไว้คุมมอเตอร์)
- เซอร์โวมอเตอร์ความเร็วสูง 2 ตัว (เช่น SG90 หรือ MG90S) ติดตั้งบนข้อต่อ Gimbal 2 แกนที่พิมพ์จากเครื่อง 3D Printer
- แผ่นอะคริลิคใส หรือกระจกขาว (พื้นหลังต้องตัดกับลูกบอลสีส้มให้ชัด จะได้ให้ OpenCV วิเคราะห์ภาพง่ายๆ ไม่มีหลุด)