exs_vl53l1x 扩展库
作者:江访 | 最后修改:2026-08-06
一、概述
exs_vl53l1x 是基于 ST(意法半导体) 出品的 VL53L1X ToF 激光测距传感器开发的 LuatOS 扩展库。 VL53L1X 采用940nm不可见的1类激光发射器(对人眼安全),通过测量光子飞行时间实现绝对距离测量。
1.1 主要特性
-
测距范围:最近 4cm,最远可达 4m(标称值,理想条件),典型可靠测距约 3.6m(暗室,Long 模式,90% 反射率目标)
-
供电:2.8V 单电源(AVDD 和 AVDDVCSEL)
-
输出单位:毫米(mm)
-
接口:I2C,7 位固定地址 0x29
-
支持三种测距模式:short(约 1.36m,抗强光)、standard(约 2.9m,默认)、long(约 3.6m)
-
软件 I2C / 硬件 I2C 均可
-
内置 I2C 总线卡死自动检测与恢复
-
支持软件待机睡眠与唤醒
-
支持串扰校准(用于带保护玻璃的模组)
-
支持 GPIO1 中断(数据就绪通知,响应更快)
1.2 注意事项
-
推荐适用软件 I2C 模式(
{scl=xx, sda=yy}):VL53L1X 在异常通信后可能锁死 SDA 总线,软件 I2C 可通过 GPIO 脉冲 SCL 恢复 -
硬件 I2C + scl/sda 也支持自动恢复:同时传
i2c_id和scl/sda时,总线卡死后会将引脚临时切为 GPIO 进行脉冲恢复, 再重新初始化硬件 I2C 外设。仅传i2c_id不传scl/sda时不具自动恢复能力 -
初始化后自动启动测距,无需额外调用 start 方法
-
每次读取测距数据时自动跳过无效帧(如刚启动、刚唤醒时的第一帧)
-
最低工作距离 4cm,低于此值距离值不准
-
SCL/SDA 需外接 4.7kΩ~10kΩ 上拉电阻
1.3 测距模式说明
| 模式 | 暗室最远 | 强光下最远 | 特点 |
|---|---|---|---|
| short | 约 1.36m | 约 1.35m | 抗环境光干扰最强 |
| standard(默认) | 约 2.9m | 约 0.76m | 一般场景均衡模式 |
| long | 约 3.6m | 约 0.73m | 远距离,暗光环境 |
1.4 GPIO1 中断说明
GPIO1 是 VL53L1X 的中断输出引脚,每次测距完成时自动输出一个低电平脉冲(约 10μs),通知主机有新数据就绪。
中断触发方式:
-
GPIO1 默认配置为下降沿触发(ACTIVE_LOW),测距完成后引脚被拉低
-
每次调用
get_data()后,库会自动清除中断(写寄存器 0x0086=0x01),释放 GPIO1 -
未使用 GPIO1 时,库通过 I2C 轮询内部寄存器判断数据是否就绪,速度稍慢但不影响功能
中断频率:
-
每次测距完成触发一次中断,频率取决于测距模式的测量周期
-
Standard Ranging 模式下连续测距,每次完成一帧立即触发下一次,约每秒 30~50 帧
-
中断频率 = 1 /(实际测量时间)
使用方式:
-
通过
setup({int1 = {int_gpio = 引脚号}})注册中断引脚 -
有
cb回调时:每帧测距完成自动调用回调函数(适合低频场景,如 1~10 帧/秒) -
无
cb回调时:通过get_int_flag()轮询中断标志(适合高频场景,如 30+ 帧/秒,比回调更可靠)
1.5 中断事件类型说明
通过 setup() 的 config.int1 参数配置中断事件。详情见 setup 参数说明。
| 中断事件 | 触发时机 | 推荐用途 |
|---|---|---|
data_ready(int1.cb) |
每次测距完成时触发。30~50 帧/秒高频场景不建议用 cb 回调,改用 get_int_flag() 轮询 |
实时数据采集 |
1.6 中断回调与 get_data() 返回数据说明
通过 setup() 的 config.int1.cb 收到的 data 参数与 get_data() 返回的数据结构完全一致,包含以下字段:
data.distance -- 测距距离,单位 mm,取值范围 4~4000
data.status -- 测距状态码,0 表示数据可靠
-- 0 = 测距成功
-- 1 = Sigma 失效
-- 2 = 信号失效
-- 3 = 目标距离小于最小值
-- 4 = 相位超出范围
-- 5 = 硬件故障
-- 6 = 测距成功(未绕行检查)
-- 7 = 相位绕行
-- 8 = 处理失败
-- 9 = 串扰信号
-- 10 = 同步中断
-- 11 = 合并脉冲
-- 12 = 信号弱
-- 13 = 最小距离失败
-- 14 = 范围无效
data.status_str -- 测距状态中文描述,如 "测距成功"
data.stream_count -- 帧计数,0~255 循环,stream=0 的帧为无效帧
注意:
- 回调中 data 的结构与 get_data() 返回值完全一致,可以共用同一处理函数。
- 使用 cb 回调时,get_int_flag() 仍能读到中断标志(冗余信息),但实际不需要。
1.7 芯片功耗参考
| 模式 | 功耗 | 说明 |
|---|---|---|
| 软件待机(sleep) | 约 6μA | 调用 sleep() 后进入 |
| 连续测距 | 约 20mW | 正常测距时(按10Hz频率,每33ms完成一次测量计算) |
| 激光发射峰值 | 40mA | VCSEL 点亮的瞬间 |
1.8 接线方式

