VL53L0X Pinout, I²C Address, XSHUT and ESP32 Arduino Guide

VL53L0X pinout, default 0x29 I2C address, XSHUT multi-sensor address setup, ESP32 connection table and Adafruit Arduino example.

The VL53L0XPriceAliExpress price is a miniature infrared time-of-flight (ToF) distance sensor. It measures the return of invisible 940 nm laser light instead of waiting for an ultrasonic echo and reports distance in millimetres over I²C. This practical hardware guide covers the Adafruit VL53L0XAliExpress price breakout (#3317), generic GY-VL53L0XAliExpress price modules, the XSHUT input, I²C address changes, safe ESP32 wiring, and a working Arduino IDE example using the official Adafruit library.

Quick answer: connect the Adafruit breakout VIN to ESP32 3V3, GND to GND, SDA to GPIO21 and SCL to GPIO22 on a classic ESP32-WROOM DevKit. Its default 7-bit I²C address is 0x29. You do not need XSHUT for one module; use independent XSHUT control when multiple modules need unique software-assigned addresses. The VL53L0X does not have a normal I²C-address solderPrice jumper.

This article complements the existing VL53L0X versus VL53L1X comparison on esp32.co.uk/. All five accompanying illustrations will use verified pinout labels and connection tables, without drawn wires.

Adafruit VL53L0X and generic sensor module pinout showing VIN 2v8 GND SDA SCL GPIO XSHUT
Adafruit #3317 function names versus generic breakout functions. The physical order of generic board headers is not universal.

VL53L0X specifications at a glance

PropertyVL53L0X practical information
TechnologyST FlightSense, 940 nm VCSEL emitter and SPAD light detector
Range outputDistance in millimetres, with separate measurement status
Measuring distanceST specifies operation up to 2 m in favourable conditions; Adafruit describes a practical 30–1000 mm breakout use case
Laser safetyIntegrated Class 1 laser device when used in its intended configuration; never modify the emitter or optics
Digital interfaceI²C, with 100 kHz a safe initial ESP32 test speed
Default address0x29 (7-bit); 0x52 is the corresponding 8-bit write address
Address selectionSoftware only; not retained after reset or power-off
XSHUTActive-low hardware shutdown, useful for multiple devices
GPIO1Optional data-ready interrupt output
Adafruit supplyVIN accepts 3–5 V; onboard regulator provides a 2.8 V output
Raw sensorLow-voltage silicon; not a 5 V-tolerant bare chip
Arduino libraryAdafruit VL53L0X

A “2 m maximum” should not be interpreted as a guarantee that every surface is reliably measured at that distance. Ambient infrared, target reflectance and angle, cover material, contaminants and timing configuration all affect the distance at which valid results are available. Start testing at about 100–500 mm with a clean, matte target.

Adafruit VL53L0X pinout and breakout differences

The Adafruit breakout supplies the circuitry a bare sensor lacks: voltage regulation and I²C level handling. The exact position of its pins can vary with breakout revisions; use the printed silkscreen on your board. Generic six-pin or smaller blue and purple carriers can share the VL53L0X chip while using different regulator, XSHUT and GPIO1 arrangements.

SignalAdafruit meaningConnection on classic ESP32
VINPower INPUT for Adafruit breakout, accepts 3–5 VESP32 3V3
2v8OUTPUT of onboard 2.8 V regulator, up to 100 mA according to AdafruitLeave unconnected in normal setup
GNDCommon groundESP32 GND
SDAI²C dataESP32 GPIO21
SCLI²C clockESP32 GPIO22
GPIO / GPIO1Programmable data-ready or status interrupt; not level shifted on Adafruit boardOptional 3.3 V MCU GPIO after checking logic high
SHDN / XSHUTShutdown input: LOW disables sensor; Adafruit board pulls it HIGH and has a level-shifting diodePriceLeave default for one sensor; dedicated GPIO for each sensor in multi-sensor design
STEMMA QTI²C/power connectors on equipped board revisionsOptional compatible cable

VIN is not 2v8. VIN is the Adafruit board’s power input and 2v8 is the regulator output. Do not inject 3.3 V or 5 V into 2v8. Also, GPIO1 is not level shifted on the Adafruit breakout; the sensor’s native logic level must be checked for the receiving microcontroller. The Adafruit SHDN circuit has its own protection arrangement; some generic modules expose the raw chip pin instead.

Can I use 5 V on the VL53L0X?

The Adafruit breakout VIN can accept up to 5 V as specified by Adafruit, but the bare VL53L0X chip and unprotected XSHUT/GPIO signals are not 5 V logic. When working with an ESP32, the simplest safe approach is to feed the breakout from 3V3 and use a 3.3 V-compatible I²C bus. For generic modules, confirm the actual board specification before connecting 5 V anywhere.

Default I²C address 0x29 and why there is no solder jumper

At power-up, every normal VL53L0X starts at 0x29 (7-bit). ST may describe this as 0x52 in 8-bit write-address notation. The Arduino Wire API and the Adafruit library use 0x29. Unlike a PCF8574 or ADS1115 module, VL53L0X address selection is performed by writing a device register in software rather than bridging an A0/A1 address pad.

The programmed address does not persist after power cycling. If two powered VL53L0X sensors both begin at 0x29, addressing one by itself is impossible until the other is held in hardware shutdown. The XSHUT procedure below is the standard solution; an I²C multiplexer is another option.

VL53L0X XSHUT address setup showing boot at 0x29 then setting two devices to 0x30 and 0x31
XSHUT is active low. Each sensor gets a temporary address during startup; all return to 0x29 after a reset.
StepSensor A XSHUTSensor B XSHUTAction
StartLOWLOWBoth devices are held in shutdown
Enable AHIGHLOWOnly A appears at 0x29; initialise as 0x30
Enable BHIGHHIGHB appears at 0x29; initialise as 0x31
MeasureHIGHHIGHRead A from 0x30 and B from 0x31
RestartLOWLOWRepeat; new addresses are not permanent

Board-specific voltage warning: Adafruit’s SHDN breakout interface is designed for 3–5 V logic control. Some generic VL53L0X carriers expose a native, non-level-shifted XSHUT input. Do not force a 3.3 V push-pull HIGH level into an unverified lower-voltage chip pin. Use the board’s schematic, open-drain control or appropriate interface circuitry when necessary.

Functional reference: power, optical ranging and GPIO

VL53L0X functional reference with regulator I2C XSHUT GPIO1 and optical ranging blocks without wires
Reference blocks are not a reproduction of Adafruit or generic board PCB traces.
Functional blockWhat it does
Optical emitterA 940 nm VCSEL produces invisible light toward the target
ReceiverA SPAD array detects reflected photons; onboard processing estimates range
Board regulatorAdafruit breakout converts VIN into the sensor rail; 2v8 is an output
I²C level interfaceProvides SDA/SCL communication, respecting the carrier board supply voltage
XSHUT inputActive-low reset/shutdown for controlled startup sequencing
GPIO1 outputOptional interrupt / measurement-ready status; separate from XSHUT
Electrical groundAll connected boards need a common GND reference

Because several VL53L0X carrier boards exist, it is misleading to draw a single “universal” transistor/regulator schematic and claim every board is wired that way. An exact PCB schematic should be obtained from the particular manufacturer. The five technical images therefore show reliable functional labels and lookup tables rather than decorative electrical wires.

ESP32 connection table: one VL53L0X module

ESP32 DevKit pinAdafruit breakout pinNote
3V3VINPower the breakout, not the bare chip
GNDGNDCommon supply reference
GPIO21SDAI²C data
GPIO22SCLI²C clock
Not connectedSHDN / XSHUTDefault pull-up enables a single sensor
Not connectedGPIOOptional data-ready output
Not connected2v8This is a regulator OUTPUT, not an input

GPIO21/GPIO22 are common I²C choices for classic ESP32-WROOM development boards; the ESP32-C3, C6, S3 and other variants can have different suitable pins. Make sure your sketch calls Wire.begin(SDA, SCL) with the GPIO numbers for the actual MCU, rather than copying a generic ESP32 picture.

VL53L0X and ESP32 pin-to-pin I2C connection tables including optional XSHUT on GPIO25 and GPIO26, no drawn wires
One-sensor and two-sensor pin maps without ambiguous wire crossings.

Arduino IDE code using the Adafruit VL53L0X library

Open Arduino IDE, install the ESP32 board package if needed, then install Adafruit VL53L0X through Library Manager. Accept any dependencies requested. The sketch uses the library’s normal begin() and rangingTest() methods. Results are in millimetres, and invalid range status codes are not presented as genuine distances.

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_VL53L0X.h>

Adafruit_VL53L0X lox;

void setup() {
  Serial.begin(115200);
  delay(400);
  Wire.begin(21, 22);          // Classic ESP32 DevKit SDA/SCL
  Wire.setClock(100000);

  if (!lox.begin()) {          // Default 7-bit address: 0x29
    Serial.println("VL53L0X not detected. Check power and I2C pins.");
    while (true) delay(1000);
  }
  Serial.println("VL53L0X ready");
}

void loop() {
  VL53L0X_RangingMeasurementData_t reading;
  VL53L0X_Error err = lox.rangingTest(&reading, false);

  if (err == VL53L0X_ERROR_NONE && reading.RangeStatus == 0) {
    Serial.print("Distance: ");
    Serial.print(reading.RangeMilliMeter);
    Serial.println(" mm");
  } else {
    Serial.print("Invalid or out-of-range reading. Status: ");
    Serial.println(reading.RangeStatus);
  }
  delay(250);
}

This example checks RangeStatus == 0 for valid ranging. The basic Adafruit demonstration checks for status 4 (out of range), but printing other error status codes as actual millimetres could be misleading. A missing sensor causes begin() to fail; a sensor that responds but has poor optical conditions can still return invalid ranges. The code uses documented library API names and has not been physically bench-tested.

Illustrative Serial Monitor output

VL53L0X ready
Distance: 148 mm
Distance: 151 mm
Distance: 149 mm
Invalid or out-of-range reading. Status: 4

Serial Monitor must be set to 115200 baud. Test with a matte target at known distances and first remove the thin protective film on the sensor window. Treat these output numbers as examples, not measurements made for this article.

Two sensors: XSHUT configuration and Arduino example

For two verified Adafruit breakout boards, add one XSHUT wire per module. Both devices continue to share VIN, GND, SDA and SCL; use GPIO25 for A SHDN and GPIO26 for B SHDN on a classic ESP32-WROOM DevKit. Other ESP32 variants or unprotected generic SHDN signals require their own pin/voltage review.

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_VL53L0X.h>

constexpr int XSHUT_A = 25;
constexpr int XSHUT_B = 26;
Adafruit_VL53L0X a, b;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);
  pinMode(XSHUT_A, OUTPUT);
  pinMode(XSHUT_B, OUTPUT);
  digitalWrite(XSHUT_A, LOW);
  digitalWrite(XSHUT_B, LOW);
  delay(20);

  digitalWrite(XSHUT_A, HIGH);
  delay(20);
  if (!a.begin(0x30)) {
    Serial.println("Sensor A failed");
    while (true) delay(1000);
  }
  digitalWrite(XSHUT_B, HIGH);
  delay(20);
  if (!b.begin(0x31)) {
    Serial.println("Sensor B failed");
    while (true) delay(1000);
  }
  Serial.println("Sensors at 0x30 and 0x31");
}

