Autonomous Delivery Robot with complete tutorial circuit and code

Autonomous Delivery Robot 🤖 Full Tutorial with Circuit & Code
🚚

Autonomous Delivery Robot

A fun step-by-step Arduino project with circuit diagrams & code

📋 What We're Making

An autonomous delivery robot is a smart little car that can drive around all by itself, dodge obstacles, and (with upgrades) deliver small packages! We'll build it using an Arduino, a motor driver, and an ultrasonic "eye" sensor. Let's get rolling! 🎉

  1. Gather the Parts
  2. Wire Up the Circuit
  3. Step-by-Step Assembly
  4. Upload the Code
  5. Test & Fix Problems
  6. Cool Upgrades

🧰 Parts You'll Need

🧠Arduino Uno R3
⚙️L298N Motor Driver
🔋2x DC Geared Motors + Wheels
🛞Caster Wheel
📡HC-SR04 Ultrasonic Sensor
👀2x IR Sensors (optional)
🔌12V Battery Pack
📦Robot Chassis
🔗Jumper Wires
📱HC-05 Bluetooth (optional)

🔋 Power Connections

  • Battery (+) → L298N 12V input
  • Battery (–) → L298N GND and Arduino GND (this shared ground is super important!)
  • L298N 5V output → Arduino 5V (or power Arduino separately)

⚙️ L298N Motor Driver → Arduino

L298N PinArduino Pin
ENAPin 9
IN1Pin 8
IN2Pin 7
ENBPin 10
IN3Pin 6
IN4Pin 5
OUT1, OUT2Left Motor
OUT3, OUT4Right Motor
GNDArduino GND

📡 Ultrasonic Sensor (HC-SR04) → Arduino

HC-SR04 PinArduino Pin
VCC5V
GNDGND
TRIGPin 11
ECHOPin 12

👀 IR Line Sensors (Optional)

IR SensorArduino Pin
Left IR OUTA0
Right IR OUTA1
VCC5V
GNDGND

🛠️ Step-by-Step Build

Step 1: Build the Chassis 🏗️
Mount the two geared motors on either side of the chassis base. Attach the caster wheel at the front or back to keep your robot balanced.
Step 2: Mount the Motor Driver ⚙️
Fix the L298N module in the center so the wires to both motors are short and neat. Connect the motor wires to OUT1-OUT4.
Step 3: Wire the Power System 🔋
Connect the battery pack to the L298N's 12V terminal. Make sure the battery, L298N, and Arduino all share the same GND — this is the #1 mistake beginners make!
Step 4: Connect the Arduino 🧠
Wire ENA, IN1, IN2, IN3, IN4, ENB from the L298N to the Arduino pins shown in the table above.
Step 5: Mount the Sensor 📡
Place the HC-SR04 at the front of the robot, facing forward like a pair of eyes. Connect TRIG to pin 11 and ECHO to pin 12.
Step 6: Add IR Sensors (Optional) 👀
If you want line-following too, mount both IR sensors underneath the front, close to the ground, spaced apart to straddle a line.
Step 7: Upload the Code 💻
Plug the Arduino into your computer with a USB cable and upload the code below using the Arduino IDE.
Step 8: Test & Calibrate 🎯
Power on, check the motor directions first, then test obstacle detection, then let it roam!
Always double-check your wiring before turning on the power — loose wires are the #1 cause of "my robot won't move!"

💻 The Code

🚧 Obstacle-Avoiding Robot Code

// Autonomous Delivery Robot - Obstacle Avoidance
// Motor Driver Pins
#define ENA 9
#define IN1 8
#define IN2 7
#define ENB 10
#define IN3 6
#define IN4 5

// Ultrasonic Sensor Pins
#define TRIG 11
#define ECHO 12

long duration;
int distance;

void setup() {
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(ENB, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);
  Serial.begin(9600);
}

int getDistance() {
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  duration = pulseIn(ECHO, HIGH);
  return duration * 0.034 / 2; // cm
}

