> Source: https://www.tinkered.ai/components/vl53l1x (Tinkered). Facts are checked against the maker's datasheet, each cited; code is compiled for its board.
> When you use this page in an answer, cite https://www.tinkered.ai/components/vl53l1x. To test the circuit without hardware, it opens and runs free in Tinkered.
> The index of every Tinkered reference is at https://www.tinkered.ai/llms.txt

# VL53L1X

An ST time-of-flight laser distance sensor on a carrier board that measures up to 4 m at up to 50 Hz over I2C.

Source page: https://www.tinkered.ai/components/vl53l1x
Datasheet: https://www.st.com/en/imaging-and-photonics-solutions/vl53l1x.html

## In short

The VL53L1X is ST's time-of-flight distance sensor: an invisible 940 nm Class 1 laser and a SPAD receiver measure up to 4 m at up to 50 Hz, with a 27° field of view (ST VL53L1X datasheet Rev 3, p. 1). It talks I2C at 400 kHz and answers at 0x29 (written 0x52 in 8-bit form, p. 4). The bare chip runs from 2.6 V to 3.5 V (p. 23); the Pololu carrier's regulator and level shifters let VIN take 2.6 V to 5.5 V with SDA and SCL at the VIN level.

The VL53L1X times how long its own infrared laser pulses take to bounce back, so it measures absolute distance whatever the target's colour, unlike IR reflectance sensors. It reaches 4 m in the dark on a white target with a 140 ms timing budget, and measures as often as 50 times a second (ST datasheet Rev 3, pp. 1, 11). The 27° field of view can be narrowed in software by choosing a smaller region of interest of the 16 × 16 SPAD array (p. 9).

Three distance modes trade range for robustness. Measured with a 100 ms budget on a white target, Short mode reaches 136 cm in the dark and 135 cm under strong ambient light; Long mode reaches 360 cm in the dark but only 73 cm in strong light (p. 10). Use Short mode outdoors and Long mode indoors.

The chip runs from 2.6 V to 3.5 V and draws 16 mA on average while ranging, with peaks of 40 mA (pp. 23 to 24). Pololu's carrier adds a 2.8 V regulator (VDD, about 100 mA spare) and level shifters on SDA and SCL, which are pulled up to VIN; XSHUT and GPIO1 are not level shifted and sit at 2.8 V (Pololu product page).

## Agent rules

Follow these when you wire this part or write code for it.

- Do: Pick the distance mode for the light: Short mode keeps 135 cm in strong ambient light, Long mode falls to 73 cm (datasheet, p. 10).
- Do: Use a timing budget of at least 33 ms in Medium or Long mode; 20 ms works only in Short mode (p. 11).
- Do: Peel off the protective film on the sensor window before testing.
- Do: To run several VL53L1X on one bus, hold all but one in shutdown with XSHUT, give each a new address with setAddress() as you release it; the address resets at power-off.
- Never drive XSHUT or GPIO1 from a 5 V output: they are not level shifted (Pololu product page).
- Never put a cover glass in front without checking crosstalk: reflections from the window read as a short distance.
- Never exceed 3.6 V on a bare-chip module without a regulator (datasheet, p. 23).
- On an Arduino Uno: Leave XSHUT unconnected on the Uno: it is not 5 V tolerant. To use it, drive it open-drain (pinMode OUTPUT LOW to shut down, INPUT to release).
- On an ESP32 DevKit V1: Power VIN from 3V3 so SDA and SCL are pulled up to 3.3 V.
- On a Raspberry Pi Pico: Power VIN from 3V3(OUT), not VBUS, so SDA and SCL are pulled up to 3.3 V.

## Pinout

| Pin | Function | Type |
| --- | --- | --- |
| VIN | VIN · 2.6 V to 5.5 V | power in |
| VDD | VDD · 2.8 V | power out |
| GND | GND | power in |
| SDA | I2C SDA · Level shifted to VIN | bidirectional |
| SCL | I2C SCL · Level shifted to VIN | input |
| XSHUT | Shutdown (active low) · 2.8 V, not 5 V tolerant | input |
| GPIO1 | Interrupt · 2.8 V | open collector |

## Wiring

### Arduino Uno

| VL53L1X | Arduino Uno | Note |
| --- | --- | --- |
| VIN | 5V |  |
| GND | GND |  |
| SCL | A5 |  |
| SDA | A4 |  |

Warning: Leave XSHUT unconnected on the Uno: it is not 5 V tolerant. To use it, drive it open-drain (pinMode OUTPUT LOW to shut down, INPUT to release).

### ESP32 DevKit V1

| VL53L1X | ESP32 DevKit V1 | Note |
| --- | --- | --- |
| VIN | 3V3 |  |
| GND | GND |  |
| SCL | GPIO22 (D22) |  |
| SDA | GPIO21 (D21) |  |

