The VL53L0X measures distance by timing how long a pulse of invisible laser light takes to bounce back. It is tiny, accurate to a few millimetres, and has a much narrower view than an ultrasonic sensor. That makes it good for robots, gesture triggers and tank-level checks through an opening.
On the Uno it is an I2C device at 0x29 on SDA/SCL, and breakouts with a regulator run from 5V. The Pololu VL53L0X library is compact, which matters on the Uno’s 32 KB of flash.
The sketch reads continuously with a 50 ms timing budget — a little slower than the default, but steadier. It reports timeouts and out-of-range readings plainly instead of printing a misleading number.
Wiring
| Arduino Uno R3 | VL53L0X ToF distance sensor | Wire | Notes |
|---|---|---|---|
| 5V | VIN | red | Breakouts with a regulator (GY-530 / GY-VL53L0XV2) take 5 V. |
| GND | GND | black | |
| SCL | SCL | yellow | Same signal as A5 |
| SDA | SDA | blue | Same signal as A4 |
2.6–5 V (on-board regulator) part, 5 V board. Breakouts with a regulator and level shifting accept 3.3 V or 5 V. Bare boards without them are 2.8 V-only — check the listing.
Board quirks
- Range is about 30 mm to 1.2 m indoors (up to 2 m on a white wall in long-range mode). Sunlight shortens it a lot — it is an indoor sensor.
- Peel off the thin protective film over the two windows. With it on, readings are stuck at a few centimetres.
- Every VL53L0X starts at address 0x29. For two sensors, wire each XSHUT to its own Uno pin, hold one off, and give the other a new address with
setAddress(). - Unlike an HC-SR04, the beam is narrow (about 25°) and it measures soft or angled surfaces that absorb ultrasound — but very dark or glass surfaces can confuse it.
- The Pololu library is small (a few KB of flash, little RAM), which suits the Uno better than ST’s full API.
Code
// VL53L0X time-of-flight distance sensor on an Arduino Uno R3, Pololu library.
// VIN → 5V, GND → GND, SCL → SCL (A5), SDA → SDA (A4). XSHUT and GPIO1 unconnected.
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;
void setup() {
Serial.begin(9600);
Wire.begin();
sensor.setTimeout(500);
if (!sensor.init()) {
Serial.println(F("VL53L0X not found at 0x29 - check wiring"));
for (;;) {}
}
sensor.setMeasurementTimingBudget(50000); // 50 ms per reading: steadier than the 33 ms default
sensor.startContinuous();
Serial.println(F("VL53L0X ready"));
}
void loop() {
uint16_t mm = sensor.readRangeContinuousMillimeters();
if (sensor.timeoutOccurred()) {
Serial.println(F("Timeout"));
} else if (mm >= 8000) {
Serial.println(F("Out of range")); // nothing within about 1.2–2 m
} else {
Serial.print(F("Distance "));
Serial.print(mm);
Serial.println(F(" mm"));
}
delay(100);
}// VL53L0X time-of-flight distance sensor on an Arduino Uno R3, Pololu library.
// VIN → 5V, GND → GND, SCL → SCL (A5), SDA → SDA (A4). XSHUT and GPIO1 unconnected.
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;
void setup() {
Serial.begin(9600);
Wire.begin();
sensor.setTimeout(500);
if (!sensor.init()) {
Serial.println(F("VL53L0X not found at 0x29 - check wiring"));
for (;;) {}
}
sensor.setMeasurementTimingBudget(50000); // 50 ms per reading: steadier than the 33 ms default
sensor.startContinuous();
Serial.println(F("VL53L0X ready"));
}
void loop() {
uint16_t mm = sensor.readRangeContinuousMillimeters();
if (sensor.timeoutOccurred()) {
Serial.println(F("Timeout"));
} else if (mm >= 8000) {
Serial.println(F("Out of range")); // nothing within about 1.2–2 m
} else {
Serial.print(F("Distance "));
Serial.print(mm);
Serial.println(F(" mm"));
}
delay(100);
}Library: VL53L0X (Pololu) — compiled with VL53L0X 1.3.1.
Expected serial output
VL53L0X ready
Distance 243 mm
Distance 241 mm
Out of rangeVL53L0X ready Distance 243 mm Distance 241 mm Out of range
Common errors
“VL53L0X not found at 0x29”
Check SDA/SCL and power, then run the I2C scanner. If XSHUT is wired, it must be HIGH (or left unconnected).
Always reads 8190 or “Out of range”
Nothing within range, the film is still on, or it points at glass or a black surface.
Readings jump by 1–2 cm
Normal noise. A longer timing budget (e.g. 100 ms) or averaging a few readings steadies it.