jjzjj

【毕业设计】基于单片机的火灾报警系统设计与实现 - 物联网 stm32

Mdc_stdio 2024-07-12 原文

文章目录


1 简介

Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目

基于单片机的火灾报警系统设计与实现

大家可用于 课程设计 或 毕业设计


单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052


2 绪论

2.1 课题背景与目的

火灾是指在时间或空间上失去控制的燃烧所造成的灾害。在各种灾害中,火灾是最经常、最普遍地威胁公众安全和社会发展的主要灾害之一。人类能够对火进行利用和控制,是文明进步的一个重要标志。火,给人类带来文明进步、光明和温暖。但是,失去控制的火,就会给人类造成巨大的灾难。本系统是一个由单片机控制的火灾烟雾浓度、温度检测系统,它将传感器输出地电压信号进行A/D转换、滤波、线性化,由单片机将电压值转换为气体浓度和温度送LED显示,并判断是否超过报警上限,若超过,则发出声光报警。同时用户可以自己设定报警上限和定时时间,使用户可以根据实际情况方便的掌握安全状况。本系统的设计能够及时监测到系统故障和环境中有无火灾,火灾一旦发生将实现声光报警,并采取有效措施控制火情的发展,将火灾消灭在萌芽状态,以确保人身财产安全,最大限度地减少损失。

目标

通过设计一个以 stm32单片机为核心外加 MQ-2 型半导体电阻式雾敏感器件的火灾报警器可以实现声光报警、 故障自诊断、 浓度显示、 报警限设置、 延时报警及与上位机串口通信等功能。

是一种结构简单、 性能稳定、 使用方便、 价格低廉、智能化的火灾报警器, 具有一定的实用价值。

3 烟雾传感器介绍

3.1 类型

烟雾传感器种类繁多, 从检测原理上可以分为三大类:

  • (a) 利用物理化学性质的烟雾传感器: 如半导体烟雾传感器、 接触燃烧烟雾传感器等。
  • (b) 利用物理性质的烟雾传感器: 如热导烟雾传感器、 光干涉烟雾传感器、 红外传感器等。
  • © 利用电化学性质的烟雾传感器: 如电流型烟雾传感器、 电势型气体传感器等。

3.2 MQ系列传感器介绍

MQ系列传感器使用的敏感材料是活性很高的金属氧化物半导体,传感器加热后,在不同气体浓度中电导率不同。使用简单的电路就可以将电导率的变化转换成与该气体浓度相对应的信号输出了。

3.3 模块介绍

MQ-2传感器对可燃气、烟雾等气体灵敏度高,基于MQ-2的烟雾传感器模块通过电路设计,提供了两种输出方式:

  • 数字量输出:通过板载电位器设定浓度阈值,当检测到环境气体浓度超过阈值时,通过数字引脚DO输出低电平。
  • 模拟量输出:浓度越高,AO引脚输出的电压值越高,通过ADC采集的模拟值越高。

4 系统设计

报警器系统结构框图如下图所示,系统以单片机为核心,配合外围电路共同完成:

  • 信号采集
  • 浓度显示
  • 时间显示
  • 状态显示
  • 声音及闪烁报警
  • 按键输入
  • 故障自检等功能。

报警器采用巡检的工作方式,进行两级报警值设定,并发出不同的光、声信号。系统应采用高性能的单片机,要求工作稳定、测量精度高、通用性强、功耗低,保证报警器的精确性及可靠性,而且最好体积小,成本低有利于减少报警器的体积,降低报警器的成本

4.1 自诊断故障报警功能

当传感器加热丝或者电缆线发生断线或者接触不良的情况时, 报警器发出警报, 并且黄色指示灯闪烁, 提醒用户检查传感器或者电路线接触情况, 及时排除故障, 保证安全。

4.2 烟雾浓度显示

通过液晶屏显示可燃烟雾的浓度值, 并且可以切换到设置状态, 通过键盘设置或者更改报警限值, 以便于用户或检测人员随时观测烟雾浓度及更改报警限。

4.3 烟雾报警功能

