STM32项目分享:室内环境监测系统

目录

一、前言

二、项目简介

1.功能详解

2.主要器件

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

六、实验效果 

七、资料内容

项目分享


一、前言

项目成品图片:

哔哩哔哩视频链接:

STM32室内环境监测系统

(资料分享见文末) 

二、项目简介

1.功能详解

基于STM32的室内环境监测系统

功能如下:

  1. 使用STM32F103C8T6单片机作为主控单元
  2. 光敏电阻采集环境光强度,温度传感器采集温度,光电红外传感器采集人体有无
  3. OLED显示屏实时显示当前环境信息
  4. 光电红外检测到有人,可根据环境光照强度控制照明灯开关,根据环境温度情况控制风扇风速(低/高风速)和加热/制冷的操作
  5. 按键可设置阈值
  6. 可以通过蓝牙接入APP,APP实现数据上传与控制下发的功能

2.主要器件

  • STM32F103C8T6单片机
  • OLED 屏幕
  • DS18B20温度传感器
  • 光电红外传感器
  • 光敏传感器
  • BT04A蓝牙模块
  • TB6612电机调速模块
  • 继电器
  • 风扇模块
  • PTC加热片

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
#include "gpio.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "adc.h"
#include "ds18b20.h"
#include "timer.h"
#include "motor_dianji.h"


/**********************************
变量定义
**********************************/
uint8_t key_num = 0;									//按键扫描标志位	
uint8_t flag_display = 0;							//显示界面标志位
uint32_t time_num = 0;								//10ms计时
uint32_t light_value = 0;							//光照数值
uint32_t light_min = 40;							//光照数值
u16  temp_value = 0;									//温度值
u16  temp_min = 15;										//温度最小值
u16  temp_zj = 25;										//温度中间值
u16  temp_max = 30;										//温度最大值
extern uint8_t usart1_buf[256];				//串口1接收数组
char display_buf[32];									//显示缓存区
_Bool flag_mode = 0;									//模式标志位
uint8_t flag_motor_speed = 0;					//电机速度标志位
uint32_t speed_value = 0;							//速度值

_Bool flag_mode_r = 0;                //模式标志位
/**********************************
函数声明
**********************************/
void Key_function(void);							//按键函数
void Monitor_function(void);					//监测函数
void Display_function(void);					//显示函数
void Manage_function(void);						//处理函数


/****
*******	主函数 
*****/
int main(void)
{
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断优先分组
	Delay_Init();	    	 								//延时初始化	  
	Gpio_Init();		  									//IO初始化
	Key_Init();		  										//按键初始化
	Oled_Init();		  									//OLED初始化
	Oled_Clear_All();										//清屏
	Usart1_Init(9600);    							//串口1初始化
//	TIM3_Init(99,7199);									//定时器初始化函数
	DS18B20_Init();
	Adc_Init();
	Motor_Dianji_Init();								//直流电机初始化
	TIM_SetCompare1(MOTOR_DIANJI_TIM,0);
  Delay_ms(1000);
	Delay_ms(1000);

	
	while(1)
	{
		Key_function();										//按键函数
		Monitor_function();								//监测函数
		Display_function();								//显示函数
		Manage_function();								//处理函数

		time_num++;												//计时变量+1
		Delay_ms(10);
		if(time_num %10 == 0)
			LED_SYS = ~LED_SYS;
		if(time_num >= 5000)
		{
			time_num = 0;
		}
	}
}

/****
*******按键函数
*****/
void Key_function(void)
{
	key_num = Chiclet_Keyboard_Scan(0);		//按键扫描
	if(key_num != 0)											//有按键按下
	{
		switch(key_num)
		{
			case 1:								            //按键1,切换设置界面
				flag_display++;
				if(flag_display >= 5)
					flag_display = 0;
				
				Oled_Clear_All();					      //清屏
			break;

			case 2:											      //按键2 各个阈值+1
				switch(flag_display)
				{	
					case 1:												//界面1:
						if(temp_max < 99)
							temp_max++;
					break;
					
					case 2:												//界面2:
						if(temp_min < temp_zj)
							temp_min++;
					break;
					
					case 3:												//界面3:
						if(temp_zj < temp_max)
							temp_zj++;
					break;
					
					case 4:												//界面4:
						if(light_min < 70)
							light_min ++ ;
					break;
					
					default:
					break;
				}
			break;

			case 3:														//按键3   各个阈值-1
				switch(flag_display)
				{
					case 1:												//界面1:
						if(temp_max > temp_zj)
							temp_max --;
					break;
					
					case 2:												//界面2:
						if(temp_min > 0)
							temp_min --;
					break;
					
					case 3:												//界面3:
						if(temp_zj > temp_min)
							temp_zj --;
					break;
					
					case 4:												//界面4:
						if(light_min > 0)
							light_min --;
					break;
					
					default:
					break;
				}
			break;

			default:
				
			break;
		}
	}
}

