[STM32F1] STM32F103驱动VL53L0X激光测距模块

[复制链接]
3176|43
 楼主| t61000 发表于 2023-7-31 13:51 | 显示全部楼层 |阅读模式
简介
TOF 是飞行时间(Tlme of Flight)技术的缩写,即传感器发出经过调制的近红外光,遇到物体后反射,传感器通过计算光线发射和反射时间差或相位差,来换算被测量物体的距离。
VL53L0X是新一代飞行时间(ToF)激光测距模块,无论目标反射率如何,都能提供精确的距离测量。它可以测量2m的绝对距离,为测距性能等级设定了新的基准。VL53L0X集成了一个领先的SPAD阵列(单光子雪崩二极管),并内嵌ST的第二代FlightSense™专利技术。
VL53L0X的940nm VCSEL发射器(垂直腔面发射激光器)完全不为人眼所见,加上内置的物理红外滤光片,使其测距距离更长,对环境光的免疫性更强,对盖片的光学串扰具有更好的稳定性。
VL53L0X 传感器提供了 4 种测量模式。分别为默认测量模式、高精度测量模式、长距离测量模式以及高速测量模式。根据 ST 官方提供的 4 种不同的精度模式的特点,具体参数如下表所示。
6550264c74bea90220.png


 楼主| t61000 发表于 2023-7-31 13:54 | 显示全部楼层
由表格可知,在不同精度工作模式下,测量时间长短是不同的,测量时间最快是高速模式,只需 20ms 内就可以采样一次,但精度确存在有±5%的误差范围。而在长距离精度模式下,测距距离能达到 2m,测量时间在 33ms 内,但测量时需在黑暗条件。用户可以根据实际需要,在不用的应用场景可使用不同的工作模式。

1429664c74c9f2beba.png
 楼主| t61000 发表于 2023-7-31 14:25 | 显示全部楼层
引脚定义 3400164c753bf3be74.png
 楼主| t61000 发表于 2023-7-31 14:26 | 显示全部楼层
SCL:IIC接口时钟信号线;
SDA:IIC接口数据信号线;.
VIN:3.3-5V电源正极;
GND:电源负极
XSHUT(reset):复位,低有效;
GPIO1:中断输出
IIC器件地址:0x52
IIC通信频率:可达400KHz
 楼主| t61000 发表于 2023-7-31 14:26 | 显示全部楼层
STM32F103ZET6开发板与VL53L0X模块接线
4613464c75408301bd.png
 楼主| t61000 发表于 2023-7-31 14:27 | 显示全部楼层
 楼主| t61000 发表于 2023-7-31 14:27 | 显示全部楼层
测试代码
主函数与初始化配置
以下按照程序的执行流程,代码清单 1 main 函数(main.c 文件),在 main 函数中,首先对 USART 串口初始化配置。然后进入VL53L0X 传感器功能测试阶段。
  1. int main(void)
  2. {
  3. /*初始化 USART 配置模式为 115200 8-N-1,中断接收*/
  4. USART_Config();

  5. printf(" 欢迎使用野火开发板\r\n");
  6. printf(" 激光测距传感器实验\r\n");
  7.   while (1) {
  8. vl53l0x_test();
  9. }
  10. }
 楼主| t61000 发表于 2023-7-31 14:30 | 显示全部楼层
代码清单2 VL53L0X 传感器测试(VL53L0X.c 文件)在测试函数中先是对 VL53L0X 传感器进行了初始化设置,当初始化成功则退出 while循环函数进入激光测距过程(第 16 行代码)。
  1. 1 /**
  2. 2 * [url=home.php?mod=space&uid=247401]@brief[/url] VL53L0X 主测试程序
  3. 3 * @param 无
  4. 4 * @retval 无
  5. 5 */
  6. 6 void vl53l0x_test(void)
  7. 7 {
  8. 8 /*vl53l0x 初始化*/
  9. 9 while (vl53l0x_init(&vl53l0x_dev)) {
  10. 10 printf("初始化失败\r\n");
  11. 11 printf("请检查连接\r\n");
  12. 12 }
  13. 13 printf("初始化成功\r\n");
  14. 14
  15. 15 while (1) {
  16. 16 vl53l0x_general_test(&vl53l0x_dev);
  17. 17 }
  18. 18 }
 楼主| t61000 发表于 2023-7-31 14:31 | 显示全部楼层
