Back to All Blog Posts
Tutorial EltroNerd Engineering

Arduino Line Following Robot with Obstacle Avoidance

This robot follows a black line on a white surface using 5 IR sensors and avoids obstacles using an ultrasonic sensor. It uses two DC motors controlled via an H-bridge and can move forward, turn left/right, and stop based on sensor input.

Overview

Here's a complete explanation and setup for a Line Following Robot with 5 IR Sensors and 1 Ultrasonic Sensor, based on the Arduino code provided earlier. Below is a detailed explanation of how the line following robot with IR sensors and ultrasonic sensor Arduino code works.

setup() Function

void setup() {
  Serial.begin(9600);
  pinMode(LEFT_IR, INPUT);
  pinMode(LEFT_CENTER_IR, INPUT);
  pinMode(CENTER_IR, INPUT);
  pinMode(RIGHT_CENTER_IR, INPUT);
  pinMode(RIGHT_IR, INPUT);
  
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  
  pinMode(RIGHT_MOTOR_A_PIN, OUTPUT);
  pinMode(RIGHT_MOTOR_B_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_A_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_B_PIN, OUTPUT);
}
  • Serial.begin(9600);: Enables serial debugging.
  • pinMode(..., INPUT): Configures IR sensors and ultrasonic pins.
  • pinMode(..., OUTPUT): Sets up motor control pins.

loop() Function

int distance = sonar.ping_cm();

  • This reads the distance using the HC-SR04 ultrasonic sensor via the NewPing library.

int L = digitalRead(LEFT_IR); int LC = digitalRead(LEFT_CENTER_IR); int C = digitalRead(CENTER_IR); int RC = digitalRead(RIGHT_CENTER_IR); int R = digitalRead(RIGHT_IR);

  • Reads all 5 IR sensor values.
  • Sensor returns 0 if over black line and 1 if over white surface.

Decision Logic

if (distance > 0 && distance < 10) { motor_stop(); return; }

  • If an object is within 10 cm, robot stops to avoid a collision.

Line Following Rules

Sensor Pattern Meaning Action
0 0 1 0 0 Center Forward
0 1 1 0 0 Slight Left Turn Left
0 0 1 1 0 Slight Right Turn Right
1 1 0 0 0 Hard Left Turn Left
0 0 0 1 1 Hard Right Turn Right
1 1 1 1 1 No line Stop or reverse

 

The code then matches these patterns using if-else logic and calls:

  • forward(speed);
  • left(speed);
  • right(speed);
  • reverse(speed);
  • motor_stop();

Motor Functions

Each function sets:

  • PWM speed via analogWrite() on ENA, ENB.
  • Direction via setting IN1–IN4 pins HIGH or LOW.

Example:

void forward(int speed) { 
analogWrite(ENA, speed); 
analogWrite(ENB, speed); 
digitalWrite(RIGHT_MOTOR_A_PIN, HIGH); 
digitalWrite(RIGHT_MOTOR_B_PIN, LOW); 
digitalWrite(LEFT_MOTOR_A_PIN, HIGH); 
digitalWrite(LEFT_MOTOR_B_PIN, LOW); 
}

This rotates both motors forward.


motor_stop() Function

void motor_stop() {
  analogWrite(ENA, 0);
  analogWrite(ENB, 0);
  digitalWrite(..., LOW); // All motor pins LOW
}

Stops the robot by cutting power and direction.

 

Final Code

c
#include <NewPing.h>

// IR sensor pin config
#define IR_LEFT A0
#define IR_LEFT_CENTER A1
#define IR_CENTER A2
#define IR_RIGHT_CENTER A3
#define IR_RIGHT A4

// Ultrasonic sensor config
#define TRIGGER_PIN A5
#define ECHO_PIN A6
#define MAX_DISTANCE 100

// Motor Speed Pins
#define RIGHT_SPEED_PIN 10
#define LEFT_SPEED_PIN 11

