使用STM32 再实现感应开关盖垃圾桶

硬件介绍

SG90舵机


如上图所示的舵机SG90,橙线对应PWM信号,而PWM波的频率不能太高,大约50Hz,即周期0.02s,20ms左右。

在20ms的周期内,高电平占多少秒和舵机转到多少度的关系如下: 

0.5ms-----0度;2.5%对应函数中占空比为250

1.0ms-----45度;5.0%对应函数中占空比为500

1.5ms-----90度;7.5%对应函数中占空比为750

2.0ms-----135度;10.0%对应函数中占空比为1000

2.5ms-----180度;12.5%对应函数中占空比为1250

震动传感器

产生震动时,会输出低电平,绿色指示灯亮(开关信号指示灯)

蜂鸣器

 低电平触发

 超声波传感器

 使用方式见之前的博客

项目要求

检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

使用STM32控制舵机SG90

已知,舵机的驱动要使用周期20ms左右的PWM波,并通过调整占空比x来控制舵机的角度:

那如果我现在想要让舵机每隔1S转动一个角度,使得角度为0,45,90,135,180,0度。

那就可以使用我上节实现呼吸灯的CubeMX项目,对其进行修改:

1. 由于舵机中角度的计算是和高电平占周期的比例来换算的,所以要将CH Polarity改为High

2. 由于舵机需要的PWM的周期是20ms,则可以设置PSC = 7199, ARR = 199,这样当Tclk = 72M时,周期正好是0.02s,即20ms。

 3. 这就设置好了,更新项目并打开Keil,修改main.c中的main函数,CCRx为(ARR的199对应20ms,那0.5ms就对应199/40)约等于 5 时对应0度,10对应45度,15对应90度,20对应135度,25对应180度。

  HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); //打开Timer4的3号Channelwhile (1){HAL_Delay(1000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度HAL_Delay(1000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 10); //45度HAL_Delay(1000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15); //90度HAL_Delay(1000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20); //135度HAL_Delay(1000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 25); //180度}

实现效果:(由于之前在用89C52做小车的时候,我已经把舵机和无线测距模块用热熔胶固定在小车上了,所以只看效果就可以) 

使用STM32控制无线测距模块HC-SR04

HC-SR04的开发逻辑在之前的章节里已经非常详细的介绍过了,这里直接开始实践:

Trig接入PB6Echo接入PB7,然后依然可以在刚刚舵机的CubeMX项目基础上修改:

1. 在之前的基础上,再使用一个TIM2,并且只用来作为计数功能,并软件控制何时停止计数,因此只需要设置TIM2的PSC而不需要设置ARR

值得一提的是,在89C52的使用中,驱动HC-SR04是Trig给至少10毫秒的高电平,所以我一开始是直接用HAL_Delay(20)来驱动的,但是我发现不行,所以很神奇的一件事情是,当使用STM32来驱动HC-SR04的时候,Trig的有效驱动又变回微秒级的了。。。

计数一次经过的时间是 (PSC + 1) / Tclk , 因此如果我想要计数1微秒,即0.000001s, 已知Tclk = 72 000 000, 那么PSC就应该设置为 71。然后在main.c中就可以定义出一个实现微秒级延时的函数:

//使用TIM2来做us级延时函数
void TIM2_Delay_us(uint16_t n_us)
{
/* 使能定时器2计数 */
__HAL_TIM_ENABLE(&htim2);
__HAL_TIM_SetCounter(&htim2, 0);
while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
/* 关闭定时器2计数 */
__HAL_TIM_DISABLE(&htim2);
}

然后,只要将PB6设置成GPIO_outputTrig是单片机发给HCSR04的信号), 将PB7设置成GPIO_inputEcho是HCSR04发回单片机的信号)就可以了:

2. 这就配置好了,HC-SR04的控制主要是在KEIL中自主实现的代码,其实思路和51的时候是一样一样的:

我现在想要实现的效果就是,当检测到距离小于5cm时,使得舵机转到135度,持续两秒然后回来:

