VL53L1X ToF避障怎么接:4米量程与改地址

2026-11-01 14:27:33 32阅读

给小车、底盘或者云台加避障,很多人的第一反应是超声波模块,其次是指红外对管。这两样便宜,但各有各的老毛病:超声波的波束角宽,测的是一整片锥形区域里最近的东西,障碍物斜着进锥就容易误判;红外对管靠反射光强反推距离,目标颜色一深一浅,读数立刻飘。VL53L1X 走的是另一条路:芯片自己打出 940nm 的不可见激光,数一数光子飞出去再弹回来花了多长时间,直接换算成毫米。Pololu 产品页对它的形容是“一颗自成一体的微型激光雷达”,环境光、目标颜色和纹理不改变测量原理,只会影响它能打到的最远距离。

VL53L1X ToF 测距传感器载板实拍

先看清这颗芯片的底细

VL53L1X 是 ST 的单芯片测距方案,正式料号是 VL53L1CXV0FY/1,社区里都习惯叫它 VL53L1X。发射端是 940nm 的 Class 1 不可见 VCSEL 激光(人眼安全等级),接收端是 16×16 的 SPAD 单光子雪崩二极管阵列加集成镜头,典型视场角 27 度。距离读数走 I2C 总线输出,16 位、单位毫米,总线时钟可以跑到 fast mode 的 400kHz。

买之前先看同家族的横向对比,Pololu 给的这组数字很说明问题:

型号最大量程最小量程视场角
VL6180X60cm约10mm25度
VL53L0X200cm约30mm25度
VL53L1X400cm40mm15到27度,可编程
VL53L3CX500cm10mm25度,支持多目标

做机器人避障,VL53L1X 的 4 米量程和可编程视场角是它区别于前辈 VL53L0X 的核心卖点;如果只做近距离的小型桌面设备,60cm 的 VL6180X 反而更便宜更够用。本文以 VL53L1X 为主,用 Pololu 的载板加官方 Arduino 库把流程走通。

量程怎么选:三种距离模式与时间预算

VL53L1X 有三档距离模式,这是调优的第一抓手:

  • Short 短距模式:最多约 130cm,最高 50Hz 采样,对环境光干扰最不敏感;
  • Medium 中距模式:暗环境下最多约 300cm,最高 30Hz;
  • Long 长距模式:暗环境下最多 400cm,最高 30Hz,但最大量程受环境光影响明显。

还有一个新手最容易忽略的约束:最小测距距离 4cm。目标贴得比 4cm 更近时传感器仍会报“有东西”,但数值本身不可信。装在小车正前方时,别把传感器怼到保险杠边上。

量程之外,真正决定读数稳不稳的是测量时间预算(timing budget)。数据手册里那张 Figure 6 曲线给得很直白:反射率 54% 的灰靶、暗环境,33ms 预算下最大只能打到 310cm,重复性标准差 5mm;把预算加到 140ms 就能摸到 400cm,标准差降到 3.5mm;200ms 进一步降到 2.5mm。Pololu 库里对应的函数是 setMeasurementTimingBudget,单位微秒,Short 模式下限 20ms,Medium 和 Long 模式下限 33ms。读数跳,先想想是不是预算给太抠了。

VL53L1X 数据手册曲线:最大距离与重复性误差随时间预算变化

接线:七个脚,其实只接四根

VL53L1X 载板引脚图:VDD VIN GND SDA SCL XSHUT GPIO1

载板一共七个引脚:

引脚作用
VIN主供电,2.8V 到 5.5V,板载稳压器降到 2.8V 给芯片
GND地,必须与主控共地
SDA / SCLI2C 数据与时钟,板上带电平位移,高电平跟随 VIN
VDD稳压后的 2.8V 输出,能带约 100mA 外设;想绕过稳压,也可以直接给它喂 2.6V 到 3.5V(VIN 悬空)
XSHUT低电平有效的关断输入,板上默认上拉到 VDD,拉低进硬件待机
GPIO1可编程中断输出,开漏,板上已上拉

单颗跑通只要四根线:VIN、GND、SDA、SCL。库的 README 给了两组标准接法——5V 板(Uno、Leonardo、Mega、A-Star 32U4)用 5V 接 VIN;3.3V 板(Due 等)用 3V3 接 VIN,其余同名相接。

