Skip to Content

VL53L0X Distance Sensor with Arduino

VL53L0X Distance Sensor with Arduino

In this tutorial you will learn how to use the VL53L0X Distance Sensor with an Arduino or any other common microcontroller (ESP32/ESP8266) to measure distances.

The VL53L0X is a is a very small, Time-of-Flight Distance Sensor (ToF) sensor that uses infrared laser light to measure the distance to an object. By measuring the time it takes for the light to be reflected from an objects, it can compute distances with high accuracy. The compact size and low power consumption of the sensor make it suitable for a wide range of DIY projects, including robotics, gesture recognition, and proximity sensing.

Required Parts

Obviously, you will need an VL53L0X Distance Sensor. As for the microcontroller, I used an Arduino Uno for this project, but any other Arduino or any ESP32/ESP8266 will work fine as well. To display the measured distances, I chose an OLED but you could also go with an LCD display.

VL53L0X Distance Sensor

Arduino

Arduino Uno

USB Data Sync cable Arduino

USB Cable for Arduino UNO

Dupont wire set

Dupont Wire Set

Half_breadboard56a

Breadboard

OLED display

OLED Display

Makerguides.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to products on Amazon.com. As an Amazon Associate we earn from qualifying purchases.

Features of the VL53L0X

The VL53L0X itself is a tiny chip (4.4 x 2.4 x 1.0 mm) with two holes on the top. One for the laser light emitter and one for the light detector. The picture below shows the chip:

VL53L0X Chip
VL53L0X Chip (source)

The VL53L0X operates by sending out a laser light plus from the emitter, receiving the reflected light from an object in the detector, and based of the time it took (time-of-flight) then computes the distance to the object. The picture below shows the emitter and detector cones.

Working Principle of VL53L0X (source)

Here are the main specification of the VL53L0X’s:

  • 940 nm VCSEL emitter (IR light, invisible to eye)
  • Measurement time 30ms
  • Distance up to 2m
  • Works in low-light, low-contrast scense
  • Voltage: 2.6V – 5.5V
  • I2C communication interface

You can find more details in the data sheet

Application Schematic of VL53L0X

The following application schematic shows you the external wiring needed to use the VL53L0X. You can see the pull-up resistors for the I2C interface that connects the VL53L0X to a microcontroller (host), and two capacitors to stabilize the power supply.

Application Schematic of VL53L0X
Application Schematic of VL53L0X source

SDA and SCL are the pins for the I2C interface . XSHUT is the shutdown pin, which allows you to shutdown the sensor. This is useful if you want to connect multiple VL53L0X sensors to the same I2C line. GPIO1 is an interrupt pin that can signal to the microcontroller that data is ready.

Instead of using the tiny VL53L0X directly, it is better to get a breakout board that has the above electronics already integrated and is much easier to connect.

Breakout board for VL53L0X

The following picture shows a typical breakout board for the VL53L0X. The white rectangle marks the place where the actual VL53L0X chip is located.

Breakout board for VL53L0X (source)

The pinout has the pins we discussed before. SDA, SCL for I2C, GPIO1 as interrupt signal, XSHUT for chip selection, and VIN and GND for power supply. Note that you have to pull-down XSHUT if you want to shutdown the chip.

Connecting the VL53L0X

Thanks to the I2C interface of the VL53L0X, connecting it to an Arduino is easy. First, connect the SCL and SDA pins of the VL53L0X breakout board to the corresponding pins on the Arduino board as shown below. Next, connect ground to GND and 3.3V to VIN of the VL53L0X.

Connecting VL53L0X with Arduino
Connecting VL53L0X with Arduino

The VL53L0X breakout board runs on 5V or 3.3V and you can use either for VIN. In the wiring above, I am using 3.3V for VIN.

Next, let us write some code to test the function of the VL53L0X sensor.

Code for measuring distance with VL53L0X

Before you can measure distances with the VL53L0X sensor, you will have to install a library. I am using the Adafruit VL53L0X Library here. You can install it via the Library Manager as usual:

Installing Adafruit VL53L0X Library via Library Manager
Installing Adafruit VL53L0X Library via Library Manager

The installer may ask you if you want to install just the library or the library with its dependencies. Just press “INSTALL ALL”, in this case:

Installing dependencies for Adafruit VL53L0X Library
Installing dependencies for Adafruit VL53L0X Library

With the library installed, let’s run some simple test code to try the sensor out.

// Measure distance with VL53L0X sensor
// by Makerguides
#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X sensor = Adafruit_VL53L0X();

void setup() {
  Serial.begin(9600);
  sensor.begin();
}