void TIM2_Delay_us(uint16_t n_us)
{
/* 使能定时器2计数 */__HAL_TIM_ENABLE(&htim2);__HAL_TIM_SetCounter(&htim2, 0);while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );/* 关闭定时器2计数 */__HAL_TIM_DISABLE(&htim2);
}void StartHC()
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //Trig写0HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); //Trig写1TIM2_Delay_us(20); //持续20微妙HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //Trig写0}void deal_dist()
{int cnt;float dist;StartHC();while((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)) == GPIO_PIN_RESET); //等待Echo变高的一瞬间HAL_TIM_Base_Start(&htim2); //TIM2开始计时__HAL_TIM_SetCounter(&htim2,0); //将TIM2的计数器置0while((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)) == GPIO_PIN_SET); //等待Echo变低的一瞬间	HAL_TIM_Base_Stop(&htim2); //TIM2停止计时cnt = __HAL_TIM_GetCounter(&htim2);//求出计了多少次,由于计数一次经过的时间是1usdist = cnt*340/2*0.000001*100;  //求出距离if(dist < 10){ //如果距离小于10cm__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20); //135度HAL_Delay(2000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度}else{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度}}int main(void)
{HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); //打开Timer4的3号Channelwhile (1){deal_dist();HAL_Delay(200);}
}

实现效果:

感应开关盖垃圾桶实现

为了方便,就继续使用“mjm_test_PWM”的CubeMX项目文件!
在之前的基础上,要再额外加装震动传感器蜂鸣器,将震动传感器的D0接到PB5; 蜂鸣器的I/O接到PB4。

打开CubeMX修改:

1.添加GPIO口,并把PB4先拉高,并设置中断触发方式

 

 

 

 2. 打开中断,并设置优先级(把0的位置留给滴答定时器)

 

打开Keil修改:

打开stm32f1xx_it.c --> EXTI4(9_5)_IRQHandler() --> HAL_GPIO_EXTI_IRQHandler() --> HAL_GPIO_EXTI_Callback( )

HAL_GPIO_EXTI_Callback()就是中断处理程序,将他在main.c中重写:

注意,和电动车钥匙扣一样,因为要在中断函数中调用HAL_Delay,因此需要设置滴答定时器的优先级!!

void TIM2_Delay_us(uint16_t n_us)
{/* 使能定时器2计数 */__HAL_TIM_ENABLE(&htim2);__HAL_TIM_SetCounter(&htim2, 0);while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );/* 关闭定时器2计数 */__HAL_TIM_DISABLE(&htim2);
}void beep()
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); //蜂鸣器响HAL_Delay(200);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET); //蜂鸣器停	
}void StartHC()
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //Trig写0HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); //Trig写1//HAL_Delay(10);TIM2_Delay_us(20);HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //Trig写0}void deal_dist()
{int cnt;float dist;StartHC();while((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)) == GPIO_PIN_RESET); //等待Echo变高的一瞬间HAL_TIM_Base_Start(&htim2); //TIM2开始计时__HAL_TIM_SetCounter(&htim2,0); //将TIM2的计数器置0while((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)) == GPIO_PIN_SET); //等待Echo变低的一瞬间	HAL_TIM_Base_Stop(&htim2); //TIM2停止计时cnt = __HAL_TIM_GetCounter(&htim2);//求出计了多少次,由于计数一次经过的时间是1usdist = cnt*340/2*0.000001*100;  //求出距离if(dist < 10){ //如果距离小于10cm__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20); //135度beep();HAL_Delay(2000);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度}else{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度}}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin == GPIO_PIN_5){ //震动导致的中断if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5) == GPIO_PIN_RESET){ //这个判断很重要__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20); //135度beep();HAL_Delay(2000);//__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度 //不需要,因为main中的while一直再检测,如果震动之后,检测到有靠近,依然需要开盖;如果没有靠近,main里面的deal_dist函数也会关闭盖子}}if(GPIO_Pin == GPIO_PIN_0){ //按钮导致的中断HAL_Delay(50); //在检测到按键被按下的低电平的时候,先延迟50ms,再进行判断if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){ //如果延迟过后依然是低电平__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20); //135度beep();HAL_Delay(2000);//__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5); //0度 //不需要,因为main中的while一直再检测,如果按键之后,检测到有靠近,依然需要开盖;如果没有靠近,main里面的deal_dist函数也会关闭盖子}}
}int main(void)
{HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); //打开Timer4的3号ChannelHAL_NVIC_SetPriority(SysTick_IRQn,0,0); //必须写在" SystemClock_Config() "后面!!!while (1){deal_dist();HAL_Delay(200); //这句延迟也很重要}}

实现效果