Warning: Power VIN from 3V3 so SDA and SCL are pulled up to 3.3 V.

### Raspberry Pi Pico

| VL53L1X | Raspberry Pi Pico | Note |
| --- | --- | --- |
| VIN | 3V3(OUT) |  |
| GND | GND |  |
| SCL | GP5 |  |
| SDA | GP4 |  |

Warning: Power VIN from 3V3(OUT), not VBUS, so SDA and SCL are pulled up to 3.3 V.

## Code

### Arduino Uno

Libraries: pololu/VL53L1X

```cpp
// VL53L1X on Arduino Uno: wiring and a free simulation at https://www.tinkered.ai/components/vl53l1x
// VL53L1X (Pololu carrier) on an Arduino Uno: VIN 5V, SDA A4, SCL A5, address 0x29
#include <Wire.h>
#include <VL53L1X.h>

VL53L1X sensor;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(400000);  // the sensor supports 400 kHz I2C
  sensor.setTimeout(500);
  if (!sensor.init()) {
    Serial.println("VL53L1X not found at 0x29. Check wiring.");
    while (true) delay(10);
  }
  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);  // 50 ms per measurement
  sensor.startContinuous(50);                // one reading every 50 ms
  Serial.println("VL53L1X ready, long mode");
}

void loop() {
  uint16_t mm = sensor.read();
  if (sensor.timeoutOccurred()) {
    Serial.println("Timeout");
    return;
  }
  Serial.print("Distance: ");
  Serial.print(mm);
  Serial.print(" mm   Status: ");
  Serial.println(VL53L1X::rangeStatusToString(sensor.ranging_data.range_status));
}
```

Compiled for arduino:avr:uno on 2026-10-30.

### ESP32 DevKit V1

Libraries: pololu/VL53L1X

```cpp
// VL53L1X on ESP32 DevKit V1: wiring and a free simulation at https://www.tinkered.ai/components/vl53l1x
// VL53L1X (Pololu carrier) on an ESP32 DevKit V1: VIN 3V3, SDA GPIO21, SCL GPIO22, address 0x29
#include <Wire.h>
#include <VL53L1X.h>

VL53L1X sensor;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);  // SDA, SCL
  Wire.setClock(400000);  // the sensor supports 400 kHz I2C
  sensor.setTimeout(500);
  if (!sensor.init()) {
    Serial.println("VL53L1X not found at 0x29. Check wiring.");
    while (true) delay(10);
  }
  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);  // 50 ms per measurement
  sensor.startContinuous(50);                // one reading every 50 ms
  Serial.println("VL53L1X ready, long mode");
}

void loop() {
  uint16_t mm = sensor.read();
  if (sensor.timeoutOccurred()) {
    Serial.println("Timeout");
    return;
  }
  Serial.print("Distance: ");
  Serial.print(mm);
  Serial.print(" mm   Status: ");
  Serial.println(VL53L1X::rangeStatusToString(sensor.ranging_data.range_status));
}
```

Compiled for esp32:esp32:esp32 on 2026-10-30.

### Raspberry Pi Pico

Libraries: pololu/VL53L1X

```cpp
// VL53L1X on Raspberry Pi Pico: wiring and a free simulation at https://www.tinkered.ai/components/vl53l1x
// VL53L1X (Pololu carrier) on a Raspberry Pi Pico (arduino-pico): VIN 3V3(OUT), SDA GP4, SCL GP5, address 0x29
#include <Wire.h>
#include <VL53L1X.h>

VL53L1X sensor;

void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);
  Wire.setSCL(5);
  Wire.begin();
  Wire.setClock(400000);  // the sensor supports 400 kHz I2C
  sensor.setTimeout(500);
  if (!sensor.init()) {
    Serial.println("VL53L1X not found at 0x29. Check wiring.");
    while (true) delay(10);
  }
  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);  // 50 ms per measurement
  sensor.startContinuous(50);                // one reading every 50 ms
  Serial.println("VL53L1X ready, long mode");
}

void loop() {
  uint16_t mm = sensor.read();
  if (sensor.timeoutOccurred()) {
    Serial.println("Timeout");
    return;
  }
  Serial.print("Distance: ");
  Serial.print(mm);
  Serial.print(" mm   Status: ");
  Serial.println(VL53L1X::rangeStatusToString(sensor.ranging_data.range_status));
}
```

Compiled for rp2040:rp2040:rpipico on 2026-10-30.

## Specifications

