15单片机通过WIFI模块ESP8266实现手机远程监控可燃气体浓度
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
一,系统方案
1、方案描述
当烟雾报警系统处于正常环境中,系统会主动向手机终端发送实时温度,和当前环境中的可燃气体数值。当烟雾报警系统处于达到可燃气体检测设定值时或当温度达到预设定值时,单片机控制端会自动启动继电器进行断气和开窗指令,并且通过互联网向手机终端发送报警,提醒人们采取相应的指示。
2、原理框图
文章图片
3、设计好的实物图
文章图片
4、设计系统原理图
文章图片
二、系统软件设计
1、单片机软件设计
系统采用15单片机(51内核高速单片机内置8通道10位高速ADC,速度可达30万次/秒)
主函数展示:
main()
{
LCD1602_Init();
//初始化LCD
WriteString(0,0,"TEMP: ");
//LCD中写入 TEMP:
WriteString(12,0,"C");
//LCD中写入 C
WriteString(0,1,"KAD:");
//LCD中写入KAD
WriteString(10,1,"M%");
//LCD中写入PPM
ADC_P11_init();
//初始化ADC
esp8266_init();
//初始化ESP8266
delay1ms();
//一毫秒延时while(1)
{
Process_receiveData();
//处理接收数据,并控制继电器操作
LcdDisplayDS18B20(Ds18b20ReadTemp());
//LCD显示ds18b20数据
LcdDisplayADC(ADData);
//LCD显示AD采集MQ-2数据
ESP8266_Set("AT+CIPSEND=0,18");
//向esp8266发送传输18字节数据请求
Delay100ms() ;
Temp_data(Ds18b20ReadTemp());
//获取ds18b20温度传感器数据
ESP8266_ArraySends(ds18b20Wd_buf,8);
//发送ds18b20温度数组
Delay100ms() ;
ADC_data(ADData);
//获取AD采集 数据
ESP8266_ArraySends( ADC_datas_buf,6);
//发送AD采集数组
Delay100ms() ;
//AlertLogic();
处理接受设置上限值
//ESP8266_ArraySends(AlertLogic_buf,3);
返回上限数据结果
ESP8266_ArraySends(Recive_table,4);
//返回接收数据
Delay100ms() ;
ControlLogic();
}
}
串口初始化以及ESP8266初始化函数:
/*********************************************************************
名称: 初始化esp8266
作用: 配置esp8266参数
*********************************************************************/
void esp8266_init()
{
UsartConfiguration();
ms_delay(500);
/ESP8266_Set(“AT+CWMODE=1”); 选择WiFi模式1
ms_delay(500);
ESP8266_Set(“AT+RST”);
ms_delay(1000);
ESP8266_Set("AT+CWJAP=“haqimeme”,“guoxuan@123"”);
ms_delay(3000);
ESP8266_Set("AT+CIPSTA=“192.168.1.113”,“192.168.1.1”,“255.255.255.0"”);
ms_delay(1000);
ESP8266_Set(“AT+RST”);
ms_delay(6000);
ESP8266_Set(“AT+CIPMUX=1”);
ms_delay(500);
//ESP8266_Set(“AT+CIFSR”); //查看ip地址
ESP8266_Set(“AT+CIPSERVER=1,8080”);
ms_delay(500);
ESP8266_Set(“AT+CIPSTO=0”); /
ESP8266_Set("AT+CIPMUX=1");
//允许多连接
ms_delay(500);
// ESP8266_Set(“AT+CIFSR”); //查看ip地址
ESP8266_Set(“AT+CIPSERVER=1,8080”);
ms_delay(500);
ES = 1;
//开串口中断
}
/*******************************************************************************
- 函 数 名 : UsartConfiguration()
- 函数功能 : 设置串口
- 输 入 : 无
- 输 出 : 无
*******************************************************************************/
{
ACC = P_SW1;
ACC &= ~(S1_S0|S1_S1); //S1_S0=1,S1_S1=0;
ACC |= S1_S0; //(P3.6/RxD_2,P3.7/TxD_2)
P_SW1 = ACC;
TMOD = 0x20;
// 0010 0000 定时器1工作于方式2(8位自动重装方式)l
TH1= 0xFD;
// 波特率:9600 /11.0592MHZ
TL1= 0xFD;
// 波特率:9600 /11.0592MHZ
TR1= 1;
//下面代码设置定串口
AUXR &= 0xBE;
//先对需要设置的位进行清零 1011 1110
AUXR = 0x00;
// 很关键,使用定时器1作为波特率发生器,S1ST2=0
SCON = 0x50;
// 0101 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接受)
ES = 1;
//开放串口中断
EA = 1;
//开放CPU中断
}
esp8266发送数组函数
/*********************************************************************************
- 函数名 :ESP8266_ArraySends
- 函数功能 :发送数组
- 输出 :无
- 输入 :发送数组,发送数组位数
*********************************************************************************/
{
uchar i;
for(i=0;
i
}
esp8266在收到数据并转发给单片机时的数据格式:+IPD,
/*********************************************************************
名称:串行通讯中断
作用:发送或接收结束后进入该函数,对相应的标志位软件清0,实现模块对数
据正常的收发。
********************************************************************/
void Uart_Interrupt() interrupt 4 using 1
{
if(RI)
{
EA=0;
Recive_esp8266mode[j]=SBUF;
RI=0;
j++;
if(j==2)
{
if(Recive_esp8266mode[0]=='+'&&Recive_esp8266mode[1]=='I')//判断接收到数据是否是上位机发送的数据
{
;
}
else
{
j=0;
}
}
if(j==13)
{
j=0;
Recivedata_flag=1;
}EA=1;
}
}
2、Android APP软件开发部分
Android APP软件开发环境为Android studio ,界面简洁终端ID输入的是IP地址192.168.1.112,端口号是8080;因为esp8266选择的是WiFi模式一与家中的路由器组成局域网,在通过指令AT+CIPSTA=“192.168.1.112”,“192.168.1.1”,“255.255.255.0”); //设置静态IP方便连接互联网时能够寻址。连接互联网时需要公网ip,这里博主通过花生壳解析域名获取公网IP达到访问系统效果。
文章图片
Android APP软件逻辑接收代码:
class Myhandler extends Handler {
byte[] SocketReadData= https://www.it610.com/article/new byte[socketclient.RC_DATA.length];
@Override
public void handleMessage(Message msg) {
SocketReadData=https://www.it610.com/article/(byte[])msg.obj;
if(SocketReadData[0]==0&&SocketReadData[1]==1){
Temp= SocketReadData[3]*10000+SocketReadData[4]*1000+SocketReadData[5]*100+SocketReadData[6]*10+SocketReadData[7];
if(SocketReadData[2]==0){
Temp=-(Temp/100);
}
else{
Temp=Temp/100;
}
}else{
Temp=0;
}
if(SocketReadData[8]==0&&SocketReadData[9]==2){
KAD=SocketReadData[10]*1000+SocketReadData[11]*100+SocketReadData[12]*10+SocketReadData[13];
}
if ( KAD>550||Temp>50)
{
flag++;
if(flag==2){//flag 为出发警报Activity标志位,数值为2 防止数据误发导致出发报警
Intent intent1 = new Intent(SecondActivity.this, ThirdActivity.class);
//显示intent
startActivity(intent1);
}}if(SocketReadData[14]==1&&SocketReadData[15]==1&&SocketReadData[16]==1&&SocketReadData[17]==1)
{
imageButton1.setImageDrawable(getResources().getDrawable(R.mipmap.shut));
a=1;
}
if(SocketReadData[14]==1&&SocketReadData[15]==1&&SocketReadData[16]==2&&SocketReadData[17]==2)
{
imageButton1.setImageDrawable(getResources().getDrawable(R.mipmap.open));
a=0;
}
/*if(SocketReadData[19]==1&&SocketReadData[20]==2&&SocketReadData[21]==1&&SocketReadData[22]==1)
{
imageButton2.setImageDrawable(getResources().getDrawable(R.mipmap.shut));
b=1;
}
if(SocketReadData[19]==1&&SocketReadData[20]==2&&SocketReadData[21]==2&&SocketReadData[22]==2)
{
imageButton2.setImageDrawable(getResources().getDrawable(R.mipmap.open));
b=0;
}*/tvReceive.setText("DS18B20温度 :"+ Temp+"℃"+"\n"+"KAD :"+ KAD +"M%");
}}
【物联网|15单片机通过WIFI模块ESP8266实现手机远程监控可燃气体浓度】Android APP软件逻辑向可燃气体监测系统发送数据代码:
public void sends(String j){
switch (j){
case “0x00156f4”:SD_DATA[1]=1; SD_DATA[2]=1; SD_DATA[3]=1; break; //闭合继电器1
case “0x00256f4”:SD_DATA[1]=1; SD_DATA[2]=2; SD_DATA[3]=2; break; //断开继电器1
// case “0x00356f4”:SD_DATA[1]=2; SD_DATA[2]=1; SD_DATA[3]=1; break; //闭合继电器2
// case “0x00456f4”:SD_DATA[1]=2; SD_DATA[2]=2; SD_DATA[3]=2; break; //闭合继电器2
}
socketclient.Sends(SD_DATA);
}}
报警界面代码:
public class ThirdActivity extends AppCompatActivity {
MediaPlayer player;
Vibrator vibrator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
player = MediaPlayer.create(this, R.raw.huozaijingbaosheng);
player.start();
vibrator = (Vibrator)this.getSystemService(this.VIBRATOR_SERVICE);
long[] patter = {1000, 1000, 2000, 5000}; //首先,这里使用的是一个长整型数组,数组的a[0]表示静止的时间,a[1]代表的是震动的时间,然后数组的a[2]表示静止的时间,a[3]代表的是震动的时间……依次类推下去,然后这里的代码有一点小小的改变:
vibrator.vibrate(patter, 0); //最后一行中vibrate的第二参数表示从哪里开始循环,比如这里的0表示这个数组在第一次循环完之后会从下标0开始循环到最后,这里的如果是-1表示不循环。
}
public void click(View v) {flag=0;
player.release();
vibrator.cancel();
finish();
}
}
系统博主挂到淘宝上,如需详细资料可点击下面链接购买:
https://item.taobao.com/item.htm?spm=a2oq0.12575281.0.0.75dc1debztCHw3&ft=t&id=602060950301