可见,不管是距离小于10cm震动发生;还是按钮按下都可以触发舵机的转动,蜂鸣器的滴滴声,以及两秒后舵机的归位。(由于舵机在之前做小车的时候用热熔胶固定了,所以只要功能实现了就好,别太纠结长啥样!) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/20525.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件进行压力测试的主要目的

软件进行压力测试是指通过模拟大量用户访问和负载压力&#xff0c;在正常和峰值使用情况下对软件系统进行测试的过程。软件进行压力测试的主要目的是确保软件在实际应用中能够稳定、可靠地运行&#xff0c;满足用户的需求。 首先&#xff0c;软件进行压力测试的主要目的是评估系…

小程序页面顶部标题栏、导航栏navigationBar如何隐藏、变透明?

在app.json中的 "window"下面追加一行 "navigationStyle": "custom" 小程序顶部的白色背景条就不见了&#xff0c;直接变透明&#xff0c;只剩下右上角的胶囊按钮 警告&#xff1a; 如果页面有 <web-view src"{{src}}" /> …

8年资深测试总结,性能测试+性能优化(详细)进军高级测试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能优化常见概念…

小程序开发:必须掌握的 HTML、CSS 和 JavaScript 技术

引言 小程序是一种轻量级的应用程序&#xff0c;通过HTML、CSS和JavaScript等前端技术开发&#xff0c;可在移动设备上直接访问和使用&#xff0c;无需下载和安装。 文章目录 引言一、小程序开发的背景和重要性二、HTML、CSS和JavaScript在小程序开发中的作用三、HTML基础知识1…

靶场的安装

sqli-lab 1.将安装包解压放到WWW目录下 2.修改 db-creds.inc文件里面的数据库的用户名密码为自己的用户名密码 路径&#xff1a;D:\phpStudy_64\phpstudy_pro\WWW\sqli-labs-master\sql-connections\db-creds.inc 3. 更改php版本位5.9版本&#xff0c;不然会报错 4.安装数…

物联网会是下一个支柱产业吗?

近年来&#xff0c;物联网 (IoT) 无疑已成为一个重要且快速增长的行业。尽管绝对确定地预测未来具有挑战性&#xff0c;但许多专家和分析师认为&#xff0c;物联网有潜力成为支柱产业&#xff0c;对各个行业产生变革性影响。 物联网是指由可以收集、交换和分析数据的互连设备、…

SpringBoot第25讲:SpringBoot对TypeHandler的使用

SpringBoot第25讲&#xff1a;SpringBoot对TypeHandler的使用 本文是SpringBoot第25讲&#xff0c;SpringBoot对TypeHandler的使用&#xff0c;TypeHandler就是当SpringBoot 实体类中字段类型和数据库中字段类型不一致时进行使用。 文章目录 SpringBoot第25讲&#xff1a;Sprin…

ELK-日志服务【logstash-安装与使用】

目录 【1】安装logstash logstash input 插件的作用与使用方式 【2】input --> stdin插件&#xff1a;从标准输入读取数据&#xff0c;从标准输出中输出内容 【3】input -- > file插件&#xff1a;从文件中读取数据 【4】input -- > beat插件&#xff1a;从filebe…

MongoDB 事务与数据落盘

文章目录 概要一、持久性1.1、journal log刷盘机制1.2、数据刷盘机制1.3、复制集下的写安全机制 二、隔离性总结 概要 MongoDB并不像MySQL一样天然支持多文档事务&#xff0c;其演变过程如下&#xff1a; MongoDB4.0之前只支持单文档事务&#xff0c;在单个文档上支持ACID原子…

vs2013 英文语言包

因为安装其它插件报错&#xff0c;有文档说需要更换为英文包。我电脑只有中文&#xff0c;于是开始了英文语言包下载。 官网下载 https://my.visualstudio.com/Downloads?qVisual%20Studio%202013%20Language%20Pack 刚开始没有使用官网&#xff0c;因为除了要注册登陆&…

Redis_客户端命令和数据操作(3)

目录 切换数据库 键命令 数据结构 string类型 hash类型 list类型 set类型 zset类型 查看中文value 源码等资料获取方法 切换数据库 redis数据库没有名称&#xff0c;默认有16个&#xff0c;通过0-15来标识&#xff0c;连接redis默认选择第一个数据库&#xff0c;可以…

Nacos(服务注册与发现)+SpringBoot+openFeign项目集成

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…