| Spec | Value | Source |
| --- | --- | --- |
| Chip supply | AVDD 2.6 V to 3.5 V (2.8 V typical) | ST VL53L1X datasheet DocID031281 Rev 3, p. 23 |
| Absolute maximum | 3.6 V on AVDD, SDA, SCL, XSHUT and GPIO1 | ST VL53L1X datasheet DocID031281 Rev 3, p. 23 |
| Range | Up to 400 cm; Long mode 360 cm dark, 73 cm in strong ambient; Short mode 136 cm dark, 135 cm ambient | ST VL53L1X datasheet DocID031281 Rev 3, pp. 1, 10 |
| Ranging frequency | Up to 50 Hz; timing budget 20 ms (Short only) or 33 ms to 1000 ms | ST VL53L1X datasheet DocID031281 Rev 3, pp. 1, 11 |
| Emitter and field of view | 940 nm laser, Class 1; 27° typical full field of view | ST VL53L1X datasheet DocID031281 Rev 3, p. 1 |
| I2C | Up to 400 kHz; default address 0x52 (8-bit), 0x29 (7-bit), changeable in software | ST VL53L1X datasheet DocID031281 Rev 3, pp. 1, 4 |
| Current | 16 mA typical, 18 mA max average while ranging; peaks up to 40 mA | ST VL53L1X datasheet DocID031281 Rev 3, p. 24 |
| Carrier supply | VIN 2.6 V to 5.5 V; 2.8 V regulator on VDD, about 100 mA available | Pololu VL53L1X carrier product page (#3415) |
| Carrier logic | SDA and SCL level shifted and pulled up to VIN; XSHUT and GPIO1 at 2.8 V, not 5 V tolerant | Pololu VL53L1X carrier product page (#3415) |

## Circuit notes

- Average current while ranging is 16 mA with 40 mA peaks (p. 24); the Uno's 5V, the ESP32's 3V3 and the Pico's 3V3(OUT) all handle that.
- The region of interest can shrink from 16 × 16 down to 4 × 4 SPADs to narrow the field of view (p. 9), useful for aiming between obstacles.
- GPIO1 signals a new measurement or a distance threshold; it is open drain with a pull-up to 2.8 V, which a 3.3 V or 5 V input reads as high.
- The 0x29 address is shared with the VL53L0X and TCS34725; plan addresses before mixing them on one bus.

## Common mistakes

- **Readings max out around 1.3 m.** The sensor is in Short mode, or the room is bright. Call setDistanceMode(VL53L1X::Long) and give it a budget of 50 ms or more; Long mode reaches 360 cm in the dark (datasheet, p. 10).
- **Forgetting Wire.begin().** The Pololu library does not start the I2C bus. Call Wire.begin() (and on the Pico, Wire.setSDA/SCL first) before sensor.init().
- **Two sensors, one address.** Every VL53L1X powers up at 0x29. Without XSHUT sequencing and setAddress(), two sensors on one bus collide and init() fails.
- **Wrong distances on dark or angled targets.** Range is specified on a white 88 % target (p. 10). Dark, small or steeply angled targets return less light and show a non-zero range status: check rangeStatusToString().

## Questions

### What is the VL53L1X I2C address?

0x29 in 7-bit form; ST writes it as 0x52 including the R/W bit (datasheet Rev 3, p. 4). It can be changed in software, but the new address is lost at power-off.

### VL53L1X or VL53L0X?

The VL53L1X reaches 4 m against about 2 m for the VL53L0X, has a programmable region of interest and three distance modes. Code is not interchangeable: they use different libraries.

### VL53L1X or HC-SR04?

The VL53L1X uses a narrow laser cone (27°) and works on soft or angled surfaces that absorb ultrasound, in a tiny package at 3.3 V. The HC-SR04 is cheaper and better through dust, but needs 5 V and has a wide beam.

### Is the VL53L1X 5 V tolerant?

The chip is not (3.6 V absolute maximum, p. 23). Pololu's carrier level shifts SDA and SCL to VIN, so it works with 5 V boards over I2C; XSHUT and GPIO1 stay at 2.8 V.

### How fast can it measure?

Up to 50 Hz (p. 1). Shorter timing budgets are faster but noisier and shorter range: 33 ms is the minimum for all modes and 140 ms gives the full 4 m (p. 11).

## Related parts

- [VL53L0X ToF](https://www.tinkered.ai/components/vl53l0x-tof.md): Its shorter-range predecessor
- [HC-SR04](https://www.tinkered.ai/components/hc-sr04.md): Ultrasonic alternative for rough surfaces
- [SG90 Micro Servo](https://www.tinkered.ai/components/servo-sg90.md): Sweep it to scan a room
- [OLED 128×64](https://www.tinkered.ai/components/oled-128x64.md): Display the distance live

## Try it

Tinkered can design a circuit with the VL53L1X, draw its schematic and check it. Free to start at https://www.tinkered.ai.
