Fix VL53L0X “Failed to detect and initialize sensor!” / “Failed to boot VL53L0X”
The VL53L0X didn’t answer at 0x29. Check SDA/SCL, VIN and the XSHUT pin, and give each sensor its own address when using two or more.
Community draft — report a mistake
What you see
Failed to detect and initialize sensor!Failed to detect and initialize sensor!
Both common VL53L0X libraries read the sensor’s ID over I2C during init()/begin(). This message means that read failed: no sensor at 0x29, a sensor held in shutdown by XSHUT, or a second sensor fighting for the same address.
#include <Wire.h>
#include <VL53L0X.h>
VL53L0X sensor;
void setup() {
Serial.begin(115200);
Wire.begin();
sensor.setTimeout(500);
if (!sensor.init()) {
Serial.println("Failed to detect and initialize sensor!");
while (1) delay(1000);
}
sensor.startContinuous();
}Quick fix — try in order
- 1
Scan for 0x29
Run the scanner below. The VL53L0X’s default address is 0x29. If nothing answers, check wiring and power before the code.
- 2
Wire VIN, GND, SDA, SCL
GY-530 / GY-VL53L0XV2 boards have a regulator: VIN takes 3.3–5 V. ESP32: SDA 21, SCL 22. Uno: SDA A4, SCL A5.
- 3
Hold XSHUT high
XSHUT low keeps the sensor in shutdown — it won’t answer at all. Leave it unconnected only if your board pulls it up; otherwise tie it to VIN or a GPIO set HIGH.
- 4
Two or more sensors? Change addresses at boot
All start at 0x29. Hold every XSHUT low, release one, call
sensor.setAddress(0x30), release the next, and so on. Without this only one (or none) works. - 5
Call Wire.begin() before init()
Wire.begin(); sensor.setTimeout(500); if (!sensor.init()) …. Forgetting Wire.begin() gives the same failure.
Diagnostic sketch
// I2C scanner — lists every device address that answers on the bus.
// ESP32 DevKit V1: SDA = GPIO21, SCL = GPIO22. Uno/Nano: SDA = A4, SCL = A5.
#include <Wire.h>
void setup() {
Serial.begin(115200);
while (!Serial) {}
#if defined(ARDUINO_ARCH_ESP32)
Wire.begin(21, 22); // SDA, SCL
#else
Wire.begin();
#endif
Serial.print("I2C scanner on SDA=");
Serial.print(SDA);
Serial.print(" SCL=");
Serial.println(SCL);
}
void loop() {
Serial.println("Scanning...");
uint8_t found = 0;
// 0x08..0x77 are the usable 7-bit addresses; the rest are reserved.
for (uint8_t addr = 0x08; addr <= 0x77; addr++) {
Wire.beginTransmission(addr);
uint8_t err = Wire.endTransmission();
if (err == 0) {
Serial.print("Found device at 0x");
if (addr < 0x10) Serial.print('0');
Serial.println(addr, HEX);
found++;
} else if (err == 4) {
Serial.print("Unknown error at 0x");
Serial.println(addr, HEX);
}
}
if (found == 0) {
Serial.println("No I2C devices found");
Serial.println("Check: SDA/SCL swapped? Module powered? Pull-ups present?");
} else {
Serial.print(found);
Serial.println(" device(s) found");
}
Serial.println();
delay(5000);
}// I2C scanner — lists every device address that answers on the bus.
// ESP32 DevKit V1: SDA = GPIO21, SCL = GPIO22. Uno/Nano: SDA = A4, SCL = A5.
#include <Wire.h>
void setup() {
Serial.begin(115200);
while (!Serial) {}
#if defined(ARDUINO_ARCH_ESP32)
Wire.begin(21, 22); // SDA, SCL
#else
Wire.begin();
#endif
Serial.print("I2C scanner on SDA=");
Serial.print(SDA);
Serial.print(" SCL=");
Serial.println(SCL);
}
void loop() {
Serial.println("Scanning...");
uint8_t found = 0;
// 0x08..0x77 are the usable 7-bit addresses; the rest are reserved.
for (uint8_t addr = 0x08; addr <= 0x77; addr++) {
Wire.beginTransmission(addr);
uint8_t err = Wire.endTransmission();
if (err == 0) {
Serial.print("Found device at 0x");
if (addr < 0x10) Serial.print('0');
Serial.println(addr, HEX);
found++;
} else if (err == 4) {
Serial.print("Unknown error at 0x");
Serial.println(addr, HEX);
}
}
if (found == 0) {
Serial.println("No I2C devices found");
Serial.println("Check: SDA/SCL swapped? Module powered? Pull-ups present?");
} else {
Serial.print(found);
Serial.println(" device(s) found");
}
Serial.println();
delay(5000);
}Why it happens
Adafruit vs Pololu wording
The Pololu VL53L0X library example prints “Failed to detect and initialize sensor!”; the Adafruit library prints “Failed to boot VL53L0X”. Same check, same causes.
Sensor initialises but always reads 8190 or 65535
Out of range or timeout. Remove the protective film over the lens, and keep the target within about 1.2 m for default settings.
Works once, fails after reset
A sensor whose address you changed keeps it until it loses power. After an ESP32 reset it may be at 0x30 while code looks at 0x29 — power-cycle or reset it via XSHUT.
Board-specific notes
ESP32: 3.3 V logic; fine with the regulator board. Avoid GPIO 34–39 for XSHUT (input-only).
Parts: VL53L0X — range, address and XSHUT notes.
Did this fix it?
Thanks — that helps us keep this page right.