当烟雾浓度连续 20 秒取值都在报警限值之上, 蜂鸣器开始报警, 且声音越来越急促,并且伴随红灯闪烁。 因为人对变化的信号更为敏感, 所以变化的声音及灯光更容易引起用户的注意。

4.4 防止报警器误报功能

快速重复检测及延时报警可以区别出是管道中可燃烟雾的泄漏, 还是由于打开阀门时的微量烟雾的散失。

4.5 看门狗自检单片机状态功能

调用单片机中的看门狗程序, 定时检查单片机工作状态, 一旦发现单片机出现死循环状态, 立即复位, 保证报警器工作正常。

4.6 与上位机通讯功能

可以实现与计算机串口通讯, 对报警器采取统一控制, 以及便于采集和处理数据, 也可以在计算机上更改报警限值等。

4.7 自动控制相关安全装置的扩展功能

留有继电器接口, 可以带动排风扇或大功率蜂鸣器, 也可以控制管道电子阀门, 可在报警的同时自动启动相关安全装置。

5 软件设计

主程序流程图如图所示。

首先要给传感器预热三分钟, 因为 MQ-2 型半导体电阻式烟雾传感器在不通电存放一段时间后, 再次通电时, 传感器不能立即正常采集烟雾信息,需要一段时间预热。 程序初始化结束后, 系统进入监控状态。 本论文的主程序设计先对传感器预热三分钟, 预热同时, 对传感器加热丝故障检测, 采用软件方式检测传感器加热丝或电缆线是否断线或者接触不良。

5.1 初始化流程

5.2 传感器数据滤波

在烟雾传感器对烟雾浓度采样时, 可能会遇到尖脉冲干扰的现象。 干扰通常只影响个别采样点的数据, 此数据与其他采样点的数据相差比较大。

5.3 报警子程序

当烟雾浓度超过报警设定值时, 报警器发出一种近似警笛的鸣叫声, 对应通道的红灯闪亮, 以提示操作人员采取安全对策或自动控制相关安全装置, 从而保障生产安全, 避免火灾和爆炸事故的发生。

6 实现效果

7 部分相关代码


/************************************************
 
 作者:丹成学长,Q746876041
************************************************/

#ifndef __SMOKE_H
#define	__SMOKE_H


#include "stm32f10x.h"
#include "stm32f10x_gpio.h"


//正常状态高电平,有烟雾低电平,单片机检测到下降沿触发中断

//引脚定义
#define SMOKE_INT_GPIO_PORT         GPIOB
#define SMOKE_INT_GPIO_CLK          (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)
#define SMOKE_INT_GPIO_PIN          GPIO_Pin_4
#define SMOKE_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOB
#define SMOKE_INT_EXTI_PINSOURCE    GPIO_PinSource4
#define SMOKE_INT_EXTI_LINE         EXTI_Line4            //中断标志位
#define SMOKE_INT_EXTI_IRQ          EXTI4_IRQn

#define SMOKE_IRQHandler            EXTI4_IRQHandler

#define SMOKE_BIT  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)//读取




void EXTI_SMOKE_Config(void);



#endif

//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//功能:烟雾探测器模块驱动
//作用:
//编写:MARK
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
#include "smoke.h"
#include "stm32f10x_gpio.h"

static void SMOKE_NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源*/
  NVIC_InitStructure.NVIC_IRQChannel = SMOKE_INT_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

}

 /**
  * @brief  配置 IO为EXTI中断口,并设置中断优先级
  * @param  无
  * @retval 无
  */
void EXTI_SMOKE_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;

	/*开启GPIO口的时钟*/
	RCC_APB2PeriphClockCmd(SMOKE_INT_GPIO_CLK,ENABLE);
	
	/* 配置 NVIC 中断*/
	SMOKE_NVIC_Configuration();
	

	/* 选择用到的GPIO */	
  GPIO_InitStructure.GPIO_Pin = SMOKE_INT_GPIO_PIN;
  /* 配置为浮空输入 */	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(SMOKE_INT_GPIO_PORT, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(SMOKE_INT_EXTI_PORTSOURCE, SMOKE_INT_EXTI_PINSOURCE); 
  EXTI_InitStructure.EXTI_Line = SMOKE_INT_EXTI_LINE;
	


	/* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	/* 上升沿下降沿中断触发 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
  /* 使能中断 */	
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}