void report(const char* name, Adafruit_VL53L0X& sensor) {
  VL53L0X_RangingMeasurementData_t r;
  if (sensor.rangingTest(&r, false) == VL53L0X_ERROR_NONE &&
      r.RangeStatus == 0) {
    Serial.printf("%s: %u mm  ", name, (unsigned)r.RangeMilliMeter);
  } else {
    Serial.printf("%s: invalid  ", name);
  }
}

void loop() {
  report("A", a);
  report("B", b);
  Serial.println();
  delay(300);
}

The Adafruit library’s begin(new_address) configures a sensor at the specified runtime address. A reset returns both sensors to 0x29, so the XSHUT sequence must run each time. If you cannot independently disable two sensors, an I²C multiplexer such as the TCA9548A is a practical alternative.

Range, accuracy and common troubleshooting

VL53L0X 940 nm ranging, status errors, XSHUT and optical limitations troubleshooting table without wires
The displayed millimetres are only meaningful when the reading status indicates valid ranging.
SymptomCause and recommended check
No sensor at 0x29Check VIN, GND, SDA/SCL, selected ESP32 GPIOs, I²C 100 kHz and XSHUT not held LOW.
Two sensors collideBoth boot at 0x29; use independent XSHUT control and new runtime addresses.
All measurements invalidRemove optical film, use matte target, reduce ambient IR and check optical window.
Only short distances workReflectance, ambient light, angle and timing affect usable range; 2 m is not guaranteed.
XSHUT damages or fails on generic moduleVerify the raw pin logic level; some carrier boards do not shift XSHUT.
Very close target failsOperation at a few millimetres is beyond many practical module use cases.
Incorrect reading through plasticCover-glass reflections and IR absorption can cause crosstalk; test the material.
GPIO1 unreadableCheck that the signal is an unshifted low-voltage output and whether interrupt is configured.

