Problem running multiple VL53L0X sensors

Hello!
So I already posted same topic with an explained schematic to my board OS support forum with code details and schematic of my connections:
https://forums.mbed.com/t/problem-running-multiple-vl53l0x-tof-sensors/7521

Now I also found this topic on this forum: VL53L0X -- maximum sensors on I2C arduino bus - #7 by oleglyan

In this post, I stumbled upon this comment by user oleglyan and instead of using my GPIOs in only output mode and switching between 3.3V high and low states, I now also set up my “current configured address” to be in an input state and be pulled up to 2.8V through XSHUT of the sensor. The thing I couldn`t understand in his code is that he is setting the xshuts into high mode in a row, but during the next address setting, only one pin should be INPUT(the one which address is going to be set) and others still set back to an active low state in output mode? But in this example code, with every setting of an address the input states are being added on and on, so the previous is also in mode of an input…

Here`s my new code following oleglyan method:

void initSensors()
{
i2cGPIOexpanderINIT(0x22); //SET PINS TO OUTPUT AND LOW.

i2cGPIOexpanderConfigure(0x22, 0b11111000); //4 LAST BITS configure pins - “1000” - first sensor pin now set as input!
sensor1.setAddress(0x31);
i2cGPIOexpanderConfigure(0x22, 0b11110100); // “0100” first pin now to low state, 2nd as INPUT /2.8V, to configure only 2nd sensor address.
sensor2.setAddress(0x34);
i2cGPIOexpanderConfigure(0x22, 0b11111100); // Set both two sensors to input - 2.8V
wait_us(10000);
sensor1.init();
sensor2.init();

sensor1.setTimeout(500);
sensor2.setTimeout(500);

#if defined LONG_RANGE
// lower the return signal rate limit (default is 0.25 MCPS)
sensor1.setSignalRateLimit(0.1);
sensor2.setSignalRateLimit(0.1);
// increase laser pulse periods (defaults are 14 and 10 PCLKs)
sensor1.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
sensor1.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
sensor2.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);
sensor2.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);
#endif

#if defined HIGH_SPEED
// reduce timing budget to 20 ms (default is about 33 ms)
sensor1.setMeasurementTimingBudget(20000);
sensor2.setMeasurementTimingBudget(20000);
#elif defined HIGH_ACCURACY
// increase timing budget to 200 ms
sensor1.setMeasurementTimingBudget(200000);
sensor2.setMeasurementTimingBudget(200000);
#endif
}

My i2cGPIOexpanderConfigure method:

void i2cGPIOexpanderConfigure(int address, char pinState)
{
char conf_reg[2] = {0x03, pinState}; //0x00 output, 0xFF input
int error = i2c.write(address << 1, conf_reg, sizeof(conf_reg));
serial_pc.printf(“Result: %s\n”, (error == 0?“ACK \r\n”:“NAK \r\n”));
wait_us(10000);
}

Initial INIT method to set pins as low output. *I am only using last 4 bits for my 4 pins.

void i2cGPIOexpanderINIT(int address) {
i2c.frequency(100000);
char conf_reg[2] = {0x03, 0x00}; //0x00 output, 0xFF input = SET TO OUTPUT.
int error = i2c.write(address << 1, conf_reg, sizeof(conf_reg));
serial_pc.printf(“Result: %s\n”, (error == 0?“ACK \r\n”:“NAK \r\n”));
char conf_reg2[2] = {0x01, 0xF0}; //Last 4bits for PIN configure // ACTIVE-LOW STATE
error = i2c.write(address << 1, conf_reg2, sizeof(conf_reg2));
serial_pc.printf(“Result: %s\n”, (error == 0?“ACK \r\n”:“NAK \r\n”));
}

After doing this, I still find my PCA9554 chip address, default sensor address 0x29(should be 0x31), and scans the 2nd sensor as 0x34.
Now If I reverse the xshut pin wiring connections on the sensors, both of the sensors scan on address 0x31.

Thanks in advance!!

Edit: Measured all the 4 extended GPIO pins for 3.3V output, although the last two pins according to code should be close to 0V, because I have set them to be output, which I configured them to be low state before in the i2cGPIOexpanderINIT method (0xF0). And here is the final write to the PCA9554 chip, which sets the last two pins as OUTPUT:

sensor2.setAddress(0x34);
i2cGPIOexpanderConfigure(0x22, 0b11111100); // Set both two sensors to input - 2.8V
wait_us(10000);

Whether or not is that the case for wrong addresses, I am thinking that I am still doing something wrong in this input/output configure field according to my voltage measurements from the last two pins.

Hello,

I haven’t looked closely at your code, but I think the cause of your confusion is that changing the address of the VL53L0X only stays in effect until it is reset or powered off. By driving the first sensor’s XSHUT pin low again, you are resetting it and therefore resetting its address.

In case it helps, this is how multiple sensors are set up, in detail:

  1. Start with both sensors’ XSHUT pins driven low, so that both sensors are disabled.
  2. Allow Sensor 1 to come out of reset (stop driving its XSHUT pin low). Sensor 1 is now enabled with the default address, 0x29.
  3. Send a command to address 0x29, telling it to change its address to 0x31. This changes Sensor 1’s address to 0x31.
  4. Allow Sensor 2 to come out of reset. Sensor 2 is now enabled with the default address, 0x29.
  5. Send a command to address 0x29, telling it to change its address to 0x34. This changes Sensor 2’s address to 0x34.
  6. You can now access Sensor 1 at 0x31 and Sensor 2 at 0x34.

What allows this to work is that in step 5, only Sensor 2 “hears” the command because it is the only sensor that has an address of 0x29 at that time; Sensor 1 does not hear it because its address has already been changed to 0x31. (However, it’s not really necessary to change the last sensor’s address because there is nothing else for it to conflict with.)

So what oleglyan did in his code is correct: once you enable a sensor, you need to keep it enabled or else it will forget its address. Could you try changing your code to match this behavior and see if it works?

Kevin