基于Lora实现的屋内火灾报警系统

1.功能设计

  本项目设计一种基于LORA无线通信的屋内火灾报警控制系统,采用DH11温湿度传感器跟MQ-2烟雾传感器作为火警安防系统,对房内温度,湿度,还有环境可燃气体,烟雾等实时检测,LORA通信为通信报警方法,LED跟蜂鸣器为声光报警,SG90舵机做为应急措施的开关。当温度湿度传感部分采集到超过限定温度值和低于限定湿度值时,会将信号发给相对应的传感检测部分,然后传感检测部分将信号发给核心处理器单片机,STM32F103RCT6核心处理单片机引脚电平转换,驱动声光报警系统和应急措施,同时启动LORA通信发送给业主和物业,让救援人员来时了解到大致情况做好充足准备。

基于Lora实现的屋内火灾报警系统_第1张图片

 (1) 检测项目:当环境温度≥45℃,湿度≤10%就可被判定为火灾,或者可燃气体甲烷浓度≥5%也可被判定为火灾可能发生,实施报警,并且采取应急措施。烟雾浓度≥5%被认定为有毒害,实施报警。

基于Lora实现的屋内火灾报警系统_第2张图片

 

(2) 报警方式:声光报警,小区物业报警,户主报警。

(3) 应急措施:通过舵机控制阻燃气体的发射。

2.硬件设计

  本系统由电源电路、主控制器、温度,湿度检测电路、烟雾可燃气体检测电路,LORA模块收发电路,应急措施电路,信息显示电路,声光报警电路等8个部分组成。

基于Lora实现的屋内火灾报警系统_第3张图片

 基于Lora实现的屋内火灾报警系统_第4张图片

3.软件设计

基于Lora实现的屋内火灾报警系统_第5张图片 

 

其余介绍看,评论区报告链接,硬件设备工作流程图,以及步骤介绍等等。。。

程序分享

1.main.c

#include "led.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "dh11.h"   
#include "adc.h"  
#include "sys.h"
#include "delay.h"
#include "pwm.h"
#include "beep.h"
#include "lora.h"
#include "usart1.h"
#include "usart3.h"
char lora_tx_data[100];
char lora_rx_data[100];
 int main(void)
 { 
	u16 ADC_SHIDU ;
	u8 t=0;			 
	u8 temp;   
	u8 humi;
	 
	delay_init();	    	 //延时函数初始化	  
  Adc_Init();   	 //延时函数初始化	  
	uart_init(115200);	 	//串口初始化为9600
	LED_Init();		  		//初始化与LED连接的硬件接口
 	LCD_Init();
	Beep_Init();//蜂鸣器初始化 
  SystemInit();	//配置系统时钟为 72M  
	USART1_Config();
	TIM3_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz 
	USART3_Config(115200); //USART3 配置 		
	LORA_Init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	 
	 
 	POINT_COLOR=BLUE;//设置字体为蓝色 
	LCD_ShowString(60,50,200,16,16,"GHB");	
	LCD_ShowString(60,70,200,16,16,"GXW");	
	LCD_ShowString(60,90,200,16,16,"LX");
	LCD_ShowString(60,110,200,16,16,"2021/12/6");		  
	LCD_ShowString(60,130,200,16,16,"DHT11 OK");
	LCD_ShowString(60,150,200,16,16,"QCM2  OK");
	POINT_COLOR=BLUE;//设置字体为蓝色 
 	LCD_ShowString(60,170,200,16,16,"Temp:   . C");	 
	LCD_ShowString(60,190,200,16,16,"Humi:   %");	 
	LCD_ShowString(60,210,200,16,16,"Qtzl:   %");
	

	while(DHT11_Init())	//DHT11初始化	
	{
		LCD_ShowString(60,130,200,16,16,"DHT11 Error");
		delay_ms(200);
		LCD_Fill(60,130,239,130+16,WHITE);
 		delay_ms(200);
	}								   
	while(1)
	{	    	   
   ADC_SHIDU=ADC_Get_aveg(ADC_Channel_1,10);
	 ADC_SHIDU = (float)(ADC_SHIDU/4096.0)*100;   

		{		
			
       DHT11_Read_Data(&temp,&humi);	//读取温湿度值	
       LCD_ShowNum(60+40+4,170,temp,2,16);	//显示温度		
       LCD_ShowNum(60+40+28,170,temp%10,1,16);	//显示温度				
	     LCD_ShowNum(60+40+6,190,humi,2,16);		//显示湿度	 			
       LCD_ShowNum(60+40+6,210,ADC_SHIDU,2,16);	
				delay_ms(100);
		}
	 	delay_ms(10);
		t++;
		if(t==20)
		{
			t=0;
			LED1=!LED1;
		}
		
		if(temp>30)
		{
			
			delay_ms(100);
		LED0=!LED0;
		delay_ms(100);
		LED1=!LED1;
		GPIO_ResetBits(GPIOA, GPIO_Pin_8);//输出低电平
		delay_ms(100);		
		GPIO_SetBits(GPIOA, GPIO_Pin_8);//输出高电平
		delay_ms(100);			//延时100毫秒
		TIM_SetCompare1(TIM3, 195);//0度
		delay_ms(100);
		TIM_SetCompare1(TIM3, 190);//45度
		delay_ms(100);	
	 sprintf((char*)lora_tx_data,"温度:%d‰\r\n烟雾:%d %$", temp,  ADC_SHIDU);
		lora_transmit(lora_tx_data);	
		delay_ms(100);	
		}
		if(ADC_SHIDU>40)
		{
			
		delay_ms(100);
		LED0=!LED0;
		delay_ms(100);
		LED1=!LED1;
		GPIO_ResetBits(GPIOA, GPIO_Pin_8);//输出低电平
		delay_ms(100);		
		GPIO_SetBits(GPIOA, GPIO_Pin_8);//输出高电平
		delay_ms(100);			//延时100毫秒
		TIM_SetCompare1(TIM3, 195);//0度
		delay_ms(100);
		TIM_SetCompare1(TIM3, 190);//45度
		delay_ms(100);	
	 sprintf((char*)lora_tx_data,"温度:%d‰\r\n烟雾:%d %$", temp,  ADC_SHIDU);
		lora_transmit(lora_tx_data);	
		delay_ms(100);
		}
		
	}
}

