Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

VL53L1X, I dont' received distance

Hi,
I developing in C code a application that communication in I2C with VL53L1X sensor. The communication work well because i receive the response 0xEACC at the request MODEL_ID.The my problem is that i don’t read the distance in mm. Can you help me ?

I post my code :

bool			VL53L1X_init ( bool io_2v8 , uint8_t tmp_addr )
{
	writeReg ( SOFT_RESET, 0x00 ) ;
	nrf_delay_ms ( 1 ) ;
	writeReg ( SOFT_RESET, 0x01 ) ;

	nrf_delay_ms ( 1000 ) ;

	// Setto il nuovo address
	setAddress ( tmp_addr ) ;

	nrf_delay_ms ( 100 ) ;

	// check model ID and module type registers (values specified in datasheet)
	if ( readReg16Bit ( IDENTIFICATION__MODEL_ID ) != 0xEACC )	
		return false ; 

	nrf_delay_ms ( 1 ) ;

	if ( ( readReg ( FIRMWARE__SYSTEM_STATUS ) & 0x01 ) == 0 )		
	return false ;	

	if ( io_2v8 )
	{
		writeReg ( PAD_I2C_HV__EXTSUP_CONFIG,
		readReg ( PAD_I2C_HV__EXTSUP_CONFIG ) | 0x01 ) ;

	}

	uint16_t fast_osc_frequency ;	

	// store oscillator info for later use
	fast_osc_frequency = readReg16Bit ( OSC_MEASURED__FAST_OSC__FREQUENCY ) ;
	// osc_calibrate_val = readReg16Bit ( RESULT__OSC_CALIBRATE_VAL ) ;

	writeReg16Bit ( DSS_CONFIG__TARGET_TOTAL_RATE_MCPS, TargetRate ) ; // should already be this value after reset
	writeReg ( GPIO__TIO_HV_STATUS, 0x02 ) ;
	writeReg ( SIGMA_ESTIMATOR__EFFECTIVE_PULSE_WIDTH_NS, 8 ) ; // tuning parm default
	writeReg ( SIGMA_ESTIMATOR__EFFECTIVE_AMBIENT_WIDTH_NS, 16 ) ; // tuning parm default
	writeReg ( ALGO__CROSSTALK_COMPENSATION_VALID_HEIGHT_MM, 0x01 ) ;
	writeReg ( ALGO__RANGE_IGNORE_VALID_HEIGHT_MM, 0xFF ) ;
	writeReg ( ALGO__RANGE_MIN_CLIP, 0 ) ; // tuning parm default
	writeReg ( ALGO__CONSISTENCY_CHECK__TOLERANCE, 2 ) ; // tuning parm default

	// general config
	writeReg16Bit ( SYSTEM__THRESH_RATE_HIGH, 0x0000 ) ;
	writeReg16Bit ( SYSTEM__THRESH_RATE_LOW, 0x0000 ) ;
	writeReg ( DSS_CONFIG__APERTURE_ATTENUATION, 0x38 ) ;

	// timing config
	writeReg16Bit ( RANGE_CONFIG__SIGMA_THRESH, 360 ) ; // tuning parm default
	writeReg16Bit ( RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, 192 ) ; // tuning parm default

	// dynamic config

	writeReg ( SYSTEM__GROUPED_PARAMETER_HOLD_0, 0x01 ) ;
	writeReg ( SYSTEM__GROUPED_PARAMETER_HOLD_1, 0x01 ) ;
	writeReg ( SD_CONFIG__QUANTIFIER, 2 ) ; 

	writeReg ( SYSTEM__GROUPED_PARAMETER_HOLD, 0x00 ) ;
	writeReg ( SYSTEM__SEED_CONFIG, 1 ) ; // tuning parm default

	// from VL53L1_config_low_power_auto_mode
	writeReg ( SYSTEM__SEQUENCE_CONFIG, 0x8B ) ; // VHV, PHASECAL, DSS1, RANGE
	writeReg16Bit ( DSS_CONFIG__MANUAL_EFFECTIVE_SPADS_SELECT, 200 << 8 ) ;
	writeReg ( DSS_CONFIG__ROI_MODE_CONTROL, 2 ) ; // REQUESTED_EFFFECTIVE_SPADS


	// default to long range
	setDistanceMode( Long ) ;

	// the API triggers this change in VL53L1_init_and_start_range() once a
	// measurement is started; assumes MM1 and MM2 are disabled
	writeReg16Bit ( ALGO__PART_TO_PART_RANGE_OFFSET_MM ,
	readReg16Bit ( MM_CONFIG__OUTER_OFFSET_MM ) * 4 ) ;

	nrf_delay_ms ( 100 ) ;

	startContinuous ( 100 ) ;

	return true ;
	
}
//////////////////////////////////////////////////////////////////
void			startContinuous ( uint32_t period_ms )
{
	uint16_t osc_calibrate_val = readReg16Bit(RESULT__OSC_CALIBRATE_VAL);
	
  // from VL53L1_set_inter_measurement_period_ms()
  writeReg32Bit ( SYSTEM__INTERMEASUREMENT_PERIOD , period_ms * osc_calibrate_val ) ;

  writeReg ( SYSTEM__INTERRUPT_CLEAR , 0x01 ) ;	// sys_interrupt_clear_range
  writeReg ( SYSTEM__MODE_START , 0x40 );	// mode_range__timed
	
}
//////////////////////////////////////////////////////////////////
void			readResults ( void )
{
	uint8_t buff_reg [ 2 ] = "" ;
	
	buff_reg [ 0 ] = ( RESULT__RANGE_STATUS >> 8 ) & 0xFF ;	// reg high byte
	buff_reg [ 1 ] = RESULT__RANGE_STATUS          & 0xFF ;	// reg low byte
 	
	nrf_drv_twi_tx ( &m_twi , address , buff_reg , 2 , false ) ;
	
	uint8_t buff_resp [ 20 ] = "" ;
		
	nrf_drv_twi_rx ( &m_twi , address , buff_resp , 17 ) ;

	range_status = buff_resp [ 0 ] ;

	// buff_resp [ 1 ] // report_status: not used

	stream_count = buff_resp [ 2 ] ;

	dss_actual_effective_spads_sd0  = ( uint16_t ) buff_resp [ 3 ] << 8 ; // high byte
	dss_actual_effective_spads_sd0 |=              buff_resp [ 4 ] ;			// low byte

	// buff_resp [ 5 ] ; // peak_signal_count_rate_mcps_sd0: not used
	// buff_resp [ 6 ] ;

	ambient_count_rate_mcps_sd0  = ( uint16_t ) buff_resp [ 7 ] << 8 ;	// high byte
	ambient_count_rate_mcps_sd0 |=              buff_resp [ 8 ] ;				// low byte

	// buff_resp [ 9 ] ; // sigma_sd0: not used
	// buff_resp [ 10 ] ;

	// buff_resp [ 11 ] ; // phase_sd0: not used
	// buff_resp [ 12 ] ;

	final_crosstalk_corrected_range_mm_sd0  = ( uint16_t ) buff_resp [ 13 ] << 8 ;	// high byte
	final_crosstalk_corrected_range_mm_sd0 |=              buff_resp [ 14 ] ;				// low byte

 
	peak_signal_count_rate_crosstalk_corrected_mcps_sd0  = (uint16_t) buff_resp [ 15 ] << 8 ; // high byte
	peak_signal_count_rate_crosstalk_corrected_mcps_sd0 |=            buff_resp [ 16 ] ;      // low byte
	
}
//////////////////////////////////////////////////////////////////
void	main ( void )
{
	VL53L1X_init ( true , 0x29 );
	
	while( 1 )
	{
		readResults ( ) ;		
		
	}
	
}

