Is VL53L0X Time-of-Flight Distance Sensor Compatible with Home Assistant (ESPHome)?
Electrical Specifications
Always confirm pin assignments against the manufacturer datasheet before wiring.
Compatibility Overview
Laser ToF distance sensor for precise tank level monitoring garage vehicle position detection or presence proximity sensing.
Wiring VL53L0X Time-of-Flight Distance Sensor to ESP32
| Module pin | ESP32 | Note |
|---|---|---|
| VIN | 3V3 | Carriers with a regulator, such as Pololu's, accept 2.6–5.5V and shift the I2C lines to match. The bare sensor is a 2.8V part with a 3.5V operating maximum. |
| GND | GND | |
| SDA | GPIO21 | |
| SCL | GPIO22 | |
| XSHUT | unconnected | Pulled up on the carrier, so the sensor runs. Wire it to a GPIO and set enable_pin only for a second VL53 sensor on the same bus or an address other than 0x29. |
| GPIO1 (interrupt) | unconnected | ESPHome polls the sensor. |
Host pins are the ones the configuration on this page uses. Move a pin here and change it in the YAML — they are documented together so they cannot disagree.
Technical Specification Matrix
| Feature / Attribute | Specification / Status |
|---|---|
| Hardware Protocol | I2C Bus / 3.3V |
| Bridge Required | NO |
| Border Router Needed | None |
| Hardware Capabilities & Peripherals | Distance Sensor (mm) Range Status Signal Rate Note: these entities come from the ESPHome configuration you flash — each one needs its matching component in that YAML before it appears. |
| Pairing Complexity | Plug-and-Play |
| Factory Reset Instruction | Hold BOOT button for 3s to enter download mode. |
Wire, Flash, Adopt, Check
Wire it up
Follow the wiring table above. The ESP32 pins there are the ones the configuration uses, so if you move one, change it in both places.
Flash the configuration
Create a new device in the ESPHome dashboard (the Home Assistant add-on) and paste the configuration below into it, or save it as emb_esp32_vl53l0x_esphome.yaml and run esphome run emb_esp32_vl53l0x_esphome.yaml. The first flash goes over USB. If it is not detected, hold BOOT button for 3s to enter download mode to put it in download mode. Every update after that is over the air.
Adopt it in Home Assistant
Settings → Devices & Services. A node on the same network shows up as a discovered ESPHome device within a minute of joining Wi-Fi; choose Configure and enter the API encryption key from your secrets.yaml. If discovery does not find it, add the ESPHome integration by hand with the node's IP address.
Check it works
The I2C scan at boot finds a device at 0x29, and Distance updates once a minute and follows a sheet of white paper as you move it towards the sensor. A scan that finds nothing means SDA and SCL, the power supply, or XSHUT held low. If Distance stays at unknown and the log warns that the distance is out of range, the target is too far away or too dark, or the liner is still on the window.
ESPHome Configuration
Starting configuration for VL53L0X Time-of-Flight Distance Sensor on ESP32. Untested on hardware — verify wiring and pins against your own board.
# ESPHome configuration for VL53L0X Time-of-Flight Distance Sensor
# Host: ESP32. Pin numbers below are host-side defaults — any free
# GPIO will do, and you should change them to match your own wiring.
esphome:
name: emb_esp32_vl53l0x_esphome
friendly_name: "VL53L0X Time-of-Flight Distance Sensor"
esp32:
board: esp32dev
framework:
type: esp-idf
logger:
api:
encryption:
key: !secret api_encryption_key
ota:
- platform: esphome
password: !secret ota_password
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
i2c:
id: i2c_main
sda: GPIO21
scl: GPIO22
scan: true
sensor:
- platform: vl53l0x
name: "Distance"
address: 0x29
long_range: true
update_interval: 60s
Before you flash:
the !secret values come from your
secrets.yaml, and the GPIO numbers are host-side
defaults rather than properties of this part — change them to match how you actually wired it.
If the device is not found:
it is usually the I2C address, not the config. Many breakouts strap their address with
solder jumpers, so two boards of the same part can differ. This config leaves
scan: true on — the boot log lists every address
actually present on the bus, and you can copy the right one from there.
What Appears in Home Assistant
In metres with two decimals, so Home Assistant shows 0.43 m rather than 432 mm. Setting accuracy_decimals: 3 on the sensor shows the full millimetre reading the chip returns. Out-of-range readings arrive as unknown.
Known Problems and Fixes
Peel off the liner
The sensor may ship with a protective liner over its window, and Pololu says it has to come off for the sensor to work properly. It is thin and easy to miss.
Two metres is the best case
ST's 2m figure is for a white target indoors, using the long-range profile. In the same table, a grey target reaches a typical 80cm indoors, and in overcast daylight a white target reaches 80cm and a grey one 50cm. Expect a dark target in daylight to fall well short of the headline figure.
long_range trades accuracy for reach
The config sets long_range: true, which lowers the signal rate limit from 0.25 to 0.1 MCPS so that weaker returns still count as readings. That is what reaches 2m, and it also lets through noisier readings. For a target that stays within a metre, long_range: false gives steadier numbers.
0x29 is a crowded address
The VL53L1X, TSL2591 and TCS34725 also start up at 0x29. With two VL53 sensors on one bus, ESPHome requires every one of them to have XSHUT wired to a GPIO and named as enable_pin, and each needs its own address. ESPHome uses those pins to bring each sensor up on its own and set its address at every boot, because the address is lost at power-off.
Once a minute is slow
update_interval: 60s suits a tank that changes over hours. A parking aid or a presence trigger wants a second or less. A measurement takes about 33ms, so the sensor keeps up easily, but a faster interval also fills Home Assistant's history faster.
Cover glass reads short
Behind a window, some of the laser light bounces off the glass straight back into the sensor. ST provides offset and crosstalk calibration for this, but the ESPHome component has no options for it, so readings taken through a cover are off by a fixed amount. Give it a clear view, or cut an opening in the enclosure.
A 25° cone
The field of view is 25°, so at 1m the sensor sees a spot about 44cm across. The side of a tank or a nearby wall inside that cone can be what it measures. Mount it so nothing but the target is in view.
Shares I²C address 0x29
These parts default to the same address. At least one can be re-strapped, so they can coexist once you change it:
- TSL2591 HDR Ambient Lux Sensor — resolvable
- TCS34725 RGB Color Sensor with IR Filter — resolvable
Boots at 0x29; can be moved in software with XSHUT sequencing. Check a full build in the planner · The ways out of an address conflict
Report a Pinout Error or Submit Tested Code Snippets
Found a pin mapping quirk or built a custom ESPHome YAML driver for VL53L0X Time-of-Flight Distance Sensor? Submit a pull request or report corrections to our index.
Hardware Correction Reporter (emb-esp32-vl53l0x-esphome)
Frequently Asked Questions
Does VL53L0X Time-of-Flight Distance Sensor work without an internet connection?
How is VL53L0X Time-of-Flight Distance Sensor powered and wired to the host board?
How does the host board reach Home Assistant (ESPHome)?
Alternatives
VL53L1X Long Range ToF Sensor (4m)
Four metres and an adjustable region of interest, at the cost of an external component. Same pins and same address.
HC-SR04 Ultrasonic Ranging Sensor Module
Ultrasonic: the target's colour and sunlight do not matter, but soft or angled targets are invisible to it.
TOF10120 Laser Rangefinder Module
Another laser rangefinder, 10–180cm, with a UART option alongside I2C.
A02YYUW Waterproof Ultrasonic Sensor
A waterproof ultrasonic probe for tank levels, where condensation would blind an optical sensor.