代码清单2 VL53L0X 传感器测试(VL53L0X.c 文件)在测试函数中先是对 VL53L0X 传感器进行了初始化设置,当初始化成功则退出 while循环函数进入激光测距过程(第 16 行代码)。
  1. 1 /**
  2. 2 * @brief VL53L0X 主测试程序
  3. 3 * @param 无
  4. 4 * @retval 无
  5. 5 */
  6. 6 void vl53l0x_test(void)
  7. 7 {
  8. 8 /*vl53l0x 初始化*/
  9. 9 while (vl53l0x_init(&vl53l0x_dev)) {
  10. 10 printf("初始化失败\r\n");
  11. 11 printf("请检查连接\r\n");
  12. 12 }
  13. 13 printf("初始化成功\r\n");
  14. 14
  15. 15 while (1) {
  16. 16 vl53l0x_general_test(&vl53l0x_dev);
  17. 17 }
  18. 18 }
 楼主| t61000 发表于 2023-7-31 14:31 | 显示全部楼层
代码清单 3 VL53L0X 工作模式测试函数(VL53L0X.c 文件)在 test 函数中,第 8 行使用 scanf 函数,使开发板获取来自串口调试助手发出的控制指令。当开发板接收到的指令字符 ch 为有效指令时(0<=ch<4 的整数),开发板控制传感器通过vl53l0x_general_start(dev,ch)函数(第 17 行代码)进入相对应激光测距模式;当接收的字符是无效指令时,则打印提示用户输入合法指令。
 楼主| t61000 发表于 2023-7-31 14:32 | 显示全部楼层
  1. 1 /**
  2. 2 * @brief vl53l0x 工作模式测试
  3. 3 * @param dev:设备 I2C 参数结构体
  4. 4 * @retval 无
  5. 5 */
  6. 6 void vl53l0x_general_test(VL53L0X_Dev_t *dev)
  7. 7 {
  8. 8 uint32_t ch;
  9. 9
  10. 10 Show_GenTask_Message(); //显示普通测量模式 UI
  11. 11
  12. 12 while (1) {
  13. 13 scanf("%d",&ch);
  14. 14 printf("接收到字符:%d\r\n",ch);
  15. 15
  16. 16 if ((ch>=0) && (ch<=3)) {
  17. 17 vl53l0x_general_start(dev,ch);
  18. 18 Show_GenTask_Message();
  19. 19 } else {
  20. 20 /*如果不是指定指令字符,打印提示信息*/
  21. 21 printf("请输入合法指令!\r\n");
  22. 22 Show_GenTask_Message();
  23. 23 }
  24. 24 }
  25. 25 }
 楼主| t61000 发表于 2023-7-31 14:33 | 显示全部楼层