#include <stdio.h>
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "./LED/LED.h"
#include "./usart3/usart3.h"
#include "./cJSON/cJSON.h"
#include "./millis/millis.h"
#include "./yun/yun.h"
#include "./systick/bsp_SysTick.h"
#include "./dht11/bsp_dht11.h"
#include "all_init.h"
#include "math_display.h"
#include "bsp_beep.h" 
#include "./stepmotor/stepmotor.h"
#include "smoke.h"

volatile u8 aRxBuffer[1024]={0x00};
volatile u8 RxCounter=0;
volatile u8 ReceiveState=0;

unsigned long lastCheckInTime = 0;   //记录上次报到时间
unsigned long lastCheckStatusTime = 0; 
unsigned long lastSayTime = 0; 
unsigned long lastUpdateTime = 0;   //记录上次上传数据时间
const unsigned long postingInterval = 40000; // 每隔40秒向服务器报到一次
const unsigned long statusInterval = 100000; // 数据上传间隔时间10秒
const unsigned long updateInterval = 5000;


/*用CJSON处理接收到的信息*/
int processMessage(char *msg) {
    cJSON *jsonObj = cJSON_Parse(msg);
    cJSON *method;
    char *m;
    //json字符串解析失败,直接退出
    if(!jsonObj)
    {
        //uart1.printf("json string wrong!");
        return 0;
    }
    method = cJSON_GetObjectItem(jsonObj, "M");
    m = method->valuestring;
    if(strncmp(m, "WELCOME", 7) == 0)
    {
        //防止设备在线状态未消除,先登出
        checkout();
        //防止连续发送指令过快
			  Delay_ms(50);
        checkin();
    }
    if(strncmp(m, "connected", 9) == 0)
    {
        checkout();
				Delay_ms(50);
        checkin();
    }
    //有设备或用户登录,发送欢迎信息
    if(strncmp(m, "login", 5) == 0)
    {
        char *from_id = cJSON_GetObjectItem(jsonObj, "ID")->valuestring;
        char new_content[] = "Dear friend, welcome to BIGIOT !";
        say(from_id, new_content);
    }
    //收到say指令,执行相应动作,并进行相应回复
    if(strncmp(m, "say", 3) == 0 && millis() - lastSayTime > 10)
    {
        char *content = cJSON_GetObjectItem(jsonObj, "C")->valuestring;
        char *from_id = cJSON_GetObjectItem(jsonObj, "ID")->valuestring;
        lastSayTime = millis();
        if(strncmp(content, "play", 4) == 0)
        {
            char new_content[] = "led1 played";
            //do something here....
            Led_On(LED1);//板载LED1亮
            say(from_id, new_content);
        }
        else if(strncmp(content, "stop", 4) == 0)
        {
            char new_content[] = "led stoped";
            //do something here....
            Led_Off(LED1);//板载LED灭
            say(from_id, new_content);
        }
				else if(strncmp(content, "up", 2) == 0)
				{
					  char new_content[] = "led2 played";
            //do something here....
            Led_On(LED2);//板载LED2亮
					  say(from_id, new_content);
				}
				else if(strncmp(content, "plus", 4) == 0)
				{
					  char new_content[] = "led2 stoped";
            //do something here....
            Led_Off(LED2);//板载LED2灭
					  say(from_id, new_content);
				}
				else if(strncmp(content, "pause", 5) == 0)
				{
					  char new_content[] = "beep played";	
            macBEEP_ON();//打开蜂鸣器
					  say(from_id, new_content);
				}
				else if(strncmp(content, "right", 5) == 0)
				{
					  char new_content[] = "beep stoped";
            macBEEP_OFF();//关闭蜂鸣器 
					  say(from_id, new_content);
				}
				else if(strncmp(content, "down", 4) == 0)
				{
					  char new_content[] = "stepmotor played";	
            Motor_angle(-720,200);  //步进电机顺时针	
					  say(from_id, new_content);
				}
				else if(strncmp(content, "forward", 7) == 0)
				{
					  char new_content[] = "stepmotor stoped";
            Motor_angle(720,200);  //步进电机逆时针
            say(from_id, new_content);					
				}				
    }
    if(jsonObj)cJSON_Delete(jsonObj);
    return 1;
}

