Skip to main content
ALohr.1
Associate II
March 8, 2023
Question

VL53L5CX _start_ranging() fails with 255 error

  • March 8, 2023
  • 7 replies
  • 10935 views

Hi all,

For the last several days I have been battling this API for the VL53L5CX and finally reached the point where the initialisation passes every time. I proceed to set some of the configuration parameters (mostly resetting to the default values suggested in the application note). These functions also return status = 0.

Then I start a ranging session. The problem is that checking the status/error output shows me that the function is failing with a 255 error. Further investigation with a debugger has yielded that the final if() check in the function sets the status too 255. This means that the data_read_size check has failed. see screenshot below for reference.

0693W00000aIQYxQAO.pngI should note that, every single function and I2C transaction passes with no error. In other words, status = 0, the whole time, until this if statement. It is the physical value of the variables that does not match. Has anyone else had this error? or can offer some suggestions as to what is happening and how to fix it?

Thanks

7 replies

John E KVAM
ST Employee
March 10, 2023

check the value of status prior to the final check. My thought is that they are all failing, but at the last line you set it to 255 masking all the other failures.

I like status += function() better than status |= but there are advantages to both.

print out thd two values that don't match - and should.

There might be an answer there.

  • john
ALohr.1
ALohr.1Author
Associate II
March 10, 2023

hi John,

I am using a debugger to individually step through each line and monitor the status. it remains zero until it enters the if statement. there it gets set to 255. With the debugger i can see the variables as they get edited. the value of "tmp" is read out as 0 from the temp_buffer its pulled from. Inspecting the I2c communications with a logic analyser also shows that the sensor is sending back "0'.

The question remains, how does every other read/write pass with no errors, and yet this check fails

John E KVAM
ST Employee
March 10, 2023

The status of the last read is OK and you read 0 bytes? That does not seem right. But I can guess...

The STM can read and write 32k bytes in one go. But it's one of the few MCUs that can do that.

All other MCUs have a limitation of 512, 256 and one is limited to 16 bytes.

That read is requesting some 6K bytes.

And I'm going to guess your MCU can't to that in one go.

You can edit Platform.c and uncomment some of the result data. (Starting at line 114 or so.) That will reduce the length of your return buffer.

Or you can break the I2C request into smaller chunks.

  • john
ALohr.1
ALohr.1Author
Associate II
March 12, 2023

I have implemented the I2C as a custom bit banging. I'm not storing the values in a temporary "i2c buffer" as most MCUs do when running the transactions. I.E. When writing the ULD library uses a pointer to where the data is. I simply increment that pointer and de-reference to send the value. When reading, this time the ULD seems to use the "temp_buffer" variable to store most reads. again the RdByte/Multi functions are passed a pointer to this buffer. I simply increment it for each byte read from the sensror.

I have also reduced the size of the data down to 64 Bytes. By uncommenting most of the disable macros. At this stage I've also changed the RdMulti and WrMulti functions. Writing will send 64 byte blocks. Reading will read 1 byte at a time. I still get the same behaviour.

Associate
November 2, 2023

Hello,

I have a verry similar problem on a vl53l8cx. Have you found a solution?

Thanks

Anne BIGOT
Technical Moderator
November 14, 2023

hello

Did you try John's sugestion regarding IC2 chunks ?
I mean : 

The STM can read and write 32k bytes in one go. But it's one of the few MCUs that can do that.

All other MCUs have a limitation of 512, 256 and one is limited to 16 bytes.

That read is requesting some 6K bytes.

And I'm going to guess your MCU can't to that in one go.

You can edit Platform.c and uncomment some of the result data. (Starting at line 114 or so.) That will reduce the length of your return buffer.

Or you can break the I2C request into smaller chunks.

Anne

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'
Visitor II
March 19, 2024

I am having similar issues to the original poster. It seems that I am able to init the vl53l5cx but when I try reading any data (not just ranging), even the resolution, it returns 0 for the data but also returns 0 for status...very confusing.

 

