cancel
Showing results for 
Search instead for 
Did you mean: 

Connect multiple VL53L5CX on the same I2C bus of Jetson Nano

MMube.1
Associate

Hi, I have a jetson nano and am trying to connect multiple VL53L5CX sensors to its I2C Bus 1. Therefore, I have to update the address for the sensors. According to the documentation, I need to initially pull down all the Lpn pins for the connected sensors, then pull up the Lpn pin for one of the sensor whose address I would like to change. Then I would have to call the following function after the sensor has been initialized.

status = vl53l5cx_set_i2c_address(&Dev, 0x40);

Now, I am facing multiple issues: -

  • First of all, according to the docs, my sensor should be detected at address 0x52, but instead, It is getting detected at 0x29.
  • My second issue is that the return status for the above mentioned function call is 254 instead of 0.
  • The third issue is that the address of the sensor does get updated after calling the function, but instead of whatever address I give it, it sets it to its half. For example, in the above case, instead of setting the new address to 0x40, it sets the new address to 0x20.
  • Lastly, and the most important one, let's say as mentioned in the above point, if I try to access the sensor at the updated address (0x20), the program gives me an error of "VL53L5CX not detected at requested address". I am running the examples provided by the Linux_driver_1.1.1. I made sure to update the vl53l5cx_comms_init function in platform.cpp file from this
if (ioctl(p_platform->fd, I2C_SLAVE, 0x29) <0) {

to

if (ioctl(p_platform->fd, I2C_SLAVE, 0x20) <0) {

Any help would be appreciated.

Note: I am connecting the sensors with SCL, SDA using pull-up resistors of 2.2k whereas, the LPn have been pulled up/down using 47k resistors. Moreover, I had updated the platform.cpp file to use address 0x29.

7 REPLIES 7
John E KVAM
ST Employee

One of the real pains about I2C is the fact that 0x29 and 0x52 are the same number.

If one uses the 7-bit address (0x29) one must add a read/write bit by shifting left one bit and putting a zero into the LSB to get a write address of 0x52 and a read address of 0x53.

And so, depending on the conventions of your CPU you either specify the base (0x29) or the write address (0x52). And yes, what a pain.

Different manufactures refer to either the 0x29 or the write address 0x52. The best way would be to refer to the write/read pair as 0x52/0x53.

So depending on how you've implemented the I2C read and write functions, the argument can be either the 29 or the 53.

The trick is to make them consistent.

  • john


Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'
MMube.1
Associate

Thanks John for this info, it pretty much solves issues 1 and 2. Do you have any info regarding the error status I am getting along with the reason that even after reading from the newly updated address, why I am unable to still read from the sensor and getting an error?

Mubeen

John E KVAM
ST Employee

I think it's still an addressing issue. Instead of trying with multiple sensors, just use one and change the address. Then talk to it.

If you change the address and you cannot communicate, then you the address you chose and your new read address do not match. It might well be that you change the address to 0x20 and have to write to 0x40 and read from 0x41. Or it might be the other way around.

One day I'll meet the person who came up with this idea, and I will NOT buy them a beer.

(But in their defense, the I2C bus was never intended to become what it has. It was a tiny bus to change a couple of settings on a TV chip. We are driving it to it's limits.)

Sorry this is such a pain.

  • john

Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'
MMato.1
Associate

I was facing the exact same issues as you described, using a Raspberry Pi 4 and a VL53L5CX-SATEL board. I got it working by doing the following:

  • The function write_read_multi() included in the platform.c file provided by the api always uses the same address 0x29:
messages[0].addr = 0x29;

but this address should vary according to the device address variable, something like this:

messages[0].addr = p_platform->address;

This write_read_multi() function currently only takes the file descriptor number from the device. To also pass the address some changes have to be made to this and related functions ( see attachment ) .

  • Regarding the third issue, i got around it by removing the right shift operation in this line from the file vl53l5cx_api.c , vl53l5cx_set_i2c_address():
status |= WrByte(&(p_dev->platform), 0x4, (uint8_t)(i2c_address >> 1));

to this:

status |= WrByte(&(p_dev->platform), 0x4, (uint8_t)(i2c_address));

I've attached the platform.c file i'm currently using, hope it helps.

So why exactly is ST using the 8-bit addressing scheme in their datasheets (or at least in the VL53L5 one)?

According to the I2C specification, the Address is either 7-bit or 10-bit, an 8-bit scheme adding the read/write bit to the actual address doesn't exist.

This only adds to the confusion.

And how is it handled in the ST APIs?

In the VL53L5CX_RegisterBusIO-function, do I have to put the 7-bit-address or the "8-bit-address" of the sensor? If 8-bit, the one for reading or for writing?

Which addresses are to be used for the BSP_I2C1_ReadReg and BSP_I2C1_WriteReg functions as these already specify reading/writing?

This is all the fault of the I2C standard written by Philips years ago. (NXP bought Philips, so they now maintain the spec.)

But the 7bit address is the root. But spec'ing the write address (7bit<<1)is just as valid. And unfortunately it depends more on which MCU you are using. They have their own scheme.

IN my code, the first line of code is:

uint8_t bus_address = 0x52;

That's mostly because the platform.c file expects the write address for my MCU.

I use the addresses:

uint16_t DevAddr[9] = {0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C, 0x6E, 0x70, 0x72};

when I need a lot of sensors.


Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'

I dug a little farther. The function:

VL53l5cx_set_i2c_address( *p_dev, i2c_address) 

contains the line:

status += WrByte((&(p_dev->platform),0x4, (uint8_t)(i2c_address >>1);

So clearly register 4 in the hardware expects the 7-bit address.

And just as clearly the software function uses the 8-bit write address.

But you are right - documentation should be better.

  • john

Our community relies on fruitful exchanges and good quality content. You can thank and reward helpful and positive contributions by marking them as 'Accept as Solution'. When marking a solution, make sure it answers your original question or issue that you raised.

ST Employees that act as moderators have the right to accept the solution, judging by their expertise. This helps other community members identify useful discussions and refrain from raising the same question. If you notice any false behavior or abuse of the action, do not hesitate to 'Report Inappropriate Content'