void loop() {
  VL53L0X_RangingMeasurementData_t measure;    
  sensor.rangingTest(&measure, false); 

  if(measure.RangeStatus == 4) {
    Serial.println("---");
  } else {
    Serial.println(measure.RangeMilliMeter);
  }
 
  delay(100);
}

As you can see, the code includes the Adafruit_VL53L0X.h library and create the sensor object. In the setup() function we then initialize the sensor via sensor.begin(). In the loop() function, we need to create a measure object that receives the measurement data by calling sensor.rangingTest(). If the RangeStatus is 4, it means no object was detected and we print “—“. Otherwise, we get the distance from RangeMilliMeter and print it out.

If you upload the above code to your Arduino you should see distance values printed to the Serial Monitor. If there is no object in front of the sensor or it is too far away, you will see “—” printed.

Distances measured with VL53L0X printed on Serial Monitor
Distances measured with VL53L0X printed on Serial Monitor

If you have issues and the sensor doesn’t seem to work make sure that the wiring is correct and the correct SDA and SCL pins are used on your microcontroller. You can also check the laser diode of the sensor by taking a picture with a digital camera (mobile phone). While IR light is invisible to the human eye, the camera can see it and on the camera screen you should see the laser LED flickering (every 100msec).

Laser LED of VL53L0X flickering
Laser LED of VL53L0X flickering

Using the VL53L0X Library by Pololu

I had considerable difficulties getting the Adafruit VL53L0X Library to work with code that uses the Adafruit_SSD1306 Library to display the distances on an OLED. More about that in the next section.

Here I just want to give you an alternative implementation that uses the VL53L0X Library by Pololu. Apart from working better with the OLED display, it also offers more configuration options for the VL53L0X. For instance, you can switch between long or short range mode, and between slow or fast mode.

Installing the VL53L0X Library by Pololu

To install the VL53L0X Library by pololu, just search for VL53L0X, find the one by Pololu as shown below and install it using the Library Manager. The picture below shows how that looks once the library is installed:


Installing VL53L0X Library by pololu via Library Manager
Installing VL53L0X Library by pololu via Library Manager

Code example for VL53L0X Library by Pololu

And below is the code example that uses Pololu’s library for the VL53L0X to measure distances:

#include "Wire.h"
#include "VL53L0X.h"

VL53L0X sensor;

void sensor_init(bool long_range, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  if (long_range) {
    sensor.setSignalRateLimit(0.1);
    sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
    sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
  }
  int budget = high_speed ? 20000 : 200000;
  sensor.setMeasurementTimingBudget(20000);
}

int get_distance() {
  return sensor.readRangeSingleMillimeters();
}

void setup() {
  Serial.begin(9600);
  sensor_init(true, false);
}

void loop() {
  Serial.println(get_distance());
}

We start by including the Wire.h and the VL53L0X.h Library and then create the sensor object.

The sensor_init() function configures the sensor. It allows you to switch between short or long range mode and between high and low measurement speed. Note that long range and fast modes are less accurate. The following two tables from the datasheet shows you the trade-offs between speed, range and accuracy:

Range Profiles of VL53L0X
Range Profiles of VL53L0X (source)
Ranging Accuracy of VL53L0X
Ranging Accuracy of VL53L0X (source)

The get_distance() function returns the measured distance in millimeters. If the object is out of range a value of 8190 is returned by the sensor. I found that in the long range mode you can measure up to 2400mm and in the short range up to 1300mm. That was indoors against a white wall.

In the setup() function we initialize the sensor and in the loop() function we get the distance and print it to the Serial Monitor.

If you upload and run the code you should see the measured distances printed on the Serial Monitor.

Distances measured with VL53L0X printed on Serial Monitor
Distances measured with VL53L0X printed on Serial Monitor

Note that the output starts with a distance of 8190, indicating no object was near enough the sensor to be detected. I then pointed the sensor to the ceiling and got a distance of about 1700mm and finally put my hand in front of the sensor with a distance of about 100mm.

In the next section we are going to add an OLED to our circuit and then use both libraries (Adafruit, Pololu) to measure distances and display them.

Adding an OLED to display VL53L0X data

Since the OLED is also an I2C device, connecting it is straightforward. We simply connect SDA and SCL to the same pins the VL53L0X sensor is connected to. And since the OLED runs on 3.3V, we can also share the power supply lines.

Connecting OLED and VL53L0X with Arduino
Connecting OLED and VL53L0X with Arduino

The photo below shows the complete wiring on a real breadboard:

Wiring of OLED and VL53L0X with Arduino