Here is my swap buffer code:

void VL53L5CX::SwapBuffer(uint8_t *buffer, uint16_t size)
{
 uint32_t i, tmp;

//TODO: Swap buffer gets 0 for resolution and range ui content
 /* Example of possible implementation using <string.h> */
 for (i = 0; i < size; i = i + 4) {
 tmp = (buffer[i] << 24) | (buffer[i + 1] << 16) | (buffer[i + 2] << 8) |
 (buffer[i + 3]);
 // PX4_INFO("Swapped: %lu", tmp);

 memcpy(&(buffer[i]), &tmp, 4);
 }

Also here is my RdMulti

uint8_t VL53L5CX::RdMulti(VL53L5CX_Platform *p_platform, uint16_t RegisterAddress,
 uint8_t *p_values, uint32_t size)
{
 int8_t ret;

 uint8_t mread_local[2];

 /* Write the register address of the sensor*/

 mread_local[0] = (RegisterAddress >> 8) & 0xff;
 mread_local[1] = RegisterAddress & 0xff;

 ret = transfer(&mread_local[0], sizeof(mread_local), nullptr, 0);

 if (ret != PX4_OK) {
 perf_count(_comms_errors);
 return ret;
 }

 ret = transfer(nullptr, 0, p_values, size);

 if (ret != PX4_OK) {
 perf_count(_comms_errors);
 return ret;
 }

 return PX4_OK;
}

 

It appears that when I specifically try to read the data buffer for resolution, the swap buffer has a bunch of zeros. When I compare the tmp with p_dev->data_read_size I always fail this check, again due to swapbuffer only getting 0's from the device. 



John E KVAM
ST Employee
March 19, 2024

If you are not getting any answers back - everything zero - then I'm going to guess you did not get the processor started. 

During the initialization phase you need to download some 80K of data. With the last byte, the ranging engine will start. 

Could you have a look at the code in:

Solved: How do I verify I have my I2C configured correctly... - STMicroelectronics Community

And add that to the top of your program. 

Hopefully it will verify your I2C interface.

- john

Visitor II
March 19, 2024

Thanks John! So the strange thing is the return status is fine, but there is no data being received.
vl53l5cxoutput.png
I am able to pass all the poll for answers at firmware update. Now I did have to chunk out the firmware update into blocks <=1024 bytes, and this may be the issue. I am running on an nxp s32k344:

 /* Download FW into VL53L5 */
 status |= WrByte(&(p_dev->platform), 0x7fff, 0x09);

 // WaitMs(&(p_dev->platform), 1);

 uint32_t fw_addr = 0x0;

 // Transfer initial 32k bytes
 for (uint8_t i = 0; i < 32; ++i) {

 status |= WrMulti(&(p_dev->platform), 0, (uint8_t *)&VL53L5CX_FIRMWARE[fw_addr], 0x400);
 // WaitMs(&(p_dev->platform), 5);
 fw_addr += 0x400;

 }

 status |= WrByte(&(p_dev->platform), 0x7fff, 0x0a);

 // Transfer next 32k bytes
 for (uint8_t i = 0; i < 32; ++i) {

 status |= WrMulti(&(p_dev->platform), 0, (uint8_t *)&VL53L5CX_FIRMWARE[fw_addr], 0x400);
 // WaitMs(&(p_dev->platform), 5);
 fw_addr += 0x400;

 }

 status |= WrByte(&(p_dev->platform), 0x7fff, 0x0b);

 for (uint8_t i = 0; i < 20; ++i) {

 status |= WrMulti(&(p_dev->platform), 0, (uint8_t *)&VL53L5CX_FIRMWARE[fw_addr], 0x400);
 // WaitMs(&(p_dev->platform), 5);
 fw_addr += 0x400;

 }

 // WaitMs(&(p_dev->platform), 10);
 PX4_INFO("last transfer: %lu", fw_addr);



Associate
August 29, 2024

Hi 

i have similar issue using driver VL53L5CX_ULD_driver_2.0.0 on my STM32WB5MM. 

I disabled all outputs except "Distance mm" and "Target status"; when i read temp_buffer using vl53l5cx_dci_read_data i have  temp_buffer[0x8] == 56 but data_read_size == 60 and sensor doesn't work.

Can someone help me?

Thanks in advance

Davide

John E KVAM
ST Employee
August 29, 2024

you need 'number of valid targets' as well. 

To determine a range, the logic is:

If (the number of targets is greater than 0, AND the RangeStatus is 5, 6, 9 or sometimes 12) then use the range for that zone. 

But to do this, you do need 'number of valid targets'.

At least I think so. I replied just yesterday to a similar question, but I have not heard back if it solved the issue. 

My assumption is that we never checked this case, as we knew it was invalid. 

- john

Associate
August 30, 2024

I John 

thanks for your reply

i'm new using VL53L5CX and i would start a simple ranging example.

I have setted VL53L5CX_NB_TARGET_PER_ZONE == 1 and i'm using the the example in the folder.

The init function is ok but i'm unable to start ranging. Below our schematic and my code

kappa182_1-1725025594130.png

uint8_t vl53l5cx_init(I2C_HandleTypeDef *p_i2c)
{
 uint8_t tmp;
 uint8_t pipe_ctrl[] = { VL53L5CX_NB_TARGET_PER_ZONE, 0x00, 0x01, 0x00 };
 uint32_t single_range = 0x01;
 uint8_t isAlive;
 uint8_t status = VL53L5CX_STATUS_OK;

// Wake-up: The device is set in HP idle (high power), waiting for instructions.
// • Sleep: The device is set in LP idle (low power), the low power state. The device cannot be used until set in
// wake-up mode. This mode retains the firmware and the configuration.

// vl53l5cx_set_power_mode(VL53L5CX_Configuration *p_dev,
// 				uint8_t power_mode)

 g_dev.platform.address = VL53L5CX_DEFAULT_I2C_ADDRESS;

 g_dev.platform.serif = p_i2c;

 VL53L5CX_Reset_Sensor();

 status = vl53l5cx_is_alive(&g_dev, &isAlive);

 if(!isAlive)
 {
 printf("VL53L5CXV0 not detected at requested address (0x%x)\n",
	 g_dev.platform.address);
 return 255;
 }
 printf("Sensor initializing, please wait few seconds\n");

 g_dev.default_xtalk = (uint8_t*)VL53L5CX_DEFAULT_XTALK;
 g_dev.default_configuration = (uint8_t*)VL53L5CX_DEFAULT_CONFIGURATION;
 g_dev.is_auto_stop_enabled = (uint8_t)0x0;

 /* SW reboot sequence */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0009, 0x04);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000F, 0x40);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000A, 0x03);
 status |= VL53L5CX_RdByte(&(g_dev.platform), 0x7FFF, &tmp);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000C, 0x01);

 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0101, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0102, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x010A, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x4002, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x4002, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x010A, 0x03);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0103, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000C, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000F, 0x43);
 status |= VL53L5CX_WaitMs(&(g_dev.platform), 1);

 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000F, 0x40);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000A, 0x01);
 status |= VL53L5CX_WaitMs(&(g_dev.platform), 100);

 /* Wait for sensor booted (several ms required to get sensor ready ) */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);
 status |= _vl53l5cx_poll_for_answer(&g_dev, 1, 0, 0x06, 0xff, 1);
 if(status != (uint8_t)0)
 {
 goto exit;
 }

 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x000E, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x02);

 /* Enable FW access */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x03, 0x0D);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x01);
 status |= _vl53l5cx_poll_for_answer(&g_dev, 1, 0, 0x21, 0x10, 0x10);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);

 /* Enable host access to GO1 */
 status |= VL53L5CX_RdByte(&(g_dev.platform), 0x7fff, &tmp);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0C, 0x01);

 /* Power ON status */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x101, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x102, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x010A, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x4002, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x4002, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x010A, 0x03);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x103, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x400F, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x21A, 0x43);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x21A, 0x03);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x21A, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x21A, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x219, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x21B, 0x00);

 /* Wake up MCU */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);
 status |= VL53L5CX_RdByte(&(g_dev.platform), 0x7fff, &tmp);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0C, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x01);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x20, 0x07);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x20, 0x06);

 /* Download FW into VL53L5 */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x09);
 status |= VL53L5CX_WrMulti(&(g_dev.platform), 0,
			 (uint8_t*)&VL53L5CX_FIRMWARE[0], 0x8000);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x0a);
 status |= VL53L5CX_WrMulti(&(g_dev.platform), 0,
			 (uint8_t*)&VL53L5CX_FIRMWARE[0x8000], 0x8000);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x0b);
 status |= VL53L5CX_WrMulti(&(g_dev.platform), 0,
			 (uint8_t*)&VL53L5CX_FIRMWARE[0x10000], 0x5000);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x01);

 /* Check if FW correctly downloaded */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x02);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x03, 0x0D);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x01);
 status |= _vl53l5cx_poll_for_answer(&g_dev, 1, 0, 0x21, 0x10, 0x10);
 if(status != (uint8_t)0)
 {
 goto exit;
 }

 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);
 status |= VL53L5CX_RdByte(&(g_dev.platform), 0x7fff, &tmp);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0C, 0x01);

 /* Reset MCU and wait boot */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7FFF, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x114, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x115, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x116, 0x42);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x117, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0B, 0x00);
 status |= VL53L5CX_RdByte(&(g_dev.platform), 0x7fff, &tmp);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0C, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x0B, 0x01);
 status |= _vl53l5cx_poll_for_mcu_boot(&g_dev);
 if(status != (uint8_t)0)
 {
 goto exit;
 }

 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x02);

 /* Get offset NVM data and store them into the offset buffer */
 status |= VL53L5CX_WrMulti(&(g_dev.platform), 0x2fd8,
			 (uint8_t*)VL53L5CX_GET_NVM_CMD,
			 sizeof(VL53L5CX_GET_NVM_CMD));
 status |= _vl53l5cx_poll_for_answer(&g_dev, 4, 0,
 VL53L5CX_UI_CMD_STATUS,
				 0xff, 2);
 status |= VL53L5CX_RdMulti(&(g_dev.platform), VL53L5CX_UI_CMD_START,
			 (uint8_t*)&g_dev.temp_buffer,
			 VL53L5CX_NVM_DATA_SIZE);
 (void)memcpy(&g_dev.offset_data, &g_dev.temp_buffer,
 VL53L5CX_OFFSET_BUFFER_SIZE);
 status |= _vl53l5cx_send_offset_data(&g_dev, VL53L5CX_RESOLUTION_4X4);

 /* Set default Xtalk shape. Send Xtalk to sensor */
 (void)memcpy(&g_dev.xtalk_data, (uint8_t*)VL53L5CX_DEFAULT_XTALK,
 VL53L5CX_XTALK_BUFFER_SIZE);
 status |= _vl53l5cx_send_xtalk_data(&g_dev, VL53L5CX_RESOLUTION_4X4);

 /* Send default configuration to VL53L5CX firmware */
 status |= VL53L5CX_WrMulti(&(g_dev.platform), 0x2c34,
			 (uint8_t*)&g_dev.default_configuration,
			 sizeof(VL53L5CX_DEFAULT_CONFIGURATION));
 status |= _vl53l5cx_poll_for_answer(&g_dev, 4, 1,
 VL53L5CX_UI_CMD_STATUS,
				 0xff, 0x03);

 status |= vl53l5cx_dci_write_data(&g_dev, (uint8_t*)&pipe_ctrl,
 VL53L5CX_DCI_PIPE_CONTROL,
				 (uint16_t)sizeof(pipe_ctrl));
