cancel
Showing results for 
Search instead for 
Did you mean: 

Unreasonable Data from VL53L8CX Sensor

kgb
Associate III

Hello Everyone,

I am currently using the vl53lmz_uld_api  tto process data measured by the VL53L8CX sensor. I have also used the "example_12_cnh_data" to retrieve data from my sensor. However, the incoming data seems completely incorrect, and I don't know where the issue lies. When I hold my sensor 20-25 cm in front of an obstacle, I receive highly unreasonable data:

Zone :  40, Status :   0, Distance : 1383 mm

Zone :  41, Status :  13, Distance : 1892 mm

Zone :  42, Status :   5, Distance : 1371 mm

Zone :  43, Status :   5, Distance : 1367 mm

Zone :  44, Status :   5, Distance : 1347 mm

Zone :  45, Status :   5, Distance : 1370 mm

Zone :  46, Status :   5, Distance : 2448 mm

Zone :  47, Status :   9, Distance : 2262 mm

Zone :  48, Status :   4, Distance : 2977 mm

Zone :  49, Status :   0, Distance : 1398 mm

Zone :  50, Status :   5, Distance : 1381 mm

 

 

Can someone please help me to understand what i am doing wrong  here is my main.c: 

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
 // UartComm_Restart();

  //__________MY CODE ___________

 p_dev.platform.address = 0x52;


 Reset_Sensor();

 if (status != VL53LMZ_STATUS_OK){
 		printf("vl53lmz_init failed : %d\n");
 		return status;
 	}

	/* (Mandatory) Initialise the VL53LMZ sensor */
	status = vl53lmz_init(&p_dev);
	if(status)
	{
		printf("VL53LMZ ULD Loading failed\n");
		return status;
	}

	printf("VL53LMZ ULD ready ! (Version : %s)\n",
			VL53LMZ_API_REVISION);

	status = vl53lmz_set_resolution(&p_dev, 64);
	status |= vl53lmz_set_ranging_mode(&p_dev, VL53LMZ_RANGING_MODE_AUTONOMOUS);
	status |= vl53lmz_set_ranging_frequency_hz(&p_dev, 5);
	status |= vl53lmz_set_integration_time_ms(&p_dev, 20);
	if(status)
	{
		printf("ERROR - Failed basic configuration sequence, status=%u\n", status);
		return status;
	}

	status = vl53lmz_cnh_init_config( &cnh_config,
											0,		/* StartBin 	*/
											18,		/* NumBins   	*/
											1);	/* SubSample 	*/

	if (status != VL53LMZ_STATUS_OK){
			printf("VL53LMZ CNH init config failed\n");
			return status;
		}

	status = vl53lmz_cnh_create_agg_map( &cnh_config,
												64,				/* Resolution. Must match value used in vl53lmz_set_resolution() */
												0,				/* StartX 		*/
												0,				/* StartY 		*/
												1,				/* MergeX		*/
												1,				/* MergeY		*/
												8,				/* Cols			*/
												8 );			/* Rows 		*/

	if (status != VL53LMZ_STATUS_OK){
			printf("VL53LMZ CNH set aggregate map failed\n");
			return status;
		}

	status = vl53lmz_cnh_calc_required_memory( &cnh_config, &cnh_data_size );
	if (status != VL53LMZ_STATUS_OK){
		printf("VL53LMZ CNH calc required memory failed\n");
		if (cnh_data_size < 0){
			printf("Required memory is too high : %d. Maximum is %d!\n", (int)-cnh_data_size, (int)VL53LMZ_CNH_MAX_DATA_BYTES);
		}
		return status;
	}


	/* Send this CNH configuration to the sensor.										*/
	status = vl53lmz_cnh_send_config(&p_dev,&cnh_config);
	if (status != VL53LMZ_STATUS_OK){
		printf("VL53LMZ CNH send config failed\n");
		return status;
	}

	/* First create the standard data upload(output) configuration. 						*/
	status = vl53lmz_create_output_config(&p_dev);
	if (status != VL53LMZ_STATUS_OK){
		printf("VL53LMZ CNH create output config failed\n");
		return status;
	}

	/* Next, add the CNH data block, sized correctly for the configuration we are using. */
	union Block_header cnh_data_bh;
	cnh_data_bh.idx = VL53LMZ_CNH_DATA_IDX;
	cnh_data_bh.type = 4;
	cnh_data_bh.size = cnh_data_size / 4;
	status = vl53lmz_add_output_block(&p_dev, cnh_data_bh.bytes);
	if (status != VL53LMZ_STATUS_OK){
		printf("VL53LMZ CNH add output block failed\n");
		return status;
	}

	status = vl53lmz_send_output_config_and_start(&p_dev);

	   	printf("Started ranging\n");



  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	   	while (1)

	   	{

	   		   		// __________________ MY CODE _______________
	   		   	    uint8_t buffer[512];
	   		   	    uint8_t *ptr = buffer;
	   		   	    size_t buffer_index = 0;  // To keep track of the actual size of the data

	   		   	    status = vl53lmz_check_data_ready(&p_dev, &isReady);
	   		   	    if (isReady)
	   		   	    {
	   		   	        vl53lmz_get_ranging_data(&p_dev, &Results);

	   		   	        printf("Print data no : %3u\n", p_dev.streamcount);
	   		   	        for (i = 0; i < 64; i++)
	   		   	        {


	   		   	            uint16_t zone = i;
	   		   	            uint16_t distance = Results.distance_mm[VL53LMZ_NB_TARGET_PER_ZONE * i];
                            /*
	   		   	            memcpy(ptr + buffer_index, &zone, sizeof(uint16_t));
	   		   	            buffer_index += sizeof(uint16_t);
	   		   	            memcpy(ptr + buffer_index, &distance, sizeof(uint16_t));
	   		   	            buffer_index += sizeof(uint16_t);
                             */
	   		   	           printf("Zone : %3d, Status : %3u, Distance : %4d mm\n",
	   		   	                   i,
	   		   	                   Results.target_status[VL53LMZ_NB_TARGET_PER_ZONE * i],
	   		   	                   distance);
	   		   	        }

	   		   	        status = vl53lmz_results_extract_block(&p_dev, VL53LMZ_CNH_DATA_IDX, (uint8_t *)cnh_data_buffer, cnh_data_size);
	   		   	        if (status != VL53LMZ_STATUS_OK)
	   		   	        {
	   		   	            printf("ERROR at %s(%d) : vl53lmz_results_extract_block failed : %d\n", __func__, __LINE__, status);
	   		   	            return status;
	   		   	        }

	   		   	        for (agg_id = 0; agg_id < cnh_config.nb_of_aggregates; agg_id++)
	   		   	        {
	   		   	            vl53lmz_cnh_get_block_addresses(&cnh_config,
	   		   	                                            agg_id,
	   		   	                                            cnh_data_buffer,
	   		   	                                            &(p_hist), &(p_hist_scaler),
	   		   	                                            &(p_ambient), &(p_ambient_scaler));

	   		   	            amb_value = ((float)*p_ambient) / (2 << *p_ambient_scaler);

	   		   	            printf("Agg, %2d, Ambient, % .1f, Bins, ", agg_id, amb_value);

	   		   	            for (bin_num = 0; bin_num < cnh_config.feature_length; bin_num++)
	   		   	            {
	   		   	                bin_value = ((float)p_hist[bin_num]) / (2 << p_hist_scaler[bin_num]);
	   		   	                printf("% .1f, ", bin_value);
	   		   	            }
                             /*
	   		   	            uint16_t Agg_id = agg_id;
	   		   	            float ambient = amb_value;
	   		   	            float bins_val = bin_value;

	   		   	            memcpy(ptr + buffer_index, &Agg_id, sizeof(uint16_t)); buffer_index += sizeof(uint16_t);
	   		   	            memcpy(ptr + buffer_index, &ambient, sizeof(float));  buffer_index += sizeof(float);
	   		   	            memcpy(ptr + buffer_index, &bins_val, sizeof(float)); buffer_index += sizeof(float);
                              */
	   		   	            // Now transmit only the actual data in the buffer
	   		   	            //HAL_UART_Transmit(&huart2, sizeof(buffer) , buffer, HAL_MAX_DELAY) ;

	   		   	            printf("\n");
	   		   	        }

	   		   	        loop++;
	   		   	    }

	   		   	    // Wait a few ms to avoid too high polling
	   		   	   // WaitMs(&(p_dev.platform), 5);
	   		   	    HAL_MAX_DELAY;
	   		   	}




}
15 REPLIES 15
ahsrabrifat
Senior

 