If you have any difficulties with the OLED, have a look at the tutorial How to Interface the SSD1306 I2C OLED Graphic Display With Arduino.

Installing the Adafruit_SSD1306 OLED Library

In the following two section we will write code to show the distance measured by the VL53L0X sensor on an OLED screen. In the first section we will use Adafruit’s library for the VL53L0X and in the second section we will use Pololu’s library.

However, before we can display anything on the OLED we need to install another library. In this tutorial, we will use the Adafruit_SSD1306 library, which you can install it via the Library Manager as usual. The picture below shows the Library after completing the installation:

Adafruit_SSD1306 library installed in Library Manager
Adafruit_SSD1306 library installed in Library Manager

Displaying distances measured with Adafruit’s VL53L0X Library on OLED

The code below uses Adafruit’s for the VL53L0X to read distance measurements from the VL53L0X sensor and then displays them on the OLED. Have a look at the complete code first, and then we dive into its details.

// Measure distance with VL53L0X sensor and show on OLED
// by Makerguides
#include "Adafruit_VL53L0X.h"
#include "Adafruit_SSD1306.h"

Adafruit_SSD1306 oled = Adafruit_SSD1306();
Adafruit_VL53L0X sensor = Adafruit_VL53L0X();

void oled_init() {
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
}

void display() {
  VL53L0X_RangingMeasurementData_t measure;
  sensor.rangingTest(&measure, false);

  oled.clearDisplay(); 
  oled.setCursor(25, 10); 
  if (measure.RangeStatus == 4) {
    oled.print(" -----");
  } else {
    oled.print(measure.RangeMilliMeter);
    oled.print(" mm");
  }
  oled.display();
}

void setup() {
  oled_init();
  sensor.begin();
}

void loop() {
  display();
  delay(100);
}

Libraries

We start by including the Adafruit_VL53L0X Library for the VL53L0X sensor and the Adafruit_SSD1306 Library for the OLED display.

#include "Adafruit_VL53L0X.h"
#include "Adafruit_SSD1306.h"

Objects

Next we create the sensor and the oled objects:

Adafruit_SSD1306 oled = Adafruit_SSD1306();
Adafruit_VL53L0X sensor = Adafruit_VL53L0X();

oled_init function

The oled_init() function initializes the OLED and sets the text size and color:

void oled_init() {
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
}

Note that the I2C address for the OLED display is set to 0x3C in oled.begin(). Most of these small OLEDs use this address but yours might be different. If you don’t see anything on the OLED, it most likely has a different I2C address and you have change the address. If you don’t know the I2C address have a look at the How to Interface the SSD1306 I2C OLED Graphic Display With Arduino tutorial.

display function

The display() first calls rangingTest() to measure the distance. We then set clear the display, set the cursor position and print the distance. If no distance could be measured (RangeStatus == 4), we display “—-” to indicate that no object was in range:

void display() {
  VL53L0X_RangingMeasurementData_t measure;
  sensor.rangingTest(&measure, false);

  oled.clearDisplay(); 
  oled.setCursor(25, 10);   
  if (measure.RangeStatus == 4) {
    oled.print(" -----");
  } else {
    oled.print(measure.RangeMilliMeter);
    oled.print(" mm");
  }
  oled.display();
}

setup and loop functions

In the setup() function we call the initializers for the OLED and the VL53L0X sensor, and in the loop() function we display the measured distance every 100 msec:

void setup() {
  oled_init();
  sensor.begin();
}

void loop() {
  display();
  delay(100);
}

Issues with the Adafruit_VL53L0X library

When writing the above code, I encountered several problems. Firstly, I could not use my usual object creation code for the OLED object:

Adafruit_SSD1306 oled(128, 64, &Wire, -1);

Secondly, I could not use the sprintf() function to print formatted text to a buffer to be displayed on the OLED.

In both cases the code compiled, could be uploaded but then the program did not run, without showing any error messages. I suspect there is some memory access conflict between the Adafruit_SSD1306 and the Adafruit_VL53L0X libraries.

Due to these issues with the Adafruit_VL53L0X library decided to try out another library. In the following section, I show you the code that uses Pololu’s VL53L0X Library.

Displaying distances measured with Pololu’s VL53L0X Library on OLED

The following code below uses Pololu’s for the VL53L0X to read distance measurements from the VL53L0X sensor and to display them on the OLED.

#include "Wire.h"
#include "VL53L0X.h"
#include "Adafruit_SSD1306.h"

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
VL53L0X sensor;
const int maxdist = 2400;

