摘要:本文介绍ESP32如何使用激光测距模块VL53L0X进行距离测量
在前面的自动避障小车中,主要使用超声波传感器来进行障碍物距离的测量,接下来将介绍另一种经常用到的测距传感器——激光测距传感器。其测量原理是传感器发出激光,然后再通过接收到的返回的激光来测量距离的方法。激光测距的方法有两种,一种是脉冲法,一种是相位法。脉冲法的原理与超声波传感器类似,是利用激光发射出去到返回之间的时间来计算激光器到物体之间的距离。而相位法则利用发出去的激光返回后的相位与仪器内直接返回激光的相位差来计算激光器到物体之间的距离。
这次使用的为新一代飞行时间(ToF)激光测距模块,这款飞行测距模块是基于基于VL53L0X设计的。样子如下图所示:
VL53L0X是ST推出的第二代FlightSense技术的飞行时间传感器,与传统的测距传感器不同,VL53L0X采用ST的ToF技术,是目前最小的激光测距芯片,无论目标颜色和反射率如何,都可以进行距离测量,抗干扰能力更强。芯片如下图所示:
VL53L0X是完全集成的传感器,配有嵌入式红外、人眼安全激光,先进的滤波器和超高速光子探测阵列。VL53L0X增强了ST FlightSense?系列,测量距离更长,速度和精度更高,从而开启了新应用之门。即使在恶劣工作条件下,该传感器也可以直接确定与目标物体之间的距离,最远2米,并且不受目标反射率影响。
VL53L0X芯片的主要特征:
n 940nm激光VCSEL
n VCSEL驱动器
n 测距传感器,配有高级的嵌入式微控制器
n 4.4mmx2.4mmx1.0mm
n 快速、准确的距离测量
n 测量绝对距离达2m
n 报告的距离不受目标反射率影响
n 在高红外光环境下运行
n 先进的嵌入式光学串扰补偿,以简化玻璃罩的设计
n 1类激光设备,符合最新标准IEC 60825-1:2014(第3版)
n 可回流焊元件
n 无需额外光学器件
n 单电源
n I2C接口,用于器件控制和数据传输
n Xshutdown(复位)和中断GPIO
VL53L0X的参数:
工作电压:3.3V/5V
产品尺寸:4.4mm × 2.4mm?× 1.0mm
测距范围:30 ~ 2000mm
测距精度:±5% (高速模式),±3% (高精度模式)
测距时间(min):20ms (高速模式),200ms(高精度模式)
测距角度:25°
激光波长:940nm
工作温度:-20 ~ 70°C
VL53L0X传感器提供了3种测量模式:单次测量模式、连续测量模式和定时测量模式。
(1)单次测量模式:在这种测量模式下,一次触发只执行一次距离测量,测量结束后,VL53L0X传感器会返回待机状态,等待下一次触发。
(2)连续测量模式:在该模式下会以连续的方式执行距离测量。一次测量结束,下一次测量就会立即启动,用户必须停止测距才能返回到待机状态,最后的一次测量在停止前完成。
(3)定时测量模式:这种模式实际上就是指定时间间隔的连续测量模式。当一次测量结束后,经过用户定义的延迟时间之后,才会启动下一次测量。用户必须停止测距才能返回到待机状态,最后的一次测量在停机前完成。
VL53L0X传感器还提供了4种不同的精度模式:
精度模式 | 测量时间预算范围(ms) | 测距距离(m) | 典型应用场景 |
默认 | 30 | 1.2 | 标准 |
高精度 | 200 | 1.2(精度<±3%) | 精确测量 |
长距离 | 33 | 2 | 长距离,只适用于黑暗无红外线条件 |
高速 | 20 | 1.2(精度<±5%) | 高速,精度不优先 |
在实际的应用中,需根据当前的要求去选择合适的精度模式,以达到最佳的测量效果。
VL53L0X的激光测距模块的接口如下:
VCC | 电源正(3.3V/5V电源输入) |
GND | 电源地 |
SDA | I2C的数据引脚 |
SCL | I2C的时钟引脚 |
SHUT | 引脚,可接IO口 |
INT | 中断输出引脚,可接IO口 |
下面就来将激光测距模块与ESP32开发板连接到一起。在这里,IIC通信使用的是ESP32的默认引脚21和22。具体连接如下表所示:
激光测距模块 | ESP32模块 |
VCC | +5V |
GND | GND |
SDA | P21 |
SCL | P22 |
接下来就是打开开发软件Arduino IDE,首先需要安装VL53L0X的库,利用库可以免去我们很多底层的开发工作,需不要关注IIC通信的细节,也不需要仔细的去了解VL53L0X内部寄存器的结构,使用库文件所提供的函数,直接就可以完成模块的使用了。
打开Arduino IDE的库管理面板,在搜索框中输入“VL53L0X”然后选择安装“Adafruit_VL53L0X”库,如下图所示:
接下来就来看一个简单的单次测量模式的模板程序。如下所示:
#include?"Adafruit_VL53L0X.h" //创建Adafruit_VL53L0X对象的实例 Adafruit_VL53L0X lox = Adafruit_VL53L0X(); void?setup()?{ ? // put your setup code here, to run once: ??Serial.begin(115200); ? // 初始化激光测距模块 ? if?(!lox.begin())?{ ? ? Serial.println(F("Failed to boot VL53L0X")); ? ? while(1); ? } } void?loop()?{ ? // put your main code here, to run repeatedly: // 创建测量对象实例 ? VL53L0X_RangingMeasurementData_t?measure; ? ? ??// 触发单次测量 ? lox.rangingTest(&measure, false);?// pass in 'true' to get debug data printout! ? if?(measure.RangeStatus?!= 4)?{??// 判断测量结果的状态 ????//输出测量结果 Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter); ? }?else?{ ????//超出测量范围 ? ? Serial.println(" out of range "); ? } ? ? ? delay(100); } |
在上面的代码中可以看到,完成激光测距模块的单次测量需要经过以下这些步骤:
(1)创建Adafruit_VL53L0X对象的实例
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
(3)创建保存测量结果的VL53L0X_RangingMeasurementData_t结构的实例
(4)调用rangingTest()方法完成一次测量
(5)测量结果对象的RangeStatus属性表示测量结果的状态,RangeMilliMeter属性的值为测量的距离(单位是毫米)。
对于连续测量,与上面单次测量的区别是在调用begin()完成模块初始化之后,还要调用startRangeContinuous()方法,将激光测距模块切换到连续测量模式。在读取数据上的区别是要使用isRangeComplete()方法判断激光测距模块是否完成了一次测量,然后再通过readRange()方法来读取测量的结果。程序模板如下所示:
#include?"Adafruit_VL53L0X.h" Adafruit_VL53L0X lox = Adafruit_VL53L0X(); void?setup()?{ ? Serial.begin(115200); ? if?(!lox.begin())?{ ? ? Serial.println(F("Failed to boot VL53L0X")); ? ? while(1); ? } ? // start continuous ranging ? lox.startRangeContinuous(); } void?loop()?{ ? if?(lox.isRangeComplete())?{ ? ? Serial.print("Distance in mm: "); ? ? Serial.println(lox.readRange()); ? } } |
好了,激光测距模块就基本介绍到这里了。有兴趣的可以将这个模块装到小车上,替换掉超声波测距模块,然后测试一下用激光测距模块实现的避障小车的效果咋样了。