VL53L0X是新一代飞行时间(ToF)激光测距模块(不同于传统技术),采用目前市场上最小的封装,无论目标反射率如何,都能提供精确的距离测量。VL53L0X提供三种特殊测量模式:高精度、远距离、高速测量模式

API移植

VL53L0X使用IIC通讯,但是ST官方并没有给出实际的寄存器读写控制说明,只提供了API,移植API需要在vl53l0x_platform.c中实现以下函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

VL53L0X_Error VL53L0X_WriteMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata,uint32_t count); // 连续写数据

VL53L0X_Error VL53L0X_ReadMulti(VL53L0X_DEV Dev, uint8_t index, uint8_t *pdata,uint32_t count); //连续读数据

VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data); //写单字节寄存器

VL53L0X_Error VL53L0X_WrWord(VL53L0X_DEV Dev, uint8_t index, uint16_t data); //写字(2字节)寄存器

VL53L0X_Error VL53L0X_WrDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t data); //写双字(4字节)寄存器

VL53L0X_Error VL53L0X_UpdateByte(VL53L0X_DEV Dev, uint8_t index, uint8_t AndData, uint8_t OrData); //更新单字节寄存器

VL53L0X_Error VL53L0X_RdByte(VL53L0X_DEV Dev, uint8_t index, uint8_t *data); //读单字节寄存器

VL53L0X_Error VL53L0X_RdWord(VL53L0X_DEV Dev, uint8_t index, uint16_t *data); //读字(2字节)寄存器

VL53L0X_Error VL53L0X_RdDWord(VL53L0X_DEV Dev, uint8_t index, uint32_t *data); //读双字(4字节)寄存器

VL53L0X_Error VL53L0X_PollingDelay(VL53L0X_DEV Dev); //基本延时函数

VL53L0X_UpdateByte();比较特殊,需要先读寄存器然后将寄存器值和AndData与,再和OrData或,之后写入寄存器。

VL53L0X_PollingDelay();基本延时函数好像没什么要求,手册说明在多任务或操作系统中对轮寻API延时5ms,部分例程随意执行了250个空循环运行也正常。

VL53L0X_DEV结构体中保存了传感器的基本IIC信息,其中传感器中默认IIC地址为0x52。

返回值VL53L0X_Error错误码可以通过函数L53L0X_GetPalErrorString(Status,buf);
转换为易读的错误信息。buf长度可以设置为API宏定义VL53L0X_MAX_STRING_LENGTH

传感器初始化

API移植完成后可以正常调用API函数对传感器进行初始化。(首先对传感器引脚Xshut置位使之使能)

对传感器配置前先设置IIC结构体信息

1
2
3
VL53L0X_Dev_t->I2cDevAddr = 0x52;
VL53L0X_Dev_t->comms_type = 1;
VL53L0X_Dev_t->comms_speed_khz = 400;

如果有多个传感器则使用VL53L0X_SetDeviceAddress();设置新的IIC通讯地址。
使用VL53L0X_DataInit(); VL53L0X_StaticInit(); 使设备初始化。VL53L0X_StaticInit();之后才允许对传感器进行设置。

之后需要使传感器自校准

1
2
3
VL53L0X_PerformRefCalibration(dev, &VhvSettings, &PhaseCal);

VL53L0X_PerformRefSpadManagement(dev, &refSpadCount, &isApertureSpads);

校准值可以保存在MCU中,调用下面函数直接写入。(意义是啥?)

1
2
3
VL53L0X_SetRefCalibration(dev,Vl53l0x_data.VhvSettings,Vl53l0x_data.PhaseCal);

VL53L0X_SetReferenceSpads(dev,Vl53l0x_data.refSpadCount,Vl53l0x_data.isApertureSpads);

设定传感器参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
VL53L0X_SetDeviceMode(dev,VL53L0X_DEVICEMODE_SINGLE_RANGING);   //单次测量

VL53L0X_SetLimitCheckEnable(dev,VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,1); //开启SIGMA范围检查

//SIGMA表示是激光飞行时间

VL53L0X_SetLimitCheckEnable(dev,VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,1); //使能信号速率范围检查

VL53L0X_SetLimitCheckValue(dev,VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE,sigmaLimit);//设定SIGMA范围

VL53L0X_SetLimitCheckValue(dev,VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,signalLimit);//设定信号速率范围范围

VL53L0X_SetMeasurementTimingBudgetMicroSeconds(dev,timingBudget);//设定完整测距最长时间

VL53L0X_SetVcselPulsePeriod(dev, VL53L0X_VCSEL_PERIOD_PRE_RANGE, preRangeVcselPeriod);//设定VCSEL脉冲周期

VL53L0X_SetVcselPulsePeriod(dev, VL53L0X_VCSEL_PERIOD_FINAL_RANGE, finalRangeVcselPeriod);//设定VCSEL脉冲周期范围

//sigmaLimit, signalLimit, timingBudget, preRangeVcselPeriod, finalRangeVcselPeriod参数的典型值可以在API手册第7部分 Example API range profiles 找到

获得测量信息

获取之前首先创建VL53L0X_RangingMeasurementData_t结构体

调用函数VL53L0X_Error VL53L0X_PerformSingleRangingMeasurement(VL53L0X_DEV Dev,VL53L0X_RangingMeasurementData_t *pRangingMeasurementData);得到测量信息。

传感器校准

调用函数VL53L0X_PerformOffsetCalibration(dev,CalDistanceMilliMeter,&OffsetMicroMeter);可进行传感器偏移较准CalDistanceMilliMeter用于提供校准距离,OffsetMicroMeter用于保存新的偏移量。
CalDistanceMilliMeter参数在手册里好像没有找到距离单位,我参考了正点原子的代码发现他将10CM的参数定义为

1
uint32_t CalDistanceMilliMeter = 100<<16;

校准完成后每次启动需要通过VL53L0X_SetOffsetCalibrationDataMicroMeter(dev,OffsetMicroMeter);函数将偏移量提供给传感器。

如果传感器上使用了特定的滤镜,需要进行串扰校准,参考手册2.6章节 Cross-talk calibration 部分。

调用VL53L0X_PerformXTalkCalibration(dev,XTalkCalDistance,&XTalkCompensationRateMegaCps);进行串扰校准,XTalkCalDistance参数为测试物距离,但是此时它的单位为毫米,所以10CM设置为100。

同样,每次启动后需要设置串扰测量值VL53L0X_SetXTalkCompensationRateMegaCps(dev,XTalkCompensationRateMegaCps);

参考资料