cancel
Showing results for 
Search instead for 
Did you mean: 

VL53L0X long range mode not working

RBerk.1
Associate II

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
1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

5 REPLIES 5
RBerk.1
Associate II

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
Associate II

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 II

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

Seb

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

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);

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. It helps the next guy.