两个细节值得专门提醒。第一,XSHUT 和 GPIO1 这两个脚不走电平位移,也不耐 5V:多数 3.3V 和 5V 主控“能用”,但官方页明确写了别把 XSHUT 主动推高,正确姿势是在“输出低”和“高阻输入”之间切换,后文的例程就是这么做的;拿不准就外接一颗四通道双向电平转换。第二,功耗按 20mA 典型值估,峰值可以到 40mA,电池小车要抠电的话,ST 还提供一套超低功耗 API(STSW-IMG032),部分场景能把待机检测电流压到 100 微安以内。

VL53L1X 载板插在面包板上

载板是 0.1 英寸标准间距,尺寸 13×18×2mm,不带排针重 0.5g,配两颗 0.5 英寸间距的 M2 安装孔,面包板和洞洞板都能直接插,随机附一排直插和一排弯插排针。

装库与跑通:从一颗到三颗是同一套代码

Arduino IDE 里开 Library Manager 搜 VL53L1X,装 Pololu 的这颗(写稿时最新 1.3.1,2022 年 2 月更新,这版专门加了多传感器例程);装不上就手动下 release 包,把目录改名为 VL53L1X 丢进 sketchbook 的 libraries 里,重启 IDE。库的常用函数就这几个:init() 完成初始化(默认 io_2v8=true,即 2.8V IO 模式);setDistanceMode 设 Short、Medium、Long 三档;setMeasurementTimingBudget 设时间预算;startContinuous(周期毫秒) 启动连续测距;read() 阻塞返回毫米读数,同时刷新 ranging_data,里面的 range_status 必须等于 VL53L1X::RangeValid 这条读数才算数;偶尔测一次用 readSingle()。

下面这份代码是官方库自带的 ContinuousMultipleSensors 例程,逐字符照搬,只做了一处平台兼容替换:站点编辑器会剥掉尖括号头文件,所以 #include 写成 #include "Wire.h",两种写法对库搜索路径在 Arduino 工具链下等价,编译结果一致。先看声明部分:

/*
This example shows how to set up and read multiple VL53L1X sensors connected to
the same I2C bus. Each sensor needs to have its XSHUT pin connected to a
different Arduino pin, and you should change sensorCount and the xshutPins array
below to match your setup.

For more information, see ST's application note AN4846 ("Using multiple VL53L0X
in a single design"). The principles described there apply to the VL53L1X as
well.
*/

#include "Wire.h"
#include "VL53L1X.h"

// The number of sensors in your system.
const uint8_t sensorCount = 3;

// The Arduino pin connected to the XSHUT pin of each sensor.
const uint8_t xshutPins[sensorCount] = { 4, 5, 6 };

VL53L1X sensors[sensorCount];

sensorCount 是传感器数量,xshutPins 是每个传感器 XSHUT 脚接的 Arduino 引脚,按 4、5、6 三个脚接三颗。只接一颗的话,把 sensorCount 改成 1、数组留一个脚就行,setup 里的循环逻辑完全不用动。再看 setup:

void setup()
{
  while (!Serial) {}
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(400000); // use 400 kHz I2C

  // Disable/reset all sensors by driving their XSHUT pins low.
  for (uint8_t i = 0; i < sensorCount; i++)
  {
    pinMode(xshutPins[i], OUTPUT);
    digitalWrite(xshutPins[i], LOW);
  }

  // Enable, initialize, and start each sensor, one by one.
  for (uint8_t i = 0; i < sensorCount; i++)
  {
    // Stop driving this sensor's XSHUT low. This should allow the carrier
    // board to pull it high. (We do NOT want to drive XSHUT high since it is
    // not level shifted.) Then wait a bit for the sensor to start up.
    pinMode(xshutPins[i], INPUT);
    delay(10);

    sensors[i].setTimeout(500);
    if (!sensors[i].init())
    {
      Serial.print("Failed to detect and initialize sensor ");
      Serial.println(i);
      while (1);
    }

    // Each sensor must have its address changed to a unique value other than
    // the default of 0x29 (except for the last one, which could be left at
    // the default). To make it simple, we'll just count up from 0x2A.
    sensors[i].setAddress(0x2A + i);

    sensors[i].startContinuous(50);
  }
}

loop 里就是挨个 read 并打印,超时用 timeoutOccurred() 兜底:

void loop()
{
  for (uint8_t i = 0; i < sensorCount; i++)
  {
    Serial.print(sensors[i].read());
    if (sensors[i].timeoutOccurred()) { Serial.print(" TIMEOUT"); }
    Serial.print('\t');
  }
  Serial.println();
}