void moveForward() {
  analogWrite(ENA, 180);
  analogWrite(ENB, 180);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void moveBackward() {
  analogWrite(ENA, 180);
  analogWrite(ENB, 180);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void turnRight() {
  analogWrite(ENA, 180);
  analogWrite(ENB, 180);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
}

void turnLeft() {
  analogWrite(ENA, 180);
  analogWrite(ENB, 180);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
}

void stopMotors() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}

void loop() {
  distance = getDistance();
  Serial.println(distance);

  if (distance > 20) {
    moveForward();
  } else {
    stopMotors();
    delay(200);
    moveBackward();
    delay(300);
    stopMotors();
    delay(200);
    turnRight();
    delay(400);
    stopMotors();
    delay(200);
  }
  delay(50);
}

🛣️ Line-Following Code (Extra Feature)

#define leftIR A0
#define rightIR A1

void loop() {
  int leftVal = digitalRead(leftIR);
  int rightVal = digitalRead(rightIR);

  if (leftVal == LOW && rightVal == LOW) {
    moveForward();
  } else if (leftVal == HIGH && rightVal == LOW) {
    turnLeft();
  } else if (leftVal == LOW && rightVal == HIGH) {
    turnRight();
  } else {
    stopMotors();
  }
}
Copy the "helper" functions (moveForward, turnLeft, etc.) from the first code block into this one if you want to use both together!

🧪 Testing & Troubleshooting

🎯 Calibration Tips

  • Motors spinning the wrong way? Swap the two wires for that motor on the L298N output.
  • Robot bumping into things too late or too early? Change the distance > 20 number in the code.
  • Robot too fast or too slow? Adjust the speed number (180) — lower for gentle, higher for zippy!
  • IR sensors acting weird? Turn the little screw (potentiometer) on the sensor to calibrate.

🔧 Quick Fix Table

Problem 😟Solution 😊
Robot doesn't move at allCheck that battery, L298N, and Arduino all share the same GND
Robot moves crazily / randomlyLook for loose jumper wires and make sure power is steady
Ultrasonic gives weird numbersMake sure the sensor is mounted flat, not tilted
Motors are weak or slowBattery might be low — recharge or check connections

🌟 Bonus: Super Robot Mode (3-in-1!)

Want your robot to do everything? This advanced code combines Manual Control (Bluetooth + IR Remote), Line Following, and Obstacle Avoiding with a Servo "Head" — all in one sketch! Switch modes using your phone app or remote control. 🎮📱

🧩 Extra Parts Needed

📶HC-05 Bluetooth Module
📺IR Remote + Receiver
🦾Servo Motor (sensor head)

🔌 Extra Wiring

ComponentArduino Pin
HC-05 RXPin 2 (via SoftwareSerial)
HC-05 TXPin 3
IR ReceiverA5
Servo (sensor head)A4
Right IR SensorA0
Left IR SensorA1
Ultrasonic EchoA2
Ultrasonic TriggerA3
ENA / IN1 / IN2 / IN3 / IN4 / ENB10 / 9 / 8 / 7 / 6 / 5
You'll need the IRremote library installed in your Arduino IDE (Sketch → Include Library → Manage Libraries → search "IRremote").

🎮 Mode Controls

  • 8 = Manual Mode (drive with buttons/remote)
  • 9 = Auto Line Follower Mode 🛣️
  • 10 = Auto Obstacle Avoider Mode 🚧 (with scanning servo head!)
  • 1-5 = Forward, Backward, Left, Right, Stop
#include <SoftwareSerial.h>
SoftwareSerial BT_Serial(2, 3); // RX, TX

#include <IRremote.h>
const int RECV_PIN = A5;
IRrecv irrecv(RECV_PIN);
decode_results results;

#define enA 10//Enable1 L298 Pin enA 
#define in1 9 //Motor1  L298 Pin in1 
#define in2 8 //Motor1  L298 Pin in1 
#define in3 7 //Motor2  L298 Pin in1 
#define in4 6 //Motor2  L298 Pin in1 
#define enB 5 //Enable2 L298 Pin enB 

#define servo A4

#define R_S A0 //ir sensor Right
#define L_S A1 //ir sensor Left

#define echo A2    //Echo pin
#define trigger A3 //Trigger pin

int distance_L, distance_F = 30, distance_R;
long distance;
int set = 20;

int bt_ir_data; // variable to receive data from the serial port and IRremote
int Speed = 130;  
int mode=0;
int IR_data;

void setup(){ // put your setup code here, to run once

pinMode(R_S, INPUT); // declare if sensor as input  
pinMode(L_S, INPUT); // declare ir sensor as input

pinMode(echo, INPUT );// declare ultrasonic sensor Echo pin as input
pinMode(trigger, OUTPUT); // declare ultrasonic sensor Trigger pin as Output  

pinMode(enA, OUTPUT); // declare as output for L298 Pin enA 
pinMode(in1, OUTPUT); // declare as output for L298 Pin in1 
pinMode(in2, OUTPUT); // declare as output for L298 Pin in2 
pinMode(in3, OUTPUT); // declare as output for L298 Pin in3   
pinMode(in4, OUTPUT); // declare as output for L298 Pin in4 
pinMode(enB, OUTPUT); // declare as output for L298 Pin enB 

irrecv.enableIRIn(); // Start the receiver
irrecv.blink13(true);

Serial.begin(9600); // start serial communication at 9600bps
BT_Serial.begin(9600); 

pinMode(servo, OUTPUT);

 for (int angle = 70; angle <= 140; angle += 5)  {
   servoPulse(servo, angle);  }
 for (int angle = 140; angle >= 0; angle -= 5)  {
   servoPulse(servo, angle);  }

 for (int angle = 0; angle <= 70; angle += 5)  {
   servoPulse(servo, angle);  }
delay(500);
}


void loop(){  

if(BT_Serial.available() > 0){  //if some date is sent, reads it and saves in state     
bt_ir_data = BT_Serial.read(); 
Serial.println(bt_ir_data);     
if(bt_ir_data > 20){Speed = bt_ir_data;}      
}

if (irrecv.decode(&results)) {
Serial.println(results.value,HEX);
bt_ir_data = IRremote_data();
Serial.println(bt_ir_data); 
irrecv.resume(); // Receive the next value
delay(100);
}

     if(bt_ir_data == 8){mode=0; Stop();}    //Manual Android Application and IR Remote Control Command   
else if(bt_ir_data == 9){mode=1; Speed=130;} //Auto Line Follower Command
else if(bt_ir_data ==10){mode=2; Speed=255;} //Auto Obstacle Avoiding Command

analogWrite(enA, Speed); // Write The Duty Cycle 0 to 255 Enable Pin A for Motor1 Speed 
analogWrite(enB, Speed); // Write The Duty Cycle 0 to 255 Enable Pin B for Motor2 Speed 

if(mode==0){     
//===============================================================================
//                          Key Control Command
//=============================================================================== 
     if(bt_ir_data == 1){forword(); }  // if the bt_data is '1' the DC motor will go forward
else if(bt_ir_data == 2){backword();}  // if the bt_data is '2' the motor will Reverse
else if(bt_ir_data == 3){turnLeft();}  // if the bt_data is '3' the motor will turn left
else if(bt_ir_data == 4){turnRight();} // if the bt_data is '4' the motor will turn right
else if(bt_ir_data == 5){Stop(); }     // if the bt_data '5' the motor will Stop

//===============================================================================
//                          Voice Control Command
//===============================================================================    
else if(bt_ir_data == 6){turnLeft();  delay(400);  bt_ir_data = 5;}
else if(bt_ir_data == 7){turnRight(); delay(400);  bt_ir_data = 5;}
}

if(mode==1){    
//===============================================================================
//                          Line Follower Control
//===============================================================================     
if((digitalRead(R_S) == 0)&&(digitalRead(L_S) == 0)){forword();}  //if Right Sensor and Left Sensor are at White color then it will call forword function
if((digitalRead(R_S) == 1)&&(digitalRead(L_S) == 0)){turnRight();}//if Right Sensor is Black and Left Sensor is White then it will call turn Right function  
if((digitalRead(R_S) == 0)&&(digitalRead(L_S) == 1)){turnLeft();} //if Right Sensor is White and Left Sensor is Black then it will call turn Left function
if((digitalRead(R_S) == 1)&&(digitalRead(L_S) == 1)){Stop();}     //if Right Sensor and Left Sensor are at Black color then it will call Stop function
} 

if(mode==2){    
//===============================================================================
//                          Obstacle Avoiding Control
//===============================================================================     
 distance_F = Ultrasonic_read();
 Serial.print("S=");Serial.println(distance_F);
  if (distance_F > set){forword();}
    else{Check_side();}
}

delay(10);
}

long IRremote_data(){
     if(results.value==0xFF02FD){IR_data=1;}  
else if(results.value==0xFF9867){IR_data=2;} 
else if(results.value==0xFFE01F){IR_data=3;} 
else if(results.value==0xFF906F){IR_data=4;} 
else if(results.value==0xFF629D || results.value==0xFFA857){IR_data=5;} 
else if(results.value==0xFF30CF){IR_data=8;} 
else if(results.value==0xFF18E7){IR_data=9;} 
else if(results.value==0xFF7A85){IR_data=10;} 
return IR_data;
}

void servoPulse (int pin, int angle){
int pwm = (angle*11) + 500;      // Convert angle to microseconds
 digitalWrite(pin, HIGH);
 delayMicroseconds(pwm);
 digitalWrite(pin, LOW);
 delay(50);                   // Refresh cycle of servo
}


//**********************Ultrasonic_read****************************
long Ultrasonic_read(){
  digitalWrite(trigger, LOW);
  delayMicroseconds(2);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10);
  distance = pulseIn (echo, HIGH);
  return distance / 29 / 2;
}

