锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

51单片机WIFI功能APP控制火灾报警仿真系统

时间:2023-07-31 06:37:30 ydl连接器

最近用手机做了51单片机驱动8266APP控制火灾报警功能的板。下面给大家介绍一下,有需要的朋友可以私信。

由于时间有限,我会慢慢更新这部分。

先上整体图

手机app截图

1.功能描述。

a、使用DS18B读取温度,并在app上显示。超过26度报警,报警灯亮,蜂鸣器响,app报警灯变红。

b、使用MQ-2.阅读烟雾浓度,并在app超过40ppm报警,报警灯亮,蜂鸣器响,app报警灯变红。

c、用120度火焰传感器感受火焰app报警。检测到火焰后,报警灯亮,蜂鸣器响,app报警灯变红。

d、上电后,手动模式指示灯在板上和app同时点亮绿灯。这时,可以手动操作app上按上 下 左 右按钮,控制光源跟踪板旋转;可按水泵按钮,控制水泵继电器吸合,然后控制水泵动作。

e、在app按下手动按钮,切换到自动模式,自动模式指示灯在板上app同时点亮,为绿灯。此时,光源跟踪板自动跟踪光源旋转,可用手电筒模拟;对准光源后,打开水泵;水泵工作10s之后,自动关闭。之后,流程循环进行。

硬件设计。

直接上图。

没什么好说的,看图就行了。

3.软件设计。

#include  #include  #include "math.H" #include  #include "PCF8591.H"  #define uchar unsigned char  // 以后unsigned char就可以用uchar代替 #define uint  unsigned int  // 以后unsigned int 就可以用uint 代替 #define del   20//调速 #define ydl   20 //移动调节 #define  PCF8591 0x90    //PCF8591 地址   sbit temp_led=P0^0; sbit smoke_led=P0^1; sbit fire_led=P0^2; sbit auto_led=P0^3; sbit manual_led=P0^4; sbit pump=P1^0; sbit fire1=P3^3; sbit fire2=P3^4; sbit fire3=P3^5; sbit fire4=P3^6; sbit fire5=P3^7;   sbit DQ       = P1^1;     // 温度传感器的引脚 sbit ADC_CS   = P1^2;     // ADC0832的CS引脚 sbit ADC_CLK  = P1^3;     // ADC0832的CLK引脚 sbit ADC_DAT  = P1^4;     // ADC0832的DI/DO引脚 sbit Buzzer_P = P0^5;     // 蜂鸣器  bit up_flag; bit down_flag; bit left_flag; bit right_flag; bit pump_flag; bit AM_flag=0; bit Auto_start;   uchar Motor_Up[4]={0x08,0x04,0x02,0x01}; uchar Motor_Down[4]={0x01,0x02,0x04,0x08};   uchar Motor_Left[4]={0x10,0x20,0x40,0x80}; uchar Motor_Right[4]={0x80,0x40,0x20,0x10};   uchar AD_CHANNEL; uchar AD_Up,AD_Down,AD_Left,AD_Right;   uint i;  uchar dat[20];  uchar temp_flag;        // 温度报警标志位 uchar smoke_flag;        // 烟雾报警标志位 uchar fire_flag;        // 火焰报警标志位  int   temp;         // 保存温度值 uchar smoke;         // 保存烟雾值 uchar Smoke_Alarm=30;        // 烟雾报警值 int   Temp_Alarm=26;       // 温度报警值   uint time_20ms=0;//定时器计数 bit disFlag ;  //显示标志 unsigned char Recive_table[15];       /*********************************************************/ // 毫秒延迟函数,time毫秒数要延迟 /*********************************************************/ void DelayMs(uint time) {  uint a,b;  for(a=0;a3)    {     AD_CHANNEL=0;    }   }   if((AD_Up25)//上转    {    for(i=0;iAD_Down)&&(AD_Up-AD_Down>25)//下转   {    for(i=0;i25)//左转   {    for(i=0;iAD_Right)&&(AD_Left-AD_Right>25))//右转
		{
			for(i=0;i0)		// 写1
		{
			DQ=0;
			Delay15us();
			DQ=1;
			Delay15us();
			Delay15us();
			Delay15us();
			Delay15us();
		}
		else			// 写0
		{
			DQ=0;
			Delay15us();
			Delay15us();
			Delay15us();
			Delay15us();
			DQ=1;
			Delay15us();
		}
	}
}


