รถไร้คนขับนี่เป็นเรื่องฮิตสุดๆ ไปแล้ววัยรุ่น พวกนักเล่นๆ ก็พยายามทำกันด้วย Raspberry Pi กับ Computer Vision นั่นก็เป็นวิธีหนึ่ง แต่มีอีกวิธีที่ง่ายกว่านั่นคือทำพวกหุ่นยนต์ไลน์ฟอลโลเวอร์หรือหุ่นแก้เขาวงกต พวกนี้มันจะวิ่งตามเส้นสีที่เราวาดไว้บนพื้น เราทำได้ด้วยกล้องหรือเซ็นเซอร์ IR
แต่ถ้าพี่บอกว่า... "เฮ้ย พี่ไม่อยากวาดเส้นบนพื้นเลยอะ อยากให้มันวิ่งตามเส้นล่องหน" ล่ะ? นี่แหละที่พี่ทำมา Virtual Maze Solver/Path follower robot ตัวนี้มันวิ่งตามเส้นทางที่ส่งมาจากคอมพิวเตอร์อีกเครื่องนึง หมายความว่าตัวหุ่นมันไม่มีเซ็นเซอร์อะไรเลย มันแค่รับพิกัดจาก PC — ที่มีหุ่นยนต์ซอฟต์แวร์อีกตัวกำลังแก้เขาวงกตอยู่ — แล้วหุ่นยนต์จริงๆ (ฮาร์ดแวร์) ก็จะขยับตามที่หุ่นซอฟต์แวร์ขยับ ดูวิดีโอข้างบนจะเข้าใจมากขึ้น เอาล่ะ มาดูกันดีกว่าว่าพี่ทำยังไง
อุปกรณ์ที่ต้องใช้:






ฮาร์ดแวร์ -
ส่วนอิเล็กทรอนิกส์ -
- Arduino Nano (บอร์ดอื่นก็ได้ แต่ PCB ของพี่ออกแบบมาสำหรับตัวนี้) - 1 ตัว
- L298n Motor Driver module (เอาไว้ควบคุมมอเตอร์) - 1 ตัว
- มอเตอร์ - 4 ตัว
- ล้อ (ให้เข้ากับมอเตอร์) - 4 ล้อ
- HC05 Bluetooth module (สำหรับส่ง/รับข้อมูล) - 1 ตัว
- Multi-functional robot PCB ที่พี่ออกแบบเอง - 1 แผ่น
- พินหัวผู้-หัวเมียบ้าง
- ตะกั่วบัดกรี (เอาไว้บัดกรีของลง PCB)
สำหรับทำโครงตัวถัง -
- แผ่น PVC (จะใช้ไม้อัดหรือกระดาษแข็งก็ได้ พี่ชอบ PVC)
- กาวร้อนกับปืนกาว
ซอฟต์แวร์ -
- Arduino.ide
- Python3 (ไม่ต้องกังวล พี่จะค่อยๆ บอกวิธีติดตั้งให้)
แค่นี้แหละน้อง เอาล่ะ มาดูกันต่อว่าทุกอย่างมันจะทำงานยังไง
หลักการทำงาน (มันจะทำงานยังไง)

ง่ายๆเลยน้อง โรบอทตัวนี้จะเป็นรถโรบอทควบคุมผ่านบลูทูธ (Bluetooth) ตัวโค้ด Python จะโหลดแผนที่หรือเขาวงกตขึ้นมาในคอม แล้วพยายามหาทางออก ส่วนตัวฮาร์ดแวร์โรบอทจะรับข้อมูลจากโปรแกรม Python ผ่านบลูทูธแล้วขยับตามนั้น
โปรแกรม Python จะหาทางโดยการเปรียบเทียบค่าสี แผนที่ของเราจะเป็นเส้นทางสีขาว ตราบใดที่ยังมีพิกเซลสีขาวอยู่ รถในซอฟต์แวร์ก็จะวิ่งไปข้างหน้า แล้วตัวโรบอทจริงๆก็จะขยับตามไปด้วย เอาล่ะ มาลงมือทำกันเลยดีกว่า
มาสร้างโครงรถ (Chassis) กัน











พี่หยิบแผ่น PVC สองแผ่นมาตัดตามที่ออกแบบไว้ น้องจะทำแบบไหนก็ตามสไตล์เลย หลังจากตัดแผ่นแล้วก็วางมอเตอร์ ต่อสายให้เรียบร้อย มอเตอร์สองตัวที่อยู่ข้างเดียวกันจะทำงานเหมือนเป็นมอเตอร์ตัวเดียว ดังนั้นก็ต่อสายรวมกันเลย ในรูปที่ 6 พี่ใช้สายจัมเปอร์แบบเมีย-เมีย (female-to-female) ต่อจากขาควบคุมมอเตอร์ไปยัง PCB หลังจากนั้นก็เพิ่มชิ้นส่วน PVC สีฟ้าเข้าไปสองชิ้นเพื่อตกแต่งตัวถัง แล้วก็ติดล้อเข้าไป
แผนภาพวงจรและ PCB


พี่ออกแบบวงจรโดยใช้ซอฟต์แวร์ออกแบบ PCB ออนไลน์ วงจรมันง่ายพอควร พี่ปล่อยขาแอนะล็อกทั้งหมดว่างไว้ ยกเว้น A4 กับ A5 (สองขานี้ไว้สำหรับการสื่อสาร I2C) แล้วเพิ่มตัวอ่านการ์ด SD, โมดูลบลูทูธ และตำแหน่งสำหรับ Arduino nano เข้าไป โมดูลบลูทูธแยกออกมาด้วยจัมเปอร์ (ตอนอัปโหลดโค้ด เราต้องถอดมันออก) เราไม่ต้องใช้ตัวต้านทาน (Resistor) เพราะ Arduino จะเป็นฝ่ายรับข้อมูลอย่างเดียว ไม่ได้เขียนออกไป
หลังจากนั้นพี่ก็ส่งไฟล์ไปผลิต PCB ผ่านบริการผลิต PCB ออนไลน์ พี่ว่าบริการของเค้าประทับใจมากเลย ให้ของคุณภาพดีในราคาที่ไม่แพง พี่เลยชอบใช้บริการเค้าเวลาทำ PCB พี่เข้าไปที่หน้า "สั่งผลิต PCB ด่วน" อัพโหลดไฟล์ Gerber ขึ้นไป ทุกอย่างดำเนินการอัตโนมัติโดยเว็บไซต์ หลังจากที่ PCB ของพี่ผ่านการตรวจสอบโดยวิศวกรของทางร้านแล้ว พี่ก็ชำระเงินและได้รับของภายใน 3 วันจากจีนมาถึงบังกลาเทศเลย คุณภาพสุดยอดมาก ทั้ง solder mask, เส้นลายวงจร, ความเงาแวววาว ทำให้พี่ตื่นเต้นทุกที
การต่อสาย (Connections):
พี่ต่อสายดังนี้
- มอเตอร์ซ้าย ไปที่ขา D5, D6
- มอเตอร์ขวา ไปที่ขา D3, D4
โมดูลบลูทูธต่อเข้ากับพอร์ตที่จัดไว้ให้แล้ว แต่ถ้าจะให้ชัดเจนก็คือ...
- VCC ต่อกับ 5v
- Gnd ต่อกับ gnd
- tx ต่อกับ Arduino Rx
- Rx ต่อกับ Arduino Tx
หลักการง่ายๆ คือ สิ่งที่น้องส่ง (Tx) คือสิ่งที่พี่รับ (Rx) นั่นเอง ดังนั้นขา Rx ของ Arduino ก็ต้องไปต่อกับขา Tx ของโมดูลบลูทูธ
จากนั้นก็จ่ายไฟให้ PCB จากโมดูลขับมอเตอร์ พี่ชอบใช้แหล่งจ่ายไฟ 7.4V สำหรับโปรเจคหุ่นยนต์ของพี่เสมอ แบตเตอรี่ลิเธียมสองก้อนก็พอ 3.7+3.7=7.4V เหมาะเจาะมากสำหรับงานแบบนี้
ตอนนี้หุ่นยนต์บลูทูธของเราพร้อมแล้ว ขั้นต่อไปคือการโปรแกรมมัน
Programming1: Arduino Code
ถึงเวลาอัพโหลดโปรแกรมลงหุ่นยนต์แล้ว เนื่องจากโมดูลบลูทูธต่ออยู่กับ Serial ฮาร์ดแวร์ พี่เลยถอดจัมเปอร์ออกก่อนอัพโหลดโค้ด
เริ่มแรกพี่กำหนดก่อนว่ามอเตอร์แต่ละตัวต่ออยู่กับขาไหน -
// Declare motor pins
// motors of same side work as one
// so we can consider both as one.
int rightMotor1 = 2; // right side
int rightMotor2 = 3;
int leftMotor1 = 5; // left side
int leftMotor2 = 6;
จากนั้นพี่ประกาศให้ขามอเตอร์เป็น OUTPUT ในฟังก์ชัน setup() -
// Set pin modes
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
แล้วก็เริ่มต้นการสื่อสารแบบ Serial เพื่อรับข้อมูลจากโมดูลบลูทูธ -
// Initialize serial communication
Serial.begin(9600);
โค้ดจะตรวจสอบข้อมูลไบต์จากพอร์ต Serial ที่โมดูลบลูทูธต่ออยู่
// Variable to store received data
byte command;
// Get command data from bluetooth serial port
command = Serial.read();
ถ้ามันได้รับ -
- 'f' = เดินหน้า
- 'b' = ถอยหลัง
- 'l' = เลี้ยวซ้าย
- 'r' = เลี้ยวขวา
มอเตอร์แต่ละตัวมีสองขา ถ้าจะให้มันหมุนไปทิศทางนึง เราต้องเซ็ตขานึงเป็น HIGH และอีกขาเป็น LOW ถ้าทั้งสองขาเป็น HIGH หรือ LOW พร้อมกัน มอเตอร์จะไม่หมุน ดูตัวอย่างการให้รถเดินหน้า -
if (command == 'f'){
// indicates forward motion
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);}
ด้วยการผสมผสานแบบนี้ เราก็สามารถสั่งงานหุ่นยนต์ได้แล้ว
ดาวน์โหลดโค้ดจากด้านล่างได้เลย พี่แนะนำให้คัดลอกให้ดีๆ ระวังผิดพลาดนะ
/* ** Virtual Path Following Robot *
* Robot Actuator's program
*
* This robot takes commands from a python program
* and follows those commands. This robot demonstrates
* virtual path following robots and it's scopes.
*
* *********** License: GPL3+ *************
* You should receive a copy of the license
* with this program.
*
* (c) author: ashraf minhaj
* mail : ashraf_minhaj@yahoo.com
*
* Tutorial for this project:
* http://youtube.com/fusebatti
* http://ashrafminhajfb.blogspot.com
*
* written on 15th Feb 2021
*/
// Declare motor pins
// motors of same side work as one
// so we can consider both as one.
int rightMotor1 = 2; // right side
int rightMotor2 = 3;
int leftMotor1 = 5; // left side
int leftMotor2 = 6;
// Variable to store received data
byte command;
void setup() {
// Set pin modes
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
// Initialize serial communication
// at 9600 buad rate
// sender/python code will also use
// the same buad
Serial.begin(9600);
}
void loop() {
// Get command data from bluetooth serial port
command = Serial.read();
// Decide which way to go based on received data
if (command == 'f'){
// indicates forward motion
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
}
if (command == 'b'){
// Backward motion
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
}
if (command == 'r'){
// Right turn
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
}
if (command == 'l'){
// Left turn
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
}
if (command == 's'){
// Stops the robot/car
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, LOW);
}
}
จัดไปวัยรุ่น! อัพโหลดโค้ดนี้ผ่าน Arduino IDE ได้เลย แล้วไปขั้นตอนต่อไปโลด
Programming2: Python Code


