DIY Self-Driving Car for Beginners (Arduino & LiDAR)

Greetings everyone, and welcome to my article tutorial. Today, I'll guide you through the process of creating an Obstacle Avoiding Car using LiDAR Sensor and Arduino.

 

Project Overview:

This beginner-friendly DIY project teaches you how to build a self-driving car using an Arduino and a LiDAR sensor. You’ll learn essential skills like microcontroller programming, sensor integration, and motor control while creating a car that autonomously avoids obstacles. The project features a VL53L0X LiDAR sensor for accurate distance detection up to 2 meters and Mecanum wheels for smooth, omnidirectional movement—allowing your car to move forward, backward, sideways, and even rotate in place. With clear, step-by-step instructions, you’ll assemble a simple cardboard chassis, wire up the Adafruit L293D Motor Driver, and upload the code to your Arduino Uno, ending up with a fully functional autonomous vehicle. Perfect for hobbyists, students, or anyone curious about Arduino projects, robotics, or obstacle-avoiding robots, this tutorial makes it easy to get started and have fun building your own mini self-driving car!

 

Before beginning a huge shoutout to JLCMC for sponsoring.

 

Now, let's get started with our project!

Supplies

Electronic Components Required:

Arduino Uno

Adafruit L293D Motor Driver/Servo Shield

Mecanum Wheels

VL53L0X TOF Based LIDAR Sensor

10 × 14 Cm CardBoard for Chassis

Battery Holder

18650 Battery

Additional Tools:

Soldering Iron

Hot Glue

Cutter

Softwares:

Arduino IDE

STEP 1
Making the Chassis

Here is a step-by-step guide for making the Chassis:

Cut a piece of cardboard to the dimensions of 10cm by 14cm to create the chassis.

Obtain four-gear motors.

Attach the motors to the cardboard using a hot glue gun.

Wire the motors in a cross-word direction, as shown in the image above.

Obtain four rubber wheels for the motors.

Once these steps are completed, the chassis will be ready.

let's move to the next step...

STEP 2
Elevate Your Electronic Projects - JLCMC

JLCMC is your one-stop shop for all electronic manufacturing needs, offering an extensive catalog of nearly 600,000 SKUs that cover hardware, mechanical, electronic, and automation components. Their commitment to guaranteeing genuine products, rapid shipping (with most in-stock items dispatched within 24 hours), and competitive pricing truly sets them apart. In addition, their exceptional customer service ensures you always get exactly what you need to bring your projects to life.

they have everything you need for your next project:

Custom Linear Guide Shafts: Precision-engineered for applications like 3D printing, CNC machines, and industrial automation.

Aluminum Profiles: Versatile, durable framing solutions—perfect for machine enclosures, workstations, and custom assemblies.

To show their support for our community, JLCMC is offering an exclusive $70 discount coupon. This is the perfect opportunity to save on high-quality components for your next project. Don’t miss out—visit https://jlcmc.com/?from=RBL to explore their amazing range of products and grab your discount coupon today!

STEP 3
Motor Driver and Motor Wiring:

Mount the Shield on Your Arduino Uno

Line up all the pins on the bottom of the L293D shield with the headers on the Uno.

Press down gently until the shield is seated snugly.

DC Motors to the Adafruit L293D Shield Connection:

On the shield, you’ll see four pairs of screw terminals labeled M1, M2, M3, and M4.

Loosen both screws on the M1 terminals.

Insert Motor 1 wire into the left M1 screw and the other wire into the right M1 screw.

Tighten the screws so the wires don’t slip out.

Motor 2M2 terminals

Motor 3M3 terminals

Motor 4M4 terminals

Just the same: loosen, insert each wire into the two screws, then tighten.

STEP 4
What Is LiDAR?

LiDAR stands for “light detection and ranging,” Essentially, LiDAR works by emitting laser pulses in all directions and measuring how long it takes for each pulse to bounce back from an object. Since we know the speed of light, that time-of-flight measurement tells us exactly how far away the object is.

Imagine having hundreds of thousands of tiny laser pointers inside one sensor, each firing one at a time all around the room. Each time a pulse hits an object, the sensor measures the return time. For example, it takes twice as long for a pulse to return from an object 20 feet away compared to one 10 feet away—because light travels that much farther.

You might wonder: how does the sensor keep track of 640,000 laser pulses per second? Amazingly, they don’t all fire simultaneously. They fire sequentially—one after another—so the sensor only needs to time each pulse individually. This is possible because light is so fast that even if you slowed time down dramatically—say, so that the return from a 10 ft object takes your “slow-mo” clock four seconds—you could still wait 30 minutes on that slow-mo timescale before sending the next pulse. In reality, the pulses happen so quickly that the sensor can easily distinguish each one, even at hundreds of thousands of pulses per second.

STEP 5
LiDAR Sensor and Arduino Connection

VL53L0X LIDAR Sensor to Arduino Uno:

Connect VL53L0X VCC → Arduino 5V

Connect VL53L0X GND → Arduino GND

Connect VL53L0X SDA → Arduino A4 (SDA)

Connect VL53L0X SCL → Arduino A5 (SCL)

That’s it! After these four wires are in place, we are ready to upload the Arduino sketch.

STEP 6
Time to Upload the Sketch

Follow the steps:

Connect the Arduino uno to your Computer.

