In this tutorial we will make a homemade lidar. Is not as good as commercial lidar sensor, but it would be good enough for some small robot to avoid obstacles. I will show you what is a lidar sensor, how they work and how I’ve made a homemade one based on Arduino and an infrared distance sensor.
by: ELECTRONOOBS on 2026-08-18
I’ve designed and 3D printed a case in such a way that it could spin 360 degrees without stopping. For better support it also has a big bearing inside. The spin is controlled by a step motor and the lidar has a basic output, with values of angle and distance. We could use these values to create an obstacles map around our robot for examples. I will also show you how to get better results in case that you need higher precision.
This is what we need for this project. Firs, download the 3D files from below and print them with PLA. Then go and buy the motor, the distance IR sensor and the resto of the small parts such as the drivers, the Arduino and so on. You will also need an elastic rubber band, solder and a soldering iron.
We need:

Schematic is simple. Connect the i2c pins from the Arduino to the Slip ring. From the SLip Ring to the VL53L0 distance sensor. Then connect 5V and the D8 pin to the Hall sensor. Connect enable, step and direction to the step motor driver and the motor to the driver. Now connect 5V to the boost converter and set the output to 12V and connect that to the pwoer input of the step motor driver. That's it. As a supply I'm using the USB cable connected to the Arduino.

Downlaod the 3D stl files from above from the part list. Print the case with 2 perimeters, 0.3mm layer height, PLA material and 20% infill. Now we have the case, the rotating disc and the pully. We can mount everything inside so let's see.

Ok, now take the slip ring and place it on the top part of the case. Make sure that the rotating part of the ring is on the above side of the case so it will spin at the same time as the disc. Now, add the step motor using 2 3M screws and nuts. Not the top part of the case is ready and we have the wires from the slip ring on the inner side of the case.

Ok, now we can add the big bearing on the top part of the case. Then, pass the wires from the slip ring though the hole of the rotating disc. Once you do that solder 4 wires to the distance sensor for 5V, GND, data and clock of the i2c communication. Now, screw in place the sensor using those metal inserts you can find in the part list and 2 M3 screws. Now you can close the rotating disc over the bearing.

Ok, now this is an important step. Get the boost converter and solder wires for 5V. Then supply the converter and set it to 12V and then you can solder wires from the output to the step motor driver. Now the driver is supplied with 12V. We can solder the rest of the components.

Finally, add the hall sensor as in the schematic with a 10K resistor and connect it to D8 pin of the Arduino. Glue taht in place on the side of the rotating disc and on the disc solder the magnet. In this way we can detect the rotation of the lidar. Solder the magnet in the oposite side of the distance sensor so we have 180 degrees diference. Now, solder everything together and we can close the case. Glue the Arduino with the USB connector in front of the hole of the case. That's it. Upload the code below.