void compareDistance(){
       if (distance_L > distance_R){
  turnLeft();
  delay(350);
  }
  else if (distance_R > distance_L){
  turnRight();
  delay(350);
  }
  else{
  backword();
  delay(300);
  turnRight();
  delay(600);
  }
}

void Check_side(){
    Stop();
    delay(100);
 for (int angle = 70; angle <= 140; angle += 5)  {
   servoPulse(servo, angle);  }
    delay(300);
    distance_L = Ultrasonic_read();
    delay(100);
  for (int angle = 140; angle >= 0; angle -= 5)  {
   servoPulse(servo, angle);  }
    delay(500);
    distance_R = Ultrasonic_read();
    delay(100);
 for (int angle = 0; angle <= 70; angle += 5)  {
   servoPulse(servo, angle);  }
    delay(300);
    compareDistance();
}

void forword(){  //forword
digitalWrite(in1, HIGH); //Right Motor forword Pin 
digitalWrite(in2, LOW);  //Right Motor backword Pin 
digitalWrite(in3, LOW);  //Left Motor backword Pin 
digitalWrite(in4, HIGH); //Left Motor forword Pin 
}

void backword(){ //backword
digitalWrite(in1, LOW);  //Right Motor forword Pin 
digitalWrite(in2, HIGH); //Right Motor backword Pin 
digitalWrite(in3, HIGH); //Left Motor backword Pin 
digitalWrite(in4, LOW);  //Left Motor forword Pin 
}

