cancel
Showing results for 
Search instead for 
Did you mean: 

VL53L0X sensor PerformSingleRangingMeasurement ()

NeoMuEoLyeOwoYo
Associate

Hello. I'm a newbie to stm32 or actually to everything.
I am using VL53L0X sensor and STM32F030C8T6 MCU in stm32idecube.

What I want to do is to get a good reading of the sensor data.

And I want to use a timer interrupt to read the sensor data every certain period and I don't want to read any weird sensor data.


So I used someone's code to read the sensor data using the VL53L0X api to check the sensor data.

But this code doesn't use timer interrupt, so I modified it to set a timer and use VL53L0X_PerformSingleRangingMeasurement function in HAL_TIM_PeriodElapsedCallback function to read sensor data.
This modification didn't work, so I put the VL53L0X_PerformSingleRangingMeasurement function in a while() in the main function, and the sensor data was read in just fine.

Why did I not get the sensor data when I used the function that reads the sensor data from the timer interrupt, but I got the sensor data in while()? Is it possible that this sensor should not be used with a timer?

(For reference, I set the timer interrupt period to 1s).

 

+ I'm getting the sensor data, but I'm having trouble with the value.
It could be a hardware issue or a software issue, but when the sensor data comes in, the value is jumping around too much.
Sometimes I get a value of 20 or 8000 or something like that, otherwise the value is outputting normally.

Please, if anyone is familiar with this sensor, please help me out.

 

I've attached some code below.

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

if (htim->Instance == TIM1)

{

check += 1;

VL53L0X_RangingMeasurementData_t RangingMeasurementData;

dist[1] = VL53L0X_PerformSingleRangingMeasurement(pDev, &RangingMeasurementData);

}

}

 

/* USER CODE END 0 */

 

/**

* @brief The application entry point.

* @retval int

*/

int main(void)

{

 

/* USER CODE BEGIN 1 */

VL53L0X_Dev_t Laser_1 =

{

.I2cHandle = &hi2c1,

.I2cDevAddr = PROXIMITY_I2C_ADDRESS

};

pLaser_1 = &Laser_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_TIM1_Init();

/* USER CODE BEGIN 2 */

LaserConfig laserConfigs[] = {

{XSHUT0_GPIO_Port, XSHUT0_Pin, pLaser_1, SENSOR_ADDR_1},

};

for (int i = 0; i < sizeof(laserConfigs) / sizeof(LaserConfig); i++)

{

HAL_GPIO_WritePin(laserConfigs[i].GPIOx, laserConfigs[i].GPIO_Pin, GPIO_PIN_SET);

HAL_Delay(20);

VL53L0X_PROXIMITY_Init(laserConfigs[i].p_laser, laserConfigs[i].dev_addr);

}

dist[0] = 0;

 

if (HAL_TIM_Base_Start_IT(&htim1) != HAL_OK)

{

Error_Handler();

}

/* USER CODE END 2 */

 

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */

 

/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */

}

3 REPLIES 3
John E KVAM
ST Employee

the sensor should be ready to go after you do the:

VL53L0X_PROXIMITY_Init(laserConfigs[i].p_laser, laserConfigs[i].dev_addr);

I would suggest checking the return from the init, although that 20ms delay should give it plenty of time to boot.

After the init, the sensor is waiting for a 'Go' command, although there are lots of configuration changes you can make. 

Increasing the Timing Budget for instance will give a more accurate result.

After the 'Go' command, the sensor will run forever. 

The 'one-shot' function does a 'Go', a while loop, waiting for done, a 'Stop' command and a data read. 

You can use that code as an example and do the same thing. 

Or you can set up in 'Inter-measurement Period' to one second. Issue the Go, and the sensor will happily range every 1 second and keep the data around - you can read it at any time. 

As to your question of getting "20 or 8000 or something like that", I'm going to suggest reading the RangeStatus register. We put in 8192 minus the error number as a result as the sensor will never return any number over 2000. 

When there truly is no target near, you get a 'low signal', when the standard deviation of the signal is too wide you get a 'Sigma too High' error. When you have fast motion, you might get a wrap-around error. To much sunlight will also lead to poor detection - unless you are close.

Take only the ones that return a RangeStatus 0 and you should be good.

Place the sensor on your desk looking up at the ceiling. Check the range status. INcrease the timing budget until you can see the distance to the ceiling reliably. (Assuming your ceiling is not farther than 2M away.) Then put your hand in front of the sensor. 

- 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.

 

Thank you so much for your answer.
I'm not an English speaker, so I'm not sure if I understood it well.

Here's what I understood
1. I made a mistake and didn't attach VL53L0X_PROXIMITY_Init(), but after init, the sensor is ready to be utilized.
2. The Go command you are referring to is VL53L0X_PerformSingleRangingMeasurement(), which is the function that reads the sensor data in my code?
3. Does my code have no problem reading the sensor data now?
4. You can also change the sensor measurement period without using the timer interrupt. 6.
5. Check the RangeStatus for strange values.


That's my understanding so far.

I have more questions here.

1. What do you mean by 'one-shot' function?

2. What I was wondering is that reading sensor data from a timer interrupt doesn't work, but it works fine in a while function.
So if the position of VL53L0X_PerformSingleRangingMeasurement() is in timer interrupt, the sensor data doesn't come in, but if it's in while statement, it comes in. It's just the position of the function that reads this sensor data is different, but everything else is the same. What could be the problem?

 

And thanks to you, I see that through RangeStatus, I now have a zero coming in, so thank you very much.

When you do the initialization, the chip is ready, but it's not running. To start it, you must issue the 'start' command. 

Before you issue the start command, configure the timing budget, and the Inter-measurement period. They tell the sensor how long spend doing the integration and how long to wait before ranging again. 

VL53L0X_StartMeasurement() function must be called to start a measurement. The
device will start a measurement using the chosen mode (single or continuous).

In single mode the sensor runs once, then stops. In continous mode, it keeps running until you tell it to stop.

If you only want single measurements, and don't mind waiting for them then use:

VL53L0X_PerformSingleRangingMeasurement() function starts a measurement,
waits for data ready (by polling on the ranging status or on the interrupt status) and reports
the data. This function also clears the interrupt after the measurement.
The 3 following API functions are called internally:
• VL53L0X_PerformSingleMeasurement()
• VL53L0X_GetRangingMeasurementData()
• VL53L0X_ClearInterruptMask()

Please have a look at the user manual. To get it, download the API. The manual is in with the code.


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.