Skip to main content
RBerk.1
Associate II
November 8, 2023
Solved

VL53L0X long range mode not working

  • November 8, 2023
  • 4 replies
  • 3573 views

Hi,

I am currently actively debugging and working with the sensor and it shows correct measurement data when i set the profile to 'Long range' example (settings from the 'um2039' User manual).

 

RBerk1_0-1699435927774.png

 

however the sensor response for RangeDMaxMilliMeter: always show a value around 1200 which should be around 2000, is there another settings which i need to do before the profile is actively set to long range?

Measurement data is now also correctly measured until about 1200mm but higher results in invalid measurements.

below are my settings as they are performed in the code:

MyDevice.I2cDevAddr = 0x52;
MyDevice.comms_type = 1;	// 1 should equal I2C
MyDevice.comms_speed_khz = 100;
MyDevice.hi2c = hi2c;

VL53L0X_DEV = &MyDevice;

if (VL53L0X_DataInit(VL53L0X_DEV) != VL53L0X_ERROR_NONE)
{
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
}

if (VL53L0X_StaticInit(VL53L0X_DEV) != VL53L0X_ERROR_NONE)
{
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
}

// Calibration steps
if (calibration->memory_valid != 0)
{
 	// SPADs calibration
 VL53L0X_Error calibration_step = VL53L0X_SetReferenceSpads(VL53L0X_DEV,
 calibration->refSpadCount,
 calibration->isApertureSpads);
 if (calibration_step == VL53L0X_ERROR_CALIBRATION_WARNING)
 {
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_TIMEOUT;
 }
 else if (calibration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Temperature calibration
 calibration_step = VL53L0X_SetRefCalibration(VL53L0X_DEV,
 calibration->pVhvSettings,
 calibration->pPhaseCal);
 if (calibration_step == VL53L0X_ERROR_CALIBRATION_WARNING)
 {
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_TIMEOUT;
 }
 else if (calibration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Offset calibration
 calibration_step = VL53L0X_SetOffsetCalibrationDataMicroMeter(VL53L0X_DEV,
 calibration->pOffsetMicroMeter);
 if (calibration_step == VL53L0X_ERROR_CALIBRATION_WARNING)
 {
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_TIMEOUT;
 }
 else if (calibration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Crosstalk calibration and enabling
 calibration_step = VL53L0X_SetXTalkCompensationRateMegaCps(VL53L0X_DEV,
 calibration->XTalkCompensationRateMegaCps);
 if (calibration_step == VL53L0X_ERROR_CALIBRATION_WARNING)
 {
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_TIMEOUT;
 }
 else if (calibration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 calibration_step = VL53L0X_SetXTalkCompensationEnable(VL53L0X_DEV, 1);
 if (calibration_step == VL53L0X_ERROR_CALIBRATION_WARNING)
 {
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_TIMEOUT;
 }
 else if (calibration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Configuration steps (!!!!!!!!!!!! Long range mode !!!!!!!)

 	// Limit check value >> 1
 VL53L0X_Error configuration_step = VL53L0X_SetLimitCheckValue(VL53L0X_DEV,
 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
 (FixPoint1616_t)(0.1 *65536));
 if (configuration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Limit check value >> 2
 configuration_step = VL53L0X_SetLimitCheckValue(VL53L0X_DEV,
 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,
 (FixPoint1616_t)(60 *65536));
 if (configuration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Measurement timing budget
 configuration_step = VL53L0X_SetMeasurementTimingBudgetMicroSeconds( VL53L0X_DEV, 33000);
 if (configuration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// VCEL pulse period 1
 configuration_step = VL53L0X_SetVcselPulsePeriod(VL53L0X_DEV,
 VL53L0X_VCSEL_PERIOD_PRE_RANGE, 18);
 if (configuration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// VCEL pulse period 2
 configuration_step = VL53L0X_SetVcselPulsePeriod(VL53L0X_DEV,
 VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 14);
 if (configuration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }

 	// Device mode
 configuration_step = VL53L0X_SetDeviceMode( VL53L0X_DEV, VL53L0X_DEVICEMODE_SINGLE_RANGING);
 if (configuration_step != VL53L0X_ERROR_NONE)
 {
 	// Some error
 g_tof_state = tof_sensor_reset_sensor;
 return HAL_ERROR;
 }
Another problem i am facing is that when i connect the sensor to my devkit (NucleoF401RE) and initialize the sensor from bootup the first data i receive is incorrect and i need to power cycle the sensor before (and reinitialize) before i get correct measurement data, is there a sensor power on time before communications/configurations can start?
 
King regards,
 
Richard
This topic has been closed for replies.
Best answer by RBerk.1

Hi Seb,

An update, my problems where related to hardware and noise while calibrating. after making some changes to the calibration sequence and room variables (block out external light etc.) the sensor is now measuring beyond the 1,2m and shows accurate data.

I am currently polling for data ready so i don't use the interrupt status value.

Kind regards,

Richard

4 replies

RBerk.1
RBerk.1Author
Associate II
November 8, 2023

HI, 

An update, after looking through the API code i see the '\CurrentParameters.dmax_lut.dmax_mm[0]' is initialized at a max value of 1200  so this can't possibly return a value higher than 1200 >> do we need to change some things in the API before the long range mode of 2000 (2m) is enabled?

Below is the API's initialization of the Data_init function:

VL53L0X_Error VL53L0X_DataInit(VL53L0X_Dev_t *Dev)
{
 VL53L0X_Error Status = VL53L0X_ERROR_NONE;
 VL53L0X_DeviceParameters_t CurrentParameters;
 int i;
 uint8_t StopVariable;

 /*by default the I2C is running at 1V8 if you want to change it you
 *need to include this define at compilation level.
 */
 #
 ifdef USE_I2C_2V8
 Status = VL53L0X_UpdateByte(Dev,
 VL53L0X_REG_VHV_CONFIG_PAD_SCL_SDA__EXTSUP_HV,
 0xFE,
 0x01);#
 endif

 /*Set I2C standard mode */
 if (Status == VL53L0X_ERROR_NONE)
 Status = VL53L0X_WrByte(Dev, 0x88, 0x00);

 VL53L0X_SETDEVICESPECIFICPARAMETER(Dev, ReadDataFromDeviceDone, 0);

 #
 ifdef USE_IQC_STATION
 if (Status == VL53L0X_ERROR_NONE)
 Status = VL53L0X_apply_offset_adjustment(Dev);#
 endif

 /*Default value is 1000 for Linearity Corrective Gain */
 PALDevDataSet(Dev, LinearityCorrectiveGain, 1000);

 /*Set Default static parameters
 *set first temporary values 9.44MHz *65536 = 618660
 */
 VL53L0X_SETDEVICESPECIFICPARAMETER(Dev, OscFrequencyMHz, 618660);

 /*Set Default XTalkCompensationRateMegaCps to 0 */
 VL53L0X_SETPARAMETERFIELD(Dev, XTalkCompensationRateMegaCps, 0);

 /*Get default parameters */
 Status = VL53L0X_GetDeviceParameters(Dev, &CurrentParameters);
 if (Status == VL53L0X_ERROR_NONE)
 {
 /*initialize PAL values */
 CurrentParameters.DeviceMode =
 VL53L0X_DEVICEMODE_SINGLE_RANGING;
 CurrentParameters.HistogramMode =
 VL53L0X_HISTOGRAMMODE_DISABLED;

 /*Dmax lookup table */
 /*0.0 */
 CurrentParameters.dmax_lut.ambRate_mcps[0] = (FixPoint1616_t) 0x00000000;
 /*1200 */
 CurrentParameters.dmax_lut.dmax_mm[0] = (FixPoint1616_t) 0x04B00000;
 /*0.7 */
 CurrentParameters.dmax_lut.ambRate_mcps[1] = (FixPoint1616_t) 0x0000B333;
 /*1100 */
 CurrentParameters.dmax_lut.dmax_mm[1] = (FixPoint1616_t) 0x044C0000;
 /*2 */
 CurrentParameters.dmax_lut.ambRate_mcps[2] = (FixPoint1616_t) 0x00020000;
 /*900 */
 CurrentParameters.dmax_lut.dmax_mm[2] = (FixPoint1616_t) 0x03840000;
 /*3.8 */
 CurrentParameters.dmax_lut.ambRate_mcps[3] = (FixPoint1616_t) 0x0003CCCC;
 /*750 */
 CurrentParameters.dmax_lut.dmax_mm[3] = (FixPoint1616_t) 0x02EE0000;
 /*7.3 */
 CurrentParameters.dmax_lut.ambRate_mcps[4] = (FixPoint1616_t) 0x00074CCC;
 /*550 */
 CurrentParameters.dmax_lut.dmax_mm[4] = (FixPoint1616_t) 0x02260000;
 /*10 */
 CurrentParameters.dmax_lut.ambRate_mcps[5] = (FixPoint1616_t) 0x000A0000;
 /*500 */
 CurrentParameters.dmax_lut.dmax_mm[5] = (FixPoint1616_t) 0x01F40000;
 /*15 */
 CurrentParameters.dmax_lut.ambRate_mcps[6] = (FixPoint1616_t) 0x000F0000;
 /*400 */
 CurrentParameters.dmax_lut.dmax_mm[6] = (FixPoint1616_t) 0x01900000;

 PALDevDataSet(Dev, CurrentParameters, CurrentParameters);
 }

 /*Sigma estimator variable */
 PALDevDataSet(Dev, SigmaEstRefArray, 100);
 PALDevDataSet(Dev, SigmaEstEffPulseWidth, 900);
 PALDevDataSet(Dev, SigmaEstEffAmbWidth, 500);
 PALDevDataSet(Dev, targetRefRate, 0x0A00); /*20 MCPS in 9:7 format */

 /*Use internal default settings */
 PALDevDataSet(Dev, UseInternalTuningSettings, 1);

 Status |= VL53L0X_WrByte(Dev, 0x80, 0x01);
 Status |= VL53L0X_WrByte(Dev, 0xFF, 0x01);
 Status |= VL53L0X_WrByte(Dev, 0x00, 0x00);
 Status |= VL53L0X_RdByte(Dev, 0x91, &StopVariable);
 PALDevDataSet(Dev, StopVariable, StopVariable);
 Status |= VL53L0X_WrByte(Dev, 0x00, 0x01);
 Status |= VL53L0X_WrByte(Dev, 0xFF, 0x00);
 Status |= VL53L0X_WrByte(Dev, 0x80, 0x00);

 /*Enable all check */
 for (i = 0; i < VL53L0X_CHECKENABLE_NUMBER_OF_CHECKS; i++)
 {
 if (Status == VL53L0X_ERROR_NONE)
 Status |= VL53L0X_SetLimitCheckEnable(Dev, i, 1);
 else
 break;
 }

 /*Disable the following checks */
 if (Status == VL53L0X_ERROR_NONE)
 Status = VL53L0X_SetLimitCheckEnable(Dev,
 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP, 0);

 if (Status == VL53L0X_ERROR_NONE)
 Status = VL53L0X_SetLimitCheckEnable(Dev,
 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 0);

 if (Status == VL53L0X_ERROR_NONE)
 Status = VL53L0X_SetLimitCheckEnable(Dev,
 VL53L0X_CHECKENABLE_SIGNAL_RATE_MSRC, 0);

 if (Status == VL53L0X_ERROR_NONE)
 Status = VL53L0X_SetLimitCheckEnable(Dev,
 VL53L0X_CHECKENABLE_SIGNAL_RATE_PRE_RANGE, 0);

 /*Limit default values */
 if (Status == VL53L0X_ERROR_NONE)
 {
 Status = VL53L0X_SetLimitCheckValue(Dev,
 VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,
 (FixPoint1616_t)(18 *65536));
 }

 if (Status == VL53L0X_ERROR_NONE)
 {
 Status = VL53L0X_SetLimitCheckValue(Dev,
 VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
 (FixPoint1616_t)(25 * 65536 / 100));
 /*0.25 * 65536 */
 }

 if (Status == VL53L0X_ERROR_NONE)
 {
 Status = VL53L0X_SetLimitCheckValue(Dev,
 VL53L0X_CHECKENABLE_SIGNAL_REF_CLIP,
 (FixPoint1616_t)(35 *65536));
 }

 if (Status == VL53L0X_ERROR_NONE)
 {
 Status = VL53L0X_SetLimitCheckValue(Dev,
 VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD,
 (FixPoint1616_t)(0 *65536));
 }

 if (Status == VL53L0X_ERROR_NONE)
 {
 PALDevDataSet(Dev, SequenceConfig, 0xFF);
 Status = VL53L0X_WrByte(Dev, VL53L0X_REG_SYSTEM_SEQUENCE_CONFIG,
 0xFF);

 /*Set PAL state to tell that we are waiting for call to
 *VL53L0X_StaticInit
 */
 PALDevDataSet(Dev, PalState, VL53L0X_STATE_WAIT_STATICINIT);
 }

 if (Status == VL53L0X_ERROR_NONE)
 VL53L0X_SETDEVICESPECIFICPARAMETER(Dev, RefSpadsInitialised, 0);

 return Status;
}

Kind regards,

Richard

RBerk.1
RBerk.1Author
Associate II
November 8, 2023

Hi,

After throwing away the RangeDMaxMillimeter variable problem i am now left with the reason why my sensor does not measure beyond 1,2m. as soon as the measurement goes beyond 1,2m i get the following resulting measurement data:

RBerk1_0-1699439637839.png

Can anybody help me make sens of the values to check where the problem is (in software or surrounding noise etc). 

The RangeMillimeter variable holds a value 8190 if i go beyond 1,2m from the sensor, before the 1,2m it holds an accurate value.

Kind regards,

Richard

SLERO.1
Associate
November 18, 2023

hi, did you triy to read the register 0x14 who is Result interrupt status and decode it ?

Seb

RBerk.1
RBerk.1AuthorBest answer
Associate II
November 20, 2023

Hi Seb,

An update, my problems where related to hardware and noise while calibrating. after making some changes to the calibration sequence and room variables (block out external light etc.) the sensor is now measuring beyond the 1,2m and shows accurate data.

I am currently polling for data ready so i don't use the interrupt status value.

Kind regards,

Richard

John E KVAM
ST Employee
February 16, 2024

DMAX is a very mis-understood number. 

It's a function of ambient light. It says, "Given the amount of ambient light seen, a target can only be detected up to this distance." Said another way, "I cannot see beyond DMAX due to conditions".

The sensor can 'see' to 2M in ideal conditions. Near a window, there could be enough sunlight to reduce that max distance to that Dmax range.

Cellphone companies wanted that number to start an autofocus search at DMAX. So even if the sensor saw no target, they could save a lot of time, not needing to autofocus at the short distances.

 

As to your startup, I would always toggle the Xshut down line at the start.

Something like this, but please check your pins to make sure you are hitting the XShut pin.

This code is from my VL53L4CD setup. 

	/* Toggle Xshut pin to reset the sensor */

	HAL_GPIO_WritePin(GPIOB, TOF_C_XSHUT_Pin, GPIO_PIN_RESET);
	HAL_Delay(5);
	HAL_GPIO_WritePin(GPIOB, TOF_C_XSHUT_Pin, GPIO_PIN_SET);
	HAL_Delay(5);

	/* Print the software version */
	status = VL53L4CD_GetSWVersion(&sw_version);
	printf("Starting VL53L4CD driver version %u.%u.%u\n",
			sw_version.major,
			sw_version.minor,
			sw_version.build);