┌──────────────┐ ┌──────────────────┐
│ 主控 │ │ VL53L1X │
│ │ │ │
│ GPIO_SCL ────┼──────┼──→ SCL │
│ GPIO_SDA ────┼──────┼──→ SDA │
│ GPIO_INT ────┼──────┼──→ GPIO1 (可选) │
│ GPIO_RST ────┼──────┼──→ XSHUT (可选) │
│ VCC 3.3V ────┼──────┼──→ VIN │
│ GND ────┼──────┼──→ GND │
└──────────────┘ └──────────────────┘
GPIO1(中断输出引脚):不接不影响测距功能。接上后可用中断通知代替 I2C 轮询,响应更快、省 I2C 总线。详见 1.4 节。
XSHUT(硬件复位引脚,低电平有效):不接时传感器上电自动启动。接上后 setup({xshut = pin}) 使用硬件复位(拉低再拉高),比软复位更彻底。
如果遇到初始化不稳定、I2C 通信异常,建议接上这个引脚。
1.9 加载方式
-- 加载扩展库
local exs_vl53l1x = require "exs_vl53l1x"
二、核心示例
2.1 标准测距
展示最基础的初始化、读取数据和关闭流程。
-- 加载扩展库
local exs_vl53l1x = require "exs_vl53l1x"
-- 主任务
local function demo()
-- 初始化(软件 I2C:SCL=GPIO31, SDA=GPIO30)
local result = exs_vl53l1x.setup({scl = 31, sda = 30})
if not result then
log.error("初始化失败,请检查接线")
return
end
log.info("exs_vl53l1x", "版本:", exs_vl53l1x.version())
sys.wait(200) -- 等待第一帧稳定
for i = 1, 5 do
local data = exs_vl53l1x.get_data()
if data then
log.info(string.format("距离:%dmm 状态=%s", data.distance, data.status_str))
end
sys.wait(500) -- 每 500ms 读一次
end
exs_vl53l1x.close() -- 关闭传感器
end
sys.taskInit(demo)
2.2 测距模式切换示例
展示三种测距模式的用法。
-- 加载扩展库
local exs_vl53l1x = require "exs_vl53l1x"
local function demo()
-- short 模式(抗强光,约 1.36m)
local ok = exs_vl53l1x.setup({scl = 31, sda = 30, range_mode = "short"})
if not ok then return end
sys.wait(200) -- 等待第一帧稳定
log.info("距离:", exs_vl53l1x.get_data().distance, "mm (short)")
-- 切换 long 模式(远距离,约 3.6m)
exs_vl53l1x.close()
ok = exs_vl53l1x.setup({scl = 31, sda = 30, range_mode = "long"})
if not ok then return end
sys.wait(200) -- 等待第一帧稳定
log.info("距离:", exs_vl53l1x.get_data().distance, "mm (long)")
end
sys.taskInit(demo)
2.3 中断回调读取
适合需要及时响应测距结果的场景,省去 I2C 轮询,响应更快。data_cb 收到的 data 结构说明详见 1.5 节。
-- 加载扩展库
local exs_vl53l1x = require "exs_vl53l1x"
-- 中断回调函数,每帧测距完成后自动触发
-- data 结构见 1.5 节:{ distance, status, status_str, stream_count }
local function data_cb(data)
log.info(string.format("距离:%dmm 状态=%s", data.distance, data.status_str))
end
local function demo()
local result = exs_vl53l1x.setup({
scl = 31, sda = 30,
int1 = {int_gpio = 10, cb = data_cb}, -- GPIO1 接 GPIO10,注册回调
})
if not result then return end
-- 回调自动处理数据,主线程可做其他事
end
sys.taskInit(demo)
也可以不传 cb,通过 get_int_flag() 轮询(适合高频场景):
-- 轮询任务
local function poll_task()
while true do
if exs_vl53l1x.get_int_flag() then -- 检查中断标志
local data = exs_vl53l1x.get_data()
if data then
log.info(string.format("距离:%dmm 状态=%s", data.distance, data.status_str))
end
end
sys.wait(1) -- 每 1ms 轮询一次中断标志
end
end
sys.taskInit(poll_task)
-- 注册中断(不传 cb,只设引脚)
exs_vl53l1x.setup({scl = 31, sda = 30, int1 = {int_gpio = 10}})
2.4 休眠与唤醒
适合间歇性采样的场景,不需要时休眠省电。
exs_vl53l1x.sleep() -- 休眠(约 6μA),自动停止测距
sys.wait(5000) -- 等待 5 秒后唤醒
exs_vl53l1x.wakeup() -- 唤醒,自动恢复测距
sys.wait(200) -- 等待第一帧稳定
local data = exs_vl53l1x.get_data()
2.5 串扰校准
如果传感器装了保护玻璃或外壳,激光会在玻璃表面反射产生串扰,导致远距离测不准或信号弱。校准可以补偿这个误差。
校准前:在传感器正前方 400mm 处放一张纯白纸板。
-- 加载扩展库
local exs_vl53l1x = require "exs_vl53l1x"
local function calibration()
-- 执行串扰校准
local xtalk = exs_vl53l1x.calibrate_xtalk({
scl = 31, sda = 30,
target_distance_mm = 400, -- 目标距离
samples = 50, -- 采样帧数
})
if not xtalk then return end
log.info("校准完成,xtalk=" .. xtalk)
-- 用校准值初始化(校准值掉电丢失,需在代码中保存)
exs_vl53l1x.setup({scl = 31, sda = 30, xtalk_offset = xtalk})
end
sys.taskInit(calibration)
保存校准值:校准值掉电会丢失,需在代码中保存并在下次开机时传入。
-- 方案一:直接在代码中写死(适合量产时固定值)
local XTALK_FIXED = 45 -- calibrate_xtalk 返回的值
-- 方案二:写入可写文件系统(如 /lfs/)
io.writeFile("/lfs/xtalk.txt", tostring(xtalk))
local xtalk = tonumber(io.readFile("/lfs/xtalk.txt")) or 0
-- 使用时
exs_vl53l1x.setup({scl = 31, sda = 30, xtalk_offset = xtalk})
三、常量解释
扩展库常量,顾名思义是由合宙 LuatOS 扩展库中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用,本扩展库没有常量。
四、函数详解
4.1 exs_vl53l1x.setup(config)
功能
初始化传感器并启动测距。
参数
config
参数含义:初始化配置表
数据类型:table
取值范围:
{
参数含义:SCL 时钟引脚 GPIO 编号
数据类型:number
取值范围:有效的 GPIO 编号
是否必选:可选
注意事项:
- 单独传 scl+sda(不传 i2c_id)→ 软件 I2C,总线自动恢复(推荐)
- 与 i2c_id 同时传 → 硬件 I2C + 总线自动恢复(scl/sda 用于脉冲恢复后重初始化硬件 I2C 外设)
- 仅传 i2c_id 不传 scl/sda → 纯硬件 I2C,不具总线自动恢复能力
参数示例:31
config.scl ,
参数含义:SDA 数据引脚 GPIO 编号
数据类型:number
取值范围:有效的 GPIO 编号
是否必选:可选,与 scl 配合使用
注意事项:I2C 模式下该引脚需外接 4.7kΩ~10kΩ 上拉电阻到 VCC
参数示例:30
config.sda ,
参数含义:硬件 I2C 总线 ID
数据类型:number
取值范围:有效的 I2C 总线编号
是否必选:可选
注意事项:
- 默认 0
- 仅传 i2c_id(不传 scl/sda)→ 纯硬件 I2C,不具恢复能力
- 同时传 i2c_id 和 scl/sda → 硬件 I2C + 总线自动恢复(scl/sda 用于脉冲恢复)
参数示例:0
config.i2c_id ,
参数含义:XSHUT 复位引脚 GPIO 编号
数据类型:number
取值范围:有效的 GPIO 编号
是否必选:可选
注意事项:传此参数时使用 XSHUT 硬件复位(拉低再拉高),比软复位更彻底。不传时使用软件复位
参数示例:32
config.xshut ,
参数含义:测距模式
数据类型:string
取值范围:"standard"(默认,约 2.9m)、"short"(约 1.36m,抗强光)、"long"(约 3.6m,远距离)
是否必选:可选
注意事项:short 模式在强光下表现最好;long 模式在强光下最远距离约 0.73m,建议室内或弱光使用
参数示例:"short"
config.range_mode ,
参数含义:串扰校准偏移值
数据类型:number
取值范围:0~65535,由 calibrate_xtalk() 返回
是否必选:可选
注意事项:传入后自动写入串扰补偿寄存器。校准值掉电丢失,需在代码中保存
参数示例:45
config.xtalk_offset ,
参数含义:GPIO1 中断配置
数据类型:table
是否必选:可选
注意事项:格式为 {int_gpio = 引脚号, cb = 回调函数}。int_gpio 是 GPIO1 接的引脚,
cb 是每次测距完成后的回调函数。cb 在 GPIO 中断中触发,频率约 30~50 次/秒,
高频场景建议不传 cb,改用 get_int_flag() 轮询
参数示例:{int_gpio = 10, cb = data_cb}
config.int1 ,
}
是否必选:是
参数示例:
-- 软件 I2C,默认模式(推荐:总线自动恢复)
exs_vl53l1x.setup({scl = 31, sda = 30})
-- 硬件 I2C + scl/sda(支持总线自动恢复)
exs_vl53l1x.setup({i2c_id = 0, scl = 31, sda = 30})
-- 纯硬件 I2C(不具自动恢复能力,需用户自己处理总线卡死)
exs_vl53l1x.setup({i2c_id = 0})
-- 远距离模式 + 串扰校准
exs_vl53l1x.setup({scl = 31, sda = 30, range_mode = "long", xtalk_offset = 45})
-- 注册 GPIO1 中断回调
exs_vl53l1x.setup({scl = 31, sda = 30, int1 = {int_gpio = 10, cb = data_cb}})
返回值
local result = exs_vl53l1x.setup(config)
result
含义说明:初始化是否成功
数据类型:boolean
取值范围:true(成功),false(失败)
注意事项:失败时请检查接线、供电和 I2C 通信
返回示例:true
示例
-- 软件 I2C,默认 standard 模式(推荐:总线自动恢复)
local result = exs_vl53l1x.setup({scl = 31, sda = 30})
if not result then return end
-- 硬件 I2C + scl/sda(总线自动恢复)
local result = exs_vl53l1x.setup({i2c_id = 0, scl = 31, sda = 30})
if not result then return end
-- 纯硬件 I2C(不具自动恢复能力,请确保 I2C 总线可靠)
local result = exs_vl53l1x.setup({i2c_id = 0})
if not result then return end
-- 短距离模式(抗强光)
local result = exs_vl53l1x.setup({scl = 31, sda = 30, range_mode = "short"})
if not result then return end
-- 远距离模式 + XSHUT 硬件复位
local result = exs_vl53l1x.setup({scl = 31, sda = 30, range_mode = "long", xshut = 32})
if not result then return end
-- 串扰校准值 + GPIO1 中断回调
local result = exs_vl53l1x.setup({scl = 31, sda = 30, xtalk_offset = 45, int1 = {int_gpio = 10, cb = data_cb}})
if not result then return end
4.2 exs_vl53l1x.get_data()
功能
读取一帧测距数据。等待数据就绪后读取,自动跳过无效帧(首次启动/唤醒后的第一帧),读取后自动触发下一次测量。
参数
无
返回值
local data = exs_vl53l1x.get_data()
data
含义说明:测距数据表,失败返回 nil
数据类型:table 或 nil
取值范围:返回table 包含以下值
{
参数含义:测距距离
数据类型:number
取值范围:4~4000,单位 mm
注意事项:低于 4cm 时值不准确
返回示例:235
data.distance ,
参数含义:测距状态码,0 表示数据可靠
数据类型:number
取值范围:0(测距成功)、1(Sigma 失效)、2(信号失效)、3(目标太近)、
4(相位超出范围)、5(硬件故障)、6(测距成功但未绕行检查)、
7(相位绕行)、8(处理失败)、9(串扰信号)、10(同步中断)、
11(合并脉冲)、12(信号弱)、13(最小距离失败)、14(范围无效)
注意事项:status=0 为测距成功,数据可靠
返回示例:0
data.status ,
参数含义:测距状态描述
数据类型:string
取值范围:对应 status 的中文描述
返回示例:"测距成功"
data.status_str ,
参数含义:帧计数
数据类型:number
取值范围:每次测距递增,0~255 循环
注意事项:stream=0 的帧为无效帧,会自动跳过
返回示例:15
data.stream_count ,
}
返回示例:{distance = 235, status = 0, status_str = "测距成功", stream_count = 15}
示例
-- 读取测距数据
local data = exs_vl53l1x.get_data()
if data and data.status == 0 then -- 只使用有效数据
log.info("距离:", data.distance, "mm")
end
4.3 exs_vl53l1x.get_int_flag()
功能
查询 GPIO1 中断触发标志,查询后自动清除。适合不传 cb 时轮询用。
参数
无
返回值
local flag = exs_vl53l1x.get_int_flag()
flag
含义说明:是否触发中断
数据类型:boolean
取值范围:true(有中断),false(无中断)
注意事项:查询后自动清除标志
返回示例:true
示例
-- 轮询任务
local function poll_task()
while true do
if exs_vl53l1x.get_int_flag() then -- 检查是否有新数据
local data = exs_vl53l1x.get_data()
if data then
log.info(string.format("距离:%dmm 状态=%s", data.distance, data.status_str))
end
end
sys.wait(1) -- 每 1ms 轮询一次中断标志
end
end
sys.taskInit(poll_task)
-- 注册中断引脚(不传 cb)
exs_vl53l1x.setup({scl = 31, sda = 30, int1 = {int_gpio = 10}})
4.4 exs_vl53l1x.sleep()
功能
进入软件待机,功耗约 6μA(芯片标称6μA,测试传感器功耗约320μA)。调用后自动停止测距,保持现有配置。
参数
无
返回值
无
示例
-- 休眠(自动停止测距)
exs_vl53l1x.sleep()
4.5 exs_vl53l1x.wakeup()
功能
从软件待机唤醒,自动恢复测距。与 sleep() 配对使用。
参数
无
返回值
local ok = exs_vl53l1x.wakeup()
ok
含义说明:唤醒是否成功
数据类型:boolean
取值范围:true(成功),false(失败,未执行 setup 时返回 false)
返回示例:true
示例
-- 唤醒
local ok = exs_vl53l1x.wakeup()
if ok then
sys.wait(200) -- 等待第一帧稳定
local data = exs_vl53l1x.get_data()
end
4.6 exs_vl53l1x.close()
功能
关闭传感器。停止测距并清空内部状态,再次使用前需要重新 setup。
参数
无
返回值
无
示例
-- 关闭传感器
exs_vl53l1x.close()
4.7 exs_vl53l1x.calibrate_xtalk(config)
功能
执行串扰校准。当传感器加了保护玻璃或外壳时,激光在玻璃表面反射会产生串扰信号,导致远距离测距不准。校准后数据更准确。
什么时候需要做:
-
传感器装在带玻璃面板的外壳内
-
更换了不同厚度的保护玻璃
-
测量距离不准确或经常报信号失效
校准前准备:
- 在传感器正前方 400mm 处放一张纯白纸板,环境光不要太强。校准过程约 2~4 秒。
参数
config
参数含义:校准配置表
数据类型:table
取值范围:
{
参数含义:SCL 时钟引脚 GPIO 编号
数据类型:number
取值范围:有效的 GPIO 编号
是否必选:推荐传入(用于总线恢复)
参数示例:31
config.scl ,
参数含义:SDA 数据引脚 GPIO 编号
数据类型:number
取值范围:有效的 GPIO 编号
是否必选:推荐传入
参数示例:30
config.sda ,
参数含义:硬件 I2C 总线 ID
数据类型:number
取值范围:有效的 I2C 总线编号
是否必选:可选,不传 scl/sda 时使用
参数示例:0
config.i2c_id ,
参数含义:目标距离(传感器到校准平面的距离)
数据类型:number
取值范围:100~1000,单位 mm
是否必选:否
注意事项:默认 400,建议与官方校准距离一致
参数示例:400
config.target_distance_mm ,
参数含义:采样帧数
数据类型:number
取值范围:10~200
是否必选:否
注意事项:默认 50。帧数越大越稳定,但校准时间越长(约 2~5 秒/50 帧)
参数示例:100
config.samples ,
}
是否必选:是
参数示例:
exs_vl53l1x.calibrate_xtalk({scl = 31, sda = 30})
返回值
local xtalk = exs_vl53l1x.calibrate_xtalk(config)
xtalk
含义说明:串扰偏移值
数据类型:number 或 nil
取值范围:0~65535
注意事项:有效采样帧数不足 10 帧时返回 nil。返回值可直接传给 setup({xtalk_offset = xtalk})
返回示例:45
示例
-- 执行串扰校准
local xtalk = exs_vl53l1x.calibrate_xtalk({scl = 31, sda = 30})
if xtalk then
log.info("校准完成, xtalk=" .. xtalk)
-- 用校准值重新初始化
exs_vl53l1x.setup({scl = 31, sda = 30, xtalk_offset = xtalk})
end
4.8 exs_vl53l1x.version()
功能
获取库版本号。
参数
无
返回值
local ver = exs_vl53l1x.version()
ver
含义说明:版本号字符串
数据类型:string
取值范围:格式 "yyyymmddhhmm",表示 yyyy年mm月dd日hh时mm分发布的版本
返回示例:"202607201200"
示例
-- 获取版本号
local ver = exs_vl53l1x.version()
log.info("exs_vl53l1x", "版本:", ver)
五、版本更新说明
版本号:202607211200
-
更新时间:2026-07-21
-
更新内容:
-
支持软件 I2C、硬件 I2C 初始化
-
支持标准测距、三档模式切换(standard/short/long)
-
支持 I2C 总线卡死自动检测与恢复
-
支持睡眠/唤醒/关闭,支持低功耗待机
-
六、产品支持说明
所有支持 luatos 二次开发的模块,具体可以查看选型手册。