Hello.

Can you describe the problem better (e.g. are you getting any values and what values are you expecting to see)? Can you post the output you get from running your program?

- Amanda

Hi,

i give you some information at my project:
The I2C communication with the sensor work, in fact i recieved the response (0xEACC) at the command sended MODEL ID. The sensor power is 3V. The buffer ‘buff_resp’ ( it used in the function readResults ( void ) ) contains this data :

0x00 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

How can i understand if i setted correctly the startContinuos function ? is there a command to do this?

Thanks you,

Regards,

Looking at your code, I noticed there are parts I expect to see that are not there (e.g. setMeasurementTimingBudget()). Probably the most effective method for checking that you are interfacing with the VL53L1X sensor correctly is to look at the signals you are sending to it using an oscilloscope or logic analyzer and compare those signals to a known working communication example (like running one of the example sketches from our VL53L1X library on a standard Arduino board).

- Amanda

Hi,
I have checked my code VL53L1X main.txt (24.7 KB) is equal to VL53L1X library. I am developing with Nordic kit, the name is nrf52840-DK. I don’t have a standard arduino board. I have controlled that the sensor is powered (3V). I send the request MODEL ID i receive this response 0xEACC correctly, but when i reading the distance receiving always this buffer ( its name is buff_resp, in the function readDistance() ) :

