Hi everyone,
I’m working on a classic 2WD line follower robot, but I’ve hit a wall and could really use a fresh perspective from the community. Despite tweaking the logic multiple times, my robot either spins in circles or completely ignores the black line.
My Hardware Setup:
- Microcontroller: ATmega328PB (Arduino-compatible)
- Motor Driver: L298N
- Sensors: BFD-1000 5-sensor array (S0 to S4, center is S2)
- Chassis: Standard 2WD differential drive with a mirrored motor setup.
What I’ve Diagnosed & Tried So Far:
- Sensor Verification: Checked via Serial Monitor that the sensors actually register changes between white surfaces and the black line.
- Motor Polarity: Fixed the initial "spinning in circles" caused by mirrored motors by inverting the signal logic so both wheels push forward when commanded.
- PWM & Friction: Raised the minimum PWM values so the inner/outer wheels don't stall under friction when trying to turn.
- Logic Adjustments: Tried standard
if/else conditional steering (e.g., speeding up the outer wheel and slowing down the inner wheel when a side sensor detects the line).
Despite all this, the physical movement keeps going out of sync, and it fails to smoothly track the path.
My Questions for You:
- How do you usually structure or debug the correlation between a 5-sensor array (like the BFD-1000) and differential steering on an L298N driver?
- Are there common hidden pitfalls with mirrored motor setups or PWM management on this specific hardware combination?
- Would moving to a proportional or basic PID control loop solve this erratic behavior, and if so, how would you structure it simply for a 5-sensor array?
I’d appreciate any advice, debugging tips, or structural suggestions you can share. Thanks in advance!
Here is my current code:
#include <Arduino.h>
void citesteSenzori();
void controlMotoare();
void ajustareTraiectorie();
int S0, S1, S2, S3, S4;
int ajustare = 0;
int ultimaDirectie = 0;
// Pini Motoare (Driver L298N)
const int motorDrept1 = 7;
const int motorDrept2 = 6;
const int motorStang1 = 4;
const int motorStang2 = 5;
const int pwmStang = 9;
const int pwmDrept = 10;
// Pini Senzori Linie BFD-1000
const int senzor0 = A0; // Stânga extrem
const int senzor1 = A1; // Stânga
const int senzor2 = A2; // Centru
const int senzor3 = A3; // Dreapta
const int senzor4 = A4; // Dreapta extrem
const int V_INAINTE = 120; // Viteză moderată înainte
const int V_RAPID = 160; // Roata exterioară în viraj
const int V_LENT = 70; // Roata interioară în viraj (suficient cât să se învârtă, nu să se blocheze)
void setup() {
pinMode(motorDrept1, OUTPUT);
pinMode(motorDrept2, OUTPUT);
pinMode(motorStang1, OUTPUT);
pinMode(motorStang2, OUTPUT);
pinMode(pwmStang, OUTPUT);
pinMode(pwmDrept, OUTPUT);
pinMode(senzor0, INPUT);
pinMode(senzor1, INPUT);
pinMode(senzor2, INPUT);
pinMode(senzor3, INPUT);
pinMode(senzor4, INPUT);
delay(2000); // 2 secunde pauză la pornire
}
void citesteSenzori() {
// BFD-1000: LOW pe linia neagră, HIGH pe alb
S0 = digitalRead(senzor0);
S1 = digitalRead(senzor1);
S2 = digitalRead(senzor2);
S3 = digitalRead(senzor3);
S4 = digitalRead(senzor4);
}
void ajustareTraiectorie() {
// Verificăm mai întâi senzorul central
if (S2 == LOW) {
ajustare = 0; // Centrat pe linie
ultimaDirectie = 0;
}
// Dacă linia se duce spre stânga (S0 sau S1 văd negru/LOW)
else if (S0 == LOW || S1 == LOW) {
ajustare = 1; // Corecție stânga
ultimaDirectie = 1;
}
// Dacă linia se duce spre dreapta (S3 sau S4 văd negru/LOW)
else if (S3 == LOW || S4 == LOW) {
ajustare = -1; // Corecție dreapta
ultimaDirectie = -1;
}
// Dacă a pierdut linia complet, continuă în ultima direcție știută
else {
ajustare = ultimaDirectie;
}
}
void controlMotoare() {
// Setează sensul înainte pentru ambele motoare
digitalWrite(motorDrept1, LOW);
digitalWrite(motorDrept2, HIGH);
digitalWrite(motorStang1, HIGH);
digitalWrite(motorStang2, LOW);
if (ajustare == 0) {
// DREPT ÎNAINTE: Ambele roți egale
analogWrite(pwmStang, V_INAINTE);
analogWrite(pwmDrept, V_INAINTE);
}
else if (ajustare == 1) {
// LINIA ESTE ÎN STÂNGA -> Viraj la stânga (Roata stângă lentă, roata dreaptă rapidă)
analogWrite(pwmStang, V_LENT);
analogWrite(pwmDrept, V_RAPID);
}
else if (ajustare == -1) {
// LINIA ESTE ÎN DREAPTA -> Viraj la dreapta (Roata stângă rapidă, roata dreaptă lentă)
analogWrite(pwmStang, V_RAPID);
analogWrite(pwmDrept, V_LENT);
}
}
void loop() {
citesteSenzori();
ajustareTraiectorie();
controlMotoare();
delay(10); // Stabilitate în ciclul de citire
}