Danh sách linh kiện
Các bước thực hiện
6 bướcBước 1: Cảm biến line TCRT5000
TCRT5000 là module quang học hồng ngoại: 1 LED IR phát + 1 phototransistor nhận. Đặt cách mặt đất 0.5–1.5cm:
- Trên nền trắng: IR dội mạnh → output LOW (active low).
- Trên vạch đen: IR bị hấp thụ → output HIGH.
Cũng có thể dùng LDR + LED đỏ nhưng kém ổn định hơn. Module TCRT5000 ~15k VN, có biến trở chỉnh ngưỡng.
Bước 2: Linh kiện
- Khung xe 2 bánh + 2 motor + bánh xoay.
- Arduino Uno.
- L298N motor driver.
- 2× TCRT5000 (đặt cách nhau 2–3cm, ôm vạch line).
- Pin 8.4V (2× 18650).
2 cảm biến đủ cho line đơn giản. Cho line phức tạp (góc nhọn, ngã 3): dùng 5–8 cảm biến (module array).
Bước 3: Đấu nối
- L298N: IN1/IN2 → D8/D9 (motor trái), IN3/IN4 → D10/D11 (motor phải). ENA → D5, ENB → D6.
- TCRT5000 trái: DO → D2, VCC → 5V, GND → GND.
- TCRT5000 phải: DO → D3, VCC → 5V, GND → GND.
- Pin 8.4V → 12V L298N. GND chung.
Đặt 2 cảm biến cách trục bánh trước 5–10cm, cách mặt đất 0.8cm, cách nhau 2cm (đủ để vạch line 1.5cm đi giữa).
Bước 4: Code logic basic — bang-bang
Logic đơn giản nhất:
- Cả 2 cảm biến THẤY trắng → vạch ở giữa → đi thẳng.
- Bên trái thấy ĐEN → vạch nghiêng trái → quay TRÁI.
- Bên phải thấy ĐEN → vạch nghiêng phải → quay PHẢI.
- Cả 2 ĐEN → vạch giao nhau / cuối → dừng.
const int L_SENSOR = 2;
const int R_SENSOR = 3;
const int IN1=8, IN2=9, IN3=10, IN4=11, ENA=5, ENB=6;
const int SPEED = 130;
void setMotor(int l, int r) {
// l, r: -255..255
digitalWrite(IN1, l >= 0 ? HIGH : LOW);
digitalWrite(IN2, l >= 0 ? LOW : HIGH);
digitalWrite(IN3, r >= 0 ? HIGH : LOW);
digitalWrite(IN4, r >= 0 ? LOW : HIGH);
analogWrite(ENA, abs(l));
analogWrite(ENB, abs(r));
}
void setup() {
pinMode(L_SENSOR, INPUT);
pinMode(R_SENSOR, INPUT);
for (int p : {IN1, IN2, IN3, IN4, ENA, ENB}) pinMode(p, OUTPUT);
}
void loop() {
int l = digitalRead(L_SENSOR); // HIGH = thấy đen
int r = digitalRead(R_SENSOR);
if (l == LOW && r == LOW) {
// Cả 2 trên trắng — đi thẳng
setMotor(SPEED, SPEED);
} else if (l == HIGH && r == LOW) {
// Trái thấy đen → quay trái nhẹ
setMotor(0, SPEED);
} else if (l == LOW && r == HIGH) {
// Phải thấy đen → quay phải
setMotor(SPEED, 0);
} else {
// Cả 2 đen — dừng (cuối line hoặc ngã)
setMotor(0, 0);
}
delay(10);
}
Bước 5: Nâng cấp PID với analog sensor
Bang-bang giật giật. Để mượt hơn, dùng cảm biến output analog (đọc với analogRead):
// Đọc analog từ TCRT (output AO thay vì DO)
const int L_SENSOR_A = A0;
const int R_SENSOR_A = A1;
float Kp = 0.4, Ki = 0.001, Kd = 5.0;
float error_prev = 0, integral = 0;
void loop() {
int l = analogRead(L_SENSOR_A);
int r = analogRead(R_SENSOR_A);
// Error: dương = lệch trái, âm = lệch phải
int error = l - r;
integral += error;
integral = constrain(integral, -1000, 1000);
float derivative = error - error_prev;
float pid = Kp * error + Ki * integral + Kd * derivative;
error_prev = error;
int leftSpeed = constrain(SPEED + pid, -255, 255);
int rightSpeed = constrain(SPEED - pid, -255, 255);
setMotor(leftSpeed, rightSpeed);
delay(5);
}
Bước 6: Tune PID và đường đua
Tune PID:
- Đặt Kp lớn dần (0.1, 0.2, 0.4, 0.8) — xe bắt đầu wobble.
- Giảm Kp lại 30%.
- Tăng Kd để giảm wobble (~Kp × 10).
- Ki nhỏ (0.001–0.01) chỉ khi xe lệch lâu dài.
Đường đua: in vạch đen 1.5–2cm rộng trên giấy A0 trắng, dán xuống sàn. Đường cong bán kính > 20cm. Đường thẳng + góc 90° cho thử thách cao hơn.
Cuộc thi line follower: nhiều CLB robot ở VN tổ chức. Robot tốt chạy 1 vòng 5m trong 3–4 giây.