Distance measurement programming with the ultra-compact distance sensor VL53L1X

Overview

We will explain programming for simple distance measurement using VL53L1X, which can measure distances of up to 4 m by ToF (Time of Flight). We used the Full API officially provided by STMicroelectronics to use the VL53L1X. In this article, it is operated by STM32 microcomputer, but it can be ported to other platforms by applying the method introduced.

About VL53L1X

The VL53L1X is a ToF distance sensor with a size of 4.9 mm x 2.5 mm, which is an ultra-compact sensor. The maximum measurement distance is 4m, and since it can measure at 50Hz, it can be used in various applications (I use it for altitude control of small drones). Sold as a module at Akizuki Denshi and Switch Science There is also an Arduino library.

VL53L1X Source: API_User_Manual_UM2356_rev2.pdf

Preparation

hardware

The operation was confirmed using the following hardware.

software

You need to download it from the linked page.

testing environment

--PC: macOS Catalina (Windows and Linux can also be used)

How to use VL53L1X Full API

We will introduce a simple method to measure the distance using the VL53L1X Full API. Also, the lightweight version ULD (Ultra Light Driver) can be used in the same way, so it is omitted.

STEP1: Create a project with STM32CubeIDE

  1. Clock frequency (HCLK) is 84MHz, I2C1 is 100kHz, with Device Configuration Tool of STM32CubeIDE. USART2 was set to 115200 Bits / s. I2C pins were changed to PB8 and PB9. ピン設定

STEP2: Copy of VL53L1X Full API library

  1. Copy the downloaded VL53L1X Full API api directory to Core / in the STM32 project. api / core is the core of the API, and api / platform performs I2C communication processing that differs depending on the device.

STEP3: Copy of X-CUBE-53L1A1 library

  1. Copy and overwrite Projects / STM32F401RE-Nucleo / Examples / 53L1A1 / SimpleRanging / Inc / vl53l1_ *. H (6 in total) of X-CUBE-53L1A1 to Core / api / platform / in the project of STM32.
  2. Copy and overwrite Projects / STM32F401RE-Nucleo / Examples / 53L1A1 / SimpleRanging / Src / vl53l1_platform.c of X-CUBE-53L1A1 to Core / api / platform / in the project of STM32.

STEP4: Partial modification of the library

  1. Modify #include "stm32xxx_hal.h" in api / platform / vl53l1_platform.c and api / platform / vl53l1_platform_user_data.h to #include "stm32f4xx_hal.h".

STEP5: Project settings

  1. Set the library path. Since Paths and Symbols are in the project properties, add the paths of api / core and api / platform.

STEP6: Programming

  1. Open main.c in Core / Src / main.c.

  2. Write the include file before main.c. stdio.h was included to use printf.

    /* USER CODE BEGIN Includes */
    #include <stdio.h>
    #include "vl53l1_api.h"
    /* USER CODE END Includes */
    
  3. Next, prepare printf. I referred to Linked page. First, write the following code at the beginning of the main function.

    /* USER CODE BEGIN 1 */
    setbuf(stdout, NULL);
    /* USER CODE END 1 */
    

In addition, define the __io_putchar function after main.c.

```c
/* USER CODE BEGIN 4 */
int __io_putchar(int ch) {
  HAL_UART_Transmit(&huart2, (uint8_t*)&ch, 1, 1000);
  return 0;
}
/* USER CODE END 4 */
```

Now you can use printf.

  1. Next, write the process of distance measurement. I referred to SimpleRanging / Src / main.c of X-CUBE-53L1A1. First, the variable declaration and initialization processing are described.

    /* USER CODE BEGIN 2 */
    VL53L1_Dev_t dev;
    VL53L1_DEV Dev = &dev;
    int status = 0;
    VL53L1_RangingMeasurementData_t RangingData;
    
    Dev->I2cHandle = &hi2c1;
    Dev->I2cDevAddr = 0x52;
    
    status = VL53L1_WaitDeviceBooted(Dev);
    status = VL53L1_DataInit(Dev);
    status = VL53L1_StaticInit(Dev);
    status = VL53L1_SetDistanceMode(Dev, VL53L1_DISTANCEMODE_LONG);
    status = VL53L1_SetMeasurementTimingBudgetMicroSeconds(Dev, 50000);
    status = VL53L1_SetInterMeasurementPeriodMilliSeconds(Dev, 500);
    status = VL53L1_StartMeasurement(Dev);
    /* USER CODE END 2 */
    

Next, the iterative process is described.

```c
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
  status = VL53L1_WaitMeasurementDataReady(Dev);
  if (!status) {
    status = VL53L1_GetRangingMeasurementData(Dev, &RangingData);
    if (status == 0) {
      printf("%d\n", RangingData.RangeMilliMeter);
    }
    status = VL53L1_ClearInterruptAndStartMeasurement(Dev);
  }
}
/* USER CODE END 3 */
```

If you build with this, you can check the distance data by serial communication.

Explanation of the main points

As for the details of API, VL53L1X API_User_Manual_UM2356_rev2.pdf is in doc /, so I will leave it to that and explain only the parts that seem necessary.

★ About the distance measurement mode

The following three modes can be set by using the VL53L1_SetDistanceMode function. If you want to measure up to 4m, use LONG mode, and if you want to prioritize environmental resistance up to 1.3m, use SHORT mode.

★ About Timing budget and Inter-measurement period

The Timing budget is explained as follows.

The timing budget is defined as the programmed time needed by the sensor to perform and report ranging measurement data. During this time, the VCSEL is pulsed. An interrupt is raised or the date ready register is updated at the end of the timing budget.

The Inter-measurement period is explained as follows.

The inter-measurement period is defined as the programmed time between two consecutive measurements.

It is easy to understand by looking at the figure.

VL53L1X timings Source: API_User_Manual_UM2356_rev2.pdf

It can be interpreted that the Timing budget represents the time until the target is irradiated with the laser and the distance is measured, and the Inter-measurement period represents the measurement interval.

When I read the document, the values that can be set with VL53L1_SetMeasurementTimingBudgetMicroSeconds are from 20ms to 1000ms. In addition, VL53L1_SetInterMeasurementPeriodMilliSeconds is set to a value of Timing budget + 4ms or more.

As an example, when measuring at 20Hz (50ms), do as follows.

VL53L1_SetMeasurementTimingBudgetMicroSeconds(Dev, 46000);
VL53L1_SetInterMeasurementPeriodMilliSeconds(Dev, 50);

First, set the Inter-measurement period to 50 ms, and subtract 4 ms from the Inter-measurement period of the Timing budget to convert it to microseconds.

★ About VL53L1_RangingMeasurementData_t structure

Detailed data of distance measurement is stored in the VL53L1_RangingMeasurementData_t structure. Most of them are not needed, but distance data can be obtained by accessing RangeMilliMeter, which is a member of the structure.

★ About the status value

If the sensor does not work well, check the status value. Since the error code is defined in api / core / vl53l1_error_codes.h, you can check which error corresponds to.

in conclusion

We explained the programming of distance measurement using the ultra-small distance sensor VL53L1X. Detailed information can be obtained from the official user manual and the Example project, so please refer to it. If you have any questions or deficiencies in the content, please leave a comment.

Recommended Posts