/*********************************************************/
// 读取温度值
/*********************************************************/
int DS18B20_ReadTemp(void)
{
	uchar j;
	int b,temp=0;	

	EA=0;
	DS18B20_ReSet();							// 产生复位脉
	DS18B20_WriteByte(0xcc);			// 忽略ROM指令
	DS18B20_WriteByte(0x44);			// 启动温度转换指令

	DS18B20_ReSet();							// 产生复位脉
	DS18B20_WriteByte(0xcc);			// 忽略ROM指令
	DS18B20_WriteByte(0xbe);			// 读取温度指令

	for(j=0;j<16;j++)							// 读取温度数量
	{						
		DQ=0;
		_nop_();
		_nop_();
		DQ=1;	
		Delay15us();
		b=DQ;
		Delay15us();
		Delay15us();
		Delay15us();
		b=b<>= 1;
		if(ADC_DAT)
			dat2=dat2|0x80;
		else
			dat2=dat2|0x00;
		WavePlus();
	}
	
	_nop_();						// 结束此次传输
	ADC_DAT = 1;
	ADC_CLK = 1;
	ADC_CS  = 1;   

	if(dat1==dat2)			// 返回采集结果
		return (dat1);
	else
		return 0;
} 
/*********************************************************/
// 报警判断
/*********************************************************/
void AlarmJudge(uchar dat1, int dat2)
{
/*火焰报警判断*/
	if((fire1==1)||(fire2==1)||(fire3==1)||(fire4==1)||(fire5==1))
	{
		
			fire_led=0;
			fire_flag=1;
		
	}
	else
	{
		  fire_led=1;
		  fire_flag=0;
	}
	
	/*烟雾报警判断*/
	if(dat1>Smoke_Alarm)
	{
		smoke_led=0;
		smoke_flag=1;
	}
	else
	{
		smoke_led=1;
		smoke_flag=0;
	}
	
	/*温度报警判断*/
	if(dat2>Temp_Alarm)
	{	
		temp_led=0;
		temp_flag=1;
	}
	else
	{
		temp_led=1;
		temp_flag=0;
	}

	/*蜂鸣器报警判断*/
	if((temp_flag==1)||(smoke_flag==1)||(fire_flag==1))
	{
		Buzzer_P=0;
		//Motor_P=0;
		Auto_start=1;
	}
	else
	{
		Buzzer_P=1;
		//Motor_P=1;
		Auto_start=0;
		
	}
}

/*********************************************************/
// ATK-ESP8266向上位机发送数据
/*********************************************************/

void SendDat(int temp,uchar smoke)
{
			
	dat[0]=(char)(temp%100/10)+48;//发送温度值的十位
	dat[1]=(char)(temp%10)+48;//发送温度值的个位
	dat[2]=(char)temp_flag+48;//发送温度值报警标志位
	dat[3]=(char)fire_flag+48;//发送火焰报警标志位
	dat[4]=(char)smoke_flag+48;//发送烟雾浓度报警标志位
	dat[5]=(char)(smoke%100/10)+48;//发送烟雾浓度值的十位
	dat[6]=(char)(smoke%10)+48;//发送烟雾浓度值的个位
	
}
/*********************************************************/
// 初始化串口
/*********************************************************/
void Init_uart(void) {  
	TMOD = TMOD | 0x20;    //???1?????2  8?????  
	SCON = SCON | 0x50;    //??1?????1  10????? REN=1????  
	TH1 = 0xFd;            //???1??  
	TL1 = TH1;  
	TR1 = 1;               //???1????  
	EA =1;                 //????  
	ES =1;                 //
}
 
 

/*********************************************************/
// 串口发送一个字节数据
/*********************************************************/
void Uart_SendByteData(uchar a)
{
	SBUF = a;
	while(TI==0);
	TI=0;
	
}
/*********************************************************/
// 串口发送字符串
/*********************************************************/

void Uart_SendStrData(uchar *s)
{
	while(*s!='\0')
	{
		Uart_SendByteData(*s);
		s++;
	}
		
}
 
/*********************************************************/
// ATK-ESP8266初始化
/*********************************************************/
void Init_ESP01S(){   
	DelayMs(50);  
	Uart_SendStrData("AT+CIPMUX=1\r\n");            // ?????
	DelayMs(5);   
	Uart_SendStrData("AT+CIPSERVER=1,8080\r\n");      // ?????,??8080??
	DelayMs(5);
}
 
