关于VL53L0X多机测量速度较慢的一种解决方法

本文最后更新于 2025年5月16日 晚上

关于VL53L0X在I2C模式下多机测量速度较慢的一种解决方法与使用经验

前言

最近在做一个项目,需要使用VL53L0X在I2C模式下进行多机测量,但是发现测量速度较慢,查阅资料发现一种处理方法,在此记录一下

正文

问题定位

ST官方给出的API(STSW-IMG005)中有一个单次测量函数,我们使用时一般直接调用这个函数进行测量,函数定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 来源于官方API,产品型号STSW-IMG005
VL53L0X_Error VL53L0X_PerformSingleRangingMeasurement(VL53L0X_DEV Dev, VL53L0X_RangingMeasurementData_t *pRangingMeasurementData)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;

LOG_FUNCTION_START("");

/* This function will do a complete single ranging
* Here we fix the mode! */
Status = VL53L0X_SetDeviceMode(Dev, VL53L0X_DEVICEMODE_SINGLE_RANGING);

if (Status == VL53L0X_ERROR_NONE)
{
Status = VL53L0X_PerformSingleMeasurement(Dev);
// printf("perform 1\n");
}

if (Status == VL53L0X_ERROR_NONE)
{
Status = VL53L0X_GetRangingMeasurementData(Dev, pRangingMeasurementData);
// printf("perform 2\n");
}

if (Status == VL53L0X_ERROR_NONE)
{
Status = VL53L0X_ClearInterruptMask(Dev, 0);
// printf("perform 3\n");
}

// printf("perform 4\n");

LOG_FUNCTION_END(Status);
return Status;
}

可以看到,该函数经历了启动测量——获取数据——清除中断的过程,经实际测试发现,在I2C通讯模式下,该函数测量的频率约为每秒4次。限于使用需求I2C只有一根总线,导致多机并联至总线后获取所有数据的时间很长。

查阅相关手册发现VL53L0X默认模式下测量周期为33ms,远小于此速度,故考虑是否是单次测量模式的不足导致测量速度过慢

解决思路

查询相关资料时,在ST官方论坛中发现一条官方回复:

ST官方回复

该回复中提到了一种解决方法,即使用连续测量模式,同时给出了相关API的结构。

经搜索文件发现官方API(STSW-IMG005)中并没有给出连续测量模式的API,于是参考此回复设计相关函数

函数设计

回复中给出了VL53L0X_PerformContinuousRangingMeasurement()函数的结构,仿照单次测量的VL53L0X_PerformSingleRangingMeasurement()函数,得到以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
VL53L0X_Error VL53L0X_PerformContinuousRangingMeasurement(VL53L0X_DEV Dev, VL53L0X_RangingMeasurementData_t *pRangingMeasurementData)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;

LOG_FUNCTION_START("");

/* This function will do a complete continuous ranging
* Here we fix the mode! */
Status = VL53L0X_SetDeviceMode(Dev, VL53L0X_DEVICEMODE_CONTINUOUS_RANGING);

if (Status == VL53L0X_ERROR_NONE)
{
Status = VL53L0X_PerformContinuousMeasurement(Dev);
// printf("perform 1\n");
}

if (Status == VL53L0X_ERROR_NONE)
{
Status = VL53L0X_GetRangingMeasurementData(Dev, pRangingMeasurementData);
// printf("perform 2\n");
}

if (Status == VL53L0X_ERROR_NONE)
{
Status = VL53L0X_ClearInterruptMask(Dev, 0);
// printf("perform 3\n");
}

// printf("perform 4\n");

LOG_FUNCTION_END(Status);
return Status;
}

按照官方回复的结构,我们还需要实现VL53L0X_PerformContinuousMeasurement()函数。参考单次测量的函数得到如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
VL53L0X_Error VL53L0X_PerformContinuousMeasurement(VL53L0X_DEV Dev)
{
VL53L0X_Error Status = VL53L0X_ERROR_NONE;
VL53L0X_DeviceModes DeviceMode;

LOG_FUNCTION_START("");

/* Get Current DeviceMode */
Status = VL53L0X_GetDeviceMode(Dev, &DeviceMode);

/* Start immediately to run a continuous ranging measurement in case of
* continuous ranging or continuous histogram */
if (Status == VL53L0X_ERROR_NONE && DeviceMode == VL53L0X_DEVICEMODE_CONTINUOUS_RANGING)
Status = VL53L0X_StartMeasurement(Dev);

if (Status == VL53L0X_ERROR_NONE)
Status = VL53L0X_measurement_poll_for_completion(Dev);

/* Change PAL State in case of continuous ranging or continuous histogram */
if (Status == VL53L0X_ERROR_NONE && DeviceMode == VL53L0X_DEVICEMODE_CONTINUOUS_RANGING)
PALDevDataSet(Dev, PalState, VL53L0X_STATE_IDLE);

LOG_FUNCTION_END(Status);
return Status;
}

官方API中有连续测量模式的宏定义,直接使用即可

修改完成后,在main()中调用一次该函数启动测量,随后直接使用VL53L0X_GetRangingMeasurementData()函数获取数据即可

经实际测试,测量速度提高至接近33ms一次,大大提升测量效率。

结尾

有关清除中断函数VL53L0X_ClearInterruptMask()的使用还未完全研究透彻,没有去除,但实际测试中发现读取之后并不需要额外清除中断,中断位功效有待考证

声明

本文属于东北大学盘古实验室,未经允许严禁转载,若有错误请指出,不胜感激。

作者 plumyT@PanGu_NEU


关于VL53L0X多机测量速度较慢的一种解决方法
http://coderliuchina.github.io/2025/05/16/2025-5-16/
作者
CoderLiu@NEU_China
发布于
2025年5月16日
许可协议