Component · Sensor

VL53L0X ToF Sensor

The VL53L0X measures distance with a laser, not sound—a tight, fast, millimetre-accurate beam over I²C for robots that need precise ranging.

What it is

The VL53L0X measures distance the way a laser rangefinder does—with light instead of sound. It fires an invisible infrared laser pulse and times the round trip, giving a tight, fast, millimetre-accurate reading over I²C. Where an HC-SR04 senses a wide cone with a few-centimetre spread, the VL53L0X senses a narrow spot with precision—the sensor you reach for when “roughly how far” isn’t good enough.

Labelled diagram of a VL53L0X time-of-flight sensor breakout: a small purple board with the time-of-flight package in the centre showing two apertures—a round laser emitter and a square SPAD receiver—a laser beam arrow pointing out, and a 6-pin header (VIN, GND, SCL, SDA, GP1, XSH) along the bottom.
An infrared laser fires from the emitter and the SPAD receiver times the reflection—time-of-flight ranging with a narrow beam and millimetre precision. Download SVG

How it works

The package holds two apertures: a laser emitter and a SPAD receiver (a single-photon detector). The sensor fires a pulse of 940 nm infrared light, the receiver times how long the reflection takes to return, and—since light travels at a known speed—that time converts to a distance. All of the timing happens on-chip; your microcontroller just reads the millimetre value over I²C. The trade-offs versus sound are exactly the ones weighed in ultrasonic vs time-of-flight sensors.

When to use it

Reach for a VL53L0X when a robot needs precise, narrow-beam ranging:

  • Close, exact distances — judging a specific gap, wall-following at a set offset, or a precise stop.
  • Small or thin obstacles — a table leg or wire the wide ultrasonic cone would smear or miss.
  • Fast loops — up to 50 Hz updates for responsive control.

For cheap, forgiving “is anything ahead?” detection over a wider area, the HC-SR04 is the better-value pick—and the filtering ideas in reading the HC-SR04 apply to any ranging stream, laser included.

Wiring and gotchas

  • I²C, and address-collides. Every VL53L0X shares one default address—use the XSHUT pin to bring them up one at a time and reassign addresses to run several.
  • Mind the ambient light. Bright sun (lots of infrared) and dark or mirror-like surfaces shorten the usable range.
  • Keep the window clean. A fingerprint or dust on the aperture scatters the beam and corrupts readings.
  • Respect the near limit (~5 cm); like any ranging sensor, it has a blind zone too close to measure.

Pinout

Pin Name What it does
1 VIN 3–5 V. The breakout regulates down to the sensor’s 2.8 V
2 GND Ground
3 SCL I²C clock
4 SDA I²C data
5 GPIO1 Interrupt out — fires when a measurement is ready
6 XSHUT Shutdown, active low. Pull low to disable the sensor entirely

XSHUT is the pin that makes multiple sensors possible, and it is worth understanding before you buy the second one.

Running several VL53L0X sensors

Every VL53L0X powers up at the same address, 0x29, and there are no address-select pins. Put two on a bus and both answer at once, which corrupts every transaction. The address can be changed in software, but the change is volatile — it is lost at every power cycle.

The standard solution uses XSHUT to bring them up one at a time:

#include <Wire.h>
#include <VL53L0X.h>

const int XSHUT[] = {4, 5, 6};          // one GPIO per sensor
const uint8_t ADDR[] = {0x30, 0x31, 0x32};
VL53L0X sensor[3];

void setup() {
  Wire.begin();

  // 1. Hold every sensor in reset.
  for (int i = 0; i < 3; i++) { pinMode(XSHUT[i], OUTPUT); digitalWrite(XSHUT[i], LOW); }
  delay(10);

  // 2. Release one at a time and give each a new address before the next wakes.
  for (int i = 0; i < 3; i++) {
    digitalWrite(XSHUT[i], HIGH);
    delay(10);
    sensor[i].init();
    sensor[i].setAddress(ADDR[i]);      // now it is off 0x29 and the next can boot
    sensor[i].setTimeout(500);
  }
}

Two details that catch people: the pins must be driven LOW for reset and then released, and the whole sequence has to run again after every power cycle because the addresses do not persist. Some breakouts pull XSHUT high with an onboard resistor, so simply leaving the pin floating leaves the sensor enabled.

Timing budget: the accuracy/speed/range dial

The VL53L0X has one setting that matters more than all the others, and most example code never touches it. The timing budget is how long the sensor is allowed to integrate photons for a single measurement, and it trades three things against each other:

Timing budget Update rate Typical range Best for
20 ms ~50 Hz ~0.8 m Fast control loops, close range
33 ms (default) ~30 Hz ~1.2 m General use
66 ms ~15 Hz ~1.7 m Better precision at distance
200 ms ~5 Hz ~2 m Maximum range, static measurement
sensor.setMeasurementTimingBudget(20000);   // microseconds

There are also long-range and high-accuracy modes that adjust the signal-rate threshold and pulse periods. The practical rule: if the sensor is not reaching far enough, spend more time before you blame the sensor. A 200 ms budget genuinely doubles the usable range over a 20 ms one.

Minimal working code

#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;