int main(void)
{
    u8 i = 0;
		float wendu;
		float shidu;
	  int   yanwu;
	  int   chuanglian;
	  DHT11_Data_TypeDef DHT11_Data;	

	  all_init();                      //打包的全部初始化函数
    while (1)
    {
        //delay_ms(100);
        if (millis() - lastCheckInTime > postingInterval || lastCheckInTime == 0) 
					{
            checkin();
            lastCheckInTime = millis();
         }
        
        if (millis() - lastCheckStatusTime > statusInterval) 
					{
            check_status();
            lastCheckStatusTime = millis();
          }
				
				if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS)//调用DHT11_Read_TempAndHumidity读取温湿度,
				                                                       //若成功则输出该信息	
		    {					
						display_num(DHT11_Data.temp_int,DHT11_Data.temp_deci,DHT11_Data.humi_int,DHT11_Data.humi_deci);
																																		 //屏幕显示温度和湿度值,封装后的程序	
            if (millis() - lastUpdateTime > updateInterval)
						{					
									wendu = (float)DHT11_Data.temp_int + (float)DHT11_Data.temp_deci/10.0;
									shidu = (float)DHT11_Data.humi_int + (float)DHT11_Data.humi_deci/10.0;
									if(SMOKE_BIT == Bit_RESET)     //检测到该引脚电平变低---有烟雾
									{	
											yanwu = 1;
									}
									else if(SMOKE_BIT == Bit_SET)     //检测到该引脚电平变高---正常
									{
											yanwu = 0;
									}
									/*上传三个接口的实时数据*/
									update4(DEVICEID, INPUTID_1, wendu, INPUTID_2, shidu, INPUTID_3, yanwu, INPUTID_4, chuanglian); 
									lastUpdateTime = millis();
					  }
		    }

        if(ReceiveState == 1)
        {
            ReceiveState = 0;
            i = 0;
            processMessage(aRxBuffer);
            RxCounter = 0;
        }			
    }
}

/*******************************************************************
篇幅有限,只展示部分代码
作者:丹成学长,Q532036360
********************************************************************/




单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052


8 最后

有关【毕业设计】基于单片机的火灾报警系统设计与实现 - 物联网 stm32的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  4. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  5. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  6. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  7. ruby-on-rails - 设计注册确认 - 2

    我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:

  8. ruby-on-rails - 设计通过 reset_password_token 获取用户 - 2

    我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow

  9. ruby-on-rails - Rails 5,公寓和设计 : sign in with subdomains are not working - 2

    我已经使用Apartment设置了一个Rails5应用程序(1.2.0)和Devise(4.2.0)。由于某些DDNS问题,应用只能在app.myapp.com下访问(请注意子域app)。myapp.com重定向到app.myapp.com。我的用例是每个注册该应用的用户(租户)都应该通过他们的子域(例如tenant.myapp.com)访问他们的特定数据。用户不应限定在其子域内。基本上应该可以从任何子域登录。重定向到租户的正确子域由ApplicationController处理。根据Devise标准,登录页面位于app.myapp.com/users/sign_in。这就是问题开始的

  10. ruby-on-rails - 设计中的 ArgumentError::RegistrationsController#new 错误的参数数量(2 代表 0..1) - 2

    我在关注RyanbatesRailsCast的devise和omniauth(第235集-devise-and-omniauth-revised)。当我尝试使用Twitter登录时,标题中不断出现错误。defself.new_with_session(params,session)ifsession["devise.user_attributes"]new(session["devise.user_attributes"],without_protection:true)do|user|user.attributes=paramsuser.valid?end完整跟踪:C:/Ruby20

随机推荐