Can You Make a LiDAR Self Driving Car?

by Shahbaz Hashmi Ansari in Circuits > Arduino

301 Views, 5 Favorites, 0 Comments

Can You Make a LiDAR Self Driving Car?

LiDAR based Self Driving Car || Obstacle Avoiding || Arduino

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

Project Overview:

This Obstacle Avoiding Car project leverages advanced sensing and mobility to create an autonomous robot capable of navigating complex environments. The core of this smart car is an Arduino Uno microcontroller, which processes sensor data and controls vehicle movement. For precise distance detection, the project utilizes the VL53L0X TOF Based LiDAR Laser Distance Sensor. This LiDAR sensor employs the Time-of-Flight (ToF) principle, emitting a laser pulse and measuring the time it takes for the light to return, enabling accurate, real-time obstacle detection up to 2 meters away, irrespective of the object's color or surface material. The car's unique omnidirectional movement capabilities are facilitated by Mecanum wheels, which allow for forward, backward, sideways, and diagonal motion, as well as rotation in place, offering superior maneuverability for collision avoidance in tight spaces. An Adafruit L293D Motor Driver/Servo Shield for Arduino efficiently manages the power and control signals to the four individual Mecanum wheel motors.

The operational logic for this robotics platform involves continuous scanning of the surroundings by the VL53L0X ToF sensor. When an obstacle is detected within a predefined proximity (e.g., 15 cm as per the provided code), the Arduino triggers an intelligent obstacle avoidance algorithm. Instead of merely stopping or backing up, the system evaluates the open space to the left and right by rotating the sensor's perspective. Based on which direction offers more clear path, the Mecanum wheel robot can execute precise turns or rotations to navigate around the impediment and resume its forward trajectory. This integration of accurate LiDAR sensing with the versatile Mecanum wheel system and an Arduino brain demonstrates a robust solution for autonomous navigation and enhances the overall intelligent car capabilities.

Before beginning a huge shoutout to JLCMC for sponsoring.

Now, let's get started with our project!

Supplies

Screenshot (684).png
Screenshot 2025-06-05 205535.png
Screenshot (689).png
Screenshot (688).png
Screenshot (687).png
Screenshot (686).png
Screenshot (685).png

Electronic Components Required:

  1. Arduino Uno
  2. Adafruit L293D Motor Driver/Servo Shield
  3. Mecanum Wheels
  4. VL53L0X TOF Based LIDAR Sensor
  5. 10 × 14 Cm CardBoard for Chassis
  6. Battery Holder
  7. 18650 Battery

Additional Tools:

  1. Soldering Iron
  2. Hot Glue
  3. Cutter

Softwares:

  1. Arduino IDE

Making the Chassis

Screenshot (691).png
Screenshot (692).png

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

  1. Cut a piece of cardboard to the dimensions of 10cm by 14cm to create the chassis.
  2. Obtain four-gear motors.
  3. Attach the motors to the cardboard using a hot glue gun.
  4. Wire the motors in a cross-word direction, as shown in the image above.
  5. Obtain four rubber wheels for the motors.
  6. Once these steps are completed, the chassis will be ready.

let's move to the next step...

Elevate Your Electronic Projects - JLCMC

Screenshot (694).png
Screenshot (693).png

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:

  1. Custom Linear Guide Shafts: Precision-engineered for applications like 3D printing, CNC machines, and industrial automation.
  2. 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!

Motor Driver and Motor Wiring:

Screenshot (695).png
Screenshot (696).png
Screenshot (697).png
Screenshot (698).png

Mount the Shield on Your Arduino Uno

  1. Line up all the pins on the bottom of the L293D shield with the headers on the Uno.
  2. Press down gently until the shield is seated snugly.

DC Motors to the Adafruit L293D Shield Connection:

  1. On the shield, you’ll see four pairs of screw terminals labeled M1, M2, M3, and M4.
  2. Loosen both screws on the M1 terminals.
  3. Insert Motor 1 wire into the left M1 screw and the other wire into the right M1 screw.
  4. Tighten the screws so the wires don’t slip out.
  5. Motor 2M2 terminals
  6. Motor 3M3 terminals
  7. Motor 4M4 terminals
  8. Just the same: loosen, insert each wire into the two screws, then tighten.

What Is LiDAR?

Screenshot (690).png

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.

LiDAR Sensor and Arduino Connection

Screenshot 2025-06-05 121430.png
Screenshot (699).png
Screenshot (700).png
Screenshot 2025-06-05 210805.png
Screenshot (701).png

VL53L0X LIDAR Sensor to Arduino Uno:

  1. Connect VL53L0X VCC → Arduino 5V
  2. Connect VL53L0X GND → Arduino GND
  3. Connect VL53L0X SDA → Arduino A4 (SDA)
  4. Connect VL53L0X SCL → Arduino A5 (SCL)

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

Time to Upload the Sketch

Screenshot (705).png
Screenshot (704).png
Screenshot (703).png
Screenshot (702).png

Follow the steps:

  1. Connect the Arduino uno to your Computer.
  2. 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.
  3. Then copy and paste this 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);
}

Code Breakdown:

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

AFMotor.h: Controls the Adafruit Motor Shield for managing four DC motors

Adafruit_VL53L0X.h: Interfaces with the VL53L0X Time-of-Flight laser distance sensor

Motor Configuration:

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

Four DC motors are configured for a 4-wheel drive system. Motors 1&2 use one frequency setting, while motors 3&4 use another for optimal performance.

Main Loop Decision Making:

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();
}
}

Key Logic: When an obstacle is detected within 15cm, the robot:

  1. Stops and backs up
  2. Scans left and right
  3. Turns toward the direction with more clearance
int lookRight() {
rotateRight(); // Turn sensor right
delay(500);
// Take measurement
lox.rangingTest(&measure, false);
distance = measure.RangeMilliMeter / 10;
delay(500);
rotateLeft(); // Return to center
return distance;
}

The lookRight() and lookLeft() functions physically rotate the robot to scan different directions, then return to the original position.

Working Video and Tutorial

Built a Car That Sees with LASERS! || LiDAR Tech

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 instructable 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.