VL53L0X versus an ultrasonic HC-SR04

A ToF sensor usually has a much narrower optical measurement area than an ultrasonic transmitter, which can be useful for small target detection. Ultrasonic sensing can be better for some objects that reflect little near-infrared light and for some tank geometries. Optical ranging also needs an unobstructed, suitable optical path. Neither technology is universally more accurate in all environments.

Frequently asked questions

Is the VL53L0X address 0x29 or 0x52?

Use 0x29 with Arduino as the 7-bit I²C address. 0x52 is the corresponding 8-bit write address shown in some ST documents; they refer to the same device.

Is there an I²C address jumper on a VL53L0X?

Not in the usual way. Runtime software assigns the new address, and the sensor reverts to 0x29 on reset. A manufacturer may expose other configuration pads on a carrier, but do not confuse them with a permanent address selector.

Can I use XSHUT to switch multiple sensors?

Yes. Hold all but one sensor inactive, assign a new address to the active device, then enable and configure the next. Ensure the control signal levels suit the particular carrier board.

Can a VL53L0X measure through a tank wall?

Not reliably by assumption. Plastic transmission, reflections and cover-glass crosstalk vary, and many opaque walls block the 940 nm light. For liquid-level use, test the exact material or select a different sensor technology.

What is the difference between XSHUT and GPIO1?

XSHUT is the active-low shutdown input. GPIO1 is a programmable interrupt or data-ready output. They are not interchangeable, and generic boards may expose them at different voltage levels.

References and further reading

Editorial accuracy: The connection tables refer to Adafruit breakout functions and an example classic ESP32-WROOM board. Generic variants can differ in regulator design, pin placement, and raw XSHUT/GPIO levels. The example code was checked against the Adafruit library API; it was not physically bench-tested. Image generation is a separate job and must use wire-free verified pinouts and tables.

CONTINUE EXPLORING / ARDUINO

Read next

Practical guides related to this article.

Explore the topic →
HARDWARE DECISION GUIDEArduino or ESP32 for your next build?

Compare practical options before you choose hardware.

Compare options →