Skip to content

Croionxx/line-follower

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🤖 Line Follower Robot

An Arduino-based autonomous line following robot featuring PID control, ultrasonic obstacle avoidance, adaptive speed ramping, and intelligent lost-line recovery.


📸 Media

Circuit Diagram

Circuit Diagram Wiring schematic showing connections between the Arduino, L298N motor driver, IR sensor array, and HC-SR04 ultrasonic sensor.


Robot Build

Robot Photo Fully assembled robot showing sensor placement, motor mounting, and chassis layout.


Demo Video

Demo Video Click to watch the robot navigating a test course.


📋 Table of Contents


Hardware Requirements

Component Description
Arduino Uno / Nano Microcontroller
L298N Motor Driver Dual H-bridge for 2 DC motors
8x IR Reflectance Sensors Analog line sensors (A0–A7)
HC-SR04 Ultrasonic Sensor Front-facing obstacle detection
2x DC Gear Motors Left and right drive wheels
Power Supply 7–12V for motors; 5V for logic

Pin Mapping

Motor Driver (L298N)
  ENA  → Pin 10   (Left motor PWM speed)
  IN1  → Pin 9    (Left motor direction A)
  IN2  → Pin 8    (Left motor direction B)
  IN3  → Pin 7    (Right motor direction A)
  IN4  → Pin 6    (Right motor direction B)
  ENB  → Pin 5    (Right motor PWM speed)

Ultrasonic Sensor (HC-SR04)
  TRIG → Pin 3
  ECHO → Pin 4

IR Sensor Array
  S0–S7 → A0–A7  (8 analog inputs)

Status LED
  LED  → Pin 13  (built-in, active during calibration)

System Architecture

┌─────────────────────────────────────────────────────┐
│                      MAIN LOOP                      │
│                                                     │
│  ┌─────────────┐     ┌──────────────────────────┐   │
│  │  Ultrasonic │────▶│   Obstacle Check (60ms)  │   │
│  │   Sensor    │     └──────────┬───────────────┘   │
│  └─────────────┘                │ clear              │
│                                 ▼                   │
│  ┌─────────────┐     ┌──────────────────────────┐   │
│  │  IR Sensor  │────▶│  Read Line Position      │   │
│  │   Array     │     │  (Weighted Average)      │   │
│  └─────────────┘     └──────────┬───────────────┘   │
│                                 │                   │
│                                 ▼                   │
│                      ┌──────────────────────────┐   │
│                      │    PID Controller        │   │
│                      │   error = 3500 - pos     │   │
│                      │   correction = Kp·P      │   │
│                      │              + Ki·I      │   │
│                      │              + Kd·D      │   │
│                      └──────────┬───────────────┘   │
│                                 │                   │
│                                 ▼                   │
│                      ┌──────────────────────────┐   │
│                      │    Motor Drive           │   │
│                      │  Left  = base + correct  │   │
│                      │  Right = base - correct  │   │
│                      └──────────────────────────┘   │
└─────────────────────────────────────────────────────┘

Algorithms Explained

1. Sensor Calibration

Before the robot starts driving, it runs a 5-second auto-calibration routine. During this window, you manually sweep the sensor array over both the line and the background surface. The firmware records the minimum and maximum raw ADC readings for each of the 8 sensors independently.

At runtime, each raw sensor value is normalised to a 0–1000 scale:

mappedValue = map(rawValue, sensorMin[i], sensorMax[i], 0, 1000)

A noise gate then zeros out any reading below 60, preventing ambient light interference from being misread as a line signal.

Why this matters: Different surfaces, lighting conditions, and sensor aging all affect raw readings. Calibration makes the robot adapt to its environment rather than relying on hardcoded thresholds.


2. Line Position Detection (Weighted Average)

The 8 sensors are assigned position weights of 0, 1000, 2000, ..., 7000. A weighted average across active sensors gives a continuous position value from 0 (far left) to 7000 (far right), with 3500 representing the centre.

position = Σ(sensorValue[i] × i×1000) / Σ(sensorValue[i])

To reduce noise, the weighted average is computed only over a 3-sensor window centred on the sensor with the highest reading, rather than all 8 sensors simultaneously.

Special cases handled:

Condition Detection Action
> 5 sensors active simultaneously Intersection Return centre (3500), continue straight
No sensor above threshold 150 Line lost Return extreme value, trigger recovery
1–5 sensors active Normal line Return weighted average position

3. PID Controller

The heart of the steering system is a Proportional–Integral–Derivative (PID) controller.

error             = 3500 - position        // How far off-centre the line is
motorCorrection   = Kp×P + Ki×I + Kd×D

Proportional Term (P)

P = error

Applies a steering correction proportional to how far off-centre the line currently is. A large error produces a strong turn; a small error produces a gentle correction.

Integral Term (I)

I += error   (clamped to ±5000)

Accumulates persistent error over time. This corrects for systematic bias — such as one motor being slightly faster than the other — that the P term alone cannot fix. An anti-windup clamp prevents the integral from growing unboundedly during recovery manoeuvres.

Derivative Term (D)

rawDerivative      = error - lastError
smoothedDerivative = (smoothedDerivative × 0.7) + (rawDerivative × 0.3)
D = smoothedDerivative