void setup() {
  Serial.begin(115200);
  Wire.begin();

  if (!sensor.init()) {
    Serial.println("VL53L0X not found");   // check wiring and XSHUT
    while (1) {}
  }
  sensor.setTimeout(500);
  sensor.setMeasurementTimingBudget(33000);
  sensor.startContinuous();
}

void loop() {
  uint16_t mm = sensor.readRangeContinuousMillimeters();

  if (sensor.timeoutOccurred()) {
    Serial.println("timeout");
  } else if (mm >= 8190) {
    Serial.println("out of range");        // 8190/8191 mean "no valid target"
  } else {
    Serial.println(mm);
  }
  delay(20);
}

8190 and 8191 are not distances. They are the sensor’s way of saying it got no usable return — either nothing is there, or the target is too dark or too far. Code that treats 8191 as 8.19 metres will behave strangely in an empty room; code that treats it as zero will emergency-stop in one.

What it cannot see

The VL53L0X fails on almost exactly the opposite set of surfaces to an ultrasonic sensor, which is the entire basis for choosing between them.

Condition What happens Why
Black matte surfaces Range drops sharply, often to a third Very little of the 940 nm light comes back
Mirrors and polished metal Reads far, or nothing The beam reflects away specularly, like light off glass
Bright direct sunlight Range collapses Sunlight is full of 940 nm infrared, swamping the return
Glass Reads what is behind it, or the glass, unpredictably Partly transmits, partly reflects
Closer than ~3–5 cm Unreliable Below the sensor’s minimum working distance
Beyond ~1.2 m at default settings Times out Raise the timing budget before concluding it is broken

The sunlight one is worth emphasising because it is the most surprising. A VL53L0X that works perfectly indoors can be nearly useless in a sunlit conservatory, and the failure is gradual — the range shortens rather than the readings becoming obviously wrong.

Troubleshooting

Symptom Likely cause Fix
init() fails Wiring, or XSHUT held low Scan the bus for 0x29; check XSHUT is high or floating-high
Two sensors, only one works Both on 0x29 Use the XSHUT sequence above at every boot
Addresses lost after a power cycle They are volatile by design Re-run the assignment sequence in setup()
Reads 8190/8191 constantly No valid return Check the target’s colour, distance, and ambient light
Range much shorter than 2 m Default timing budget Raise it to 100–200 ms
Works indoors, fails outside Ambient IR from sunlight Shade the sensor, or use ultrasonic outdoors
Readings drift over minutes Window fouled, or temperature Clean the aperture; run the sensor’s calibration
Occasional wild values Edge of a target, or partial reflection Median-filter the stream, as with any ranging sensor

VL53L0X or something else?

Part Range Notable Choose it when
VL53L0X 5 cm – 2 m The cheap, ubiquitous default Precise short-range ranging indoors
VL53L1X 4 cm – 4 m Twice the range, programmable region of interest You need more reach, or to narrow the field of view in software
VL6180X 5 mm – 20 cm Very short range, also senses ambient light Gap sensing and proximity at centimetre scale
HC-SR04 2 cm – 4 m Sound, wide cone, no library needed Cheap, forgiving obstacle detection; sees dark surfaces
Sharp GP2Y0A21 10–80 cm Analog IR triangulation, one ADC pin No I²C available, and a non-monotonic output is acceptable

The VL53L1X is worth calling out specifically: it is a drop-in improvement in almost every respect, and its programmable region of interest lets you narrow the field of view in software — effectively steering the beam without moving the sensor. If you are choosing today rather than using what you have, it is usually the better buy.

Explore the graph

Used in these builds

Projects, learning paths, and simulators that include the VL53L0X ToF Sensor.

Compare

Alternatives

Questions

VL53L0X ToF Sensor FAQ

What is the maximum distance of the VL53L0X?

About 2 metres in standard mode—some boards trade update rate for a longer range. It's most accurate in the near band; beyond a couple of metres, or in bright ambient infrared like sunlight, readings become unreliable. It also has a near blind zone below about 5 cm.

What are the limitations of the VL53L0X?

Its range is short (~2 m) next to an ultrasonic sensor, bright sunlight and dark or mirror-like surfaces cut it further, and every sensor ships with the same I²C address—so running several needs the XSHUT trick to reassign addresses. Keep the little window clean too; dust scatters the beam.

Does the VL53L0X work on black surfaces?

Poorly. Dark, matte surfaces absorb the infrared laser, so the reflection is weak and the usable range drops sharply—a black wall reads far closer to the sensor's limit than a white one. Glossy or mirror-like surfaces also throw it off by bouncing the beam away from the receiver.

What is the VL53L0X laser distance sensor?

A tiny time-of-flight sensor that measures distance with light instead of sound. It fires an invisible 940 nm infrared laser pulse and times how long the reflection takes to return, giving a tight, fast, millimetre-accurate reading over I²C.

Time-of-flight vs ultrasonic—which is better?

A time-of-flight sensor like the VL53L0X has a narrow beam and millimetre precision, so it senses a specific point and small objects an ultrasonic sensor would miss. The HC-SR04 is cheaper, ranges farther, and its wide cone actually helps not miss obstacles. Use ToF for precision, ultrasonic for cheap, forgiving detection.

Further reading

References