VL53L1X 载板出厂自带的传感器保护膜需要撕掉

这里插一个官方页专门提醒的坑:载板出厂可能在传感器芯片上贴着一层保护膜,上电前必须撕掉,否则测距性能直接打折。别笑,真有人贴着膜调了一下午参数。

多颗同总线的关键:XSHUT 逐个唤醒、挨个改地址

VL53L1X 出厂的 7 位 I2C 地址是 0101001b,也就是 0x29,所有芯片都一样,直接把几颗并到一条总线上必然打架。地址可以写配置寄存器改掉,但复位或断电就丢回去,所以多颗方案的标准流程是靠 XSHUT 控制“谁醒着”:全部拉低复位,然后一次只放一颗出来,趁它独占总线时立刻 setAddress 改成新地址(例程从 0x2A 往上数,最后一颗可以留在默认 0x29),改完再放下一颗。ST 的应用笔记 AN4846(Using multiple VL53L0X in a single design)讲的正是这套思路,对 VL53L1X 同样适用。

例程里最容易被误解的一行是 pinMode(xshutPins[i], INPUT):因为 XSHUT 不做电平位移也不耐 5V,放行靠的是把主控脚切成高阻输入、让载板自己的上拉电阻把它拉高,而不是 digitalWrite(HIGH) 硬推。第一次接多颗总是莫名失败的话,先检查这一处。

另外,改地址只改了 RAM,断电即失。这意味着每次上电都要重跑一遍这套唤醒流程,例程把它放在 setup 里就是这个原因;别想着改一次存进芯片,它没有这个机制。

读数不对劲,先查这四处

  • 保护膜没撕:症状是距离一近就正常、一远就乱跳,先撕膜再排查别的;
  • 目标吸光或环境光太强:黑绒布、深色磨砂塑料会吞掉激光,大太阳底下 Long 模式打不满 4 米,换 Short 模式、加大时间预算,或者用 ranging_data 里的 ambient_count_rate_MCPS 看看环境光计数;
  • 状态位没看:range_status 不等于 RangeValid 的读数直接丢掉,库里还给 rangeStatusToString() 能把状态翻译成人话,AVR 上别调它(字符串存在 RAM 里,要吃 200 多字节);
  • 目标在 4cm 以内:会报有目标但数值不准,避障逻辑要把这一段单独处理。

进阶一点还有 ROI 可调:setROISize 最小 4×4、默认 16×16(即全部 256 个 SPAD),setROICenter 默认 199 居中。把视场收窄能挡掉旁边的干扰源,代价是灵敏度下降,做窄通道避障时很好用。要注意库没有提供加盖玻璃后的校准功能,给传感器罩壳开孔的尺寸和距离自己留余量。

写在最后

整套下来,VL53L1X 的上手成本其实很低:四根线、一个库、一套固定的多传感器流程,剩下的功夫都在模式与时间预算的取舍上。它不是超声那种“插上就能糊弄”的器件,但只要按数据手册的曲线给足预算、老老实实看状态位,4 米量程加毫米级分辨率的稳定性,是红外和超声给不了的。做轮式机器人避障、机械臂防撞、跟随小车的前向测距,这颗都值得进你的常用件清单。


作者:固件烧录仔
链接:https://www.aiddithome.com/p/165484e2718012.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
4条评论
参数党小马
1楼 · 2026-11-01 14:33:24

时间预算这块写到位了。我最早拿它做前向避障就吃过大亏:Long 模式配 33ms 预算,白天车间窗边一晒,3 米开外读数直接掉一半,还以为是模块坏了。后来照着数据手册那条曲线把预算加到 140ms,配合 Short 模式在 1.3 米内用,稳得完全不像同一个传感器。补充一个实测细节:ambient_count_rate_MCPS 这个值能当环境光指示器用,超过 1.0 左右就该考虑降模式或者加遮光罩了,比等读数跳了再排查省事得多。

调参到凌晨
2楼 · 2026-11-01 14:33:24

XSHUT 别推高那条是真坑,我第一块板就是这么烧的 IO,血泪换来的经验。

线比代码多
3楼 · 2026-11-01 14:33:24

多颗改地址这套流程我照官方例程接过三颗,一次点亮,例程写得确实扎实。

入门没多久的新手
4楼 · 2026-11-01 14:33:24

请问这套代码直接搬到 ESP32 上能用吗?引脚是不是换成任意 GPIO 就行?