2025-04-10 5:44 AM - last edited on 2025-04-10 12:04 PM by Peter BENSCH
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;
}
}
Solved! Go to Solution.
2025-04-23 6:59 AM - last edited on 2025-04-23 11:39 AM by John E KVAM
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
2025-04-23 9:24 AM
Hallo @ahsrabrifat ,
Thanks for your help but i am not sure this would help me. Then in one Documentation you can be read this :
2025-04-23 10:21 AM - edited 2025-04-23 10:32 AM
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.
2025-04-23 10:28 AM
The above post is incorrect .... target_status == 0 actually means the the data IS NOT VALID and should be ignored.
2025-04-23 11:12 AM
@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");
}
2025-04-24 12:39 AM
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.