2. LORA.C

#include "lora.h"
//#include "usart.h"
#include "usart1.h"
#include "usart3.h"
#include "delay.h"
#include "led.h"

void MD0_Config(void)	
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); // 使能PC端口时钟  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;	//选择对应的引脚
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化PC端口
  GPIO_ResetBits(GPIOA, GPIO_Pin_11 );	 //拉低
}

void AUX_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启按键端口PA的时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //端口配置为下拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//初始化端口
	GPIO_ResetBits(GPIOA, GPIO_Pin_4 );	 // 关闭所有LED
}

int AUX(void) 
{
		if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4) == 1)
			return 1;
		else
			return 0;
}					
void lora_check(void)
{
	int OK_state = 0;
	while(AUX())//检测模块是否在忙
	{
		 UART1TX("Lora正忙1");
		 delay_ms(500);
	}
	MD0(1);
	delay_ms(40);
	UART1TX("LORA检测中......");
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT");
		UART3Test(&OK_state);	
	}
	UART1TX("LORA检测成功");
	UART1TX("   ");
}

void lora_set(void)
{
	/*#####设置地址#########*/
	int OK_state = 0;
	char addr[20] = {0};int t1 = 0,t2 = 0;
	unsigned char i = 0;
	while(AUX())//等待模块空闲
	{
		 UART1TX("Lora正忙2");
	}
	MD0(1);
	delay_ms(40);
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+ADDR=00,00");
		UART3Test(&OK_state);
		UART1TX("地址设置中......");
	}
	UART1TX("地址为:");
	UART3TX("AT+ADDR?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");
	/*#################设置信道和速率###############*/
	OK_state = 0; 
	t1 = 0;
	t2 = 0;
	
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+WLRATE=23,5");
		UART3Test(&OK_state);
		UART1TX("信道速率设置中......");
	}
	UART1TX("信道,速率为:");
	UART3TX("AT+WLRATE?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");	
/*#############发射功率##############*/
	OK_state = 0; 
	t1 = 0;
	t2 = 0;
	
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+TPOWER=3");
		UART3Test(&OK_state);
		UART1TX("发射功率设置中......");
	}
	UART1TX("发射功率为:");
	UART3TX("AT+TPOWER?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");	
/*#################工作模式###################*/
	OK_state = 0; 
	t1 = 0;
	t2 = 0;
	
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+CWMODE=0");
		UART3Test(&OK_state);
		UART1TX("工作模式设置中......");
	}
	UART1TX("工作模式为:");
	UART3TX("AT+CWMODE?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");		
/*#################发送状态#################*/
	OK_state = 0; 
	t1 = 0;
	t2 = 0;
	
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+TMODE=0");//0:透明传输,1:定向传输
		UART3Test(&OK_state);
		UART1TX("发送状态设置中......");
	}
	UART1TX("发送状态为:");
	UART3TX("AT+TMODE?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");	
