跳转至

exvib1 - exvib1 震动传感器扩展库

作者:孟伟

一、概述

应用场景

此库适用于搭配合宙配件板 AirVIBRATING_1000 或者滚珠震动传感器 BL_2529,核心功能是对传感器 GPIO 中断产生的脉冲信号进行滤波和智能识别,从而判断出有效的震动事件。该库的实现思路也可作为其他类似震动传感器中断处理的参考。

核心功能

1、GPIO 中断检测:通过配置的 GPIO 引脚检测震动传感器产生的脉冲信号。

2、双重消抖机制:

IO 中断硬件消抖 (gpio.debounce())。

时间窗口检测:在指定的时间窗口 (time_window) 内统计有效的脉冲数量。

3、阈值触发:当统计的脉冲数超过设定的阈值 (pulse_threshold) 时,触发用户自定义的回调函数。

4、脉冲超时机制:在检测状态下,如果超过 pulse_timeout 时间没有新的脉冲产生,则提前结束当前检测周期并判断是否触发回调,提高响应速度。

状态机工作流程

1、IDLE 状态:等待第一个有效脉冲。

2、DETECTING 状态:进入检测窗口,统计脉冲数量。

3、触发条件:

时间窗口结束。

脉冲空闲时间超过设定的脉冲超时时间。

4、结果判断:脉冲数 ≥ 阈值则调用用户回调函数。

二、核心示例

1、核心示例是指:使用本库文件提供的核心API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的demo,请参考 LuatOS仓库 中的demo/exvib1

--加载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,
})

三、常量详解

核心库常量,顾名思义是由合宙LuatOS内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;

exvib1扩展库没有常量。

四、函数详解

exvib1.open(opts)

功能

启动震动检测功能。根据提供的配置参数初始化 GPIO 中断、设置消抖、启动状态机定时器,开始监听传感器信号。

参数

opts

参数含义:震动检测功能的配置参数表;
数据类型:table
是否必选:是;
参数格式:
{
    -- 参数含义:传感器中断信号所连接的 GPIO 引脚编号;
    -- 数据类型:number
    -- 是否必选:是;
    -- 参数示例:24
    gpio_pin = ,

    -- 参数含义:GPIO 引脚的上拉/下拉模式;
    -- 数据类型:number (使用 gpio.PULLUP 或 gpio.PULLDOWN)
    -- 是否必选:否;
    -- 默认值:gpio.PULLUP
    -- 参数示例:gpio.PULLUP
    pull = ,

    -- 参数含义:GPIO 中断触发方式;
    -- 数据类型:number (使用 gpio.RISING 或 gpio.FALLING 或 gpio.BOTH
    -- 是否必选:否;
    -- 默认值:gpio.RISING
    -- 参数示例:gpio.RISING
    trigger = ,

    -- 参数含义:GPIO 中断硬件消抖时间,单位毫秒(ms);
    -- 数据类型:number
    -- 是否必选:否;
    -- 默认值:100
    -- 参数示例:100
    debounce_irq = ,

    -- 参数含义:检测脉冲的有效时间窗口,单位毫秒(ms)。在此时间窗口内统计脉冲数;
    -- 数据类型:number
    -- 是否必选:否;
    -- 默认值:1000
    -- 参数示例:1000
    time_window = ,

    -- 参数含义:触发回调函数的脉冲数量阈值;
    -- 数据类型:number
    -- 是否必选:否;
    -- 默认值:3
    -- 参数示例:3
    pulse_threshold = ,

    -- 参数含义:脉冲超时时间,单位毫秒(ms)。在 DETECTING 状态下,超过此时间无新脉冲则提前结束本次检测;
    -- 数据类型:number
    -- 是否必选:否;
    -- 默认值:200
    -- 参数示例:200
    pulse_timeout = ,

    -- 参数含义:状态机轮询检查的时间间隔,单位毫秒(ms);
    -- 数据类型:number
    -- 是否必选:否;
    -- 默认值:10
    -- 参数示例:10
    poll_interval = ,

    -- 参数含义:用户定义的回调函数。当有效震动被检测到时,会调用此函数;
    -- 数据类型:function
    -- 是否必选:是;
    -- 参数示例:function(pulse_cnt) log.info("VIB", pulse_cnt) end
    on_event = ,
}
返回值

无返回值

示例

本示例章节仅列举一些常用功能的核心代码片段

更加完整和详细的demo,请参考 https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/demo/exvib1

--加载exvib1扩展库
local exvib1= require "exvib1"

-- 震动事件回调
--最简单的,测试时候用的,只打印下触发次数
local function vibration_cb(pulse_cnt)
    log.info("VIB", "detected! pulses =", pulse_cnt)
end

--触发震动后把对应的消息通过网络协议发布出去
--[[
local function vibration_cb_mqtt(pulse_cnt)
    log.info("VIB", "detected! pulses =", pulse_cnt)
    -- 发布 MQTT 报警
    local msg = {type="quake", level=pulse_cnt, ts=os.time()}
    mqttc:publish("/alert/quake", json.encode(msg), 1)
end
]]

--震动预警类,发生震动时打开摄像头/gnss/发送消息
--[[
local function vibration_cb(pulse_cnt)
    log.info("VIB", "detected! pulses =", pulse_cnt)
    -- 例如打开gnss
    local function mode1_cb(tag)
        log.info("TAGmode1_cb+++++++++", tag)
        log.info("nmea", "rmc", json.encode(exgnss.rmc(2)))
    end
    exgnss.open(exgnss.TIMER, { tag = "MODE1", val = 60, cb = mode1_cb })

    --例如打开摄像头拍照
    --打开摄像头供电
    gpio.set(pin, 1)
    sys.wait(500)
    -- 等摄像头稳定local id = os.date("%Y%m%d%H%M%S")
    camera.capture(0, "/capture.jpg", 80)
    -- 延迟 30 s 再关摄像头
    sys.timerStart(function()
        gpio.set(18, 0)
    end, 30000)

    -- 例如发送短信
    --sms.send("+86138xxxxxxxx", "Vehicle shock detected! " .. lng ..lat)
end
]]--


-- 如果触发频繁,可以加冷却期
--[[
local cool = false
local function vibration_cb(pulse_cnt)
    log.info("VIB", "detected! pulses =", pulse_cnt)
    if cool then return end
    cool = true
    -- ... 业务逻辑 ...
    sys.timerStart(function()
        cool = false
    end, 60000)     -- 冷却 60 send
end
]]


--回调里只做最小工作,把耗时逻辑丢到独立任务
--[[
local vib_msg = {}
local function vibration_cb(pulse_cnt)
    log.info("VIB", "detected! pulses =", pulse_cnt)
    sys.publish("VIB_EVT", pulse_cnt) -- 非阻塞通知
end
-- 在另一个文件
sys.subscribe("VIB_EVT", function(msg)
    log.info("VIB_EVT", msg) -- 例如写 SD、HTTP 上传
    -- 其他业务逻辑,例如写 SD、HTTP 上传
end)
]]


--演示最简单的使用方法,都使用默认配置
exvib1.open({
    -- 震动传感器中断管脚连接的 GPIO 引脚
    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)
})
]]

exvib1.close()

功能

关闭震动检测功能。释放 GPIO 引脚资源,停止状态机定时器,并将内部状态重置为空闲状态。

参数

无参数

返回值

无返回值

示例

-- 关闭震动检测
exvib1.close()

五、产品支持说明

支持LuatOS开发的所有产品都支持exvib1扩展库,不过需要搭配合宙配件板AirVIBRATING_1000,或者也可作为其他类似震动传感器中断处理的参考。