#if VL53L5CX_NB_TARGET_PER_ZONE != 1
	tmp = VL53L5CX_NB_TARGET_PER_ZONE;
	status |= vl53l5cx_dci_replace_data(&g_dev, &(g_dev.temp_buffer[0]),
		VL53L5CX_DCI_FW_NB_TARGET, 16,
	(uint8_t*)&tmp, 1, 0x0C);
#endif

 status |= vl53l5cx_dci_write_data(&g_dev, (uint8_t*)&single_range,
 VL53L5CX_DCI_SINGLE_RANGE,
				 (uint16_t)sizeof(single_range));

 tmp = (uint8_t)1;
 status |= vl53l5cx_dci_replace_data(&g_dev, g_dev.temp_buffer,
 VL53L5CX_GLARE_FILTER,
				 40, (uint8_t*)&tmp, 1, 0x26);
 status |= vl53l5cx_dci_replace_data(&g_dev, g_dev.temp_buffer,
 VL53L5CX_GLARE_FILTER,
				 40, (uint8_t*)&tmp, 1, 0x25);

 status |= vl53l5cx_set_ranging_frequency_hz(&g_dev, 15); // Set 30Hz ranging frequency

 uint8_t power_mode = 0;
 status |= vl53l5cx_get_power_mode(&g_dev, &power_mode);

 uint32_t time_ms = 0;

 time_ms = 10;

 vl53l5cx_set_integration_time_ms(&g_dev, time_ms);

 status |= vl53l5cx_get_integration_time_ms(&g_dev, &time_ms);

 uint8_t resolution = 0;
 status |= vl53l5cx_set_resolution(&g_dev, VL53L5CX_RESOLUTION_4X4);
 status |= vl53l5cx_get_resolution(&resolution);

 status |= vl53l5cx_set_ranging_mode(&g_dev, VL53L5CX_RANGING_MODE_CONTINUOUS);

 VL53L5CX_DetectionThresholds thresholds[VL53L5CX_NB_THRESHOLDS];

 /* Set all values to 0 */
 memset(&thresholds, 0, sizeof(thresholds));

 /* Add thresholds for all zones (16 zones in resolution 4x4, or 64 in 8x8) */
 for(uint8_t i = 0; i < 16; i++)
 {
 /* The first wanted thresholds is GREATER_THAN mode. Please note that the
 * first one must always be set with a mathematic_operation
 * VL53L5CX_OPERATION_NONE.
 * For this example, the signal thresholds is set to 150 kcps/spads
 * (the format is automatically updated inside driver)
 */
 thresholds[2 * i].zone_num = i;
 thresholds[2 * i].measurement = VL53L5CX_SIGNAL_PER_SPAD_KCPS;
 thresholds[2 * i].type = VL53L5CX_GREATER_THAN_MAX_CHECKER;
 thresholds[2 * i].mathematic_operation = VL53L5CX_OPERATION_NONE;
 thresholds[2 * i].param_low_thresh = 150;
 thresholds[2 * i].param_high_thresh = 150;

 /* The second wanted checker is IN_WINDOW mode. We will set a
 * mathematical thresholds VL53L5CX_OPERATION_OR, to add the previous
 * checker to this one.
 * For this example, distance thresholds are set between 200mm and
 * 400mm (the format is automatically updated inside driver).
 */
 thresholds[2 * i + 1].zone_num = i;
 thresholds[2 * i + 1].measurement = VL53L5CX_DISTANCE_MM;
 thresholds[2 * i + 1].type = VL53L5CX_IN_WINDOW;
 thresholds[2 * i + 1].mathematic_operation = VL53L5CX_OPERATION_OR;
 thresholds[2 * i + 1].param_low_thresh = 200;
 thresholds[2 * i + 1].param_high_thresh = 400;
 }

 /* The last thresholds must be clearly indicated. As we have 32
 * checkers (16 zones x 2), the last one is the 31 */
 thresholds[31].zone_num = VL53L5CX_LAST_THRESHOLD | thresholds[31].zone_num;

 /* Send array of thresholds to the sensor */
 status |= vl53l5cx_set_detection_thresholds(&g_dev, thresholds);

 /* Enable detection thresholds */
 status |= vl53l5cx_set_detection_thresholds_enable(&g_dev, 1);