To install the library, open the Library Manager, search for “VL53L0X,” scroll down, and install the Adafruit library for VL53L0X TOF Based LIDAR Sensor. To install the AFMotor.h library, type “adafruit motor” and install the Adafruit Motor Shield library.

Then copy and paste this code:

CODE
// LiDAR based Autonomous car || Obstacle Avoiding
// Created By roboattic Lab
// Contact me here https://www.instagram.com/roboattic_lab/

#include <AFMotor.h>
#include <Adafruit_VL53L0X.h>
#include <Wire.h>

#define MAX_DISTANCE 200
#define MAX_SPEED 190
#define MAX_SPEED_OFFSET 20

AF_DCMotor motor1(1, MOTOR12_1KHZ); 
AF_DCMotor motor2(2, MOTOR12_1KHZ);
AF_DCMotor motor3(3, MOTOR34_1KHZ);
AF_DCMotor motor4(4, MOTOR34_1KHZ);

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

boolean goesForward = false;
int distance = 100;
int speedSet = 0;

void setup() {

  Serial.begin(115200);
  delay(10);
  Serial.println("VL53L0X test");

  // Initialize I2C
  Wire.begin();

  // Add this to setup() before lox.begin() to scan for devices
  Serial.println("Scanning I2C bus...");
  for (byte i = 8; i < 120; i++) {
    Wire.beginTransmission(i);
    if (Wire.endTransmission() == 0) {
      Serial.print("Found device at address: 0x");
      Serial.println(i, HEX);
    }
  }

  // Try to initialize the VL53L0X (only call begin() once)
  if (!lox.begin()) {
    Serial.println("Failed to find VL53L0X sensor. Check wiring!");
    while (1)
      ;  // Stop execution if sensor not found
  }
  Serial.println("VL53L0X initialized successfully.");
}

void loop() {

  VL53L0X_RangingMeasurementData_t measure;

  lox.rangingTest(&measure, false);

  if (measure.RangeStatus == 4) {
    Serial.println("Out of range");
  } else {
    distance = measure.RangeMilliMeter / 10;
  }

  // Print the distance to the serial monitor (for debugging)
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");


  int distanceR = 0;
  int distanceL = 0;
  delay(40);

  if (distance <= 15) {
    moveStop();
    delay(100);
    moveBackward();
    delay(300);
    moveStop();
    delay(200);
    distanceR = lookRight();
    delay(200);
    distanceL = lookLeft();
    delay(200);

    if (distanceR >= distanceL) {
      turnRight();
      moveStop();
    } else {
      turnLeft();
      moveStop();
    }
  } else {
    moveForward();
  }
}

int lookRight() {
  rotateRight();
  delay(500);
  VL53L0X_RangingMeasurementData_t measure;

  lox.rangingTest(&measure, false);

  if (measure.RangeStatus == 4) {
    Serial.println("Out of range");
  } else {
    distance = measure.RangeMilliMeter / 10;
  }
  delay(500);
  rotateLeft();
  return distance;
  delay(100);
}

int lookLeft() {
  rotateLeft();
  delay(500);
  VL53L0X_RangingMeasurementData_t measure;

  lox.rangingTest(&measure, false);

  if (measure.RangeStatus == 4) {
    Serial.println("Out of range");
  } else {
    distance = measure.RangeMilliMeter / 10;
  }
  delay(500);
  rotateRight();
  return distance;
  delay(100);
}


void moveStop() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}

void moveForward() {

  if (!goesForward) {
    goesForward = true;
    motor1.run(FORWARD);
    motor2.run(FORWARD);
    motor3.run(FORWARD);
    motor4.run(FORWARD);
    for (speedSet = 0; speedSet < MAX_SPEED; speedSet += 2)  // slowly bring the speed up to avoid loading down the batteries too quickly
    {
      motor1.setSpeed(speedSet);
      motor2.setSpeed(speedSet);
      motor3.setSpeed(speedSet);
      motor4.setSpeed(speedSet);
      delay(5);
    }
  }
}

void moveBackward() {
  goesForward = false;
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
  for (speedSet = 0; speedSet < MAX_SPEED; speedSet += 2)  // slowly bring the speed up to avoid loading down the batteries too quickly
  {
    motor1.setSpeed(speedSet);
    motor2.setSpeed(speedSet);
    motor3.setSpeed(speedSet);
    motor4.setSpeed(speedSet);
    delay(5);
  }
}

void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
  delay(500);
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
  delay(500);
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}


void rotateLeft() {
  motor2.run(FORWARD);
  motor1.run(FORWARD);
  motor4.run(BACKWARD);
  motor3.run(BACKWARD);
}
void rotateRight() {
  motor2.run(BACKWARD);
  motor1.run(BACKWARD);
  motor4.run(FORWARD);
  motor3.run(FORWARD);
}
STEP 7
Working Video and Tutorial

Congratulations! You’ve successfully built your Obstacle Avoiding Car using LiDAR Sensor and Arduino. Demonstration video of this project can be viewed here: Watch Now

Thank you for your interest in this project. If you have any questions or suggestions for future projects, please leave a comment and I will do my best to assist you.

For business or promotional inquiries, please contact me via email at Email.

I will continue to update this article with new information. Don’t forget to follow me for updates on new projects and subscribe to my YouTube channel (YouTube: roboattic Lab) for more content. Thank you for your support.

License
All Rights
Reserved
licensBg
0