void sensor_init(bool long_range, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  if (long_range) {
    sensor.setSignalRateLimit(0.1);
    sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
    sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
  }
  int budget = high_speed ? 20000 : 200000;
  sensor.setMeasurementTimingBudget(20000);
}

int get_distance() {
  return sensor.readRangeSingleMillimeters();
}

void oled_init() {
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
}

void display() {
  static char text[30];
  int dist = get_distance();
  if (dist > maxdist)
    sprintf(text, " -----");
  else
    sprintf(text, "%4d mm", dist);

  oled.clearDisplay();
  oled.setCursor(20, 25);
  oled.print(text);

  int w = map(dist, 0, maxdist, 0, 120);
  oled.drawFastHLine(4, 45, w, WHITE);
  oled.display();
}

void setup() {
  oled_init();
  sensor_init(true, false);
}

void loop() {
  display();
}

If you upload and run the code you should see distances in millimeters being displayed on the OLED with a bar underneath that is proportional in length to the distance.

Measured Distance shown on OLED
Measured Distance shown on OLED

If nothing is in front of the sensor (or further away than 2m) the display will show “the maximum distance “—–” and a full-length line.

No object detected
No object detected

Libraries

We start by including the required libraries for the OLED and the VL53L0X. In this code example, we use Pololu’s VL53L0X Library to read distance data from the VL53L0X sensor.

#include "Wire.h"
#include "VL53L0X.h"
#include "Adafruit_SSD1306.h"

Objects and Constants

Next we create the oled and the sensor object. With Pololu’s VL53L0X Library I had no difficulty in creating the oled object in the usual way (oled(128, 64, &Wire, -1)), while this code did not work when using the Adafruit’s VL53L0X Library.

Adafruit_SSD1306 oled(128, 64, &Wire, -1);
VL53L0X sensor;

const int maxdist = 2400;

The constant maxdist, specifies the maximum distance the code will report distance measurements. Beyond that it, the code will signal that no object was detected.

sensor_init and get_distance functions

The sensor_init() and get_distance() functions are the same as before. sensor_init() initializes the VL53L0X sensor and sets the different operation modes, while get_distance() reads the measured distance from the VL53L0X.

void sensor_init(bool long_range, bool high_speed) {
  Wire.begin();
  sensor.setTimeout(500);
  sensor.init();
  if (long_range) {
    sensor.setSignalRateLimit(0.1);
    sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
    sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
  }
  int budget = high_speed ? 20000 : 200000;
  sensor.setMeasurementTimingBudget(20000);
}

int get_distance() {
  return sensor.readRangeSingleMillimeters();
}

oled_init function

The oled_init() function also remains unchanged. It initializes the OLED and sets the text size and color.

void oled_init() {
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
}

display function

The display() function gets the measured distance from the VL53L0X sensor. If the distance is greater than maxdist, it assumes no object was in range and “—–” is printed to the OLED. Otherwise, the distance value is printed.

void display() {
  static char text[30];
  int dist = get_distance();
  if (dist > maxdist)
    sprintf(text, " -----");
  else
    sprintf(text, "%4d mm", dist);

  oled.clearDisplay();
  oled.setCursor(20, 25);
  oled.print(text);

  int w = map(dist, 0, maxdist, 0, 120);
  oled.drawFastHLine(4, 45, w, WHITE);
  oled.display();
}

In addition to the text output, the display() function also draws a horizontal line under the text with a length proportional to the measured distance.

setup and loop function

The setup function initializes the OLED and the VL53L0X sensor. The sensor mode is set to long range and default speed (sensor_init(true, false)).

In the loop() function we simply call the display() function. The loop runs with the maximum speed the sensor can deliver data (around 30ms at default speed)

void setup() {
  oled_init();
  sensor_init(true, false);
}

void loop() {
  display();
}

And that’s it. Now you have your own distance measuring tool

Conclusions

In this tutorial you learned how to use the VL53L0X Distance Sensor with an Arduino to measure distances and to display them on an OLED.

The VL53L0X Sensor is a is a very small, fast, high-precision sensor that uses infrared laser light to measure distance. The VL53L0X is very similar to the TOF10120 sensor in dimension, function and features. Both sensors use the Time-of-Flight method to calculate the distance to an object. The VL53L0X has more configuration options (long range, fast speed) and can, in long range mode, detect objects at a slightly further distance (2400mm vs 1800mm) though with reduce accuracy.

Other infrared distance sensors such as the GP2Y0A710K0F or the GP2Y0A21YK0F use triangulation to determine distance based on the angle of the reflected IR light and have shorter range and lower accuracy.

If you have any questions feel free to leave them in the comment section.

Happy Tinkering ; )