/*********************************************************/
// 定时器0初始化
/*********************************************************/
void Init_Timer0(void)
{
    TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
    TH0=(65536-20000)/256;		  //重新赋值 20ms
    TL0=(65536-20000)%256;
    EA=1;            //总中断打开
    ET0=1;           //定时器中断打开
    TR0=1;           //定时器开关打开
}
/*********************************************************/
// 定时器0定时20ms
/*********************************************************/
void Timer0_isr(void) interrupt 1
{
    TH0=(65536-20000)/256;		  //重新赋值 20ms
    TL0=(65536-20000)%256;

    time_20ms++;
    if(time_20ms%5==0)//定时时间到
    {     
			disFlag=1;//标志位置位			 
    }
}
/*********************************************************/
// 主程序
/*********************************************************/ 
void main(){
	
	Init_Timer0();
	Init_uart();
	Init_ESP01S();    
	
	
	while(DS18B20_ReadTemp()==85)						// 等待传感器初始化完成
	{
		DelayMs(10);
	}
	
	
	while(1)
	{
		
		smoke=Get_ADC0832();				// 获取烟雾的浓度值
		smoke=smoke/2.2;							// 调整浓度值,使其在0-100之间变化
		if(smoke>100)smoke=99;
	
		
		
		temp=DS18B20_ReadTemp();	// 读取温度值
		
		AlarmJudge(smoke,temp);			// 报警判断
		
		
	
		if(AM_flag==1)
		{
			manual_led=1;
			auto_led=0;
			if(Auto_start==1)auto_move();			
		}
		else
		{
			manual_led=0;
			auto_led=1;
			manual_move();			
		}
		
		
		
		//sprintf(dat,"%d%d%d%d%d%d",temp,(int)temp_flag,(int)fire_flag,(int)smoke_flag,(int)smoke);
		SendDat(temp,smoke);

		if(disFlag==1)
		{
		
			disFlag=0;
			Uart_SendStrData("AT+CIPSEND=0,7\r\n");
			DelayMs(5);	
			Uart_SendStrData(dat);
			DelayMs(5);						
		}
		
	}
}
/*********************************************************/
// 接收数据中断服务程序
/*********************************************************/		
void UART_Interrupt(void) interrupt 4
{
    
    if(RI == 1)   
    {
        RI = 0;     //清除串口接收标志位
	      Recive_table[i]=SBUF;
	      if(Recive_table[0]=='+')
				{
					i++;
				}
				else
				{
					i=0;
				}
				if(i==10)
				{
					i=0;
					switch(Recive_table[9])//+IPD,0,1:0
						{
							case '1':{up_flag = 1;break;}
							case '2':{down_flag = 1;break;}
							case '3':{left_flag = 1;break;}
							case '4':{right_flag = 1;break;}
						  case '5':{AM_flag=1;break;}//自动标志位,AM_flag=1
							case '6':{AM_flag=0;break;}//手动标志位,AM_flag=0
							case '7':{pump_flag=1;break;}//
							case '9':{up_flag = 0;down_flag = 0;left_flag = 0;right_flag = 0;pump_flag=0;break;}						
												
						}
         }
			 }
		 }


对于程序,我不做全部解释,有疑问的朋友可以私信或者评论。

我这里只把我遇到的问题说一下:

a、DS18B20读取温度程序。

如下

/*********************************************************/
// 读取温度值
/*********************************************************/
int DS18B20_ReadTemp(void)
{
	uchar j;
	int b,temp=0;	

	EA=0;
	DS18B20_ReSet();							// 产生复位脉
	DS18B20_WriteByte(0xcc);			// 忽略ROM指令
	DS18B20_WriteByte(0x44);			// 启动温度转换指令

	DS18B20_ReSet();							// 产生复位脉
	DS18B20_WriteByte(0xcc);			// 忽略ROM指令
	DS18B20_WriteByte(0xbe);			// 读取温度指令

	for(j=0;j<16;j++)							// 读取温度数量
	{						
		DQ=0;
		_nop_();
		_nop_();
		DQ=1;	
		Delay15us();
		b=DQ;
		Delay15us();
		Delay15us();
		Delay15us();
		b=b<

 在程序的开始和末尾最好加上EA=0和EA=1。就是禁用总中断和开启总中断。因为DS18B20对于时序很敏感,如果不加这两个命令,读取温度会出现乱码!

b、ATK-ESP8266发送数据时,组成字符串程序。

如下为组成字符串程序

void SendDat(int temp,uchar smoke)
{
			
	dat[0]=(char)(temp%100/10)+48;//发送温度值的十位
	dat[1]=(char)(temp%10)+48;//发送温度值的个位
	dat[2]=(char)temp_flag+48;//发送温度值报警标志位
	dat[3]=(char)fire_flag+48;//发送火焰报警标志位
	dat[4]=(char)smoke_flag+48;//发送烟雾浓度报警标志位
	dat[5]=(char)(smoke%100/10)+48;//发送烟雾浓度值的十位
	dat[6]=(char)(smoke%10)+48;//发送烟雾浓度值的个位
	
}

如下为发送程序

SendDat(temp,smoke);

		if(disFlag==1)
		{
		
			disFlag=0;
			Uart_SendStrData("AT+CIPSEND=0,7\r\n");
			DelayMs(5);	
			Uart_SendStrData(dat);
			DelayMs(5);						
		}

组成字符串程序时,也可以用sprintf函数,比如:sprintf(dat,"%d%d%d%d%d%d",temp,(int)temp_flag,(int)fire_flag,(int)smoke_flag,(int)smoke);

如果这样写,不仅会增加代码总量大小,而且sprintf用不好的话会造成错误。所以建议使用如上的字符串组成程序。

c、初始化ATK-ESP8266时,在函数开头应该延时一段时间,让板子上电时,8266自己可以有个初始化过程,否则8266会出现错误,导致连接不上8266。

/*********************************************************/
// ATK-ESP8266初始化
/*********************************************************/
void Init_ESP01S(){   
	DelayMs(50);  
	Uart_SendStrData("AT+CIPMUX=1\r\n");            // ?????
	DelayMs(5);   
	Uart_SendStrData("AT+CIPSERVER=1,8080\r\n");      // ?????,??8080??
	DelayMs(5);
}

以上就是我的描述,想进一步了解的朋友私信我。谢谢!

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章