exit: return status;

 

uint8_t vl53l5cx_start_ranging()
{
 uint8_t resolution;
 uint16_t tmp;
 uint32_t i;
 uint32_t header_config[2] = { 0, 0 };
 uint8_t status = VL53L5CX_STATUS_OK;

 union Block_header *bh_ptr;
 uint8_t cmd[] = { 0x00, 0x03, 0x00, 0x00 };

 status |= vl53l5cx_get_resolution(&resolution);
 g_dev.data_read_size = 0;
 g_dev.streamcount = 255;

 status = VL53L5CX_STATUS_OK;

 /* Enable mandatory output (meta and common data) */
 uint32_t output_bh_enable[] = { 0x00000007U, 0x00000000U, 0x00000000U,
 0xC0000000U };

 /* Send addresses of possible output */
 uint32_t output[] = { VL53L5CX_START_BH,
 VL53L5CX_METADATA_BH,
 VL53L5CX_COMMONDATA_BH,
 VL53L5CX_AMBIENT_RATE_BH,
 VL53L5CX_SPAD_COUNT_BH,
 VL53L5CX_NB_TARGET_DETECTED_BH,
 VL53L5CX_SIGNAL_RATE_BH,
 VL53L5CX_RANGE_SIGMA_MM_BH,
 VL53L5CX_DISTANCE_BH,
 VL53L5CX_REFLECTANCE_BH,
 VL53L5CX_TARGET_STATUS_BH,
 VL53L5CX_MOTION_DETECT_BH };

 /* Enable selected outputs in the 'platform.h' file */
#ifndef VL53L5CX_DISABLE_AMBIENT_PER_SPAD
 output_bh_enable[0] += (uint32_t)8;
#endif
#ifndef VL53L5CX_DISABLE_NB_SPADS_ENABLED
 output_bh_enable[0] += (uint32_t)16;
#endif
#ifndef VL53L5CX_DISABLE_NB_TARGET_DETECTED
 output_bh_enable[0] += (uint32_t)32;
#endif
#ifndef VL53L5CX_DISABLE_SIGNAL_PER_SPAD
 output_bh_enable[0] += (uint32_t)64;
#endif
#ifndef VL53L5CX_DISABLE_RANGE_SIGMA_MM
 output_bh_enable[0] += (uint32_t)128;
#endif
#ifndef VL53L5CX_DISABLE_DISTANCE_MM
 output_bh_enable[0] += (uint32_t)256;
#endif
#ifndef VL53L5CX_DISABLE_REFLECTANCE_PERCENT
 output_bh_enable[0] += (uint32_t)512;
#endif
#ifndef VL53L5CX_DISABLE_TARGET_STATUS
 output_bh_enable[0] += (uint32_t)1024;
#endif
#ifndef VL53L5CX_DISABLE_MOTION_INDICATOR
 output_bh_enable[0] += (uint32_t)2048;
#endif

 /* Update data size */
 for(i = 0; i < (uint32_t)(sizeof(output) / sizeof(uint32_t)); i++)
 {
 if((output[i] == (uint8_t)0)
	|| ((output_bh_enable[i / (uint32_t)32]
	 & ((uint32_t)1 << (i % (uint32_t)32))) == (uint32_t)0))
 {
 continue;
 }

 bh_ptr = (union Block_header*)&(output[i]);
 if(((uint8_t)bh_ptr->type >= (uint8_t)0x1)
	&& ((uint8_t)bh_ptr->type < (uint8_t)0x0d))
 {
 if((bh_ptr->idx >= (uint16_t)0x54d0)
	 && (bh_ptr->idx < (uint16_t)(0x54d0 + 960)))
 {
	bh_ptr->size = resolution;
 }
 else
 {
	bh_ptr->size = (uint16_t)((uint16_t)resolution
	 * (uint16_t)VL53L5CX_NB_TARGET_PER_ZONE);
 }
 g_dev.data_read_size += bh_ptr->type * bh_ptr->size;
 }
 else
 {
 g_dev.data_read_size += bh_ptr->size;
 }
 g_dev.data_read_size += (uint32_t)4;
 }
 g_dev.data_read_size += (uint32_t)24;

 status |= vl53l5cx_dci_write_data(&g_dev, (uint8_t*)&(output),
 VL53L5CX_DCI_OUTPUT_LIST,
				 (uint16_t)sizeof(output));

 header_config[0] = g_dev.data_read_size;
 header_config[1] = i + (uint32_t)1;

 status |= vl53l5cx_dci_write_data(&g_dev, (uint8_t*)&(header_config),
 VL53L5CX_DCI_OUTPUT_CONFIG,
				 (uint16_t)sizeof(header_config));

 status |= vl53l5cx_dci_write_data(&g_dev, (uint8_t*)&(output_bh_enable),
 VL53L5CX_DCI_OUTPUT_ENABLES,
				 (uint16_t)sizeof(output_bh_enable));

 /* Start xshut bypass (interrupt mode) */
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x00);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x09, 0x05);
 status |= VL53L5CX_WrByte(&(g_dev.platform), 0x7fff, 0x02);

 /* Start ranging session */
 status |= VL53L5CX_WrMulti(&(g_dev.platform),
 VL53L5CX_UI_CMD_END - (uint16_t)(4 - 1),
			 (uint8_t*)cmd, sizeof(cmd));
 status |= _vl53l5cx_poll_for_answer(&g_dev, 4, 1,
 VL53L5CX_UI_CMD_STATUS,
				 0xff, 0x03);

 /* Read ui range data content and compare if data size is the correct one */
 status |= vl53l5cx_dci_read_data(&g_dev, (uint8_t*)g_dev.temp_buffer, 0x5440,
				 12);