Only use the distance value when target_status == 0. ( Edit - Should be 5, not 0 - John Kvam)

 
if (Results.target_status[VL53LMZ_NB_TARGET_PER_ZONE * i] == 0) { // Edit again should be 5 not zero
printf("Zone : %3d, Status : %3u, Distance : %4d mm\n", i,
Results.target_status[VL53LMZ_NB_TARGET_PER_ZONE * i],
Results.distance_mm[VL53LMZ_NB_TARGET_PER_ZONE * i]);
}

(Edit) Technically a status of 5 is vaild, 6 is first time (and likely valid) and 9 is a merged target (which could also be valid). But these others are kind of rare, so some people only allow 5 as a good range. - John

You set:

vl53lmz_set_resolution(&p_dev, 64);
vl53lmz_set_ranging_mode(&p_dev, VL53LMZ_RANGING_MODE_AUTONOMOUS);
vl53lmz_set_ranging_frequency_hz(&p_dev, 5);
vl53lmz_set_integration_time_ms(&p_dev, 20);

integration_time_ms = 20 is quite short, especially with low reflectivity targets or indoor lighting.

Try increasing it to 50 or 100 ms:

vl53lmz_set_integration_time_ms(&p_dev, 100);

I hope this helps. You can also make a PCB like this with the VL53L8CX ToF Sensor

