Using 2 VL53L0X ToF sensors with Arduino Uno

Hello, I am trying to use 2 Tof Sensors for my project , based on my research so far I have am addressing 2 Tof first one to x30 and x31. I want to get independent data from both , however the distance from Sensor 2 is Always just 6535 mm and sensor 1 is working as expected.
I2C scanner shows the configured address but the output is always 6535 mm on one of the sensors .
I have checked the Tof Sensors Independently and they work fine , Even if I swap the sensors , One of the sensors still give 6535 as output. I also tested on different Arduino Uno boards but it always gives me same results
What is the issue here? Please find the code below.

#include <Wire.h>
#include <VL53L0X.h>

// Create instances for both sensors
VL53L0X sensor1;
VL53L0X sensor2;

#define XSHUT_1 2  // XSHUT pin for Sensor 1
#define XSHUT_2 3  // XSHUT pin for Sensor 2

void setup() {
  Serial.begin(9600);  // Start the serial monitor
  Wire.begin();         // Start I2C communication

  // Initialize XSHUT pins
  pinMode(XSHUT_1, OUTPUT);
  pinMode(XSHUT_2, OUTPUT);

  // Disable both sensors at startup
  digitalWrite(XSHUT_1, LOW);
  digitalWrite(XSHUT_2, LOW);
  delay(10);

  // Enable and initialize Sensor 1
  digitalWrite(XSHUT_1, HIGH);
  delay(10);
  sensor1.init();
  sensor1.setAddress(0x30);  // Assign address 0x30 to Sensor 1
  Serial.println("Sensor 1 initialized at address 0x30");

  // Enable and initialize Sensor 2
  digitalWrite(XSHUT_2, HIGH);
  delay(10);
  sensor2.init();
  sensor2.setAddress(0x31);  // Assign address 0x31 to Sensor 2
  Serial.println("Sensor 2 initialized at address 0x31");

  // Start continuous ranging mode for both sensors
  sensor1.startContinuous();
  sensor2.startContinuous();
}

void loop() {
  // Read and print distance from Sensor 1
  uint16_t distance1 = sensor1.readRangeContinuousMillimeters();
  Serial.print("Sensor 1 (0x30) Distance: ");
  Serial.print(distance1);
  Serial.println(" mm");

  // Check for timeouts on Sensor 1
  if (sensor1.timeoutOccurred()) {
    Serial.println("Sensor 1 timeout!");
  }

  // Read and print distance from Sensor 2
  uint16_t distance2 = sensor2.readRangeContinuousMillimeters();
  Serial.print("Sensor 2 (0x31) Distance: ");
  Serial.print(distance2);
  Serial.println(" mm");

  // Check for timeouts on Sensor 2
  if (sensor2.timeoutOccurred()) {
    Serial.println("Sensor 2 timeout!");
  }

  delay(1500);  // 0.5-second delay between readings
}

This is the output I get

Sensor 1 initialized at address 0x30
Sensor 2 initialized at address 0x31
Sensor 1 (0x30) Distance: 65535 mm
Sensor 2 (0x31) Distance: 595 mm
Sensor 1 (0x30) Distance: 65535 mm
Sensor 2 (0x31) Distance: 606 mm

Wiring Diagram
XSHUT SENSOR 1 --- PIN2
XSHUT SENSOR 2 --- PIN3
SDA - A4
SDL - A5
VCC - 5V
GND-GND

65535 which is 0xffff (maximum value for uint16).

If the (IIC) address allowed initialization, is a timeout set too low (do pulses return too late)?

Are pulses too often (are pulses stepping on a previous reading)?

What if you wait to print the results until after the transmit/receive is complete, so transmit and receive are not being blocked by slow, serial printing?

I think data transfer (printing) uses interrupts, so maybe try other pins (Arduino pins 2 and 3 are hardware interrupts 0 and 1).

I tried your suggestions but, the readings are still at 65535. I gave enough delay to account for pulses.

If you have not already done this, write a program for one sensor that simply sets the address to 0x30, or 0x31, and test it with each sensor, for both addresses.

Hi, @4nodews
Is there something wrong here?

// Enable and initialize Sensor 1
  digitalWrite(XSHUT_1, HIGH);
  delay(10);
  sensor1.init();
  sensor1.setAddress(0x30);  // Assign address 0x30 to Sensor 1
  Serial.println("Sensor 1 initialized at address 0x30");

  // Enable and initialize Sensor 2
  digitalWrite(XSHUT_2, HIGH);
  delay(10);
  sensor2.init();
  sensor2.setAddress(0x31);  // Assign address 0x31 to Sensor 2
  Serial.println("Sensor 2 initialized at address 0x31");

you make xshut_1 high and set its address
then
you make xshut_2 high and set its address.

