火灾检测系统课设报告
目录
一、 需求分析···································1
二、 系统设计···································2
三、 详细设计···································2
四、 调试分析···································8
五、 总结分析···································9
六、 团队运行情况和个人工作描述·················9
七、 附录·············································10
一、需求分析
1、设计内容:
设计一个能对火灾进行检测的系统
2、设计要求:
能够检测到明火,能够报警,能够喷洒灭火。上位机能够显示所有节点、以及它们之间的关系,能够绑定喷洒装置,能够控制喷洒。
3、设计实现功能分析:
1)一个终端节点上连有温湿度传感器、火焰传感器、烟雾传感器
2)一个协调器上连接继电器(继电器连接水泵来控制水泵工作)、蜂鸣器
3)通过上位机能够看到所有节点的状态、实现火灾报警和能在没有火灾的时候通过上位机控制继电器的工作
4)当有火焰产生时或是温湿度超出界限或是烟雾超过一定界限,蜂鸣器就会报警上位机也会报警,同时继电器开始工作让水泵实现浇水
4、实验平台以及工具:
实验平台:IAR的Embedded Workbench系列是一种增强型一体化嵌入式集成开发环境,其中完全集成了开发嵌入式系统所需要的文件编辑、项目管理、编译、链接和调试工具。
实验工具:CC2530模块,火焰传感器,DTH11温湿度传感器,烟雾传感器,蜂鸣器,继电器,水泵。
5、课设协议栈:
Z-Stack Home 1.2.2a
二、系统设计
- 系统组成图
- 传感器模块以及与节点的接口
1)DHT11温湿度传感器:
DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
原理图:
对其口的定义:#define DATA_PIN P0_4
2)火焰传感器
火焰传感器:由各种燃烧生成物、中间物、高温气体、碳氢物质以及无机物质为主体的高温固体微粒构成的。火焰的热辐射具有离散光谱的气体辐射和连续光谱的固体辐射。不同燃烧物的火焰辐射强度、波长分布有所差异,但总体来说,其对应火焰温度的近红外波长域及紫外光域具有很大的辐射强度,根据这种特性可制成火焰传感器。
原理图:
对其口的定义:#define DATA_PIN1 P0_5
3)MQ-2烟雾传感器
MQ-2常用于家庭和工厂的气体泄漏监测装置,适宜于液化气、苯、烷、酒精、氢气、烟雾等的探测。故因此,MQ-2可以准确来说是一个多种气体探测器。
MQ-2的探测范围极其的广泛。它的优点:灵敏度高、响应快、稳定性好、寿命长、驱动电路简单。
原理图:
对其口的定义:#define DATA_PIN3 P0_6
4)蜂鸣器
原理图:
对其口的定义:P0DIR |= 0x80;
5)继电器
继电器vcc GND 接5v gnd
继电器输入端IN1 接STC89C52单片机任意io口,尽量避免P30 和 P31
上电后 继电器会不断吸和与释放
原理图:
对其口定义:#define DATA_PIN2 P1_7
- 实现流程图:
三、详细设计
对于不同的模块,我们编写了不同的函数来调用实现它们的功能。我将他们分为两大模块:一是开发板上对器件控制模块,二是上位机的实现与控制模块,具体如下:
1)火焰判断模块
因为这个输出是最简单的只要判断他输出的是0是1,所以就没写函数,只有一个简单的获取判断代码:
fire = DATA_PIN1;
2)温湿度传感器模块
针对这个传感器,主要有两个函数,一个是温湿度的写入,一个是对温湿度的读取使用。
void COM(void) // 温湿度的写入
{
uchar i;
for(i=0;i<8;i++)
{
ucharFLAG=2; //判断
while((!DATA_PIN)&&ucharFLAG++);
Delay_10us();//延时
Delay_10us();
Delay_10us();
uchartemp=0;
if(DATA_PIN)uchartemp=1;
ucharFLAG=2;
while((DATA_PIN)&&ucharFLAG++);
if(ucharFLAG==1)break;
ucharcomdata<<=1;
ucharcomdata|=uchartemp;
}
}
void DHT11(void) //温湿度的使用以及其他传感器获得数据后的输出
{
DATA_PIN=0;
Delay_ms(19); //>18MS
DATA_PIN=1;
DATA_PIN_INPUT; //输入
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
if(!DATA_PIN)
{
P1DIR &= ~0x20; //P1.5定义为输入口
ucharFLAG=2;
while((!DATA_PIN)&&ucharFLAG++);
ucharFLAG=2;
while((DATA_PIN)&&ucharFLAG++);
COM();
ucharRH_data_H_temp=ucharcomdata;
COM();
ucharRH_data_L_temp=ucharcomdata;
COM();
ucharT_data_H_temp=ucharcomdata;
COM();
ucharT_data_L_temp=ucharcomdata;
COM();
ucharcheckdata_temp=ucharcomdata;
DATA_PIN=1;
uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);
if(uchartemp==ucharcheckdata_temp)
{
ucharRH_data_H=ucharRH_data_H_temp;
ucharRH_data_L=ucharRH_data_L_temp;
ucharT_data_H=ucharT_data_H_temp;
ucharT_data_L=ucharT_data_L_temp;
ucharcheckdata=ucharcheckdata_temp;
}
wendu=ucharT_data_H;//温度最终读数
shidu=ucharRH_data_H;//湿度最终读数
fire = DATA_PIN1;//火焰情况
yanwu = ReadqitiData();//烟雾情况
}
Else//没获取到
{
shidu=0;
wendu=0;
fire = DATA_PIN1;//
yanwu = ReadqitiData();
}
DATA_PIN_OUTPUT; //输出
}
3)烟雾传感器模块
烟雾传感器的话也只有一个获取读数的函数
uint8 ReadqitiData( void )
{
uint16 reading = 0;
P0SEL &= ~0x40; //设置为普通 IO 口
P0DIR &= ~0x40; // 设置为输入方式
asm("NOP");asm("NOP");
ADCIF = 0;
ADCCON3 = (0x80 | HAL_ADC_DEC_064 | HAL_ADC_CHANNEL_6);
while ( !ADCIF );
asm("NOP");asm("NOP");
reading = ADCL;
reading |= (int16) (ADCH << 8);
reading >>= 8;
return reading;
}
4)蜂鸣器模块
蜂鸣器的话重要的是初始化,使用时只要置0置1就行
#ifdef ZDO_COORDINATOR
//协调器初始化
//逢蜂鸣器初始化
//P0SEL &= ~0x80; //设置P07为普通IO口
P0DIR |= 0x80; //P07定义为输出口
//默认蜂鸣器不响
P0_7=1;
P1SEL &= ~0x80; //设置为普通IO口
P1DIR |= 0x80; //定义为输出口
5)组网的选择模块
#endif
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;//广播
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;//组播
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
SampleApp_P2P_DstAddr.addrMode = (afAddrMode_t)Addr16Bit; //点播
SampleApp_P2P_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_P2P_DstAddr.addr.shortAddr = 0x0000; //发给协调器
SampleApp_Bind_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent;
6)协调器的任务处理模块(部分代码)
if ( events & SYS_EVENT_MSG )
{
afIncomingMSGPacket_t *MSGpkt;
while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID )) )
{
switch ( MSGpkt->hdr.event )
{
// Received when a key is pressed
case KEY_CHANGE:
SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
break;
case AF_INCOMING_MSG_CMD:
SampleApp_ProcessMSGCmd( MSGpkt );
break;
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)||
(SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
//连网成功后,启动一个定时器
SampleApp_DeviceConnect();
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
else
{
// Device is no longer in the network
}
break;
default:
break;
}
osal_msg_deallocate( (uint8 *)MSGpkt );
}
return ( events ^ SYS_EVENT_MSG );
}
7)通过串口与上位机之间的输入输出模块
输出:#ifdef ZDO_COORDINATOR
//协调器串口输出数据
{
uint8 buff[200]={0};
//格式化温度数据,用于串口输出
sprintf(buff, "%d %d %d %d %d %d %d %d %d %d %d %d %d\r\n", temp1Int, hum1Int, tm1, yanwu1Int,temp2Int, hum2Int, tm2, yanwu2Int, temp3Int, hum3Int,tm3, yanwu3Int,DATA_PIN2);
//串口输出提示信息
HalUARTWrite(0, buff, osal_strlen(buff));
}
输入:uint8 buff1[10]={0};
HalUARTRead(0,buff1,10);
if(buff1[0]=='s'&&buff1[1]=='t'&&buff1[2]=='o'&&buff1[3]=='p')
{
DATA_PIN2=0;
FLAG=ALLOW_USE;
}
if(buff1[0]=='s'&&buff1[1]=='t'&&buff1[2]=='a'&&buff1[3]=='r'&&buff1[4]=='t')
{
DATA_PIN2=1;
FLAG=DISALLOW_USE;
}
8)通过按键控制继电器工作模块
if ( keys & HAL_KEY_SW_6 )//key1,强制浇水
{
if(ledState==0)
{
DATA_PIN2=1;
FLAG=DISALLOW_USE;
HalLedSet (HAL_LED_2, HAL_LED_MODE_ON);
P0_7=1;
ledState=1;
}
else
{
DATA_PIN2=0;
FLAG=DISALLOW_USE;
HalLedSet (HAL_LED_2, HAL_LED_MODE_OFF);
P0_7=1;
ledState=0;
}
}
if ( keys & HAL_KEY_SW_1 )//key2,解除禁制
{
FLAG=ALLOW_USE;
}
9)接收终端数据并进行处理模块
#ifdef ZDO_COORDINATOR
// 接收终端上传的温度数据
uint8 id=pkt->cmd.Data[0];//终端id
uint8 t=pkt->cmd.Data[1]; //终端温度
uint8 h=pkt->cmd.Data[2]; //终端湿度
uint8 f=pkt->cmd.Data[3]; //终端火
uint8 y=pkt->cmd.Data[4]; //终端烟雾
if(id==1)
{
//保存终端1的温度和湿度
temp1Int=t;
hum1Int=h;
yanwu1Int=y;
fire1Int=f;
}
else if(id==2)
{
//保存终端2的温度和湿度
temp2Int=t;
hum2Int=h;
yanwu2Int=y;
fire2Int=f;
}
else if(id==3)
{
//保存终端3的温度和湿度
temp3Int=t;
hum3Int=h;
yanwu3Int=y;
fire3Int=f;
}
//蜂鸣器报警
if(temp1Int>25||hum1Int<30||fire1Int==0||yanwu1Int>40)
tm1=1;
else
tm1=0;
if(temp2Int>25||hum2Int<30||fire2Int==0||yanwu2Int>40)
tm2=1;
else
tm2=0;
if(temp3Int>25||hum3Int<30||fire3Int==0||yanwu3Int>40)
tm3=1;
else
tm3=0;
if(f==0&&FLAG==ALLOW_USE)//有火报警
{
P0_7=0;
DATA_PIN2=1;
}
else if(t>25&&FLAG==ALLOW_USE)//温度高于35度报警
{
P0_7=0;
DATA_PIN2=1;
}
else if(h>0&&h<30&&FLAG==ALLOW_USE)//湿度低于30报警
{
P0_7=0;
DATA_PIN2=1;
}
else if(y>40&&FLAG==ALLOW_USE)
{
P0_7=0;
DATA_PIN2=1;
}
else if(FLAG==ALLOW_USE)
{
P0_7=1;//不报警
DATA_PIN2=0;
}
10)上位机的主要代码
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string data=serialPort1.ReadLine();//通过串口读取下位机发送来的数据
textBox13.Text = data;
string[] arr = Regex.Split(data, @"\s+");
if(arr[1]!=null){//对温湿度,气体浓度的显示框显示示数
textBox1.Text = " " + arr[0];
textBox2.Text = " " + arr[1];
textBox3.Text = " " + arr[3];
textBox4.Text = " " + arr[7];
textBox5.Text = " " + arr[4];
textBox6.Text = " " + arr[5];
textBox7.Text = " " + arr[11];
textBox8.Text = " " + arr[8];
textBox9.Text = " " + arr[9];
button1.BackColor = System.Drawing.Color.Lime;
button4.BackColor = System.Drawing.Color.Lime;
button6.BackColor = System.Drawing.Color.Lime;
button8.BackColor = System.Drawing.Color.Lime;
if (Convert.ToInt32(arr[2]) == 1)//判断是否报警,来更改报警按钮颜色
{
button1.BackColor = System.Drawing.Color.Red;
SystemSounds.Beep.Play();//实现报警
}
else
button1.BackColor = System.Drawing.Color.Lime;
if (Convert.ToInt32(arr[6]) == 1)
{
button4.BackColor = System.Drawing.Color.Red;
//SystemSounds.Beep.Play();
}
else
button4.BackColor = System.Drawing.Color.Lime;
if (Convert.ToInt32(arr[10]) == 1)
{
button6.BackColor = System.Drawing.Color.Red;
//SystemSounds.Beep.Play();
}
else
button8.BackColor = System.Drawing.Color.Lime;
if (Convert.ToInt32(arr[12]) == 0)
{
flag1 = false;
button2.Image = Properties.Resources.switch1;
}
else
{
flag1 = true;
button2.Image = Properties.Resources.switch2;
}
chart_TShow(1, Convert.ToInt32(arr[0]));//绘制温度曲线
chart_TShow(2, Convert.ToInt32(arr[4]));
chart_TShow(3, Convert.ToInt32(arr[8]));
chart_HShow(1, Convert.ToInt32(arr[1]));//绘制湿度曲线
chart_HShow(2, Convert.ToInt32(arr[5]));
chart_HShow(3, Convert.ToInt32(arr[9]));
chart_SShow(1, Convert.ToInt32(arr[3]));//绘制烟雾曲线
chart_SShow(2, Convert.ToInt32(arr[7]));
chart_SShow(3, Convert.ToInt32(arr[11]));
}
}
四、调试分析
将代码分别烧录进终端与协调器里,将传感器与蜂鸣器等组装好,便可以进入测试:
测试截图:
上位机显示截图:
等待协调器与终端进行组网,组网成功后它们led灯会亮,这时候我们就能开始在上位机上了解各个节点的情况。在靠经火焰传感器的附近打火,这时候便可以听到蜂鸣器在报警,同时继电器也开 始工作让水泵也运行起来,接着我们可以听到上位机也在报警,对应节点报警的那一栏Alarm变为红色,同时有报警提示音。接着我们尝试提高温度或降低湿度或增大烟雾浓度来达到报警界限,同样能听到报警,继电器也正常进行工作。当一切正常的时候,在上位机上按下继电器的开关,也能使继电器进入工作状态,再按一下就能实现关闭。同理,按下协调器上的k1也能使继电器工作,再按一下就能实现关闭。
遇到的问题:
我们的火灾检测系统制作的磕磕碰碰,主要几点让我印象深刻的就是下面几个问题:最开始协调器上的继电器与蜂鸣器设置出现了bug,因为最开始设定检测到有火,蜂鸣器和继电器就一起工作,于是便定义了一个变量,但真正测试的时候发现蜂鸣器一直在叫而继电器工作时断时续,我们以为是代码出了问题,最后经过排查发现它们用到的口重复了。还有就是上位机中碰到的困难就是用到新的工具Visual Studio2022来制作上位机,并且用到的是C#语言,入手起来比较困难。最后便是发现上位机控制继电器,继电器并不能正常的听取控制,后来发现是协调器里的一部分代码占用了串口导致出了问题,最后经过修正也正常了。多余的没提到的小问题也基本上都是代码编写方面的问题,经过讨论与请教同学最后都得到了很好的解决。
五、总结分析
本次课设我们小组对于火灾检测系统的功能都实现了,要求分析里面的功能该有的也基本上都有了。我们完成了通过温湿度传感器、烟雾传感器和火焰传感器的判断,能对快起火情况以及起火情况做出报警并且启动继电器让水泵进行工作,同时我们也能在上位机上看到具体是哪个节点出现了问题,那个节点那里的温湿度、气体浓度以及有无火焰的状态也都能看到,还能通过手动按下上位机的按钮或是协调器的k1控制水泵的工作。
当然我们完成的这些也只能算是完成了最基本的一些功能,其实还可以加入更多的功能来完善它让火灾检测系统变得更加完整更加优秀,比如说在用几个传感器测量其他条件因素来判断是否起火的情况,加入语音模块能够实现语音控制水泵工作,加上蓝牙模块我们还可以在手机上看到节点情况,收到报警信息等等。
六、团队运行情况以及个人工作描述
我们小组成员有我、余志辉和张童欣,起初,我们的打算是一个做协调器(带有蜂鸣器),一个做终端节点(带有温湿度传感器、气体传感器和火焰传感器),最后一个也做终端(带有继电器),结果通过简单的串口调试助手显示。但是我们呢发现最后一个终端节点太过简单,没有必要在耗费一个人去做,于是就决定把继电器也放在协调器上,不做终端节点的人则去做上位机,设计一个可以控制协调器的上位机。最终的分工就是张童欣和余志辉同学负责协调器与终端节点,而我负责制作一个上位机以及负责通过串口的一些输入与输出的编写。他们俩前期是先了解传感器的工作原理与引脚,以及查看z_stack代码里面的一些函数如何使用,然后他们在考虑如何去设计组网,选用哪种方式去组网,前期进展的比较慢,都在慢慢的学习掌握。我前期则是先选择制作上位机的软件,有VB,VS等等很多工具的选择,最后我选择用VS,它的制作窗口是用C#来进行,接着我便从网上找来一些相关的串口窗口制作的文章以及视频来观看学习。当他们的代码完成的差不多了的时候,我的上位机也差不多完成了,然后我就在他们的代码基础上加上简单的串口输入以及输出,再进行后期调试。期间我们碰到问题也会进行讨论与琢磨。对于我自己工作的完成情况我是比较满意的,上位机需要有的基本功能我都实现了,对于我的两位同学的任务完成情况我认为也是很优秀的,他们对代码进行不厌其烦的修改,把一些较为混乱的代码进行简洁化与整理化,以及到最后了他们还在考虑能不能在添加一些什么功能上去,能和他们一起完成这次课设是我的荣幸。就基础功能而言我认为我们团队完成的还是比较优秀的,当然我们还需再接再厉,一起进步,一起加油!