https://www.pcbway.com/project/shareproject/ToF_Sensor_PCB_CrazyFlie_Obstacle_Avoidance_Sensor_Deck_c4b8707d.html

 

Hallo @ahsrabrifat ,

Thanks for your help but i am not sure this would help me. Then in one Documentation you can be read this  : Screenshot from 2025-04-23 18-20-10.png

RogerM
ST Employee

As John says for now just look at zones which have status == 5.
With regards the range data you are printing out.... in the platform.h file do you have the following line active or commented out?

      #define VL53LMZ_USE_RAW_FORMAT

If this is present the driver returns the raw range value which includes 2 fractional bits ...which means the raw value must be divided by 4 to get the actual range in mm.

Please look at the code within vl53lmz_get_ranging_data() which is conditional on the VL53LMZ_USE_RAW_FORMAT define.   Depending on if this is defined or not it either does, or does not,  convert from "raw" to real values.

The above post is incorrect .... target_status == 0 actually means the the data IS NOT VALID and should be ignored.

kgb
Associate III

@RogerM Thanks ,  I think you just saved my life :). I was honestly about to give up.
My goal was to get additionaly the CNH data, but since the distance measurements were incorrect, I wasn’t sure whether I could trust the CNH results either.

So just one last question, to be sure:
Are the CNH data results completely independent from the ranging data, or are they somehow linked?

I just want to be sure that I can work with the CNH data I already have , since I can’t visually verify if it's accurate or not.

Is there any current method to validate whether the CNH data ( histogram bins.) are correct or meaningful? Or do we just have to trust that if the driver is set up properly and ranging works, the CNH data should also be valid? 

I am using this function :

status = vl53lmz_results_extract_block(&p_dev, VL53LMZ_CNH_DATA_IDX, (uint8_t *)cnh_data_buffer, cnh_data_size);
	   		   	        if (status != VL53LMZ_STATUS_OK)
	   		   	        {
	   		   	            printf("ERROR at %s(%d) : vl53lmz_results_extract_block failed : %d\n", __func__, __LINE__, status);
	   		   	            return status;
	   		   	        }

	   		   	        for (agg_id = 0; agg_id < cnh_config.nb_of_aggregates; agg_id++)
	   		   	        {
	   		   	            vl53lmz_cnh_get_block_addresses(&cnh_config,
	   		   	                                            agg_id,
	   		   	                                            cnh_data_buffer,
	   		   	                                            &(p_hist), &(p_hist_scaler),
	   		   	                                            &(p_ambient), &(p_ambient_scaler));

	   		   	            amb_value = ((float)*p_ambient) / (2 << *p_ambient_scaler);

	   		   	            printf("Agg, %2d, Ambient, % .1f, Bins, ", agg_id, amb_value);

	   		   	            for (bin_num = 0; bin_num < cnh_config.feature_length; bin_num++)
	   		   	            {
	   		   	                bin_value = ((float)p_hist[bin_num]) / (2 << p_hist_scaler[bin_num]);
	   		   	                printf("% .1f, ", bin_value);
	   		   	            }

	   		   	            printf("\n");
	   		   	        }
RogerM
ST Employee

Both the CNH data and the ranging data for each frame are derived (independently) from the same underlying (raw) histogram data that the ToF ranging core collects during integration.  So in that sense that are linked.

There is no type of valid / not-valid check for histogram data. If an illegal CNH configuration is detected by the sensor it should refuse to start ranging.  For instance if you request a CNH configuration which would require more memory on the the device than is available (e.g. you ignore the result of vl53lmz_cnh_calc_required_memory() )  it will refuse to start ranging. 

Hope this clarifies things a bit.