【STM32项目开源】STM32单片机厨房安全监测系统系统
目录
一、设计背景和意义
1.1设计背景:
1.2设计意义:
二、实物展示
三、硬件功能介绍
2.1 硬件清单:
2.2 功能介绍:
四、软件设计流程图
五、硬件PCB展示
六、软件主函序展示
七、单片机实物资料
资料获取 查看主页介绍:兆龙电子单片机设计
一、设计背景和意义
1.1设计背景:
在物联网与智慧家居快速发展的当下,传统厨房安全监测方式存在诸多局限。多数家庭仍依赖人工巡检或单一功能报警器(如独立燃气报警器、烟雾报警器),缺乏多风险协同监测与智能化联动控制能力,既无法实时整合燃气泄漏、烟雾浓度、温度异常等多维度安全数据并自动响应,也难以满足厨房复杂场景下的全方位安全防护需求。随着人们对家居安全防护精度、应急响应速度要求的提升,分散式、被动式的安全监测模式已不适用。
现有厨房安全监测方案常存在功能割裂问题,远程预警、多参数联动控制、应急处置等功能未能有效整合,且部分集成化方案成本较高难以普及。基于此,本设计以 STM32F103C8T6 单片机为核心,融合燃气传感器、烟雾传感器、温度传感器与语音预警技术,构建低成本、高集成度的智能厨房安全监测系统,以解决传统厨房安全监测中智能化不足、防护维度单一、应急响应滞后的问题。
1.2设计意义:
本设计通过整合多参数监测与语音预警、智能联动控制技术,具有多重实用价值。从安全防护体验看,提供远程实时监测、本地声光预警、语音险情播报、异常自动断气(联动电磁阀)等多元防护方式,覆盖燃气泄漏、火灾隐患、高温异常等核心安全场景,尤其多参数协同分析与快速应急响应功能,大幅提升了厨房安全防护的主动性与可靠性。
从节能与安全保障角度,借助精准传感器监测实现 “按需预警、及时处置”,避免因人工巡检遗漏或单一报警器误报导致的安全风险,同时减少无效能耗(如联动关闭异常运行设备),符合智慧家居的安全、节能双重理念。从技术层面,探索了 STM32 单片机与多类型传感器、语音模块的协同工作机制,为低成本智能厨房安全监测系统开发提供了可参考的集成方案,推动厨房安全监测技术从 “被动报警” 向 “主动防护” 升级,具有较好的实践应用与家庭普及价值。
二、实物展示
下方为实物演示视频
【开源】基于STM32单片机智能厨房安全检测系统
下方为实物展示图片
三、硬件功能介绍
2.1 硬件清单:
- STM32F103C8T6
- OLED显示
- 温度传感器
- 继电器控制电路
- 水泵
- 风扇
- 火焰传感器
- 门磁
- 舵机
- 烟雾传感器
- ESP8266 WIFI模块
2.2 功能介绍:
(1)STM32单片机进行数据处理
(2)OLED液晶显示当前烟雾浓度,温度、是否发生明火
(3)MQ-2传感器检测烟雾传感器
(4)DS18B20检测当前环境温度
(5)火焰传感器检测当前厨房是否发生明火
(6)按键一:设置,按键二:加,按键三:减
(7)按键分别设置温度上限气体浓度上限
(8)温度超标,液晶闪烁提示,开启风扇进行降温
(9)气体超标液晶闪烁提示,开启风扇进行排气,降低浓度舵机旋转强制关闭燃气通道!
(10)发生明火,液晶出现火焰标志开启水泵模拟灭火舵机旋转强制关闭燃气通道!蜂鸣器 声光报警提醒
(11)通过ESP8266无线WIFI模块把数据传输到手机端进行显示
(12)手机连接WIFI后显示当前温度、烟雾浓度
(13)如果发生明火手机端会出现火焰标志
(14)通过手机端可以任意进行修改当前温度上限,浓度上限
四、软件设计流程图
五、硬件PCB展示
六、软件主函序展示
#include "sys.h"
#include "delay.h"
#include "adc.h"
#include "gpio.h"
#include "OLED_I2C.h"
#include "ds18b20.h"
#include "timer.h"
#include "usart1.h"
#include "esp8266.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>extern const unsigned char BMP[];char display[16]; //显示缓存区
short temperature=0; //温度
u8 setTempValue = 40; //温度上限
u8 setSmokeValue = 60; //烟雾上限
u8 alarmFlag = 0x00; //蜂鸣器报警标志
u16 smoke=0; //烟雾
u8 setn=0; //记录设置按键按下的次数u8 PWM=5; //PWM调节值,用于控制舵机bool shanshuo=0;
bool shuaxin=0;
bool sendFlag = 1;
bool flameFlag=0;void displayInitInterface(void) //显示初始页面
{u8 i;for(i = 0;i < 6;i ++)OLED_ShowCN(i*16+16,0,i+0,0); //显示中文: 厨房安全检测for(i = 0;i < 2;i ++)OLED_ShowCN(i*16,4,i+6,0); //显示中文: 温度for(i = 0;i < 2;i ++)OLED_ShowCN(i*16,6,i+8,0); //显示中文: 烟雾OLED_ShowChar(32,4,':',2,0);
OLED_ShowChar(32,6,':',2,0);
}void Get_Temperature(void) //获取温度
{temperature=ReadTemperature();if(temperature>=setTempValue){
if(!(alarmFlag&0x01)){alarmFlag|=0x01;shanshuo = 0;}}else{alarmFlag&=0xFE;}if(temperature>=setTempValue && shanshuo){
OLED_ShowStr(40, 4," ", 2,0);}
else{
sprintf(display," %d",temperature);
OLED_ShowStr(40, 4, (u8*)display, 2,0);//显示温度OLED_ShowCentigrade(68, 4); //显示摄氏度}
}void Get_Smoke(void) //获取烟雾浓度
{u16 test_adc=0;/* 获取烟雾浓度 */test_adc = Get_Adc_Average(ADC_Channel_9,10);//读取通道9的10次AD平均值smoke = test_adc*99/4096;//转换成0-99百分比if(smoke>=setSmokeValue){
if(!(alarmFlag&0x02)){alarmFlag|=0x02;shanshuo = 0;}}else{alarmFlag&=0xFD;}if(smoke>=setSmokeValue && shanshuo){
OLED_ShowStr(40, 6," ", 2,0);}
else{
sprintf(display," %02d %%",smoke);
OLED_ShowStr(40, 6, (u8*)display, 2,0);//显示温度}
}void displaySetValue(void) //显示设置值
{if(setn==1){
OLED_ShowChar(56,4,setTempValue%100/10+'0',2,0);//显示
OLED_ShowChar(64,4,setTempValue%10+'0',2,0);//显示}
if(setn==2){OLED_ShowChar(56,4,setSmokeValue%100/10+'0',2,0);//显示
OLED_ShowChar(64,4,setSmokeValue%10+'0',2,0);//显示OLED_ShowChar(72,4,'%',2,0); }
}void keyscan(void) //按键扫描
{u8 i;if(KEY1 == 0) //设置键{
delay_ms(20);if(KEY1 == 0){
while(KEY1 == 0);setn ++;if(setn == 1){
OLED_CLS();//清屏
for(i = 0;i < 4;i ++)OLED_ShowCN(i*16+32,0,i+10,0);//显示中文:设置温度OLED_ShowCentigrade(75, 4); //显示摄氏度}
if(setn == 2){
for(i = 0;i < 4;i ++)OLED_ShowCN(i*16+32,0,i+14,0);//显示中文:设置烟雾OLED_ShowChar(80,4,' ',2,0); }
if(setn >= 3){setn = 0;OLED_CLS();//清屏displayInitInterface();}
displaySetValue();}}if(KEY2 == 0) //加键{
delay_ms(80);if(KEY2 == 0){
if(setTempValue < 99 && setn==1)setTempValue++;if(setSmokeValue < 99 && setn==2)setSmokeValue++;
displaySetValue();}}if(KEY3 == 0) //减键{
delay_ms(80);if(KEY3 == 0){if(setTempValue > 0 && setn==1)setTempValue--;if(setSmokeValue > 0 && setn==2)setSmokeValue--;
displaySetValue();}}
}void UsartSendReceiveData(void)
{
unsigned char *dataPtr = NULL;char *str1=0,i;int setValue=0;char setvalue[3]={0};char SEND_BUF[30];dataPtr = ESP8266_GetIPD(0); //接收数据if(dataPtr != NULL){if(strstr((char *)dataPtr,"temp:")!=NULL){BEEP = 1;
delay_ms(80);BEEP = 0;str1 = strstr((char *)dataPtr,"temp:");while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字{str1 = str1 + 1;
delay_ms(10);}i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字{setvalue[i] = *str1;i ++; str1 ++;
if(*str1 == ',')break; //换行符,直接退出while循环
delay_ms(10);}setvalue[i] = '\0'; //加上结尾符setValue = atoi(setvalue);
if(setValue>=0 && setValue<=99){setTempValue = setValue; //设置的温度值displaySetValue();}} if(strstr((char *)dataPtr,"smoke:")!=NULL){str1 = strstr((char *)dataPtr,"smoke:");while(*str1 < '0' || *str1 > '9') //判断是不是0到9有效数字{str1 = str1 + 1;
delay_ms(10);}i = 0;
while(*str1 >= '0' && *str1 <= '9') //判断是不是0到9有效数字{setvalue[i] = *str1;i ++; str1 ++;
if(*str1 == '\r')break; //换行符,直接退出while循环
delay_ms(10);}setvalue[i] = '\0'; //加上结尾符setValue = atoi(setvalue);
if(setValue>=0 && setValue<=99){setSmokeValue = setValue; //设置的烟雾值displaySetValue();}} ESP8266_Clear(); //清空缓存}
if(sendFlag==1) //1秒钟上传一次数据{sendFlag = 0; memset(SEND_BUF,0,sizeof(SEND_BUF)); //清空缓冲区
sprintf(SEND_BUF,"$temp:%d#,$smoke:%d#",temperature,smoke);if(flameFlag){
strcat(SEND_BUF,"flame");}ESP8266_SendData((u8 *)SEND_BUF, strlen(SEND_BUF));ESP8266_Clear();}
}int main(void)
{
delay_init(); //延时函数初始化 NVIC_Configuration(); //中断优先级配置I2C_Configuration(); //IIC初始化delay_ms(200); OLED_Init(); //OLED液晶初始化OLED_CLS(); //清屏OLED_ShowStr(0, 2, " loading... ", 2,0);//显示加载中ESP8266_Init(); //ESP8266初始化Adc_Init(); //adc初始化
KEY_GPIO_Init(); //按键引脚初始化MOTOR_GPIO_Init(); //舵机初始化DS18B20_GPIO_Init(); //温度初始化DS18B20_Init(); //初始化显示OLED_CLS(); //清屏displayInitInterface(); //显示初始界面TIM3_Init(99,71); //定时器初始化,定时100us
//Tout = ((arr+1)*(psc+1))/Tclk ;
//Tclk:定时器输入频率(单位MHZ)
//Tout:定时器溢出时间(单位us)
while(1){ keyscan(); //按键扫描if(setn == 0){if(shuaxin == 1) //大概300ms刷新一次数据{Get_Temperature(); //获取温度Get_Smoke(); //获取烟雾shuaxin = 0;}if(FLAME == 0) //检测到火焰{
delay_ms(10);
if(FLAME == 0){
if(flameFlag == 0){
OLED_DrawBMP(88,4,120,8,(unsigned char *)BMP); //显示火焰图片}flameFlag = 1;RELAY = 1; //检测到有火,开启水泵}}else{
if(flameFlag == 1){
OLED_ShowStr(88, 4, " ", 2,0);
OLED_ShowStr(88, 6, " ", 2,0);}flameFlag = 0;RELAY = 0; //关闭水泵}if(temperature>=setTempValue || smoke>=setSmokeValue || flameFlag)BEEP=1;else BEEP=0; //检测到温度烟雾超标火焰蜂鸣器报警if(temperature>=setTempValue || smoke>=setSmokeValue)FAN=1;else FAN=0; //烟雾温度超标都开启风扇if(smoke>=setSmokeValue || flameFlag)PWM=15;else PWM=5; //烟雾超标或者是检测到火焰,舵机动作,模拟关闭阀门}UsartSendReceiveData();delay_ms(10);}
}void TIM3_IRQHandler(void)//定时器3中断服务程序,用于记录时间
{ static u16 timeCount1 = 0;static u16 timeCount2 = 0;static u16 timeCount3 = 0;if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除中断标志位 timeCount1 ++;
if(timeCount1<=PWM)MOTOR=1; else MOTOR=0;
if(timeCount1>=200) //20ms一周期{timeCount1 = 0;}timeCount2++;
if(timeCount2 >= 3000) //300ms{timeCount2 = 0;shanshuo = !shanshuo;shuaxin = 1;}timeCount3++;
if(timeCount3 >= 10000) //1000ms{timeCount3 = 0;sendFlag = 1;}}
}