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