Predicts where the error is heading and applies a damping force to prevent overshoot and oscillation. The exponential moving average (EMA) smoothing (70/30 split) prevents noisy sensor spikes from causing sudden jerky steering corrections.

Motor Mixing

leftMotorSpeed  = baseSpeed + correction    // REVERSE_STEERING = true
rightMotorSpeed = baseSpeed - correction

The REVERSE_STEERING flag accommodates robots where the motor/sensor orientation is flipped.

Default PID Gains

Gain Value Role
Kp 0.08 Proportional — main steering authority
Ki 0.0001 Integral — drift correction
Kd 1.2 Derivative — overshoot damping

4. Speed Ramping

Instead of jumping to full speed immediately (which causes wheel slip and sensor blur), the robot uses linear velocity ramping:

Every 50ms: currentBaseSpeed += 2
            (until targetBaseSpeed = 130 is reached)

This produces smooth acceleration from the initial speed of 80 PWM to the cruise speed of 130 PWM over approximately 1.25 seconds.

A stall prevention function also ensures that any PWM value between 1 and 109 is bumped up to the minimum effective motor threshold (minMotorSpeed = 110), preventing the motors from receiving a voltage too low to overcome static friction.


5. Obstacle Detection

An HC-SR04 ultrasonic sensor is polled every 60ms in a non-blocking fashion (the main loop is never halted by the sonar check). The sensor fires a 10µs trigger pulse and measures the echo return time with a 8ms timeout to avoid lockups in open-air situations.

distance (cm) = duration × 0.034 / 2

If the measured distance drops below stopDistance = 10 cm, the robot immediately stops all motors and enters the OBSTACLE_DETECTED state. It resumes automatically once the path is clear.


6. Lost Line Recovery

When all sensor readings fall below the line threshold, the robot enters smart recovery mode. Rather than spinning blindly, it uses a path history buffer to make an informed decision:

  1. A circular buffer stores the last 10 error values (updated every 50ms).
  2. The average of the history is computed to determine which side the line was most recently on.
  3. The robot spins toward the side with the higher historical error magnitude.
  4. Each successive recovery attempt increases the search speed by 5 PWM (exponential search), up to maxSpeed.
averageError < 0  →  line was to the right  →  spin right
averageError > 0  →  line was to the left   →  spin left

If the line is not reacquired within 3 seconds (maxRecoveryTime), the robot halts and enters the STOPPED state to prevent runaway behaviour.


State Machine

The robot operates as a five-state finite state machine:

              power on
                 │
                 ▼
          ┌─────────────┐
          │ CALIBRATING │  (5 second sensor calibration)
          └──────┬──────┘
                 │ done
                 ▼
          ┌─────────────┐◀──────────────────────────────┐
          │   RUNNING   │                               │
          └──────┬──────┘                               │
         ┌───────┴───────┐                              │
    line │               │ obstacle                     │
    lost │               │ detected                     │
         ▼               ▼                              │
  ┌────────────┐  ┌──────────────────┐                  │
  │  LOST_LINE │  │ OBSTACLE_DETECTED│──── clear ───────┘
  └──────┬─────┘  └──────────────────┘
         │
    timeout (3s)
         │
         ▼
    ┌─────────┐
    │ STOPPED │
    └─────────┘

Configuration & Tuning

All key parameters are defined as constants at the top of the sketch for easy adjustment:

// PID Gains — tune these first
float Kp = 0.08;
float Ki = 0.0001;
float Kd = 1.2;

// Speed Settings
const int targetBaseSpeed = 130;   // Cruise speed (0–255 PWM)
const int maxSpeed        = 220;   // Maximum speed during recovery turns
const int minMotorSpeed   = 110;   // Stall prevention threshold

// Obstacle Avoidance
const int stopDistance    = 10;    // Stop if obstacle within 10 cm

// Recovery
const unsigned long maxRecoveryTime = 3000;  // Give up after 3 seconds

// Motor Orientation (flip if robot drives backwards or steers wrong way)
const bool REVERSE_STEERING    = true;
const bool INVERT_LEFT_MOTOR   = true;
const bool INVERT_RIGHT_MOTOR  = true;

PID Tuning Guide

Symptom Likely Cause Adjustment
Oscillates/wobbles on straight line Kp too high Reduce Kp
Slow to react to curves Kp too low Increase Kp
Drifts to one side over time Insufficient Ki Increase Ki slightly
Overshoots and corrects repeatedly Kd too low Increase Kd
Jittery, erratic movement Kd too high Reduce Kd

Serial Monitor Output

Set the Serial Monitor baud rate to 9600. During operation you will see:

=== LINE FOLLOWER ROBOT ===
Calibrating... Move sensors over line and background!
......................
Calibration complete!
Sensor ranges (Min/Max):
S0: 120/890
S1: 115/905
...
Starting in 3 seconds...
GO!
Pos:3487 Err:13 L:131 R:129
Pos:3210 Err:290 L:148 R:112
OBSTACLE at 8cm
Path clear, resuming
Line lost! Recovering...
Line reacquired!

License

MIT License — free to use, modify, and distribute with attribution.

About

An Arduino-based autonomous line following robot using an 8-sensor IR array and PID control for precise steering. Features ultrasonic obstacle detection, auto-calibration, smooth speed ramping, and a history-guided lost-line recovery system. All PID gains and speed parameters are easily tunable constants.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages