ระดับกลาง
สร้างหุ่นยนต์เดินตามเส้น
หุ่นยนต์เซ็นเซอร์การเคลื่อนไหว
ขั้นต่อไปที่เหนือกว่ารถยนต์หุ่นยนต์พื้นฐาน คือการอ่านพื้นแบบเรียลไทม์และขับเคลื่อนไปตามเส้นโดยอัตโนมัติ
รวมชิ้นส่วนจริง 7 รายการ
ราคารวมชุดนี้: 1,684.00 ฿
ยังไม่รวมส่วนลดคำสั่งซื้อที่คุณอาจได้รับตอนชำระเงิน
สิ่งที่คุณต้องใช้
เป้าหมายของโครงการ
โครงการนี้ต่อยอดจากฐานหุ่นยนต์สองล้อแบบเดียวกับที่ใช้ในรถหุ่นยนต์พื้นฐาน โดยเพิ่มอาร์เรย์เซ็นเซอร์ที่หันลงด้านล่างเพื่อให้หุ่นยนต์สามารถอ่านพื้นด้านล่างและควบคุมตัวเองให้เคลื่อนที่ไปตามเส้นได้โดยอัตโนมัติ ซึ่งเป็นการก้าวไปอีกขั้นจากการขับขี่ด้วยมือหรือที่ตั้งโปรแกรมไว้ล่วงหน้าไปสู่การควบคุมแบบวงปิด
คอนโทรลเลอร์ทำอะไร
ESP32-S3 ทำงานวนลูปควบคุม: อ่านอาร์เรย์เซ็นเซอร์เส้น, ตัดสินใจว่าหุ่นยนต์อยู่ห่างจากจุดศูนย์กลางเท่าใด, คำนวณการแก้ไขการบังคับเลี้ยว, และส่งคำสั่งความเร็วที่อัปเดตไปยังแต่ละล้อผ่านไดรเวอร์มอเตอร์ ลูปนี้จะวนซ้ำอย่างต่อเนื่องและเร็วพอที่หุ่นยนต์จะสามารถตอบสนองต่อเส้นแบบเรียลไทม์ขณะเคลื่อนที่
แชสซีและมอเตอร์ทำอะไร
ชุดแชสซี 2WD มีชุดขับเคลื่อนทางกายภาพ ซึ่งประกอบด้วยล้อสองล้อที่ขับเคลื่อนอิสระ โดยแต่ละล้อหมุนด้วยมอเตอร์เกียร์ DC ของตัวเอง เนื่องจากล้อเป็นอิสระ หุ่นยนต์จึงบังคับทิศทางโดยการใช้มอเตอร์ทั้งสองที่ความเร็วต่างกัน ไม่ใช่โดยการหมุนชุดล้อ ซึ่งคล้ายกับรถถัง พลังงานสำหรับมอเตอร์มาจากแบตเตอรี่ 18650 ซึ่งแยกจากแหล่งจ่ายไฟลอจิกของคอนโทรลเลอร์ที่ไดรเวอร์มอเตอร์ต้องการ
ไดรเวอร์มอเตอร์ทำอะไร
TB6612FNG อยู่ระหว่างคอนโทรลเลอร์และมอเตอร์ พินของคอนโทรลเลอร์ไม่สามารถจ่ายกระแสไฟฟ้าที่มอเตอร์ DC ดึงได้อย่างปลอดภัย ดังนั้นไดรเวอร์จะรับสัญญาณลอจิกกำลังต่ำจากคอนโทรลเลอร์และใช้เพื่อเปิดและปิดแหล่งจ่ายไฟมอเตอร์ที่มีกระแสไฟฟ้าสูงกว่า (และในทิศทางใด) ซึ่งทำหน้าที่เป็นเครื่องขยายกระแสและสวิตช์ทิศทางสำหรับมอเตอร์ทั้งสองอย่างอิสระ
อาร์เรย์เซ็นเซอร์เส้นทำอะไร
อาร์เรย์ติดตามเส้น IR 5 ช่องติดตั้งโดยหันหน้าไปทางพื้น เซ็นเซอร์ทั้งห้าตัวแต่ละตัวจะรายงานโดยอิสระว่ากำลังมองเห็นเส้นสีเข้มหรือพื้นผิวที่สว่างกว่าอยู่ข้างใต้หรือไม่ เมื่ออ่านรวมกัน รูปแบบที่เกิดขึ้นบนเซ็นเซอร์ทั้งห้าตัว ซึ่งได้แก่ เซ็นเซอร์ตัวใดมองเห็นเส้นและตัวใดไม่เห็น จะบอกคอนโทรลเลอร์ได้อย่างแม่นยำว่าหุ่นยนต์อยู่ห่างจากจุดศูนย์กลางเมื่อเทียบกับเส้นเป็นระยะทางเท่าใด ไม่ใช่แค่ว่าอยู่บนเส้นหรือหลุดจากเส้นเท่านั้น
การบังคับเลี้ยวแบบสัดส่วน
แนวคิดการควบคุมหลักในโครงการนี้คือการบังคับเลี้ยวแบบสัดส่วน แทนที่จะเป็นการบังคับเลี้ยวแบบบิ๊กแบง (เลี้ยวซ้ายสุด / เลี้ยวขวาสุด) แทนที่จะตอบสนองในลักษณะเดียวกันกับการเบี่ยงเบนใดๆ คอนโทรลเลอร์จะคำนวณว่ารูปแบบเซ็นเซอร์แสดงว่าหุ่นยนต์เบี่ยงออกจากจุดศูนย์กลางไปเท่าใด และปรับการแก้ไขให้เหมาะสม: การเบี่ยงเบนเล็กน้อยจะได้รับการแก้ไขที่เล็กน้อยและนุ่มนวล และการเบี่ยงเบนที่ใหญ่ขึ้นจะได้รับการแก้ไขที่แรงขึ้น ซึ่งจะผ่อนคลายลงอีกครั้งเมื่อหุ่นยนต์กลับมาอยู่ตรงกลางเส้น สิ่งนี้ทำให้การติดตามเส้นราบรื่นและเร็วกว่าวิธีการแบบทั้งหมดหรือไม่มีเลย
แนวคิดซอฟต์แวร์และไลบรารี
จัดโครงสร้างโค้ดของคุณเป็นสามขั้นตอนที่ชัดเจนในแต่ละลูป: อ่านค่าเซ็นเซอร์ทั้งห้าค่าลงในอาร์เรย์, คำนวณค่า "ข้อผิดพลาด" เดียวที่แสดงว่ารูปแบบนั้นเบี่ยงเบนจากจุดศูนย์กลางเท่าใด, จากนั้นแปลงข้อผิดพลาดนั้นเป็นคำสั่งความเร็วของมอเตอร์ซ้าย/ขวาแต่ละตัวที่ส่งผ่านไลบรารีไดรเวอร์มอเตอร์ การแยกสามขั้นตอนเหล่านี้ออกจากกันในโค้ดจะทำให้การแก้จุดบกพร่องแต่ละขั้นตอนเป็นอิสระได้ง่ายขึ้นมาก เช่น การพิมพ์รูปแบบเซ็นเซอร์ดิบและค่าข้อผิดพลาดที่คำนวณได้ก่อนที่คุณจะแตะมอเตอร์ด้วยซ้ำ
การทดสอบและการแก้ไขปัญหา
- หุ่นยนต์ไม่ตรวจจับเส้นเลย — ตรวจสอบความสูงและระยะห่างของอาร์เรย์เซ็นเซอร์จากพื้น และยืนยันว่าเส้นมีคอนทราสต์เพียงพอเมื่อเทียบกับสีพื้นเพื่อให้เซ็นเซอร์ IR แยกแยะได้
- หุ่นยนต์แกว่งไปมาอย่างรุนแรงแทนที่จะติดตามอย่างราบรื่น — การแก้ไขการบังคับเลี้ยวรุนแรงเกินไปสำหรับระยะห่างของเซ็นเซอร์และความเร็วปัจจุบัน สิ่งนี้ต้องมีการปรับแต่ง โดยทั่วไปคือการลดความแรงของค่าข้อผิดพลาดที่ถูกปรับขนาดเป็นการแก้ไข
- หุ่นยนต์จะเคลื่อนที่ไปด้านใดด้านหนึ่งอย่างสม่ำเสมอแม้ในส่วนตรงของเส้น — ตรวจสอบมอเตอร์ที่ต่อสายผิดหรือทำงานได้ไม่ดีในด้านนั้นก่อนที่จะสันนิษฐานว่ามีปัญหาเซ็นเซอร์ การทดสอบง่ายๆ คือการใช้งานมอเตอร์ทั้งสองที่ความเร็วคงที่เท่ากันโดยไม่มีอินพุตจากเซ็นเซอร์ และดูว่าหุ่นยนต์ยังคงเคลื่อนที่ไปด้านใดด้านหนึ่งหรือไม่
- หุ่นยนต์หลุดจากเส้นทั้งหมดเมื่อเลี้ยวหักศอก — นี่มักเป็นสัญญาณว่าการแก้ไขตามสัดส่วนถูกจำกัดไว้ต่ำเกินไปที่จะตอบสนองได้ทันเวลา ยืนยันว่าโค้ดของคุณอนุญาตให้มีการแก้ไขสูงสุดที่แรงพอสำหรับค่าข้อผิดพลาดขนาดใหญ่
การอัปเกรดในอนาคตแบบเลือกได้: การตรวจจับสิ่งกีดขวางด้านหน้า
เมื่อการติดตามเส้นเชื่อถือได้แล้ว ให้ดูโครงการระบบเตือนระยะทางสำหรับการเพิ่มการตรวจจับสิ่งกีดขวางด้านหน้าโดยใช้แนวคิดเซ็นเซอร์ตรวจจับระยะทางอัลตราโซนิกประเภท HC-SR04 เดียวกัน ซึ่งเป็นการเพิ่มเติมที่เป็นธรรมชาติที่ช่วยให้หุ่นยนต์หยุดหรือเปลี่ยนเส้นทางแทนที่จะขับชนสิ่งกีดขวางเส้น
การเดินสาย
- ตัวยึดแบตเตอรี่ 18650 (2 ช่อง, การเดินสายอนุกรม, ~7.4V เล็กน้อย) → TB6612FNG VM ผ่านสวิตช์บนบอร์ดของตัวยึด
- GND ของชุดแบตเตอรี่ → TB6612FNG GND และเชื่อมต่อกับกราวด์ร่วมกับ ESP32-S3 และอาร์เรย์ IR
- ESP32-S3 3.3V → TB6612FNG VCC — แหล่งจ่ายไฟลอจิก
- ESP32-S3 GPIO9 → TB6612FNG STBY (`MOTOR_STBY_PIN`) — ต้องขับเป็น HIGH เพื่อเปิดใช้งานเอาต์พุตไดรเวอร์
- ESP32-S3 GPIO10 → TB6612FNG AIN1 (`AIN1_PIN`)
- ESP32-S3 GPIO11 → TB6612FNG AIN2 (`AIN2_PIN`)
- ESP32-S3 GPIO12 → TB6612FNG PWMA (`PWMA_PIN`)
- ESP32-S3 GPIO13 → TB6612FNG BIN1 (`BIN1_PIN`)
- ESP32-S3 GPIO14 → TB6612FNG BIN2 (`BIN2_PIN`)
- ESP32-S3 GPIO21 → TB6612FNG PWMB (`PWMB_PIN`)
- TB6612FNG A01/A02 → ขั้วมอเตอร์ DC ซ้าย
- TB6612FNG B01/B02 → ขั้วมอเตอร์ DC ขวา
- VCC ของอาร์เรย์เซ็นเซอร์ IR → 5V, GND → GND (ตรวจสอบโมดูลของคุณ — อาร์เรย์ IR 5 ช่องส่วนใหญ่ต้องการ 5V เพื่อความสว่างของตัวปล่อยที่สม่ำเสมอ บางตัวทำงานที่ 3.3V)
- เอาต์พุดดิจิทัล 5 ตัวของอาร์เรย์ IR → ESP32-S3 GPIO1, GPIO2, GPIO4, GPIO5, GPIO6 (`IR_PINS[0..4]`)
รายการชิ้นส่วนนี้ไม่มีตัวแปลง buck แยกสำหรับแหล่งจ่ายไฟลอจิกของ ESP32-S3 เอง — บอร์ดพัฒนา S3 จำนวนมากมีตัวควบคุมบนบอร์ดบนพิน 5V/VIN ที่รองรับอินพุตที่สูงกว่า ดังนั้นคุณอาจสามารถจ่ายแรงดันแบตเตอรี่ดิบที่นั่นได้หากตัวควบคุมของบอร์ดเฉพาะของคุณรองรับ (ตรวจสอบเอกสารข้อมูลก่อน) มิฉะนั้นให้จ่ายไฟให้ S3 จาก USB-C ผ่านพาวเวอร์แบงก์ขนาดเล็กในขณะที่ทดสอบแบบไร้สาย GPIO0 และ GPIO3 เป็นพินสำหรับ strapping บน ESP32-S3 และหลีกเลี่ยงโดยตั้งใจ หากบอร์ดพัฒนาเฉพาะของคุณสงวน GPIO อื่นๆ สำหรับแฟลช/PSRAM บนบอร์ด ให้ทำการแมป `#define` ใหม่ให้เป็นสิ่งที่มีการต่อออกมาจริง โมดูลเซ็นเซอร์ IR แต่ละตัวมักจะมีโพเทนชิออมิเตอร์บนบอร์ดของตัวเองเพื่อปรับเกณฑ์แสง/มืด — ทำเช่นนั้นบนพื้นผิวแทร็กจริงของคุณก่อนที่จะเชื่อถือเอาต์พุตดิจิทัล HIGH/LOW และยืนยันเสมอว่า STBY เป็น HIGH ก่อนที่จะคาดหวังการตอบสนองของมอเตอร์ใดๆ
แผนภาพการต่อสาย
โค้ดเริ่มต้น
// Line-following robot: 5-channel IR array + TB6612FNG dual motor driver
#define MOTOR_STBY_PIN 9
#define AIN1_PIN 10
#define AIN2_PIN 11
#define PWMA_PIN 12
#define BIN1_PIN 13
#define BIN2_PIN 14
#define PWMB_PIN 21
const int IR_PINS[5] = {1, 2, 4, 5, 6}; // far-left, left, center, right, far-right
const int BASE_SPEED = 150; // 0-255
const int MAX_SPEED = 255;
const int TURN_GAIN = 60; // how hard to correct per unit of error
void setMotor(int in1Pin, int in2Pin, int pwmPin, int speed) {
speed = constrain(speed, -MAX_SPEED, MAX_SPEED);
if (speed >= 0) {
digitalWrite(in1Pin, HIGH);
digitalWrite(in2Pin, LOW);
} else {
digitalWrite(in1Pin, LOW);
digitalWrite(in2Pin, HIGH);
speed = -speed;
}
analogWrite(pwmPin, speed); // Arduino-ESP32 core 3.x supports analogWrite() directly on PWM-capable pins
}
void setup() {
Serial.begin(115200);
pinMode(MOTOR_STBY_PIN, OUTPUT);
pinMode(AIN1_PIN, OUTPUT);
pinMode(AIN2_PIN, OUTPUT);
pinMode(PWMA_PIN, OUTPUT);
pinMode(BIN1_PIN, OUTPUT);
pinMode(BIN2_PIN, OUTPUT);
pinMode(PWMB_PIN, OUTPUT);
for (int i = 0; i < 5; i++) {
pinMode(IR_PINS[i], INPUT);
}
digitalWrite(MOTOR_STBY_PIN, HIGH); // enable driver outputs
Serial.println("Line follower ready.");
}
void loop() {
int sensorVal[5];
for (int i = 0; i < 5; i++) {
sensorVal[i] = digitalRead(IR_PINS[i]); // assume HIGH = line detected; flip if your array is inverted
}
// Weighted position error: -2 (far left) ... 0 (centered) ... +2 (far right)
int weights[5] = {-2, -1, 0, 1, 2};
int weightedSum = 0;
int activeCount = 0;
for (int i = 0; i < 5; i++) {
if (sensorVal[i] == HIGH) {
weightedSum += weights[i];
activeCount++;
}
}
if (activeCount == 0) {
// Line lost — stop rather than guess
setMotor(AIN1_PIN, AIN2_PIN, PWMA_PIN, 0);
setMotor(BIN1_PIN, BIN2_PIN, PWMB_PIN, 0);
return;
}
int error = weightedSum; // simple proportional error, no averaging needed for 5 discrete sensors
int correction = error * TURN_GAIN;
int leftSpeed = BASE_SPEED + correction;
int rightSpeed = BASE_SPEED - correction;
setMotor(AIN1_PIN, AIN2_PIN, PWMA_PIN, leftSpeed);
setMotor(BIN1_PIN, BIN2_PIN, PWMB_PIN, rightSpeed);
}
ไม่แน่ใจขั้นตอนไหน?
ถามเรา