0x00 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

When i execute this line :
bool dataReady() { return (readReg(GPIO__TIO_HV_STATUS) & 0x01) == 0; }

the function readReg return the value 0x03, what does it mean thi value ?

Another question, if not inizialitze the sensor , it sends the same the distance value ?
which is the default behavior of the sensor if doesn’t initialize ?

Do I need to do something to communicate in I2C at the hardware level?

This problem is blocking in the development the my project. Can you help me ? which problems there are in my code ? How can i understand which problems there are ?

Thanks you,

Hi, GianmarcoUtech.

I noticed an issue with your writeReg() function in your other thread. Could you see if fixing that improves your results?

Kevin

Hi,

Now i recevied this buffer ( the name is buff_resp ), at the request RESULT__RANGE_STATUS (0x0089) :
0x06 0x09 0x00 0x01 0xC0 0x00 0x13 0x00 0x00 0x00 0x39 0x6F 0xF9 0x04 0x0C 0x00 0x13

When i convert in mm i obtain the value 0x03F9, but my ceiling is about 2.5-3 meters from the sensor. These are the my conversion:
final_crosstalk_corrected_range_mm_sd0 = ( uint16_t ) buff_resp [ 13 ] << 8 ; // high byte
final_crosstalk_corrected_range_mm_sd0 |= buff_resp [ 14 ] ; // low byte

final_crosstalk_corrected_range_mm_sd0 = 0x040C

uint16_t range = final_crosstalk_corrected_range_mm_sd0 ;

range_mm = ( ( uint32_t ) range * 2011 + 0x0400 ) / 0x0800 ;

range_mm = 0x03F9

Where is the error?
I setted Long distance.

Thanks you,

Keep in mind that the sensor’s field of view is in the shape of a narrow cone, so it could be detecting objects anywhere in that cone. Is there anything about 1 meter from the front of the sensor that it could be seeing? Do you get more accurate results at closer ranges (like if you hold your hand or another object 10 cm in front of the sensor)?

You might also want to check your other I2C functions, such as writeReg16Bit(), to make sure there are not similar issues like the one in writeReg() since that could lead to unexpected behavior.

Finally, even though it seems like you are close to having some working code based on our library, I want to make sure you are aware of the APIs provided by ST, the manufacturer of the VL53L1X. There is both a full API and a “lite” version. To use either of these APIs, you would need to implement some platform-specific code for I2C communication, but they should provide all of the necessary higher-level logic for interfacing with the VL53L1X in a platform-independent way, so that might be an easier approach for you than trying to port our library.

Kevin

Hi,

“Is there anything about 1 meter from the front of the sensor that it could be seeing?” No, the sensor is isolated. Why the distance return from the sensor is not correct ? which are it the reasons so that the sensor return wrong distances ?

Did you try measuring closer objects like I asked? How does the sensor’s output change if you try to measure other distances? (For example, does it seem like a constant offset or do the measurements vary with no clear correspondence to the expected value?)

Unfortunately, I don’t know of any specific reasons that you would get incorrect distance readings from the sensor beyond that your code is probably doing something different than what our library or the API does. The VL53L1X is hard to work with because ST does not provide complete documentation on its registers or how to interface with it, and our library was developed mostly by analyzing and reverse-engineering what the API does.

If you do try to continue developing your existing code based on our library, I strongly suggest getting an Arduino board that you can set up with the sensor and our library examples, then looking closely at the I2C communication with a scope or logic analyzer and comparing it with what your own code is doing on the nrf52840. Without doing that, it is very difficult to tell what is wrong because the VL53L1X has such complex procedures for initialization and operation. As I mentioned, I also recommend checking your I2C code again (if you have not already done so) to make sure it isn’t causing other issues.

If you continue to have difficulty, you might also consider trying to implement one of the ST APIs as a different approach.

Kevin