Files
BR_YKC/4G/tools/resource/soc_script/v2025.12.31.22/lib/exvib1.lua
2026-03-31 15:46:04 +08:00

212 lines
6.9 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--[[
@summary exvib1扩展库
@version 1.0
@date 2025.09.07
@author 孟伟
@usage
-- 应用场景
此库适用于滚珠震动传感器BL_2529,主要目的是对振动中断进行过滤,识别有效震动
对于一些震动传感器的中断管脚算法处理,也可以用做参考。
实现的功能:
1. GPIO 中断检测:通过 GPIO 引脚检测震动传感器产生的脉冲信号
2. 双重消抖机制:
- io中断消抖 gpio.debounce()
3. 时间窗口检测:在指定时间窗口(time_window)内统计脉冲数量
4. 阈值触发:当脉冲数超过设定阈值(pulse_threshold)时触发回调
5. 脉冲超时机制在检测状态下如果超过pulse_timeout时间没有新的脉冲则提前结束当前检测周期并判断是否触发回调
状态机工作流程:
- IDLE状态等待第一个有效脉冲
- DETECTING状态进入检测窗口统计脉冲数量
- 触发条件:
时间窗口结束
脉冲空闲时间超过设定超时
- 结果判断:脉冲数≥阈值则调用用户回调
-- 用法实例
本扩展库对外提供了以下2个接口
1启动震动检测功能 exvib1.open(opts)
2停止震动检测功能 exvib1.close()
--加载exvib1扩展库
local exvib1= require "exvib1"
-- 震动事件回调
local function vibration_cb(pulse_cnt)
log.info("VIB", "detected! pulses =", pulse_cnt)
end
--演示最简单的使用方法,都使用默认配置
exvib1.open({
gpio_pin = 24,
on_event = vibration_cb,
})
以下为exvib1扩展库两个函数的详细说明及代码实现
]]
local exvib1 = {}
-- 默认配置
local cfg = {
gpio_pin = nil, -- 传感器中断所接 GPIO
pull = gpio.PULLUP,
trigger = gpio.RISING,
debounce_irq = 100, -- gpio消抖时间gpio.debounce 时间(ms)
time_window = 1000, -- 检测窗口(ms)
pulse_threshold = 3, -- 触发阈值
pulse_timeout = 200, -- 脉冲超时(ms)
poll_interval = 10, -- 状态机轮询(ms)
on_event = nil, -- 用户回调
}
-- 内部状态
local st = {
pulse_cnt = 0,
last_valid = 0,
detect_t0 = 0,
state = "IDLE",
}
-- 重置内部状态,将状态机置为空闲状态并清零脉冲计数
local function reset()
st.state = "IDLE"
st.pulse_cnt = 0
end
-- GPIO 中断处理函数,用于处理传感器的脉冲信号
local function isr()
local now = mcu.ticks()
st.pulse_cnt = st.pulse_cnt + 1
st.last_valid = now
-- 如果当前状态为空闲状态
if st.state == "IDLE" then
-- 切换到检测状态
st.state = "DETECTING"
-- 记录检测开始时间
st.detect_t0 = now
end
end
-- 状态机处理函数,用于检测是否满足震动触发条件
local function fsm()
-- 如果当前状态不是检测状态,则直接返回
if st.state ~= "DETECTING" then return end
local now = mcu.ticks()
-- 处理时间戳溢出情况
if now < st.detect_t0 or now < st.last_valid then
st.detect_t0 = 0
st.last_valid = 0
return -- 等待下次调用重新判断
end
-- 计算从检测开始到现在经过的时间
local elapsed = now - st.detect_t0
-- 判断是否脉冲空闲时间过长
local idle_too_long = (now - st.last_valid) >= cfg.pulse_timeout
-- 当检测窗口结束或者脉冲空闲时间过长时
if elapsed >= cfg.time_window or idle_too_long then
-- 检查脉冲计数是否达到触发阈值,并且用户回调函数存在
if st.pulse_cnt >= cfg.pulse_threshold and st.on_event then
-- 调用用户回调函数并传入脉冲计数值
st.on_event(st.pulse_cnt)
end
-- 重置内部状态
reset()
end
end
--[[
启动震动检测功能
@api exvib1.open(opts)
@table opts 配置参数表,用于自定义震动检测功能的各项属性。
@return nil 无返回值
@usage
-- 配置参数介绍
--local otps = {
-- gpio_pin --"传感器中断所接 GPIO 引脚号,默认值为 nil",
-- pull --"上拉/下拉模式,可选 gpio.PULLUP 或 gpio.PULLDOWN默认值为 gpio.PULLUP",
-- trigger --"触发方式,可选 gpio.RISING 或 gpio.FALLING默认值为 gpio.RISING",
-- debounce_irq --"GPIO 消抖时间,单位为毫秒,默认值为 100",
-- time_window --"检测窗口时间,单位为毫秒,默认值为 1000",
-- pulse_threshold --"触发阈值,即连续脉冲次数,默认值为 3",
-- pulse_timeout --"脉冲超时时间,单位为毫秒,默认值为 200",
-- poll_interval --"状态机轮询时间,单位为毫秒,默认值为 10",
-- on_event --"用户回调函数,用于处理检测到的震动事件,默认值为 nil",
--}
-- 震动事件回调
local function vibration_cb(pulse_cnt)
log.info("VIB", "detected! pulses =", pulse_cnt)
end
exvib1.open({
gpio_pin = 24,
on_event = vibration_cb,
})
--不同场景下的参数配置可参考下面的示例
--高灵敏度,响应快,误触可能高
exvib1.open({
gpio_pin = 24,
on_event = vibration_cb,
time_window = 300, -- 检测窗口(ms)
pulse_threshold = 1, -- 触发阈值
pulse_timeout = 100, -- 脉冲超时(ms)
})
--默认配置,较高灵敏度
exvib1.open({
gpio_pin = 24,
on_event = vibration_cb,
time_window = 1000, -- 检测窗口(ms)
pulse_threshold = 3, -- 触发阈值
pulse_timeout = 200, -- 脉冲超时(ms)
})
--中等灵敏度,
exvib1.open({
gpio_pin = 24,
on_event = vibration_cb,
time_window = 2000, -- 检测窗口(ms)
pulse_threshold = 3, -- 触发阈值
pulse_timeout = 300, -- 脉冲超时(ms)
})
--低灵敏度,减少误报
exvib1.open({
gpio_pin = 24,
on_event = vibration_cb,
time_window = 3000, -- 检测窗口(ms)
pulse_threshold = 10, -- 触发阈值
pulse_timeout = 500, -- 脉冲超时(ms)
})
]]
-- 启动震动检测功能
function exvib1.open(opts)
-- 如果没有传入配置参数,则使用空表
opts = opts or {}
-- 用传入的配置参数更新默认配置
for k, v in pairs(opts) do cfg[k] = v end
-- 更新用户回调函数,如果传入了新的回调则使用新的,否则保持原有回调
st.on_event = opts.on_event or st.on_event
-- 配置 GPIO 消抖时间,设置中断处理函数、上拉模式和触发方式
gpio.debounce(cfg.gpio_pin, cfg.debounce_irq)
gpio.setup(cfg.gpio_pin, isr, cfg.pull, cfg.trigger)
-- 启动定时器循环调用状态机处理函数
sys.timerLoopStart(fsm, cfg.poll_interval)
log.info("Vibration", "start on gpio", cfg.gpio_pin)
end
--[[
关闭震动检测功能
@api exvib1.close()
@return nil 无返回值
@usage
exvib1.close() --关闭震动检测功能
--]]
function exvib1.close()
-- 关闭 GPIO 引脚
gpio.close(cfg.gpio_pin)
-- 停止定时器
sys.timerStop(fsm)
reset()
end
return exvib1