/*#############睡眠时间#################*/
	OK_state = 0; 
	t1 = 0;
	t2 = 0;
	
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+WLTIME=0");
		UART3Test(&OK_state);
		UART1TX("睡眠时间设置中......");
	}
	UART1TX("睡眠时间为:");
	UART3TX("AT+WLTIME?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");	
/*################波特率,数据校验位####################*/
	OK_state = 0; 
	t1 = 0;
	t2 = 0;
	
	while(!OK_state)//模块检测成功
	{
		UART3TX("AT+UART=3,0");
		UART3Test(&OK_state);
		UART1TX("波特率,数据校验位设置中......");
	}
	UART1TX("波特率,数据校验位为:");
	UART3TX("AT+UART?");
	while(1)
	{
			UART3GetByte(&i);
			if(i==':')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='O')
					{
						addr[t1++]=i;
					}
					else if(i=='O')
						break;	 
				}
				while(1)
				{
						UART1SendByte(addr[t2++]);
						if(t1 == t2)
							break;
				}
				break;
			} 
	}
	UART1TX("  ");	
	MD0(0);
	delay_ms(40);
	while(AUX());
	USART3_Config(9600); //USART3 配置 
	
	
	UART1TX("LORA配置完成######################");
}



void lora_transmit(char* a)
{
		int i = 0;
		UART3SendByte('#');//起始符
		while(a[i] != '$')
		{
				UART3SendByte(a[i]);
				i++;
		}
		UART3SendByte('$');//结束符
		UART3SendByte('\r');
		UART3SendByte('\n');
		
}


void lora_receive(void)
{
	unsigned char i = 0;
	extern unsigned char lora_rx_data[100];
//		extern char lora_rx_data[9];
	int t1 = 0,t2 = 0;
	while(1)
	{
			UART3GetByte(&i);
			if(i=='#')
			{
				while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='$')
					{
						lora_rx_data[t1++]=i;
					}
					else if(i=='$')
						break;	 
				}
				while(1)
				{
						UART1SendByte(lora_rx_data[t2++]);
						if(t1 == t2)
						{
							UART1SendByte('\r');
							UART1SendByte('\n');
							break;
						}
				}
				break;
			}
	}
				
}

void LORA_Init(void)
{
		MD0_Config(); //初始化MD0 
		AUX_Config();
//		LED_Config();
		lora_check();
		lora_set();   //配置LORA


}

3. DHC11.C

#include "dh11.h"
#include "delay.h"
      
//复位DHT11
void DHT11_Rst(void)	   
{                 
	DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	//拉低DQ
    delay_ms(20);    	//拉低至少18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
	delay_us(50);     	//主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void) 	   
{   
	u8 retry=0;
	DHT11_IO_IN();//SET INPUT	 
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}
//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void) 			 
{
 	u8 retry=0;
	while(DHT11_DQ_IN&&retry<100)//等待变为低电平
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待变高电平
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_Read_Bit();
    }						    
    return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
 	u8 buf[5];
	u8 i;
	DHT11_Rst();
	if(DHT11_Check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=buf[0];
			*temp=buf[2];
		}
	}else return 1;
	return 0;	    
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在    	 
u8 DHT11_Init(void)
{	 
 
	DHT11_Rst();  //复位DHT11
	return DHT11_Check();//等待DHT11的回应
} 

4. PWM.C

#include "pwm.h"
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{  
	 GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能
	                                                                     	

   //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM_CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	
	TIM_TimeBaseStructure.TIM_Period = 199; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 80K
	TIM_TimeBaseStructure.TIM_Prescaler =7199; //设置用来作为TIMx时钟频率除数的预分频值  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

  TIM_CtrlPWMOutputs(TIM3,ENABLE);	//MOE 主输出使能	

	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //CH1预装载使能	 
	
	TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM3, ENABLE);  //使能TIM1
 
   
}

5.ADC.C

#include "adc.h"
void Adc_Init(void)
{

    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12MHZ 
    
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
    

  ADC_Cmd(ADC1, ENABLE);

 
  ADC_ResetCalibration(ADC1);
 
  while(ADC_GetResetCalibrationStatus(ADC1));

 
  ADC_StartCalibration(ADC1);
 
  while(ADC_GetCalibrationStatus(ADC1));
}

u16 Get_val(u8 ch)
{
    u16 DataValue; 

  ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5);
    
  
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    
 DataValue = ADC_GetConversionValue(ADC1); 
return DataValue; 
} 

u16 ADC_Get_aveg(u8 ch,u8 n) 
{ 
	u32 ad_sum = 0; 
	u8 i; 
	for(i=0;i

你可能感兴趣的:(项目学习,单片机,stm32,嵌入式硬件,算法,arm)