โอเค น้องน่าจะลง Python ไว้ในเครื่องแล้วมั้ง ถ้ายัง ไปโหลดเวอร์ชั่นล่าสุดที่เสถียรๆ มาลงเลย พี่ใช้ Python 3.7.1 นะ รู้สึกว่าโคตรจะนิ่งเลย เวลาโหลด อย่าลืมเลือก executable installer นะ ดับเบิ้ลคลิกติดตั้ง แล้วติ๊กถูกที่ช่อง 'Add python to environment variable path' ด้วยล่ะ ไม่งั้นเดี๋ยวจะหาว่าพี่ไม่เตือน
เอาล่ะ มาดูโปรแกรม Python กันดีกว่า
สำหรับโปรแกรมนี้พี่ต้องใช้ไลบรารี่ 2 ตัวคือ pygame กับ pySerial ติดตั้งผ่าน Command Prompt แบบนี้เลย -
$ pip install pygame
$ pip install pySerial
รูปสองรูปด้านบนนั่นแหละคือแผนที่เขาวงกตกับรถของเรา โปรแกรม Python จะโหลดรูปพวกนี้เข้ามา -
bg = pygame.image.load("track1.png")
car = pygame.image.load("car.png")
การจะส่งข้อมูลจาก PC ไปหา Arduino ผ่านบลูทูธ พี่ต้องเชื่อมโมดูลบลูทูธกับ PC ก่อน วิธีทำคือ -
- เปิด Bluetooth ใน PC
- ไปที่ Control Panel > Device Manager
- ค้นหาและเพิ่มอุปกรณ์ใหม่
- เพิ่มอุปกรณ์ (HC-05) พร้อมใส่พาสเวิร์ด (ปกติจะเป็น '0000' หรือ '1234')
แค่นั้นแหละ จากนั้นเข้าไปดู Properties ของอุปกรณ์เพื่อหาเลขพอร์ต (Port) ของ HC-05 ในเครื่องพี่คือ 'COM8' เลยเขียนโค้ด Python เชื่อมต่อแบบนี้ -
PORT = "COM8"
BUADRATE = 9600
robot = serial.Serial(PORT, BUADRATE) # connect robot
เพื่อให้หุ่นยนต์ตรวจสอบสิ่งรอบตัว พี่ต้องหาจุดศูนย์กลางของรถก่อน แล้วค่อยตรวจสอบรอบๆ -
# find the center of the car and draw a point on that
center_x, center_y = (int(car_x + 40 /2), int(car_y + 40 / 2))
ส่วนที่เหลือของโค้ดก็คือการตรวจสอบสิ่งกีดขวางและสั่งให้รถเลี้ยวหรือเคลื่อนที่ ถ้ามันเคลื่อนที่ไปข้างหน้าหรือทิศทางไหน ก็จะส่งข้อมูลนั้นไปหา Arduino ผ่านพอร์ตอนุกรม (serial port) แบบนี้ (เป็นข้อมูลแบบ byte) -
# start the robot
robot.write(b'f')
# turn left
robot.write(b'l')
โหลดโค้ดเต็มๆ ไปเลย หรือจะคัดลอกจากด้านล่างนี้ก็ได้ สู้งานนะน้อง!
"""
** Virtual Path Follower Robot **
License: GPL3
You should receive a copy of license with this program.
(c) author: ashraf minhaj
"""
""" install -
$ pip install pygame
$ pip install pySerial
"""
import library
import pygame import serial from time import sleep
robot port and buadrate
change these according to your need
PORT = "COM8" BUADRATE = 9600
initialize things
pygame.init() robot = serial.Serial(PORT, BUADRATE) # connect robot
create window with size (our image size)
window = pygame.display.set_mode((700