/****
*******监测函数
*****/
void Monitor_function(void)
{
	if(flag_display == 0)									//测量界面
	{
		if(time_num % 10 == 0)							//获取数据
		{
			light_value = 99-30*(Get_Adc_Average(0,3)*3.3/4096.0);		//获取光照强度
			temp_value = DS18B20_Get_Temp();
		}
		
		if(time_num % 20 == 0)							//发送数据
		{
			UsartPrintf(USART1,"温度:%d.%dC\r\n",temp_value/10,temp_value%10);
			UsartPrintf(USART1,"光照:%dlux\r\n",light_value);
			if(IRED == 0)
				UsartPrintf(USART1,"人体热释电:有人\r\n");
			else
				UsartPrintf(USART1,"人体热释电:无人\r\n");
		}

		if(USART1_WaitRecive() == 0)				//如果接收到蓝牙数据
		{
			switch(usart1_buf[0])
			{
				case('A'):											//A:切换自动模式
					flag_mode_r = 0; 
				//	flag_mode = 0;
				break;

				case('B'):											//B:		风扇低速			
					flag_mode_r = 1; 
					flag_motor_speed = 1;
				break;
				
				case('C'):											//C:风扇高速
					flag_mode_r = 1; 
					flag_motor_speed = 2;
				break;
				
				case('D'):											//D:照明灯
					flag_mode_r = 1; 
					RELAY_ZM = ~RELAY_ZM;
			
				
				break;
				
				case('E'):											//E:加热
					flag_mode_r = 1; 
					RELAY_JR = ~RELAY_JR;
			
				break;
				
				case('F'):											//F:制冷
					flag_mode_r = 1; 
					RELAY_ZL = ~RELAY_ZL;
				break;
				default:
				
				break;
			}	
			USART1_Clear();
		}
		if(flag_mode_r == 0)
		{
			if(IRED == 0)
			{
				flag_mode =0;
			}
			else
			{
				flag_mode = 1; 
				RELAY_JR = 0;
				RELAY_ZL = 0;
				RELAY_ZM = 0;
				flag_motor_speed = 0; 
			}
		}

	}
}

/****
*******显示函数
*****/
void Display_function(void)
{
	switch(flag_display)									//根据不同的显示模式标志位,显示不同的界面
	{
		case 0:									      			//界面0:
			Oled_ShowCHinese(1, 0, "温度:");
			sprintf(display_buf,"%d.%dC  ",temp_value/10,temp_value%10);				//显示温度的值
			Oled_ShowString(1, 6, display_buf);
		
			Oled_ShowCHinese(2, 0, "光照:");
			sprintf(display_buf,"%dlux  ",light_value);				//显示温度的值
			Oled_ShowString(2, 6, display_buf);
			Oled_ShowCHinese(3, 0, "人体:");
			if(IRED == 0)
				Oled_ShowCHinese(3, 3, "有人");
			else
				Oled_ShowCHinese(3, 3, "无人");
			
			Oled_ShowCHinese(4, 0, "蓝牙模式:"); 
			
			if(flag_mode_r == 1)
				Oled_ShowCHinese(4, 5, "开启");
			else
				Oled_ShowCHinese(4, 5, "关闭");
		break;
		
		case 1:															//界面1:
			Oled_ShowCHinese(1,0,"设置温度最大值");
			if(time_num % 5 == 0)
			{
				sprintf(display_buf,"%d  ",temp_max);
				Oled_ShowString(2, 7, display_buf);
			}
			if(time_num % 10 == 0)
			{
				Oled_ShowString(2, 7, "    ");
			}
		break;
		
		case 2:															//界面2:
			Oled_ShowCHinese(1,0,"设置温度最小值");
			if(time_num % 5 == 0)
			{
				sprintf(display_buf,"%d  ",temp_min);
				Oled_ShowString(2, 7, display_buf);
			}
			if(time_num % 10 == 0)
			{
				Oled_ShowString(2, 7, "    ");
			}
		break;
		
		case 3:															//界面3:
			Oled_ShowCHinese(1,0,"设置温度中间值");
			if(time_num % 5 == 0)
			{
				sprintf(display_buf,"%d  ",temp_zj);
				Oled_ShowString(2, 7, display_buf);
			}
			if(time_num % 10 == 0)
			{
				Oled_ShowString(2, 7, "    ");
			}
		break;
			
		case 4:															//界面4:
			Oled_ShowCHinese(1,0,"设置光照最小值");
			if(time_num % 5 == 0)
			{
				sprintf(display_buf,"%d  ",light_min);
				Oled_ShowString(2, 7, display_buf);
			}
			if(time_num % 10 == 0)
			{
				Oled_ShowString(2, 7, "    ");
			}
		break;
		
		default:
			
		break;
	}
}

/****
*******处理函数
*****/
void Manage_function(void)
{
	if(flag_mode == 0 && flag_mode_r == 0)
	{
		if(flag_display == 0)                  //测量界面
		{
			if(temp_value > temp_max*10)
			{
				RELAY_ZL = 1;
				RELAY_JR = 0;
				flag_motor_speed = 0;
			}
			else if(temp_value > temp_zj*10)
			{
				flag_motor_speed = 2;
				RELAY_ZL = 0;
				RELAY_JR = 0;
			}
			else if(temp_value > temp_min*10)
			{
				flag_motor_speed = 1;
				RELAY_ZL = 0;
				RELAY_JR = 0;
			}
			else
			{
				flag_motor_speed = 0;
				RELAY_ZL = 0;
				RELAY_JR = 1;
			}
			
			if(light_value < light_min)
			{
				RELAY_ZM = 1;
			}
			else
			{
				RELAY_ZM = 0;
				
			}
		}
		else													         //设置界面
		{
			RELAY_ZM = 0;
			RELAY_JR = 0;
			RELAY_ZL = 0;
			flag_motor_speed = 0;
		}
	}
	switch(flag_motor_speed)						//根据不同的电机速度标志位,控制电机转速
	{
		case 0:
			speed_value = 0;								//停止
		break;
		
		case 1:
			speed_value = 860;								//低速
		break;

		case 2:
			speed_value = 980;								//高速
		break;

		default:
		break;
	}
	TIM_SetCompare1(MOTOR_DIANJI_TIM,speed_value);
	
}

六、实验效果 

七、资料内容

项目分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值