// Motor Direction Pins
#define RIGHT_MOTOR_A_PIN 4
#define RIGHT_MOTOR_B_PIN 5
#define LEFT_MOTOR_A_PIN 6
#define LEFT_MOTOR_B_PIN 7

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
  Serial.begin(9600);
  
  pinMode(IR_LEFT, INPUT);
  pinMode(IR_LEFT_CENTER, INPUT);
  pinMode(IR_CENTER, INPUT);
  pinMode(IR_RIGHT_CENTER, INPUT);
  pinMode(IR_RIGHT, INPUT);

  pinMode(RIGHT_SPEED_PIN, OUTPUT);
  pinMode(LEFT_SPEED_PIN, OUTPUT);
  
  pinMode(RIGHT_MOTOR_A_PIN, OUTPUT);
  pinMode(RIGHT_MOTOR_B_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_A_PIN, OUTPUT);
  pinMode(LEFT_MOTOR_B_PIN, OUTPUT);

  motor_stop();
}

void loop() {
  delay(50);
  unsigned int distance = sonar.ping_cm();

  int left = digitalRead(IR_LEFT);
  int left_center = digitalRead(IR_LEFT_CENTER);
  int center = digitalRead(IR_CENTER);
  int right_center = digitalRead(IR_RIGHT_CENTER);
  int right = digitalRead(IR_RIGHT);

  if (distance > 0 && distance < 10) {
    motor_stop();
    return;
  }

  // Line following logic
  if (center == 0 && left_center == 1 && right_center == 1) {
    forward(180);
  } else if (left_center == 0) {
    slightLeft(160);
  } else if (right_center == 0) {
    slightRight(160);
  } else if (left == 0) {
    hardLeft(160);
  } else if (right == 0) {
    hardRight(160);
  } else if (left == 1 && center == 1 && right == 1 && left_center == 1 && right_center == 1) {
    motor_stop();
  } else {
    forward(180); // Default forward
  }
}

// Motor control functions
void forward(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, speed);
  digitalWrite(RIGHT_MOTOR_A_PIN, HIGH);
  digitalWrite(RIGHT_MOTOR_B_PIN, LOW);
  digitalWrite(LEFT_MOTOR_A_PIN, HIGH);
  digitalWrite(LEFT_MOTOR_B_PIN, LOW);
}

void hardLeft(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, speed);
  digitalWrite(RIGHT_MOTOR_A_PIN, HIGH);
  digitalWrite(RIGHT_MOTOR_B_PIN, LOW);
  digitalWrite(LEFT_MOTOR_A_PIN, LOW);
  digitalWrite(LEFT_MOTOR_B_PIN, HIGH);
}

void hardRight(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, speed);
  digitalWrite(RIGHT_MOTOR_A_PIN, LOW);
  digitalWrite(RIGHT_MOTOR_B_PIN, HIGH);
  digitalWrite(LEFT_MOTOR_A_PIN, HIGH);
  digitalWrite(LEFT_MOTOR_B_PIN, LOW);
}

void slightLeft(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, speed / 2);
  digitalWrite(RIGHT_MOTOR_A_PIN, HIGH);
  digitalWrite(RIGHT_MOTOR_B_PIN, LOW);
  digitalWrite(LEFT_MOTOR_A_PIN, HIGH);
  digitalWrite(LEFT_MOTOR_B_PIN, LOW);
}

void slightRight(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed / 2);
  analogWrite(LEFT_SPEED_PIN, speed);
  digitalWrite(RIGHT_MOTOR_A_PIN, HIGH);
  digitalWrite(RIGHT_MOTOR_B_PIN, LOW);
  digitalWrite(LEFT_MOTOR_A_PIN, HIGH);
  digitalWrite(LEFT_MOTOR_B_PIN, LOW);
}

void motor_stop() {
  analogWrite(RIGHT_SPEED_PIN, 0);
  analogWrite(LEFT_SPEED_PIN, 0);
  digitalWrite(RIGHT_MOTOR_A_PIN, LOW);
  digitalWrite(RIGHT_MOTOR_B_PIN, LOW);
  digitalWrite(LEFT_MOTOR_A_PIN, LOW);
  digitalWrite(LEFT_MOTOR_B_PIN, LOW);
}

Try this project in your browser

Compile code and simulate hardware output with EltroNerd Cloud IDE.

Launch Cloud IDE