当涉及到物体的震动检测和感应时,震动模块成为一种常见且实用的工具。这种小巧而功能强大的设备可以用于各种应用,从智能家居到安防系统,再到工业自动化等领域。通过感知和转换物体震动为电信号,震动模块在许多方面都发挥着重要的作用。
本文将介绍震动模块的原理、工作方式以及其在不同领域中的应用。无论您是对电子技术感兴趣还是希望了解如何利用震动模块改进产品或系统,本文将为您提供有益的信息和见解。
本文首发 良许嵌入式网 :https://www.lxlinux.net/e/ ,欢迎关注!
本文所涉及的源码及安装包如下(由于平台限制,请点击以下链接阅读原文下载):
https://www.lxlinux.net/e/stm32/SW-18010P-tutorial.html
超全的嵌入式入门教程,欢迎小白。
往期精彩教程,有兴趣的小伙伴可以看看。
让你轻松掌握温湿度传感器:【手把手教你玩转DHT11(原理+驱动):https://www.lxlinux.net/e/stm32/dht11-tutorial.html】
计算机概念理清,生动形象,通俗易懂:【图解固件、驱动、软件的区别:https://www.lxlinux.net/e/stm32/firmware-driver-software.html】
解析红外编解码模块的原理、功能和应用:【红外模块详解:https://www.lxlinux.net/e/stm32/infrared-sensor-tutorial.html】
有很多种型号的震动模块,801S、SW-520D、SW-420、SW-18010P 等等,它们之间大同小异。
今天我们的主角是 SW-18010P,模块介绍如下。
接好 VCC 和 GND,电源指示灯将被点亮。
当检测到震动时,板载指示灯点亮;震动停止,板载指示灯熄灭。
用螺丝刀转动「灵敏度调节电位器」可以调节灵敏度。大家可以将电位器旋到最左或最右,然后测试往哪边旋可以提高灵敏度。
SW-18015P 为密封弹簧型、无方向性震动感应触发开关,任何角度均可触发。
正常使用情况下开关寿命可达20万次。
引脚接线图如下:
SW-18010P | STM32 |
---|---|
VCC | 3.3或5V |
GND | GND |
DO | 任意 GPIO 口 |
AO | 模拟输出,无效,不接 |
SW-18015P 在静止时为开路 OFF 状态, 当受到外力碰触而达到相应震动力时,或者移动速度达到适当离(偏)心力时,导电接脚会产生瞬间导通呈瞬间 ON 状态;当外力消失時,开关恢复为开路 OFF 状态。
所以,SW-18015P 在无震动或者震动强度达不到设定阈值时,DO 口输出高电平,当外界震动强度超过设定阈值时,模块 D0 输出低电平。
请注意这个模块在感应到小的震动时触发时间会很短,无法驱动继电器,有些的资料显示可以直接和继电器模块相连,但实际运用效果不佳。
实现目标:我们有一个三色 LED 灯,无震动时,绿灯亮,红灯灭;当震动模块感受到震动,绿灯灭,红灯亮。
这个小案例的应用场景可以是博物馆等场所防盗,玻璃柜如果有震动,可能发生偷窃,开始报警。
本教程使用的硬件如下:
接线如下:
SW-18010P | STM32 | LED |
---|---|---|
VCC | 5V | |
GND | GND | |
DO | A4 | |
A5 | R | |
A7 | G | |
GND | GND |
烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【[STM32下载程序的五种方法:https://www.lxlinux.net/e/stm32/five-ways-to-flash-program-to-stm32.html】。
ST-Link V2 | STM32 |
---|---|
SWCLK | SWCLK |
SWDIO | SWDIO |
GND | GND |
3.3V | 3V3 |
接好如下图:
开发板使用的是我们自绘的板子。大家也可以用自己的板子,只要是 STM32F103C8T6 主控芯片就行。
LED 灯的代码简简单单,只要进行一下两个灯的初始化就行。
void led_init(void) { GPIO_InitTypeDef gpio_init_struct; LED1_GPIO_CLK_ENABLE(); /* LED1时钟使能 */ LED3_GPIO_CLK_ENABLE(); /* LED3时钟使能 */ gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1引脚 */ gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */ gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */ HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化LED1引脚 */ gpio_init_struct.Pin = LED3_GPIO_PIN; /* LED3引脚 */ HAL_GPIO_Init(LED3_GPIO_PORT, &gpio_init_struct); /* 初始化LED3引脚 */ LED1(0); /* 关闭 LED1 */ LED3(0); /* 关闭 LED3 */ }
LED 的 .h文件:
#ifndef _LED_H #define _LED_H #include "sys.h" /******************************************************************************************/ /* 引脚 定义 */ #define LED1_GPIO_PORT GPIOA #define LED1_GPIO_PIN GPIO_PIN_5 #define LED1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ #define LED3_GPIO_PORT GPIOA #define LED3_GPIO_PIN GPIO_PIN_7 #define LED3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ /******************************************************************************************/ /* LED端口定义 */ #define LED1(x) do{ x ? \ HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \ HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \ }while(0) #define LED3(x) do{ x ? \ HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_SET) : \ HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_RESET); \ }while(0) /* LED取反定义 */ #define LED1_TOGGLE() do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0) /* 翻转LED1 */ #define LED3_TOGGLE() do{ HAL_GPIO_TogglePin(LED3_GPIO_PORT, LED3_GPIO_PIN); }while(0) /* 翻转LED3 */ /******************************************************************************************/ /* 外部接口函数*/ void led_init(void); /* LED初始化 */ #endif
初始化一下震动模块的 DO 引脚。
我们采用中断的方式亮红灯,需要初始化和使能一下 EXTI。
void sw_init(void) { GPIO_InitTypeDef gpio_initstruct; SW_CLK(); /* IO口时钟使能 */ gpio_initstruct.Pin = SW_PIN; /* DO引脚 */ gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; /* 下降沿触发 */ gpio_initstruct.Pull = GPIO_NOPULL; /* 无电阻 */ HAL_GPIO_Init(SW_GPIO, &gpio_initstruct); /* 初始化DO引脚 */ HAL_NVIC_SetPriority(EXTI4_IRQn,2,0); /* 抢占优先级2,响应优先级0 */ HAL_NVIC_EnableIRQ(EXTI4_IRQn); /* 使能EXTI4 */ }
复写「HAL_GPIO_EXTI_Callback」函数,检测到中断下降沿,则表示震动模块感受到震动,「swflag」置1。
uint16_t get_swflag(void) { return swflag; } void set_swflag(uint16_t value) { swflag = value; } void EXTI4_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); /* 调用中断处理公用函数 清除中断线 的中断标志位 */ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4); /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */ } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == SW_PIN){ if(HAL_GPIO_ReadPin(SW_GPIO, SW_PIN) == GPIO_PIN_RESET) //如果有震动 { swflag = 1; } } }
主函数如下:
依据「swflag」,为0时表示无震动,绿灯亮,红灯灭;为1时表示震动模块感受到震动,绿灯灭,红灯亮。
int main(void) { HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ delay_init(72); /* 延时初始化 */ led_init(); /* LED初始化 */ sw_init(); /* 震动模块初始化 */ while(1) { if (get_swflag()) //有震动时 { HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET); //红灯亮 HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_RESET); //绿灯灭 delay_ms(500); set_swflag(0); }else{ //无震动时 HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_SET); //绿灯亮 HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); //红灯灭 } } }
拍拍面包板,戳戳震动模块都可以让震动模块感受到震动。
无震动时,绿灯亮,红灯灭。(我的小绿灯不是很亮,用旧了,嘻嘻)
有震动时,绿灯灭,红灯亮。
随着技术的不断进步和创新,我们可以期待未来震动模块的进一步发展,以满足不断变化的需求和应用场景。无论是改善生活质量、提升工作效率,还是增强安全性,震动模块将继续为我们的日常生活和工作带来更多的创新和便利。
另外,想进大厂的同学,一定要好好学算法,这是面试必备的。这里准备了一份 BAT 大佬总结的 LeetCode 刷题宝典,很多人靠它们进了大厂。
刷题 | LeetCode算法刷题神器,看完 BAT 随你挑!
推荐阅读:
欢迎关注我的博客:良许嵌入式教程网,满满都是干货!