简介
本项目基于 MicroPython 实现,用于检测设备是否处于震动或静止状态。通过 VibrationSensor 类可以轻松地配置和读取振动传感器的状态,适用于需要检测移动或静止的物联网设备、安防系统等场景。
该代码支持中断驱动的震动检测机制,并具备防抖、时间窗口判断、灵敏度调节等功能,确保在复杂环境下依然稳定工作。
主要功能
- 中断触发:下降沿触发,实时响应震动事件
- 防抖处理:200ms 防抖间隔,避免误触发
- 激活条件判断:设定时间内达到指定震动次数才判定为“移动”
- 超时自动恢复:长时间无震动后自动进入“静止”状态
- 参数可调:支持灵活配置以适应不同应用场景
一.硬件配置说明
推荐平台
- ESP32
- ESP8266
- 其他支持 MicroPython 的微控制器
所需硬件
- 振动传感器(如 SW-420 或 KY-002)
- 微控制器(如 ESP32)
- 电阻(如果传感器没有内置上拉)
接线方式
| 振动传感器引脚 | 微控制器引脚 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| OUT | GPIO_X(根据初始化参数设置) |
注意:OUT 引脚应连接到支持中断的 GPIO,例如 ESP32 上的任意 GPIO 均支持中断。
二.类与方法说明
class VibrationSensor
初始化方法
__init__(self, io, activation_ms=1500, state=True, shakes=3, timeout=3000)
参数说明(表格)
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
io | 整数 | 无默认值 | GPIO 引脚编号,例如 4 |
activation_ms | 整数 | 1500 | 激活所需震动时间窗口(毫秒),在休眠状态下需在此时间内震动一定次数才能激活 |
state | 布尔值 | True | 是否启用传感器(True = 启用,False = 关闭) |
shakes | 整数 | 3 | 激活所需的连续震动次数 |
timeout | 整数 | 3000 | 移动状态超时时间(毫秒),超过此时间无震动则回到静止状态 |
方法说明
update(self)
- 功能:更新当前传感器状态。
- 返回值:布尔值,True 表示静止,False 表示正在移动。
_shake_detected(self, _)
- 功能:中断回调函数,用于检测震动并进行防抖处理。
- 内部逻辑:
- 记录震动时间。
- 判断是否在激活窗口内达到足够震动次数。
_reset(self)
- 功能:重置震动计数器和相关时间戳。
三.代码示例
import time
from machine import Pin
from vibration_sensor import VibrationSensor # VibrationSensor另存为VibrationSensor.py文件
# 初始化振动传感器(连接到GPIO 4)
vs = VibrationSensor(io=4)
def stationary():
"""等待重新震动"""
while True:
if not vs.update():
print("移动")
return
time.sleep_ms(5)
while True:
if vs.update():
print("静止")
stationary()
time.sleep_ms(5)
运行逻辑说明:
- 主循环中调用
vs.update()获取当前状态。 - 如果返回
True,表示进入“静止”状态,进入stationary()函数等待再次震动。 - 如果检测到震动且满足激活条件,则打印
"移动"并退出stationary(),重新进入主循环。
四.使用建议
硬件连接
- 将振动传感器的信号引脚连接到 ESP32/ESP8266 的指定 GPIO。
- 推荐使用上拉输入模式(如
Pin.PULL_UP),若传感器输出低电平有效。
灵敏度调整
- 可通过修改
shakes和activation_ms来调整触发灵敏度。 - 更高震动次数代表更稳定的检测,更低则更敏感。
电源管理
- 若暂时不需要检测震动,可通过设置
state=False关闭传感器以节省功耗。
五.注意事项
- 确保使用的 MicroPython 固件版本支持中断和
machine.Pin.irq()方法。 - 中断函数中应尽量避免执行复杂操作,仅做标记即可。
- 如需更高精度检测,可适当调整
activation_window和timeout参数。
六.源码
import time
from machine import Pin, PWM
class VibrationSensor:
'''振动传感器'''
def __init__(self,io, activation_ms=1500,state=True,shakes=3,timeout=3000):
"""
初始化振动传感器
:param activation_ms: 激活所需震动时间窗口(毫秒)在处于休眠状态下1内震动一定次数才会恢复到移动
:param timeout: 移动状态超时时间(毫秒)
:param shakes: 激活需要的连续震动次数
:param state: 是否启用
"""
self._state = state
# 是否开启震动传感器
if self._state is False: # 状态(True=开启,False=关闭)
return
self.pin = Pin(io, Pin.IN, Pin.PULL_UP)
self.activation_window = activation_ms # 激活时间窗口(毫秒)
self.timeout = timeout # 转换为毫秒存储
self.shakes = shakes # 激活传感器 需要的连续震动次数 林敏度
# 状态变量
self._last_shake = 0 # 最后一次震动时间
self._sequence_start = 0 # 震动序列开始时间
self._debounce_ts = 0 # 防抖时间戳
self.shake_counter = 0 # 当前连续震动计数
self._stationary = True # 当前状态标志
# 中断配置(下降沿触发)
self.pin.irq(trigger=Pin.IRQ_FALLING, handler=self._shake_detected)
def _shake_detected(self, _):
"""震动中断处理(带200ms防抖)"""
now = time.ticks_ms()
if time.ticks_diff(now, self._debounce_ts) > 200:
self._debounce_ts = now
self._last_shake = now # 更新最后震动时间
if self._stationary:
if self.shake_counter == 0:
self._sequence_start = now # 开始新序列
self.shake_counter += 1
def update(self):
"""更新状态并返回布尔值(True=静止)"""
if self._state is False:
return
now = time.ticks_ms()
if self._stationary: # 静止状态逻辑
if self.shake_counter >= self.shakes:
if time.ticks_diff(now, self._sequence_start) <= self.activation_window:
self._stationary = False # 切换为移动状态
self._reset()
elif self.shake_counter > 0 and time.ticks_diff(now, self._sequence_start) > self.activation_window:
self._reset()
elif time.ticks_diff(now, self._last_shake) > self.timeout: # 移动状态逻辑
self._stationary = True
self._reset()
return self._stationary
def _reset(self):
"""重置计数器和时间戳"""
self.shake_counter = 0
self._sequence_start = 0
303

被折叠的 条评论
为什么被折叠?