So when you set xshut_2 address, xshut_1 is still open....

Should you set xshut_1 LOW before xshut_2 is set HIGH?

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Please tell us what model Arduino are you using?

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

1 Like

I read in the library that leaving the xshut high is advised. I, too, thought changing the first xshut to low would be how to set the second address.

Hi,
This may help.
https://robojax.com/learn/arduino/?vid=robojax_VL53L0X_multiple

The sample code does as we assumed.

Tom.. :smiley: :+1: :coffee: :australia:

1 Like

Hi Tom , Thanks for the reply.

I am using an arduino UNO SMD , along with 2 Tof Sensor with the following wiring diagram .

  • VL53L0X Sensor 1 (Address: 0x30)
  • XSHUT (Pin 2): Connect to Arduino pin 2
  • SDA: Connect to Arduino SDA (A4 for Arduino Uno)
  • SCL: Connect to Arduino SCL (A5 for Arduino Uno)
  • VIN: Connect to Arduino 5V
  • GND: Connect to Arduino GND
  • VL53L0X Sensor 2 (Address: 0x31)
  • XSHUT (Pin 3): Connect to Arduino pin 3
  • SDA: Connect to Arduino SDA (A4 for Arduino Uno)
  • SCL: Connect to Arduino SCL (A5 for Arduino Uno)
  • VIN: Connect to Arduino 5V
  • GND: Connect to Arduino GND

I tried using putting the first sensor XSHUT to Low before addressing the 2nd sensor like below

digitalWrite(XSHUT1, HIGH);  // Power on Sensor 1
  delay(10);
  sensor1.init();
  sensor1.setAddress(SENSOR1_ADDRESS);  // Change address to 0x30
  digitalWrite(XSHUT1, LOW);

  // Initialize Sensor 2
  digitalWrite(XSHUT2, HIGH);  // Power on Sensor 2
  delay(10);
  sensor2.init();
  sensor2.setAddress(SENSOR2_ADDRESS);  // Keep default 0x31

How ever the output is coming as below.

Sensor 1 (0x30) Distance: 65535 mm
Sensor 2 (0x31) Distance: 65535 mm
Sensor 1 (0x30) Distance: 65535 mm
Sensor 2 (0x31) Distance: 65535 mm
Sensor 1 (0x30) Distance: 65535 mm
Sensor 2 (0x31) Distance: 65535 mm
Sensor 1 (0x30) Distance: 65535 mm
Sensor 2 (0x31) Distance: 65535 mm

Hi,
This might help also;

Tom.. :smiley: :+1: :coffee: :australia:

Hi Tom,

I had been following the tutorial from the video you shared , however his code does not give me any output. The Library im using is just VL52L0X not adafruit.
Also I tested the code setting the xshut1 low after addressing it but it was just giving me 65535 as data. But when I removed the XSHUT1 Low im getting good data from the first sensor but sensor 2 is still showing 65535 mm

Using the below code.

// Initialize Sensor 1
  digitalWrite(XSHUT1, HIGH);  // Power on Sensor 1
  delay(10);
  sensor1.init();
  sensor1.setAddress(SENSOR1_ADDRESS);  // Change address to 0x30
  //digitalWrite(XSHUT1, LOW);

  // Initialize Sensor 2
  digitalWrite(XSHUT2, HIGH);  // Power on Sensor 2
  delay(10);
  sensor2.init();
  sensor2.setAddress(SENSOR2_ADDRESS);  // Keep default 0x31

Gives me this data:

Sensor 1 (0x30) Distance: 98 mm
Sensor 2 (0x31) Distance: 65535 mm
Sensor 1 (0x30) Distance: 102 mm
Sensor 2 (0x31) Distance: 65535 mm
Sensor 1 (0x30) Distance: 102 mm
Sensor 2 (0x31) Distance: 65535 mm

What am I missing here?

Try the Adafruit Library.

Tom.. :smiley: :+1: :coffee: :australia:

See Post #4. Isolate.

You have a "good" channel from sensor, through wire, through pin, through code, ORDER OF INITIALIZATION (which is first?). Have you tried with just initializing and using the "bad" channel? Use the "good" channel to isolate hardware problems in the "bad" channel (move the wire, move the pin, move the sensor).

Hi,
Do your sensor modules have pull up resistors on them?

Can you please post a link to where you purchased them?

Tom.. :smiley: :+1: :coffee: :australia:

Using the Adafruit Library , with the wiring and code from Robojax. I am getting the following result .

#include "Adafruit_VL53L0X.h"

// address we will assign if dual sensor is present
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31

// set the pins to shutdown
#define SHT_LOX1 3
#define SHT_LOX2 2

// objects for the vl53l0x
Adafruit_VL53L0X lox1 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox2 = Adafruit_VL53L0X();