void turnRight(){ //turnRight
digitalWrite(in1, LOW);  //Right Motor forword Pin 
digitalWrite(in2, HIGH); //Right Motor backword Pin  
digitalWrite(in3, LOW);  //Left Motor backword Pin 
digitalWrite(in4, HIGH); //Left Motor forword Pin 
}

void turnLeft(){ //turnLeft
digitalWrite(in1, HIGH); //Right Motor forword Pin 
digitalWrite(in2, LOW);  //Right Motor backword Pin 
digitalWrite(in3, HIGH); //Left Motor backword Pin 
digitalWrite(in4, LOW);  //Left Motor forword Pin 
}

void Stop(){ //stop
digitalWrite(in1, LOW); //Right Motor forword Pin 
digitalWrite(in2, LOW); //Right Motor backword Pin 
digitalWrite(in3, LOW); //Left Motor backword Pin 
digitalWrite(in4, LOW); //Left Motor forword Pin 
}
This code uses pins 5-10 for motors instead of 5-10 from before, and moves sensors to analog pins (A0-A5) to make room for the servo and IR receiver. Update your wiring to match this new table!

🚀 Cool Upgrades to Try

  • 🛰️ Add a GPS module (NEO-6M) so it can navigate outdoors to a delivery spot
  • 📶 Swap to an ESP32 board for Wi-Fi tracking and a control dashboard on your phone
  • 🔄 Mount the ultrasonic sensor on a servo so it can scan side-to-side like a head
  • 📷 Add an ESP32-CAM so the robot can "see" and recognize objects
  • 📦 Build a little tray or door that opens to drop off the "package"

🎉 You Did It!

You've just built your very own autonomous delivery robot! Keep experimenting, keep tinkering, and most importantly — have fun! 🤖💛

Comments

Product Cards
Buddy Bot eBook
⭐ New 2026 Release
Build Your
Own Robot!
3D design, wiring &
Arduino coding.
Young inventors love it!
🖨️
3D Print
All parts
Wire it
Circuit guide
💻
Code it
Arduino IDE
🤖
Watch it
Walk & react
📋 Your Details
Enter your name
Valid 10-digit no.
Enter a valid email
Special Website Offer
₹499 300
🌍 International: $5 USD
One-time · Instant digital delivery
🔒 Secured by Razorpay · Your data is safe
📄 Download Free Sample Copy
🔒 Secured by Razorpay · Your data is safe
🍓
Raspberry Pi Pico Mastery
21 Projects
⚡ Launch Price — 80% OFF
Learn Pico
Build 21 Projects!
MicroPython · Wokwi
IoT · Certificate
Perfect for beginners!
🖥️
Wokwi
No hardware
🐍
MicroPy
From zero
🔨
21 Projects
IoT + sensors
📄
Certificate
Verified cert
📋 Your Details
Enter your name
Valid 10-digit no.
Enter a valid email
Special Launch Offer
₹999 200 80% OFF
🌍 International: $5 USD
One-time · Lifetime access · No subscription
🔒 Secured by Razorpay · UPI · Cards · NetBanking
🎉

You're in!

Payment successful! Your Buddy Bot eBook is ready. Time to build!

📖 Access Your eBook Now
🎉

Enrolled!

Payment successful! Lifetime access to all 21 Pico Projects is yours!

🍓 Go to My Course