基于STM32的智能垃圾桶的Proteus仿真
文章目录
- 一、智能垃圾桶
- 1.题目要求
- 2.思路
- 3.电路仿真
- 3.1 未仿真
- 3.2 开始仿真,显示屏显示环境温度等,虚拟终端打印信息
- 3.3 红外检测到人。模拟垃圾桶盖翻盖
- 3.4 光照强度低于30,自动开启灯光
- 3.5 模拟垃圾桶容量100%,检测到垃圾桶满声光报警
- 4.仿真程序
- 4.1 程序说明
- 4.2 主程序
- 4.3 OLED显示程序
- 4.4 超声波测距函数
- 4.5 舵机函数
- 二、总结
一、智能垃圾桶
1.题目要求
- 使用超声波测距模块HC-SR04模块进行检测垃圾桶容量,检测到垃圾桶容量满载后进行报警提示,此时需要处理垃圾;
- 红外传感器HCSR501检测有人或者无人,有人时垃圾桶盖自动打开,无人时自动合上(用舵机模拟翻盖动作);
- 光敏传感器检测周围光照环境控制Led灯的亮灭;
- DHT11温湿度传感器检测环境的温度,湿度;
- MQ-135空气质量传感器检测空气质量;
- OLED显示屏显示温湿度,空气质量,有人/无人信息;
- 模拟Wifi功能,自动接收温湿度,光照强度,空气质量,垃圾桶容量等信息。
2.思路
由上面的功能需求,我们可知需要一个主控选51或者32都行,然后超声波测距模块HC-SR04,声光报警,红外传感器HCSR501,舵机,光敏电阻,Led灯,DHT11传感器,MQ-135空气质量传感器,OLED显示屏,WIfi模块等。
单片机STM32F103C8T6:
超声波测距模块:
声光报警:
红外传感器:
舵机:
光敏电阻和灯:
温湿度传感器DHT11:
MQ-135 空气质量传感器:
OLED显示屏:
模拟Wifi模块:
3.电路仿真
3.1 未仿真
3.2 开始仿真,显示屏显示环境温度等,虚拟终端打印信息
3.3 红外检测到人。模拟垃圾桶盖翻盖
3.4 光照强度低于30,自动开启灯光
3.5 模拟垃圾桶容量100%,检测到垃圾桶满声光报警
4.仿真程序
4.1 程序说明
主控芯片:STM32F103C8
HSI:64MHZ
Systick: 1ms
超声波测距:
TR:PA0
ECHO:PA1
光照传感器:LDR(PA2)
空气质量传感器:ADC(PA3)
灯光:LED(PA4)
DHT11温湿度传感器:DATA(PA6)
模拟WIFI模块(Uart1):9600(PA9:tx1,PA10:rx1)
舵机:
PWM1(PB6)
声光报警:BUZZER(PB11)
OLED显示屏:SCL(PB14),SDA(PB15)
4.2 主程序
/* Includes ------------------------------------------------------------------*/
#include "Drv_UserSystem.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/**
* @brief main function.
* @param none
* @retval none
*/
int main(void)
{
UserSystemInit();//用户配置初始化
while (1)
{
if (stSysTime.flg._10ms + TEN_MILLISECOND < Time_millis()) //10ms
{
stSysTime.flg._10ms = Time_millis();
IR_Scan();//检测是否有人
}
if (stSysTime.flg._50ms + FIFTY_MILLISECOND < Time_millis()) //50ms
{
stSysTime.flg._50ms = Time_millis();
ADC_Scan();//光照,空气质量检测
DHT11_Collect_data();//DHT11采集温度,湿度
Measurement_function();//测距函数
}
if(stSysTime.flg._100ms + BEST_MILLISECOND < Time_millis()) //100ms
{
stSysTime.flg._100ms = Time_millis();
OLED_Handel();//OLED显示
IWDG_ReloadCounter();//清开门狗
}
if (stSysTime.flg._1s + THOUSAND_MILLISECOND < Time_millis()) //1s
{
stSysTime.flg._1s = Time_millis();
Printf_Task();//打印任务
}
}
}
4.3 OLED显示程序
/*******************************************************************************
* 函数名:OLED_Handel
* 描述 :OLED显示
* 输入 :void
* 输出 :void
* 调用 :初始化
* 备注 :100ms
*******************************************************************************/
void OLED_Handel(void)
{
if(ADC_Flag)
{
OLED_Show_Character(1,1,0,16);//环
OLED_Show_Character(1,2,1,16);//境
OLED_Show_Character(1,3,2,16);//温
OLED_Show_Character(1,4,3,16);//度
OLED_Show_Character(1,5,4,16);//:
OLED_ShowNum(1,11,DHT11_temp_high,2);
OLED_Show_Character(1,7,5,16);//°
OLED_ShowString(1, 15, "C");
OLED_Show_Character(2,1,0,16);//环
OLED_Show_Character(2,2,1,16);//境
OLED_Show_Character(2,3,6,16);//湿
OLED_Show_Character(2,4,7,16);//度
OLED_Show_Character(2,5,4,16);//:
OLED_ShowNum(2,11,DHT11_humi,2);
OLED_ShowString(2, 13, "%");
OLED_Show_Character(3,1,8,16);//空
OLED_Show_Character(3,2,9,16);//气
OLED_Show_Character(3,3,10,16);//质
OLED_Show_Character(3,4,11,16);//量
OLED_Show_Character(3,5,4,16);//:
OLED_ShowNum(3,11,ADC2_Value,2);
OLED_ShowString(3, 13, "%");
if(IR_flag)
{
OLED_Show_Character(4,1,12,16);//有
OLED_Show_Character(4,2,13,16);//人
}
else
{
OLED_Show_Character(4,1,14,16);//无
OLED_Show_Character(4,2,15,16);//人
}
}
}
4.4 超声波测距函数
如果对距离要求比较精确,最好是用10us的定时器,否则距离会有误差。
/*******************************************************************************
* 函数名:Measurement_function
* 描述 :HCSR04测距函数
* 输入 :void
* 输出 :void
* 调用 :内部调用
* 备注 :50ms
*******************************************************************************/
void Measurement_function(void)
{
Trig_Out_High();
DDelay_20us();
Trig_Out_Low();
while(Read_Echo_Level()==0);//等待低电平结束
ditance_count = 0;
while(Read_Echo_Level()==1);//等待高电平结束
ditance_flag = 1;
if(ditance_count < Overtime)//小于超时时间 38ms
{
MM_ditance = ((ditance_count * 340)/2/10);//单位毫米
}
if(MM_ditance < 40)
{
capacity = 100;
}
else if((MM_ditance > 40) && (MM_ditance < 60))
{
capacity = 90;
}
else if((MM_ditance > 60) && (MM_ditance < 80))
{
capacity = 80;
}
else if((MM_ditance > 80) && (MM_ditance < 100))
{
capacity = 70;
}
else if((MM_ditance > 100) && (MM_ditance < 110))
{
capacity = 60;
}
else if((MM_ditance > 110) && (MM_ditance < 120))
{
capacity = 50;
}
else if((MM_ditance > 120) && (MM_ditance < 140))
{
capacity = 40;
}
else if((MM_ditance > 140) && (MM_ditance < 160))
{
capacity = 30;
}
else if((MM_ditance > 160) && (MM_ditance < 180))
{
capacity = 20;
}
else if((MM_ditance > 180) && (MM_ditance < 190))
{
capacity = 10;
}
else if(MM_ditance > 190)
{
capacity = 0;
}
if(capacity == 100)
{
Beep_On();
}
else
{
Beep_Off();
}
// printf("MM_ditance=%d\r\n",MM_ditance);
}
4.5 舵机函数
舵机角度为-90°-90°
/*******************************************************************************
* 函数名:User_TIM4_Init
* 描述 :定时器4的初始化
* 输入 :void
* 输出 :void
* 调用 :初始化
* 备注 :
*******************************************************************************/
void User_TIM4_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //开启TIM4的时钟
RCC_APB2PeriphClockCmd(Motor_GPIO_RCC, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//受外设控制的引脚,均需要配置为复用模式
GPIO_InitStructure.GPIO_Pin = PWM1_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Motor_GPIO_Port, &GPIO_InitStructure);//将PB6引脚初始化为复用推挽输出
/*配置时钟源*/
TIM_InternalClockConfig(TIM4); //选择TIM4为内部时钟,若不调用此函数,TIM默认也为内部时钟
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
/*输出比较初始化*/
TIM_OCInitTypeDef TIM_OCInitStructure; //定义结构体变量
TIM_OCStructInit(&TIM_OCInitStructure); //结构体初始化,若结构体没有完整赋值
//则最好执行此函数,给结构体所有成员都赋一个默认值
//避免结构体初值不确定的问题
// 配置通道1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 输出比较模式,选择PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_Pulse = 0; // 初始的CCR值
TIM_OC1Init(TIM4, &TIM_OCInitStructure); // 将结构体变量交给TIM_OC1Init,配置TIM4的输出比较通道1
/*TIM使能*/
TIM_Cmd(TIM4, ENABLE); //使能TIM1,定时器开始运行
}
/*******************************************************************************
* 函数名:PWM1_SetCompare
* 描述 :PWM设置CCR
* 输入 :Compare 要写入的CCR的值,范围:0~100
* 输出 :void
* 调用 :初始化
* 备注 :CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比.占空比Duty = CCR / (ARR + 1)
*******************************************************************************/
void PWM1_SetCompare(uint16_t Compare)
{
TIM_SetCompare1(TIM4, Compare); //设置CCR2的值
}
/*******************************************************************************
* 函数名:Servo1_SetAngle
* 描述 :舵机设置角度
* 输入 :Angle 要设置的舵机角度,范围:0~180
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void Servo1_SetAngle(float Angle)
{
PWM1_SetCompare(Angle / 180 * 2000 + 500); //设置占空比
//将角度线性变换,对应到舵机要求的占空比范围上
}
二、总结
今天主要讲了基于STM32的智能垃圾桶的Proteus仿真。
感谢你的观看!