// this holds the measurement
VL53L0X_RangingMeasurementData_t measure1;
VL53L0X_RangingMeasurementData_t measure2;

/*
    Reset all sensors by setting all of their XSHUT pins low for delay(10), then set all XSHUT high to bring out of reset
    Keep sensor #1 awake by keeping XSHUT pin high
    Put all other sensors into shutdown by pulling XSHUT pins low
    Initialize sensor #1 with lox.begin(new_i2c_address) Pick any number but 0x29 and it must be under 0x7F. Going with 0x30 to 0x3F is probably OK.
    Keep sensor #1 awake, and now bring sensor #2 out of reset by setting its XSHUT pin high.
    Initialize sensor #2 with lox.begin(new_i2c_address) Pick any number but 0x29 and whatever you set the first sensor to
 */
void setID() {
  // all reset
  digitalWrite(SHT_LOX1, LOW);    
  digitalWrite(SHT_LOX2, LOW);
  delay(10);
  // all unreset
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);

  // activating LOX1 and resetting LOX2
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, LOW);

  // initing LOX1
  if(!lox1.begin(LOX1_ADDRESS)) {
    Serial.println(F("Failed to boot first VL53L0X"));
    while(1);
  }
  delay(10);

  // activating LOX2
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);

  //initing LOX2
  if(!lox2.begin(LOX2_ADDRESS)) {
    Serial.println(F("Failed to boot second VL53L0X"));
    while(1);
  }
}

void read_dual_sensors() {
  
  lox1.rangingTest(&measure1, false); // pass in 'true' to get debug data printout!
  lox2.rangingTest(&measure2, false); // pass in 'true' to get debug data printout!

  // print sensor one reading
  Serial.print(F("1: "));
  if(measure1.RangeStatus != 4) {     // if not out of range
    Serial.print(measure1.RangeMilliMeter);
  } else {
    Serial.print(F("Out of range"));
  }
  
  Serial.print(F(" "));

  // print sensor two reading
  Serial.print(F("2: "));
  if(measure2.RangeStatus != 4) {
    Serial.print(measure2.RangeMilliMeter);
  } else {
    Serial.print(F("Out of range"));
  }
  
  Serial.println();
}

void setup() {
  Serial.begin(115200);

  // wait until serial port opens for native USB devices
  while (! Serial) { delay(1); }

  pinMode(SHT_LOX1, OUTPUT);
  pinMode(SHT_LOX2, OUTPUT);

  Serial.println(F("Shutdown pins inited..."));

  digitalWrite(SHT_LOX1, LOW);
  digitalWrite(SHT_LOX2, LOW);

  Serial.println(F("Both in reset mode...(pins are low)"));
  
  
  Serial.println(F("Starting..."));
  setID();
 
}

void loop() {
   
  read_dual_sensors();
  delay(100);
}

Shutdown pins inited...
Both in reset mode...(pins are low)
Starting...

I got the sensors online at Robu. in VL53L0x

@xfpd
I Have tried and swapped around the components , the sensors work fine when they are initialized first , its always the second initialization that is giving 65535 data

1 Like

Were there any measurements on this sketch (Adafruit)?

You can turn a "debug" flag on in the "begin()" function to watch the steps...

/*!
    @brief  Setups the I2C interface and hardware
    @param  i2c_addr Optional I2C address the sensor can be found on. Default is
   0x29
    @param debug Optional debug flag. If true, debug information will print out
   via Serial.print during setup. Defaults to false.
    @param  i2c Optional I2C bus the sensor is located on. Default is Wire
    @param vl_config Sensor configuration
    @returns True if device is set up, false on any failure
*/
/**************************************************************************/
boolean Adafruit_VL53L0X::begin(uint8_t i2c_addr, boolean debug, TwoWire *i2c,
                                VL53L0X_Sense_config_t vl_config) {

Sadly they do not provide any useful documentation as to what these sensor boards are.

There should be some way of changing a link on the sensor board to change the address a board responds to.

Yes that is what you would expect if your sensor board has no way of setting which address it responds to.

Any board worth its salt should allow the sensor board to change what address it responds to. It is NOT just a matter of using a different address, because the two boards are both responding to either I2C address.

So either get back to your supplier and ask how to change the address of each board. Or buy a decent board that allows you change the address. This is normally done with making or breaking a link on your board.

However, alternately you could use a a TCA9548A I2C Multiplexer to allow different sensors to be run from different busses, and so use this to set different addresses for each of the two boards you have.

Apologies for the delayed response. I managed to resolve the issue using a MUX . I tested the setup with multiple different configuration but I believe the only possible explanation to the I2C sensor was a dude to the manufacturing parameters .
In the future I plan on getting a the sensors from a verified manufacturer and test to figure out different results.

Thanks Mike and everyone else.

1 Like