// vl53l5cx_test_i2c(&g_dev);

 (void)memcpy(&tmp, &(g_dev.temp_buffer[0x8]), sizeof(tmp));
 if(tmp != g_dev.data_read_size)
 {
 status |= VL53L5CX_STATUS_ERROR;
 }

 return status;
}

 

I can't read output data and inside the function vl53l5cx_check_data_ready the buffer g_dev.temp_buffer == {255,4,2,1}

Thanks

 

John E KVAM
ST Employee
September 4, 2024

Did you perhaps change the section in platform.h to reduce the number of bytes:

My recommended minimum is:

// #define VL53L8CX_DISABLE_AMBIENT_PER_SPAD
 #define VL53L8CX_DISABLE_NB_SPADS_ENABLED
// #define VL53L8CX_DISABLE_NB_TARGET_DETECTED
 #define VL53L8CX_DISABLE_SIGNAL_PER_SPAD
 #define VL53L8CX_DISABLE_RANGE_SIGMA_MM
// #define VL53L8CX_DISABLE_DISTANCE_MM
 #define VL53L8CX_DISABLE_REFLECTANCE_PERCENT
// #define VL53L8CX_DISABLE_TARGET_STATUS
 #define VL53L8CX_DISABLE_MOTION_INDICATOR

Technically you don't need ambient - but it's only 8 extra bytes and it might come in handy. 

This reduces the max output of 4095 bytes down to 1327 which is the minimum. 

To verify a valid target you need NB_Target_Detected >1 AND Target_Status =(5,6,9 or sometimes 12). With that you can print Distance_MM.

- john