cancel
Showing results for 
Search instead for 
Did you mean: 

Is there a demo for VL53L3CX that help me to understand how to manage different ToFs together? Something similar to the MultiRangingSensor demo for VL53L1X.

VNava
Associate III

Hi, my name is Vincenzo.

I am working with the ToF VL53L3CX. Lately I wrote some applications to make 6 sensors work. At first I thought that the applications were working well, but now I realized that if I set too high timing budgets I had a performance problem. Since when I work with only one sensor everything works correctly, I thought the problem was in the way I manage the 6 ToF.

For this reason, I was wondering if there was a project made by you where multiple sensors are managed.

Thank you in advance for your support.

Vincenzo

10 REPLIES 10
Julien NGUYEN
ST Employee

​Hi Vincenzo, it is the same principle, you can use the MultiRangingSensor demo for the L1X. Julien


In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
VNava
Associate III

Thanks Julien!

My doubt is related to the fact that the way of managing the timing of the two ToF types seems different. I hope I can explain my problem well. I have tried two strategies to manage different VL53L3CX ToF (let's consider the case of 6 ToF).

------------------FIRST STRATEGY--------------------

do

{

for(ToF=0; ToF<6;ToF++)

{

start = HAL_GetTick();

if(ToF==0)

{

printf("____________________________________________________________________________________");

}

status = VL53LX_GetMeasurementDataReady(Dev[ToF], &NewDataReady);

while (NewDataReady == 0)

{

status = VL53LX_GetMeasurementDataReady(Dev[ToF], &NewDataReady);

}

if((!status)&&(NewDataReady!=0)){

status = VL53LX_GetMultiRangingData(Dev[ToF], pMultiRangingData);

no_of_object_found=pMultiRangingData->NumberOfObjectsFound;

printf("\n\r ToF %d  Count=%5d, ", ToF, pMultiRangingData->StreamCount);

printf("#Objs=%1d ", no_of_object_found);

for(j=0;j<no_of_object_found;j++){

if(j!=0)printf("\n\r\t\t\t   ");

printf("status=%d, D=%5dmm, Signal=%2.2f Mcps, Ambient=%2.2f Mcps",

pMultiRangingData->RangeData[j].RangeStatus,

pMultiRangingData->RangeData[j].RangeMilliMeter,

pMultiRangingData->RangeData[j].SignalRateRtnMegaCps/65536.0,

pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps/65536.0);

}

if (status==0){

status = VL53LX_ClearInterruptAndStartMeasurement(Dev[ToF]);

}

}

}

}

while (1);

-----------------------SECOND STRATEGY------------------------

 for( ; ; )

 {

 for(ToF=0; ToF<6; ToF++)

 {

 status = VL53LX_GetMeasurementDataReady(Dev[ToF], &NewDataReady[ToF]);

 while (NewDataReady[ToF] == 0)

 {

 status = VL53LX_GetMeasurementDataReady(Dev[ToF], &NewDataReady[ToF]);

 }

 if(status !=0)

 {

 while(1)

 {

 printf("\n\rERROR!!!");

 }

 }

 }

 for(ToF=0; ToF<6; ToF++)

 {

 if(NewDataReady[ToF]!=0)

 {

 status = VL53LX_GetMultiRangingData(Dev[ToF], pMultiRangingData);

 if(status !=0)

 {

 while(1)

 {

 printf("\n\rERROR!!!");

 }

 }

 no_of_object_found=pMultiRangingData->NumberOfObjectsFound;

 printf("ToF %d Count=%5d, ",ToF, pMultiRangingData->StreamCount);

 printf("#Objs=%1d ", no_of_object_found);

 for(j=0;j<no_of_object_found;j++)

 {

 if(j!=0)printf("\n\r\t\t\t  ");

 printf("status=%d, D=%5dmm, Signal=%2.2f Mcps, Ambient=%2.2f Mcps",

 pMultiRangingData->RangeData[j].RangeStatus,

 pMultiRangingData->RangeData[j].RangeMilliMeter,

 pMultiRangingData->RangeData[j].SignalRateRtnMegaCps/65536.0,

 pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps/65536.0);

 }

 printf("\n\r");

 }

 }

 for(ToF=0; ToF<6; ToF++)

 {

 status = VL53LX_ClearInterruptAndStartMeasurement(Dev[ToF]);

 if(status !=0)

 {

 while(1)

 {

 printf("\n\rERROR!!!");

 }

 }

 }

 printf("\n\r__________________________________________________________________________________\n\r");

 }

Both strategies are preceded by reset, set, initialization of the devices and the launch of the StartMeasurement driver function for each of the ToF.

In the first strategy I would like to execute the flow of instructions: VL53LX_GetMeasurementDataReady (Dev [ToF], & NewDataReady) -> VL53LX_GetMultiRangingData (Dev [ToF], pMultiRangingData) -> VL53LX_ClearInterruptAndStart [ToFeasurement] one ToF at a time

In the second strategy, on the other hand, I throw every single instruction 6 times before moving on to the next instruction.

Both of these strategies seem to work well for small timing budgets (8-30 ms), but when setting high timing budgets the ToFs don't work well. I believe this means that I am mishandling the 6 ToFs.

I could not verify if this also happens for the ToF VL53L1X, but comparing the two User Manuals I realized that while the VL53L3CX provide the information of the i-th measurement while the measurement (i + 1) is carried out, in the case of the VL53L1X the information of the i-th measurement is obtained during the inter-measured.period preceding the measurement (i + 1).

0693W000003Q7JiQAK.png

Considering all this, I would like to know if the performance problem, in the case of 6 ToF, is related to different aspects of timing compared to the VL53L1X or if I did not write the code well and I did not respect the ranging flow for the VL53L3CX.

Thanks again for answering my question

Vincenzo

VNava
Associate III

Update

I bought 4 VL53L1Xs to make a short comparison with the L3CXs. I eliminated the X-NUCLEO-53L3A1 to have a setup similar to that of the system with 6 VL53L3CX. I used the MultiSensorRanging demo and modified it to eliminate the X-NUCLEO and control 4 ToF instead of 3. I didn't notice any performance issues unlike the VL53L3CX case. At this point I wonder if I probably made some mistakes when I wrote the code to control the 6 VL53L3CX TOFs or if I have to think of some precautions due to the fact that in the case of the L3CX I have no inter-measured period.

VNava
Associate III

Update

I rewrote the code for VL53L3CX, as you advised me, based on the code written for VL53L1X. ToF performance problems no longer occur. Thanks Julien!

However, while in the case of the VL53L1X inside the while(1){} loop I repeat the StartMeasurement() function continuously, in the case of the VL53L3CX I execute this function only once, before entering the while(1){} loop and immediately after the initialization functions. After all, if I remember correctly, within the UM of the VL53L3CX API, the ranging flow requires that the startmeasurement is carried out once and then, after choosing the preferred mode (driver/host polling or interrupt) the getData-ClearInterrupt cycle is repeated continuously.

Thanks again.

Vincenzo

I have to correct my last comment. Unfortunately, the high TB ​​performance issues have not been resolved. They came back as soon as I went from 4 to 6 ToF. Probably for 4 ToF it was not perceptible, I don't know.

I report below the code I am currently using to control the 6 ToF. The principle should be the same as that of VL53L1X except for the StartMeasurement function I mentioned earlier

int main(void)

{

 uint8_t byteData;

 uint16_t wordData;

 uint8_t ToFSensor = 0;

 uint8_t newI2C = 0x52;

 VL53LX_MultiRangingData_t MultiRangingData;

 VL53LX_MultiRangingData_t *pMultiRangingData = &MultiRangingData;

 int no_of_object_found=0,j;

 /* MCU Configuration----------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

 HAL_Init();

 /* Configure the system clock */

 SystemClock_Config();

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_USART2_UART_Init();

 MX_I2C1_Init();

 HAL_GPIO_WritePin(X_SHUT_1_GPIO_Port, X_SHUT_1_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(X_SHUT_2_GPIO_Port, X_SHUT_2_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(X_SHUT_3_GPIO_Port, X_SHUT_3_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(X_SHUT_4_GPIO_Port, X_SHUT_4_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(X_SHUT_3_GPIO_Port, X_SHUT_5_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(X_SHUT_4_GPIO_Port, X_SHUT_6_Pin, GPIO_PIN_RESET);

 /* Bring the sensors out of the reset stage one by one and set the new I2C address */

  for (ToFSensor=0;ToFSensor<6;ToFSensor++)

  {

  switch(ToFSensor)

  {

  case 0:

  Dev=&dev1;

  break;

  case 1:

  Dev=&dev2;

  break;

  case 2:

  Dev=&dev3;

  break;

  case 3:

  Dev=&dev4;

  break;

  case 4:

  Dev=&dev5;

  break;

  case 5:

  Dev=&dev6;

  break;

  }

  TurnOnSensor(ToFSensor);

  Dev->comms_speed_khz = 400;

  Dev->I2cHandle = &hi2c1;

  Dev->comms_type = 1;

  Dev->I2cDevAddr=0x52;

  HAL_Delay(2);

  newI2C = Dev->I2cDevAddr + (ToFSensor+1)*2;

  status = VL53LX_SetDeviceAddress(Dev, newI2C);

  Dev->I2cDevAddr=newI2C;

  VL53LX_RdByte(Dev, 0x010F, &byteData);

  printf("\n\rVL53LX Model_ID: %02X\n\r", byteData);

  VL53LX_RdByte(Dev, 0x0110, &byteData);

  printf("VL53LX Module_Type: %02X\n\r", byteData);

  VL53LX_RdWord(Dev, 0x010F, &wordData);

  printf("VL53LX: %02X\n\n\r", wordData);

status = VL53LX_WaitDeviceBooted(Dev);

status = VL53LX_DataInit(Dev);

status = VL53LX_SetDistanceMode(Dev, VL53LX_DISTANCEMODE_SHORT);

status = VL53LX_SetMeasurementTimingBudgetMicroSeconds(Dev, 500000);

status = VL53LX_StartMeasurement(Dev);

  }

while(1)

{

for (ToFSensor=0;ToFSensor<6;ToFSensor++)

{

switch(ToFSensor)

{

case 0:

Dev=&dev1;

break;

case 1:

Dev=&dev2;

break;

case 2:

Dev=&dev3;

break;

case 3:

Dev=&dev4;

break;

case 4:

Dev=&dev5;

break;

case 5:

Dev=&dev6;

break;

}

status = VL53LX_WaitMeasurementDataReady(Dev);

if(!status)

{

status = VL53LX_GetMultiRangingData(Dev, pMultiRangingData);

if(status == 0)

{

no_of_object_found=pMultiRangingData->NumberOfObjectsFound;

printf("Count=%5d, ", pMultiRangingData->StreamCount);

printf("#Objs=%1d ", no_of_object_found);

for(j=0;j<no_of_object_found;j++)

{

if(j!=0)printf("\n\r\t\t   ");

printf("status=%d, D=%5dmm, Signal=%2.2f Mcps, Ambient=%2.2f Mcps",

pMultiRangingData->RangeData[j].RangeStatus,

pMultiRangingData->RangeData[j].RangeMilliMeter,

pMultiRangingData->RangeData[j].SignalRateRtnMegaCps/65536.0,

pMultiRangingData->RangeData[j].AmbientRateRtnMegaCps/65536.0);

}

}

status = VL53LX_ClearInterruptAndStartMeasurement(Dev);

printf ("\n\r");

}

}

printf("_______________________________________________________________________________\n\n\r");

}

}

Can you tell me why these performance problems arise when I use multiple ToFs (let's consider the case of 6 ToF) and high timing budgets (200-500ms)?

In fact, if I use low timing budget (20ms) these problems do not seem to exist.

Thanks in advance for your support.

Julien NGUYEN
ST Employee

Hi Vincenzo,

What do you mean by performances problem when the TB is high ?

Julien


In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

Thanks Julien.

I am using a NUCLEO-F401RE to control 6 ToF VL53L3CX.

Previously I used only one ToF, and for any Timing Budget selected, the ToF recognized the presence of an object (even 2 objects) and gave me the exact distance.

Then I decided to make several ToF work sequentially(like the demo MultiRangingSensor for VL53L1X), up to 6 ToF. I noticed that by working with 6 ToF, setting high TB, 2 or 3 sensors could not detect objects, and often the detected objects were accompanied by range status different from zero. The curious thing is that always using 6 sensors, but setting low TB (about 20 ms) then those problems that I listed before do not arise, In fact, All 6 ToFs detected the presence of objects with range status = 0.

I hope what I wrote is understandable.

Vincenzo

I have captured two images of my desktop while TeraTerm shows the ranging information. In the first case there are 6 ToF with Timing Budget = 20 ms, in the second case always 6 ToF with Timing Budget = 500 ms. The initial conditions, excluding TB, are practically the same. 6 sensors placed in line and an object placed at a distance of about 7-10 cm from the 6 sensors. What I don't understand is why in the first case the measurement is clean, with no "holes", while in the second case there are "holes" and some range status different from zero (often status = 12 which should means that there is a target but the signal is too low)

0693W000002lEx9QAE.png

I hope that this will make it clearer

VNava
Associate III

Hi Julien,

I would like to inform you that my high TB ​​performance issue can be considered solved. The cause was in the connections I had made. The connections were too long for the I2C protocol set in fast mode (400 kHz). Probably, at this speed the parasitic abilities did not have the time to discharge and there were problems for the I2C protocol. I reduced the length of the connections as much as possible and reduced the pull-up resistor value from 3.6k to 1.2k, this value is for fast mode. With this configuration, even if I configure high TBs, all sensors seem to work fine. Thank you.

I observed that using i2c speed = 100kHz I can also use a pull-up resistor value of 4.7k as in your 2D LIDAR application with vl53l1x. Also in this case, reducing the length of the connections as much as possible. The application works fine.

Probably if you use flying connections instead of printed connections on the board it is preferable to use I2C speed at 100 kHz.

Thank you for all!

Vincenzo