Ok, the code is not that difficult. Downlaod it from below. You will also need the library for the VL53L0X sensor. So downlaod that from the link below as well adn install it to the Arduino. In the cose we make steps, make a measurement and print the angle adn distance to the serial communication and then we make more steps and so on till we get to 360 degrees. Then we use processing to read and plot the distance.
/* Lidar code by ELECTRONOOBS
* Get distance and angle and send via serial port RX, TX
* Tutorial: https://electronoobs.com/eng_arduino_tut110.php
* Schematic: https://electronoobs.com/eng_arduino_tut110_sch1.php
* Code: https://electronoobs.com/eng_arduino_tut110_code1.php
* YouTube channel: https://www.youtube.com/channel/UCjiVhIvGmRZixSzupD0sS9Q
*/
//Libraries
#include <Wire.h>
#include <VL53L0X.h> //Downlaod it here: https://www.electronoobs.com/eng_arduino_Adafruit_VL53L0X.php
VL53L0X sensor; //Define our sensor
//If you uncomment any of lines below you activate that mode
#define LONG_RANGE
#define HIGH_SPEED
//#define HIGH_ACCURACY
//Outputs/inputs
#define dirPin 3 //Pin for direction of the stepper driver
#define stepPin 4 //Pin for steps of the stepper driver
#define Enable 5 //Pin for enable the stepper driver
//Variables
int Value = 1200; //Delay value between steps
float angle = 0; //Start angle
/* ----------------Step angle calculation----------------
* We need 1.5 rotations for 360º. (pully ratio 1.5 : 1)
* Each 200 steps the motor will make a rotation.
* We move 2 steps and the we make a measurement.
* This equals to 360º/(200steps * 1.5) * 2 = 2.4angle/loop ->
----------------Step angle calculation----------------*/
float angle_step = 2.4; //So place that value here
float maxdist = 400; //I've set the maximum distance around the sensor to only 400mm. Change to any other value.
bool loop_starts = false;
byte last_PIN_state;
void setup() {
// Declare pins as output:
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(Enable, OUTPUT);
digitalWrite(Enable,LOW); //Place enable to low so the driver is enabeled
digitalWrite(dirPin, HIGH); //Place dirPin to HIGH so we spin CW
Serial.begin(9600); //Start serial port
Wire.begin();
sensor.init();
sensor.setTimeout(500);
PCICR |= (1 << PCIE0); //enable PCMSK0 scan so we can use interrupts
PCMSK0 |= (1 << PCINT0); //Set pin "D8" trigger an interrupt on "any" state change.
//See interrupt vector below the void loop
#if defined LONG_RANGE
// lower the return signal rate limit (default is 0.25 MCPS)
sensor.setSignalRateLimit(0.1);
// increase laser pulse periods (defaults are 14 and 10 PCLKs)
sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif
#if defined HIGH_SPEED
// reduce timing budget to 20 ms (default is about 33 ms)
sensor.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
// // increase timing budget to 200 ms
// sensor.setMeasurementTimingBudget(200000);
#endif
}//End setup loop
void loop() {
if (loop_starts) //We reset angle when the magnet is detected on D8
{
angle = 0;
loop_starts = false;
}
digitalWrite(stepPin, HIGH); //Make one step
delayMicroseconds(Value); //Small delay
digitalWrite(stepPin, LOW); //Make another step
delayMicroseconds(Value); //Add another delay
int r = sensor.readRangeSingleMillimeters(); //Get distance from sensor
if (r > maxdist) //Limit the dsitance to maximum set distance above
{
r = maxdist;
}
Serial.print(angle); //Print the values to serial port
Serial.print(",");
Serial.print(r);
Serial.println(",");
angle = angle + angle_step; //Increase angle value by the angle/loop value set above (in this case 2.4º each loop)
}//end of void loop
//This is the magnet detection interruption routine
//----------------------------------------------
ISR(PCINT0_vect){
if(PINB & B00000001) //We make an AND with the pin state register, We verify if pin 8 is HIGH???
{
if(last_PIN_state == 0)
{
last_PIN_state = 1;
}
}
else if(last_PIN_state == 1) //Now verify if pin 8 is LOW??? -> Magnet was detected
{
last_PIN_state = 0;
loop_starts = true; //If yes, we set loop_starts to true so we reset the angle value
}
}//End of ISR
Go to the official page here and download Processing. Then copy the code from below and paste it in processing. Connect the Arduino to the PC and see which COM you are using. Make sure you uplaod the Arduino code from above. Then run the processing code. The LIDAR will start rotating and ploting the distance to the screen.
import processing.serial.*;
Serial myPort; // The serial port
int lf = 10; // Linefeed in ASCII
String myString = null;
float x,y,angle;
float num;
float num2;
int i = 0;
void setup() {
// List all the available serial ports
printArray(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[0], 9600);
size(820, 820);
noSmooth();
background(0);
translate(410, 410);
stroke(255);
strokeWeight(3); // Default
}
void draw() {
while (myPort.available() > 0) {
myString = myPort.readStringUntil(10);
if (myString != null) {
String[] q = splitTokens(myString, ",");
num=float(q[0]); // Converts and prints float
num2 = float(q[1]); // Converts and prints float
//Pass from polars to cartesians adna dd 410 to be in the middle of the 820 by 820 screen.
angle = num * 0.0174533;
x = (sin(angle)*num2 + 410);
y = (cos(angle)*num2 + 410);
}
if(num == 0 )
{
background(0);
translate(410, 410);
}
point(x, y);
}
myPort.clear();
}
If my videos help you, consider supporting my work on my PATREON or a donation on my PayPal. Thanks again and see you later guys.
Leave a comment
Please login in order to comment.