代码清单 4 VL53L0X 测量模式配置函数(VL53L0X.c 文件)在测量模式配置函数中,由于频繁切换精度模式容易导致采集距离数据不准 ,所以在使用之前先对 VL53L0X 传 感 器 进 行 复 位 处 理 ( 第 18 行 代 码 ) , 然 后 使 用VL53L0X_StaticIni()函数对传感器参数恢复为默认。另外,精度模式的配置是根据函数参数 mode 变量决定的,mode 值对应 0:默认,1:高精度 2:长距离,3:高速,根据全局数组 Mode_data[]变量的写入,从而实现不同精度模式的配置。
 楼主| t61000 发表于 2023-7-31 14:36 | 显示全部楼层
  1. 1 /**
  2. 2 * @brief VL53L0X 测量模式配置
  3. 3 * @param dev:设备 I2C 参数结构体
  4. 4 * @param mode: 0:默认;1:高精度;2:长距离
  5. 5 * @retval 状态信息
  6. 6 */
  7. 7 VL53L0X_Error vl53l0x_set_mode(VL53L0X_Dev_t *dev,uint8_t mode)
  8. 8 {
  9. 9 VL53L0X_Error status = VL53L0X_ERROR_NONE;
  10. 10 uint8_t VhvSettings;
  11. 11 uint8_t PhaseCal;
  12. 12 uint32_t refSpadCount;
  13. 13 uint8_t isApertureSpads;
  14. 14
  15. 15 /*复位 vl53l0x(频繁切换工作模式容易导致采集距离数据不准,需加上这一代码)*/
  16. 18 vl53l0x_reset(dev);
  17. 19 status = VL53L0X_StaticInit(dev);
  18. 20
  19. 21 /*已校准好了,写入校准值*/
  20. 22 if (AjustOK!=0) {
  21. 23 /*设定 Spads 校准值*/
  22. 24 status= VL53L0X_SetReferenceSpads(dev,Vl53l0x_data.refSpadCount,
  23. 25 Vl53l0x_data.isApertureSpads);
  24. 26 if (status!=VL53L0X_ERROR_NONE) goto error;
  25. 27 delay_ms(2);
  26. 28
  27. 29 /*设定 Ref 校准值*/
  28. 30 status= VL53L0X_SetRefCalibration(dev,Vl53l0x_data.VhvSettings,
  29. 31 Vl53l0x_data.PhaseCal);
  30. 32 if (status!=VL53L0X_ERROR_NONE) goto error;
  31. 33 delay_ms(2);
  32. 34
  33. 35 /*中间省略代码*/
  34. 36 .......
  35. 37
  36. 38
  37. 39 /*设定 VCSEL 脉冲周期*/
  38. 40 status = VL53L0X_SetVcselPulsePeriod(dev,
  39. 41 VL53L0X_VCSEL_PERIOD_PRE_RANGE,
  40. Mode_data[mode].preRangeVcselPeriod);
  41. 43 if (status!=VL53L0X_ERROR_NONE) goto error;
  42. 44 delay_ms(2);
  43. 45
  44. 46 /*设定 VCSEL 脉冲周期范围*/
  45. 47 status = VL53L0X_SetVcselPulsePeriod(dev,
  46. VL53L0X_VCSEL_PERIOD_FINAL_RANGE,
  47. Mode_data[mode].finalRangeVcselPeriod);
  48. 50
  49. 51 error:/*错误信息*/
  50. 52 if (status!=VL53L0X_ERROR_NONE) {
  51. 53 print_pal_error(status);
  52. 54 return status;
  53. 55 }
  54. 56 return status;
  55. 57}
 楼主| t61000 发表于 2023-7-31 14:37 | 显示全部楼层
代码清单 5 VL53L0X 单次距离测量函数(VL53L0X.c 文件)在该函数中,通过调用 VL53L0X_PerformSingleRangingMeasurement ()函数启动单次测量(第 15 行代码),该函数为阻塞函数,当测量结束后,测量的数据将被保存到 pdata 测量数据结构体上, 最后将获取测量结构体的测量数据赋值给 Distance_data 全局变量(第24 行代),通过读取 Distance_data 变量的值我们就可以知道测量距离了。
 楼主| t61000 发表于 2023-7-31 14:38 | 显示全部楼层
  1. 1 /**
  2. 2 * @brief VL53L0X 单次距离测量函数
  3. 3 * @param dev:设备 I2C 参数结构体
  4. 4 * @param pdata:保存测量数据结构体
  5. 5 * @retval 状态信息
  6. 6 */
  7. 7 VL53L0X_Error vl53l0x_start_single_test(VL53L0X_Dev_t *dev,
  8. VL53L0X_RangingMeasurementData_t *pdata,
  9. 9 char *buf)
  10. 10 {
  11. 11 VL53L0X_Error status = VL53L0X_ERROR_NONE;
  12. 12 uint8_t RangeStatus;
  13. 13
  14. 14 /*执行单次测距并获取测距测量数据*/
  15. 15 status = VL53L0X_PerformSingleRangingMeasurement(dev, pdata);
  16. 16 if (status !=VL53L0X_ERROR_NONE)
  17. return status;
  18. 17
  19. 18 /*获取当前测量状态*/
  20. 19 RangeStatus = pdata->RangeStatus;
  21. 20 memset(buf,0x00,VL53L0X_MAX_STRING_LENGTH);
  22. 21 /*根据测量状态读取状态字符串*/
  23. 22 VL53L0X_GetRangeStatusString(RangeStatus,buf);
  24. 23 /*保存最近一次测距测量数据*/
  25. 24 Distance_data = pdata->RangeMilliMeter;
  26. 25
  27. 26 return status;
  28. 27 }
 楼主| t61000 发表于 2023-7-31 14:38 | 显示全部楼层
实验结果
在串口助手软件输入对应测距模式的编号后,激光测距传感器获取感应信息,将结果通过开发版 usart1 串口输给串口调试助手软件显示出来。

1486364c756e478724.png
juliestephen 发表于 2023-8-4 13:37 | 显示全部楼层
stm32f103移植VL53L0X API报错__stdout多重定义
eefas 发表于 2023-8-4 14:10 | 显示全部楼层
VL53L0X模块通常需要3.3V的电源供应。确保为模块提供稳定的电源,并避免电源噪声对测距性能的影响。
lzbf 发表于 2023-8-4 14:30 | 显示全部楼层
根据VL53L0X模块的要求,确保在进行测距操作之间设置适当的延时。
pmp 发表于 2023-8-4 15:30 | 显示全部楼层
谁能帮我写一个STM32f103,I2C通信VL53L0X示例代码?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

124

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部