Line Follower Robot With Obstacle Avoidance: Code & Guide
Are you fascinated by robotics and eager to build your own line-following robot that can also navigate around obstacles? This comprehensive guide will walk you through the process of creating a line follower robot equipped with rectangular deviation capabilities. We'll delve into the code, hardware components, and the logic behind making this robot function seamlessly. Whether you're a beginner or an experienced enthusiast, this article provides valuable insights and practical steps to bring your robotic vision to life.
Understanding the Project: Line Following with Obstacle Avoidance
Before diving into the technical details, let's understand the core concepts. A line follower robot uses sensors to detect a line (usually black on a white surface or vice versa) and follows it autonomously. The obstacle avoidance feature adds another layer of sophistication, enabling the robot to detect and navigate around obstacles in its path. This project combines these two functionalities, making it an exciting challenge for robotics enthusiasts.
Key Components and Functionality
- Line Following: The robot employs infrared (IR) sensors to detect the line. These sensors differentiate between the line's color and the background, allowing the robot to make necessary adjustments to stay on track.
- Obstacle Detection: An ultrasonic sensor is used to measure the distance to objects in front of the robot. When an obstacle is detected within a certain threshold, the robot initiates an avoidance maneuver.
- Rectangular Deviation: The robot executes a pre-programmed rectangular path to circumvent the obstacle and then returns to the line, ensuring continuous operation.
- Motor Control: A motor driver (L298N) is used to control the robot's motors, enabling precise movements for line following and obstacle avoidance.
This project showcases a blend of sensor technology, motor control, and algorithmic thinking, providing a solid foundation for more advanced robotic projects. The satisfaction of seeing your robot navigate autonomously, avoiding obstacles while staying on course, is truly rewarding.
Hardware Components: What You'll Need
To build your line follower robot with obstacle avoidance, you'll need the following hardware components:
- Microcontroller: Arduino Uno (or similar) - The brain of the robot, processing sensor data and controlling the motors.
- Motor Driver: L298N - An essential component for controlling the speed and direction of the DC motors.
- DC Motors: Two DC motors with wheels - Provide the robot's locomotion.
- IR Sensors: Two digital IR sensors - Detect the line and provide input for line following.
- Ultrasonic Sensor: HC-SR04 - Measures the distance to obstacles.
- Chassis: A platform to mount the components (can be custom-built or purchased).
- Power Supply: Batteries or a power adapter to energize the robot.
- Jumper Wires: For connecting the components.
- Breadboard (optional): For prototyping the circuit.
Each component plays a vital role in the robot's functionality. The Arduino Uno acts as the central processing unit, interpreting sensor data and sending signals to the motor driver. The L298N motor driver amplifies the Arduino's signals to drive the DC motors, enabling precise control over the robot's movement. The IR sensors are the robot's eyes, detecting the line and providing feedback to the Arduino. The HC-SR04 ultrasonic sensor acts as a rangefinder, detecting obstacles in the robot's path. The chassis provides a stable platform for mounting the components, and the power supply keeps the robot running. Jumper wires and a breadboard facilitate easy connections and prototyping.
Before assembling the robot, ensure that you have a clear understanding of each component's function and how they interconnect. Proper wiring and connections are crucial for the robot's reliable operation.
Software Implementation: The Arduino Code
The heart of the robot lies in the Arduino code, which dictates its behavior. Let's break down the code snippet provided, explaining each section and its role in the robot's functionality.
/********************
Seguidor de Linha + Desvio Retangular (simples/didático)
- Driver: L298N (usando PWM nas IN1..IN4)
- Sensores IR digitais: 2 (esq/dir)
- Ultrassônico: HC-SR04
********************/
/* ===================== CONFIG RÁPIDA ===================== */
// Escolha a cor da linha (MANTIDO PRETA):
#define LINHA_PRETA
// Como seu sensor se comporta no PRETO (AJUSTE SE NECESSÁRIO):
#define PRETO_ALTO // sensor lê HIGH no preto (SE O SEU LER LOW, COMENTE ESTE E DESCOMENTE O ABAIXO)
// #define PRETO_BAIXO // sensor lê LOW no preto
// Distância (cm) para iniciar a manobra de desvio
#define OBST_THRESHOLD_CM 20
// Velocidade base (0–255) - RECOMENDADO REDUZIR PARA MELHOR ESTABILIDADE
#define VELOCIDADE 70
#define VELOCIDADEGIRO 100
/* ===== Tempos do desvio retangular (ms) – AJUSTE NO SEU PISO ===== */
#define T_RE 1000 // ré curta para “desgrudar”
#define T_GIRO90 1000 // tempo para ~90°
#define T_DESCER 300 // descer 1 faixa para fora da linha
#define T_PASSAR 100 // avançar paralelo, contornando o obstáculo
#define T_TIMEOUT_SUBIR 100 // tempo máximo procurando a linha ao "subir"
/* ================================================================ */
/* ---------- Pinos L298N (usar PWM nas INs) ---------- */
#define IN1 10 // ~10 (motor esquerdo, frente)
#define IN2 9 // ~9 (motor esquerdo, ré)
#define IN3 6 // ~6 (motor direito, frente)
#define IN4 5 // ~5 (motor direito, ré)
/* ---------- Pinos dos sensores de linha ---------- */
#define PINO_SENSOR_DIREITA 2
#define PINO_SENSOR_ESQUERDA 3
/* ---------- Pinos do ultrassônico ---------- */
#define PINO_TRIG 12
#define PINO_ECHO 11
/* ---------- Variáveis e níveis lógicos ---------- */
int sDir, sEsq;
int NIVEL_PRETO, NIVEL_BRANCO, NIVEL_LINHA, NIVEL_FUNDO;
/* =================== Movimentação (CORRIGIDA PARA GIRO NO EIXO) =================== */
void frente() {
// Motor Esquerdo: Frente
analogWrite(IN1, VELOCIDADE); analogWrite(IN2, 0);
// Motor Direito: Frente
analogWrite(IN3, VELOCIDADE); analogWrite(IN4, 0);
}
void parar() {
analogWrite(IN1, 0); analogWrite(IN2, 0);
analogWrite(IN3, 0); analogWrite(IN4, 0);
}
void re_lento(uint8_t v=45) {
// Motor Esquerdo: Ré
analogWrite(IN1, 0); analogWrite(IN2, v);
// Motor Direito: Ré
analogWrite(IN3, 0); analogWrite(IN4, v);
}
void giroDireita() { // HORÁRIO (Esq: Frente | Dir: Ré) - GIRO RÁPIDO
// Motor Esquerdo: FRENTE
parar();
delay(100);
re_lento();
delay(100);
analogWrite(IN1, VELOCIDADEGIRO); analogWrite(IN2, 0);
// Motor Direito: RÉ
analogWrite(IN3, 0); analogWrite(IN4, VELOCIDADE);
}
void giroEsquerda() { // ANTI-HORÁRIO (Esq: Ré | Dir: Frente) - GIRO RÁPIDO
// Motor Esquerdo: RÉ
parar();
delay(100);
re_lento();
delay(100);
analogWrite(IN1, 0); analogWrite(IN2, VELOCIDADEGIRO);
// Motor Direito: FRENTE
analogWrite(IN3, VELOCIDADE); analogWrite(IN4, 0);
}
/* ========== Ultrassônico: distância em cm (ou -1 se falhar) ========== */
long lerDistanciaCM() {
digitalWrite(PINO_TRIG, LOW); delayMicroseconds(2);
digitalWrite(PINO_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(PINO_TRIG, LOW);
unsigned long duracao = pulseIn(PINO_ECHO, HIGH, 30000UL); // ~30 ms
if (duracao == 0) return -1;
return duracao / 70; // ida+volta ~58 us/cm
}
/* ======== Rotina de DESVIO: “retângulo por baixo” (lado direito) ======== */
void desvioRetangularDireita() {
parar(); delay(50); // 0) segurança
re_lento(); delay(T_RE); // 1) ré curtinha
giroDireita(); delay(T_GIRO90);// 2) vira para baixo (sai da linha)
frente(); delay(T_DESCER);// 3) desce 1 faixa
giroEsquerda(); delay(T_GIRO90);// 4) volta a ficar paralelo à pista
frente(); delay(T_PASSAR);// 5) passa ao lado do obstáculo
giroEsquerda(); delay(T_GIRO90);// 6) vira para “subir” e procurar a linha
// 7) sobe até reencontrar a linha (ambos sensores na linha) com timeout
unsigned long t0 = millis();
while (millis() - t0 < T_TIMEOUT_SUBIR) {
sDir = digitalRead(PINO_SENSOR_DIREITA);
sEsq = digitalRead(PINO_SENSOR_ESQUERDA);
bool dirNaLinha = (sDir == NIVEL_LINHA);
bool esqNaLinha = (sEsq == NIVEL_LINHA);
frente();
if (dirNaLinha && esqNaLinha) break; // achou a faixa
}
// 8) realinha no sentido da pista e segue um pouco
giroDireita(); delay(T_GIRO90);
frente(); delay(50);
}
/* ========================= Setup ========================= */
void setup() {
Serial.begin(9600);
// Ponte H
pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);
// Sensores de linha (muitos funcionam melhor com INPUT_PULLUP)
pinMode(PINO_SENSOR_DIREITA, INPUT);
pinMode(PINO_SENSOR_ESQUERDA, INPUT);
// Ultrassônico
pinMode(PINO_TRIG, OUTPUT);
pinMode(PINO_ECHO, INPUT);
digitalWrite(PINO_TRIG, LOW);
#ifdef PRETO_ALTO
NIVEL_PRETO = HIGH; NIVEL_BRANCO = LOW;
#else
NIVEL_PRETO = LOW; NIVEL_BRANCO = HIGH;
#endif
#ifdef LINHA_PRETA
NIVEL_LINHA = NIVEL_PRETO; NIVEL_FUNDO = NIVEL_BRANCO;
#else
NIVEL_LINHA = NIVEL_BRANCO; NIVEL_FUNDO = NIVEL_PRETO;
#endif
parar(); delay(200);
}
/* ========================== Loop (CORRIGIDO TEMPO DE CORREÇÃO) ========================= */
void loop() {
// 0) Obstáculo?
long dist = lerDistanciaCM();
if (dist > 0 && dist <= OBST_THRESHOLD_CM) {
desvioRetangularDireita(); // faz a manobra do desenho
return; // depois retoma o seguidor
}
// 1) Ler sensores
sDir = digitalRead(PINO_SENSOR_DIREITA);
sEsq = digitalRead(PINO_SENSOR_ESQUERDA);
bool dirNaLinha = (sDir == NIVEL_LINHA);
bool esqNaLinha = (sEsq == NIVEL_LINHA);
// 2) Regras simples de seguimento
if (!esqNaLinha && !dirNaLinha) {
frente(); // nenhum na linha: segue em frente
} else if (!esqNaLinha && dirNaLinha) {
giroDireita(); delay(80); // Corrija p/ direita (Tempo de correção aumentado para 80ms)
} else if (esqNaLinha && !dirNaLinha) {
giroEsquerda(); delay(80); // Corrija p/ esquerda (Tempo de correção aumentado para 80ms)
} else {
frente(); // os dois na linha: em frente
}
}
Code Breakdown
-
Configuration Section: This section defines the pins used for motor control, sensors, and ultrasonic sensor. It also sets up parameters like line color, obstacle detection threshold, and motor speeds. This is where you can customize the robot's behavior based on your specific hardware and environment.
/* ===================== CONFIG RÁPIDA ===================== */ // Escolha a cor da linha (MANTIDO PRETA): #define LINHA_PRETA // Como seu sensor se comporta no PRETO (AJUSTE SE NECESSÁRIO): #define PRETO_ALTO // sensor lê HIGH no preto (SE O SEU LER LOW, COMENTE ESTE E DESCOMENTE O ABAIXO) // #define PRETO_BAIXO // sensor lê LOW no preto // Distância (cm) para iniciar a manobra de desvio #define OBST_THRESHOLD_CM 20 // Velocidade base (0–255) - RECOMENDADO REDUZIR PARA MELHOR ESTABILIDADE #define VELOCIDADE 70 #define VELOCIDADEGIRO 100 /* ===== Tempos do desvio retangular (ms) – AJUSTE NO SEU PISO ===== */ #define T_RE 1000 // ré curta para “desgrudar” #define T_GIRO90 1000 // tempo para ~90° #define T_DESCER 300 // descer 1 faixa para fora da linha #define T_PASSAR 100 // avançar paralelo, contornando o obstáculo #define T_TIMEOUT_SUBIR 100 // tempo máximo procurando a linha ao "subir" /* ================================================================ */ /* ---------- Pinos L298N (usar PWM nas INs) ---------- */ #define IN1 10 // ~10 (motor esquerdo, frente) #define IN2 9 // ~9 (motor esquerdo, ré) #define IN3 6 // ~6 (motor direito, frente) #define IN4 5 // ~5 (motor direito, ré) /* ---------- Pinos dos sensores de linha ---------- */ #define PINO_SENSOR_DIREITA 2 #define PINO_SENSOR_ESQUERDA 3 /* ---------- Pinos do ultrassônico ---------- */ #define PINO_TRIG 12 #define PINO_ECHO 11 -
Movement Functions: These functions control the robot's movement, including forward, stop, reverse, and turning. The
analogWrite()function is used to control the motor speed via PWM (Pulse Width Modulation)./* =================== Movimentação (CORRIGIDA PARA GIRO NO EIXO) =================== */ void frente() { // Motor Esquerdo: Frente analogWrite(IN1, VELOCIDADE); analogWrite(IN2, 0); // Motor Direito: Frente analogWrite(IN3, VELOCIDADE); analogWrite(IN4, 0); } void parar() { analogWrite(IN1, 0); analogWrite(IN2, 0); analogWrite(IN3, 0); analogWrite(IN4, 0); } void re_lento(uint8_t v=45) { // Motor Esquerdo: Ré analogWrite(IN1, 0); analogWrite(IN2, v); // Motor Direito: Ré analogWrite(IN3, 0); analogWrite(IN4, v); } void giroDireita() { // HORÁRIO (Esq: Frente | Dir: Ré) - GIRO RÁPIDO // Motor Esquerdo: FRENTE parar(); delay(100); re_lento(); delay(100); analogWrite(IN1, VELOCIDADEGIRO); analogWrite(IN2, 0); // Motor Direito: RÉ analogWrite(IN3, 0); analogWrite(IN4, VELOCIDADE); } void giroEsquerda() { // ANTI-HORÁRIO (Esq: Ré | Dir: Frente) - GIRO RÁPIDO // Motor Esquerdo: RÉ parar(); delay(100); re_lento(); delay(100); analogWrite(IN1, 0); analogWrite(IN2, VELOCIDADEGIRO); // Motor Direito: FRENTE analogWrite(IN3, VELOCIDADE); analogWrite(IN4, 0); } -
Ultrasonic Sensor Function: The
lerDistanciaCM()function reads the distance from the ultrasonic sensor and returns the value in centimeters. If the sensor fails to get a reading, it returns -1./* ========== Ultrassônico: distância em cm (ou -1 se falhar) ========== */ long lerDistanciaCM() { digitalWrite(PINO_TRIG, LOW); delayMicroseconds(2); digitalWrite(PINO_TRIG, HIGH); delayMicroseconds(10); digitalWrite(PINO_TRIG, LOW); unsigned long duracao = pulseIn(PINO_ECHO, HIGH, 30000UL); // ~30 ms if (duracao == 0) return -1; return duracao / 70; // ida+volta ~58 us/cm } -
Obstacle Avoidance Routine: The
desvioRetangularDireita()function implements the rectangular deviation maneuver. It consists of a series of movements: reversing, turning away from the line, moving forward, turning back towards the line, and realigning with the line./* ======== Rotina de DESVIO: “retângulo por baixo” (lado direito) ======== */ void desvioRetangularDireita() { parar(); delay(50); // 0) segurança re_lento(); delay(T_RE); // 1) ré curtinha giroDireita(); delay(T_GIRO90);// 2) vira para baixo (sai da linha) frente(); delay(T_DESCER);// 3) desce 1 faixa giroEsquerda(); delay(T_GIRO90);// 4) volta a ficar paralelo à pista frente(); delay(T_PASSAR);// 5) passa ao lado do obstáculo giroEsquerda(); delay(T_GIRO90);// 6) vira para “subir” e procurar a linha // 7) sobe até reencontrar a linha (ambos sensores na linha) com timeout unsigned long t0 = millis(); while (millis() - t0 < T_TIMEOUT_SUBIR) { sDir = digitalRead(PINO_SENSOR_DIREITA); sEsq = digitalRead(PINO_SENSOR_ESQUERDA); bool dirNaLinha = (sDir == NIVEL_LINHA); bool esqNaLinha = (sEsq == NIVEL_LINHA); frente(); if (dirNaLinha && esqNaLinha) break; // achou a faixa } // 8) realinha no sentido da pista e segue um pouco giroDireita(); delay(T_GIRO90); frente(); delay(50); } -
Setup Function: The
setup()function initializes the serial communication, sets the pin modes, and defines the logic levels for line detection based on the chosen line color (black or white)./* ========================= Setup ========================= */ void setup() { Serial.begin(9600); // Ponte H pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); // Sensores de linha (muitos funcionam melhor com INPUT_PULLUP) pinMode(PINO_SENSOR_DIREITA, INPUT); pinMode(PINO_SENSOR_ESQUERDA, INPUT); // Ultrassônico pinMode(PINO_TRIG, OUTPUT); pinMode(PINO_ECHO, INPUT); digitalWrite(PINO_TRIG, LOW); #ifdef PRETO_ALTO NIVEL_PRETO = HIGH; NIVEL_BRANCO = LOW; #else NIVEL_PRETO = LOW; NIVEL_BRANCO = HIGH; #endif #ifdef LINHA_PRETA NIVEL_LINHA = NIVEL_PRETO; NIVEL_FUNDO = NIVEL_BRANCO; #else NIVEL_LINHA = NIVEL_BRANCO; NIVEL_FUNDO = NIVEL_PRETO; #endif parar(); delay(200); } -
Loop Function: The
loop()function is the main control loop of the robot. It first checks for obstacles using the ultrasonic sensor. If an obstacle is detected, it calls thedesvioRetangularDireita()function. Otherwise, it reads the line sensors and adjusts the motor speeds to follow the line./* ========================== Loop (CORRIGIDO TEMPO DE CORREÇÃO) ========================= */ void loop() { // 0) Obstáculo? long dist = lerDistanciaCM(); if (dist > 0 && dist <= OBST_THRESHOLD_CM) { desvioRetangularDireita(); // faz a manobra do desenho return; // depois retoma o seguidor } // 1) Ler sensores sDir = digitalRead(PINO_SENSOR_DIREITA); sEsq = digitalRead(PINO_SENSOR_ESQUERDA); bool dirNaLinha = (sDir == NIVEL_LINHA); bool esqNaLinha = (sEsq == NIVEL_LINHA); // 2) Regras simples de seguimento if (!esqNaLinha && !dirNaLinha) { frente(); // nenhum na linha: segue em frente } else if (!esqNaLinha && dirNaLinha) { giroDireita(); delay(80); // Corrija p/ direita (Tempo de correção aumentado para 80ms) } else if (esqNaLinha && !dirNaLinha) { giroEsquerda(); delay(80); // Corrija p/ esquerda (Tempo de correção aumentado para 80ms) } else { frente(); // os dois na linha: em frente } }
This code provides a solid foundation for your line follower robot with obstacle avoidance. However, remember that fine-tuning and adjustments might be necessary based on your specific hardware and environment. Experiment with different parameter values and observe the robot's behavior to optimize its performance. Understanding the logic behind each function and how they interact will empower you to customize and expand the robot's capabilities.
Assembling the Robot: A Step-by-Step Guide
Assembling the robot involves connecting the hardware components according to the circuit diagram. Here's a general step-by-step guide:
- Mount the Motors: Attach the DC motors to the chassis. Ensure they are securely fixed and aligned for smooth movement.
- Connect the Motor Driver: Place the L298N motor driver on the chassis or a breadboard. Connect the motor outputs of the L298N to the DC motors.
- Mount the IR Sensors: Position the IR sensors on the front of the chassis, facing downwards towards the surface. They should be placed close to the line for accurate detection.
- Mount the Ultrasonic Sensor: Fix the HC-SR04 ultrasonic sensor on the front of the chassis, ensuring it has a clear view of the surroundings.
- Connect the Sensors to Arduino: Connect the signal pins of the IR sensors and the trigger and echo pins of the ultrasonic sensor to the digital pins on the Arduino.
- Connect the Motor Driver to Arduino: Connect the control pins of the L298N motor driver to the digital pins on the Arduino. These pins will control the direction and speed of the motors.
- Power Connections: Connect the power supply (batteries or power adapter) to the L298N motor driver and the Arduino. Ensure the correct polarity is maintained.
- Wiring Check: Double-check all the connections to ensure they are secure and correct. A loose connection can lead to malfunctioning.
Tips for Assembly
- Use a clear and organized wiring scheme to avoid confusion and make troubleshooting easier.
- Securely mount all the components to prevent vibrations and movement during operation.
- Use heat shrink tubing or electrical tape to insulate exposed wires and prevent short circuits.
- Test each connection individually before moving on to the next step.
- Refer to the datasheets of the components for specific wiring instructions.
Proper assembly is crucial for the robot's reliable operation. Take your time, follow the steps carefully, and double-check all connections. A well-assembled robot will perform better and be easier to troubleshoot if any issues arise.
Calibration and Testing: Fine-Tuning Your Robot
Once the robot is assembled and the code is uploaded, it's time for calibration and testing. This step involves fine-tuning the robot's parameters to achieve optimal performance. Here are some aspects to consider:
- Line Sensor Calibration: Adjust the sensitivity of the IR sensors to accurately detect the line. This may involve adjusting the sensor's position or the threshold values in the code.
- Motor Speed Adjustment: Tune the motor speeds to ensure smooth line following and obstacle avoidance. The
VELOCIDADEandVELOCIDADEGIROparameters in the code can be adjusted. - Turning Time Calibration: Calibrate the turning times (
T_GIRO90) for accurate 90-degree turns during obstacle avoidance. This may involve trial and error to determine the optimal values for your robot. - Obstacle Detection Range: Adjust the
OBST_THRESHOLD_CMparameter to set the distance at which the robot starts the obstacle avoidance maneuver. This should be set based on the robot's speed and reaction time. - Testing Environment: Test the robot in a controlled environment with different line patterns and obstacles. This will help identify any issues and fine-tune the robot's behavior.
Troubleshooting Tips
- If the robot is not following the line, check the sensor readings and adjust the sensor sensitivity or code logic.
- If the robot is overshooting or oscillating, reduce the motor speeds or adjust the turning times.
- If the robot is not detecting obstacles, check the ultrasonic sensor connections and code.
- If the robot is behaving erratically, double-check all wiring and connections.
- Use a multimeter to check for voltage and continuity issues.
Calibration and testing are essential for optimizing the robot's performance. Be patient, experiment with different settings, and observe the robot's behavior. Fine-tuning your robot will result in a smoother, more efficient, and more reliable line follower with obstacle avoidance capabilities.
Conclusion: The Journey of Building a Robot
Building a line follower robot with obstacle avoidance is a rewarding journey that combines hardware assembly, software programming, and problem-solving. This guide has provided a comprehensive overview of the process, from understanding the core concepts to assembling the robot, writing the code, and calibrating its performance. By following these steps and experimenting with different parameters, you can create a robot that autonomously navigates lines and avoids obstacles.
The beauty of robotics lies in the continuous learning and improvement. As you work on this project, you'll gain valuable skills in electronics, programming, and mechanical design. You'll also develop problem-solving abilities and a deeper understanding of how robots work.
Remember, robotics is an iterative process. Don't be discouraged by challenges or setbacks. Embrace them as opportunities to learn and grow. With persistence and a passion for robotics, you can bring your robotic visions to life.
For further exploration and advanced concepts in robotics, consider visiting the **[RobotShop Learning Center](https://www.robotshop.com/learning-center/