cancel
Showing results for 
Search instead for 
Did you mean: 

How manage errors while Init VL53L1X

nico23
Associate III

I'm using the VL53L1X ULD API to drive 4 sensors and, sometimes, the function VL53L1X_SensorInit returns error VL53L1_ERROR_CONTROL_INTERFACE while initializing the third or four sensor (the first two are always initialized correctly).

The sensor boot up correctly and returns correct measurements, tho.

What's the best practice to manage this error? Is it correct to use something like

statusRadar = VL53L1X_SensorInit(dev_address);
while(statusRadar) {
   statusRadar = VL53L1X_SensorInit(dev_address);
}

My init function is like

static void VL53L1_init(void) {
	uint16_t ToFAddresses[4] = {0x54, 0x56, 0x58, 0x5A};
	uint16_t dev_address = 0x52;
	uint8_t byteData, sensorState=0;
	// Reset the 4 ToF sensors on the expansion board
	for (ToFSensor = 0; ToFSensor < NUMERO_RADAR; ToFSensor++) {
		statusRadar = XNUCLEO53L1A1_ResetId(ToFSensor, 0);
	}

	// Bring the sensors out of the reset stage one by one and set the new I2C address
	for (ToFSensor = 0; ToFSensor < NUMERO_RADAR; ToFSensor++) {

		statusRadar = XNUCLEO53L1A1_ResetId(ToFSensor, 1); // Bring sensor out of reset

		while(sensorState==0){
			statusRadar = VL53L1X_BootState(dev_address, &sensorState);
			HAL_Delay(1);
		}

		//Device Initialization and setting
		statusRadar = VL53L1X_SensorInit(dev_address);

		statusRadar = VL53L1X_SetI2CAddress(dev_address, ToFAddresses[ToFSensor]);

		statusRadar = VL53L1X_SetDistanceMode(ToFAddresses[ToFSensor], 2); /* 1=short, 2=long */
		statusRadar = VL53L1X_SetTimingBudgetInMs(ToFAddresses[ToFSensor], 33); /* in ms possible values [20, 50, 100, 200, 500] */
		statusRadar = VL53L1X_SetInterMeasurementInMs(ToFAddresses[ToFSensor], 40); /* in ms, IM must be > = TB */
		statusRadar = VL53L1X_StartRanging(ToFAddresses[ToFSensor]);

		HAL_Delay(1);
	}
}

 

7 REPLIES 7
John E KVAM
ST Employee

if you get an init failure, you have a hardware issue. Get a scope and look at the I2C line. Do you see square edges - or something that looks like a sine wave? With multiple I2C devices on a line, you are worried about the accumulative capacitance.  You are going to have to adjust some pull-ups somewhere. Or shorten your wires.

But you could also be starving the sensors of power. the sensors draw rather a lot of power in short bursts, so you might look there. 

The init will not fail if the baud rate is good and the hardware correct.

- john


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

I'll try to see what's happening on the I2C line with a scope but, I noticed that, if I handle those errors with a block code like:

//Device Initialization and setting
statusRadar = VL53L1X_SensorInit(dev_address);
int retry_count = 0;
while (statusRadar && retry_count < MAX_RETRIES) {
	retry_count++;
	HAL_Delay(retry_count); // Short delay between retries
	statusRadar = VL53L1X_SensorInit(dev_address);
}

they all boot correctly and no errors appear at the end of every sensor's boot.

An I2C is a very un-reliable bus. Get the sensors running and introduce a bit of electrical noise. If your I2C is so flakey that it doesn't boot every time, you are going to get a failure. And when it fails you will see one of the I2C lines is stuck low. It means either the senor or the host clocked a non-existent bit, and the two are now out of sync. 

A bit of shielding, or a cap change should fix it. Maybe a stronger pull-up. There are tons of articles on how to tune an I2C bus. 

But on your code, I'd introduce a bit that cycled either the power or the X-shut line before retrying the boot. Then you could guarantee a solid restart mechanism. 


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

Thanks for the answer @John E KVAM .

After various tests, we found that some static charges generate electrical noise in some instances. This electrical noise disturbs the I2C and causes it to crash.

The microcontroller is able to put back on a HIGH state both the data and the clock line but it seems that, even after de-initializing and initializing the I2C and sending the 10 pulse on the clock line, the I2C lines won't recover.

Besides improving the connections and isolating them, my question is, is there a way to recover the I2C besides turning off both the I2C and the VL53L1X sensors?

Does toggling the X-shut mean that I need to re-init the sensors with address, timing budget, etc?

nico23
Associate III

After analyzing the CLK and DATA line before the crash I've noticed that the STM32F091 I'm using is trying to reset the CLK line sending 9 pulses but the clock won't restart as intended.

20241217_153805.jpgThe CLK and DATA line just before the crash.

 

20241217_152741.jpg

 

20241217_152751.jpgBoth lines when the I2C crashed and won't recover

 

On the board of the VL53L1X, we're using an SBLC6-2SC6 to suppress noise and a PCA9507D to convert the 5V level of the line to the 3V level of the VL53L1X. Pull-up resistors are 2.7kOhm and the GND of the VL53L1X has the two capacitators described in the datasheet 4,7uF and 100nF. We even have put BAV99 diodes on the XSHUT line.

The strange part is why the CLK line won't recover

John E KVAM
ST Employee

It's your level shifter. Why? Because it's always your level shifter. I hate those things. 

Are you sure you need it? You have a STM32F091 - and I think all STM32s can do 3v3 I2C. I could be wrong however; I'm not an expert on STM32s

But have a look. See if you can avoid the level shifter. It will save you some money and I think it will work better. 

- john


If this or any post solves your issue, please mark them as 'Accept as Solution' It really helps. And if you notice anything wrong do not hesitate to 'Report Inappropriate Content'. Someone will review it.

We put the level shifter because the I2C is 3 to 4 meters long and, with a 5V signal on the line, it should, theoretically, be more solid, shouldn't it?

Yeah, the STM32F091 can drive a 3V3 I2C line

I'll look at the level shifter, thanks for the heads-up