激光测距在生产生活中有很多应用,例如测距、定位、避障等等。而飞行时间(ToF)测距作为激光测距技术的一种,因为其测量精准、响应快速、低功耗等特点,常被用于机器人、自动驾驶汽车、交通管理中的实时对象检测,我们手机的面部检测功能,也用到这种技术。
由瑞科慧联(RAK)出品的 ToF 传感器模块 WisBlock RAK12014,采用 ST VL53L0X,后者是世界上最小的 ToF 测距传感器
本文将介绍一款 ToF 激光测距传感器模块 WisBlock RAK12014,并利用 WisBlock 开发板演示该模块如何工作。
什么是 ToF 激光测距传感器模块?
ToF 激光测距传感器模块是一种使用激光脉冲来测量自身与目标物体之间距离的模块。WisBlock RAK12014 ToF 激光测距传感器模块基于意法半导体 ST VL53L0X 而设计。VL53L0X 采用目前市场上最小的封装,可谓世界上最小的 ToF 测距传感器。
WisBlock RAK12014 能提供精确的距离测量,可测量 2 米的绝对距离。其 940nm VCSEL 发射器(垂直腔面发射激光器)完全不为人眼所见,再加上内置的物理红外滤光片,使其测距距离更长、对环境光的抗干扰性更强、对盖片的光学串扰具有更好的稳定性。换言之,无论目标反射率如何,该传感器都能提供精确的距离测量。上述特点使之能胜任高精度的测距任务,适用于更多应用场景中。
RAK12014 是模块化的硬件开发平台 WisBlock 的一款传感器模块
RAK12014 模块规格与特性:
- 测量绝对距离可达 2 m
- 用于器件控制和数据传输的I2C接口
- Xshutdown(复位)和中断 GPIO
- 电源 2.6~3.5 V
- 尺寸10 x 10 mm
RAK12014 模块包含一个兼容 WisBlock 基板传感器插槽的 24 引脚连接器。通过该连接器可以将 RAK12014 模块安装在 WisBlock 基板(如RAK5005-O)模块上。该连接器的引脚顺序以及引脚定义如下图所示。
RAK12014 的引脚分布
注意:仅 I2C 相关引脚、XSHUT(复位)、INT、3V3_S 以及 GND 连接到了该模块的连接器上。
RAK12014 典型示例:在 OLED 显示屏上显示测试距离
RAK12014 有一个很典型的应用,能够很形象地给我们展示 ToF 激光测距传感器模块的特性,即“在 OLED 显示屏上显示出测试的距离”。
在这个例子中,将 RAK12014 连接到 RAK 5005-O 基板上,通过核心模块 RAK4631 驱动它的测量距离功能,并将其测量到的距离信息在 OLED 显示屏上显示。
让 RAK12014 实现“在 OLED 显示屏上显示出测试的距离”应用所需的产品配置
- RAK12014
- RAK4631
- RAK5005-O
- RAK1921 OLED显示屏
- 跳线
- 电源线
- 原理图
以下是实现这一应用的具体步骤:
1、安装 OLED库
要控制 OLED 显示屏,需要使用到“U8g2”库。
2、安装 ToF 激光测距传感器库
要控制 ToF 激光测距传感器模块,需要使用“stm32duino_vl53l0x”库。
注意:所有的库安装完成之后需要重启 Arduino IDE,才能使安装的库生效。
3、导入代码
接着将代码导入 OLED 显示屏和 ToF 激光测距传感器模块所需的库当中,然后定义两个名为“u8g2”和“sensor_vl53l0”的对象。
#include #include // Click to install library: http://librarymanager/All#stm32duino_vl53l0x #include // Click to install library: http://librarymanager/All#u8g2 U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0); VL53L0X sensor_vl53l0x(&Wire, WB_IO2);
4、GetDistance()函数
在 GetDistance() 中,定义一个 report 数据。当有数据的时候打印出当前读到的数据测量值,当没有数据时打印如下所示内容:
void GetDistance(){ int status; char report[64]; uint32_t distance; u8g2.clearBuffer(); // clear the internal memory u8g2.setFont(u8g2_font_ncenB10_tr); // choose a suitable font // Read Range. status = sensor_vl53l0x.GetDistance(&distance); if (status == VL53L0X_ERROR_NONE) { // Output data. snprintf(report, sizeof(report), "Range: %ld mm", distance); } else { snprintf(report, sizeof(report), "Nothing at all", distance); } Serial.println(report); u8g2.drawStr(15, 30, report); u8g2.sendBuffer(); }
5、setup()函数
在 setup() 中,ToF 激光测距传感器和 OLED 显示器都会被初始化。在串口监视器上打印一条消息,这样就能知道 ToF 激光测距传感器是否成功找到了。如下所示:
void setup() { int status; pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); pinMode(WB_IO2, OUTPUT); digitalWrite(WB_IO2, HIGH); // Initialize Serial for debug output Serial.begin(115200); time_t serial_timeout = millis(); // On nRF52840 the USB serial is not available immediately while (!Serial) { if ((millis() - serial_timeout) < 5000) { delay(100); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } else { break; } } u8g2.begin(); // Initialize I2C bus. Wire.begin(); // Configure VL53L0X component. sensor_vl53l0x.begin(); // Switch off VL53L0X component. sensor_vl53l0x.VL53L0X_Off(); // Initialize VL53L0X component. status = sensor_vl53l0x.InitSensor(0x52); if(status) { Serial.println("Init sensor_vl53l0x failed..."); } }
6、loop()函数
在 loop() 中,代码在 OLED 显示屏上显示了主屏幕,而这其实是在 GetDistance() 函数中完成的。
void loop() { uint32_t distance; int status; GetDistance(); delay(300); }
7、代码上传
完成前面的代码撰写之后,选择所使用的开发板 RAK4631,选择正确的端口之后开始代码上传烧录,然后打开 Arduino IDE 的串口监视器。选择 115200 的波特率,我们就可以看见 ToF 激光测距传感器模块的测距数据:
8、演示程序
完成以上操作后,一旦 ToF 激光测距传感器上方有物体,OLED 显示屏就会显示当前物体与传感器的距离;当传感器上方没有物体时,OLED 显示屏则会显示当前无物体,点击链接查看视频展示了详细的演示过程。
总结
ToF 激光测距传感器模块可以应用的范围很广泛,它可以根据场景的不同调整距离。另外,所有来自传感器的信息都可以直接上传到云上,便于实时调整。本文主要向大家展示了如何使用 ToF 激光测距传感器模块测量物体离传感器的距离。今后再向大家介绍该模块在我们生活中的更多实际应用。
备注:以下是本次用例的完整代码,仅大家参考:
/** @file RAK12014_Distance_Detection.ino @author rakwireless.com @brief Distance detection by laser @version 0.1 @date 2021-8-28 @copyright Copyright (c) 2020 **/ #include #include // Click to install library: http://librarymanager/All#stm32duino_vl53l0x #include // Click to install library: http://librarymanager/All#u8g2 U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0); VL53L0X sensor_vl53l0x(&Wire, WB_IO2); void GetDistance(){ int status; char report[64]; uint32_t distance; u8g2.clearBuffer(); // clear the internal memory u8g2.setFont(u8g2_font_ncenB10_tr); // choose a suitable font // Read Range. status = sensor_vl53l0x.GetDistance(&distance); if (status == VL53L0X_ERROR_NONE) { // Output data. snprintf(report, sizeof(report), "Range: %ld mm", distance); } else { snprintf(report, sizeof(report), "Nothing at all", distance); } Serial.println(report); u8g2.drawStr(15, 30, report); u8g2.sendBuffer(); } void setup() { int status; pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); pinMode(WB_IO2, OUTPUT); digitalWrite(WB_IO2, HIGH); // Initialize Serial for debug output Serial.begin(115200); time_t serial_timeout = millis(); // On nRF52840 the USB serial is not available immediately while (!Serial) { if ((millis() - serial_timeout) < 5000) { delay(100); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } else { break; } } u8g2.begin(); // Initialize I2C bus. Wire.begin(); // Configure VL53L0X component. sensor_vl53l0x.begin(); // Switch off VL53L0X component. sensor_vl53l0x.VL53L0X_Off(); // Initialize VL53L0X component. status = sensor_vl53l0x.InitSensor(0x52); if(status) { Serial.println("Init sensor_vl53l0x failed..."); } } void loop() { uint32_t distance; int status; GetDistance(); delay(300); }