STM32项目分享:智能厨房安全系统(机智云)
目录
一、前言
二、项目简介
1.功能详解
2.主要器件
三、原理图设计
四、PCB硬件设计
PCB图
五、程序设计
六、实验效果
七、资料内容
项目分享
一、前言
项目成品图片:
哔哩哔哩视频链接:
STM32智能厨房安全系统(机智云)
(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的智能厨房安全系统(机智云)
功能如下:
- STM32F103C8T6单片机作为主控芯片
- 检测功能:检测环境温湿度、烟雾浓度、一氧化碳、火焰信号和人体信号
- 显示功能:OLED显示环境参数
- 手动控制:通过手机APP控制水泵、风扇、LED灯和阀门(舵机模拟)的开关
- 自动模式:系统检测到有人开启LED,温度高于阈值开启风扇,烟雾和一氧化碳超过阈值开启风扇并关闭阀门,发生火灾时关闭阀门、开启水泵
- 模式切换:可以在APP上切换模式
- 阈值调节:按键可调节阈值
- 机智云APP:接入机智云APP查看数据与控制下发
2.主要器件
- STM32F103C8T6单片机
- OLED 屏幕
- DHT11温湿度传感器
- MQ2烟雾传感器
- MQ7一氧化碳传感器
- 火焰传感器
- 光电红外传感器
- ESP8266模块(WIFI)
- 继电器
- 有源蜂鸣器
- 水泵
- 风扇模块
- 舵机
三、原理图设计
四、PCB硬件设计
PCB图
五、程序设计
#include "stm32f10x.h" // Device header
#include "iwdg.h"
#include "adcx.h"
#include "oled.h"
#include "dht11.h"
#include "led.h"
#include "key.h"
#include "tim2.h"
#include "tim3.h"
#include "usart3.h"
#include "usart.h"
#include "sensormodules.h"
#include "gizwits_product.h"
#include "flash.h"
#include "hc_sr501.h"
#include "servo.h"
#include "pwm.h"#define KEY_1 1
#define KEY_2 2
#define KEY_3 3
#define KEY_4 4#define FLASH_START_ADDR 0x0801f000 //写入的起始地址SystemState systemState; //声明系统状态结构体变量
SensorModules sensorData; //声明传感器数据结构体变量
SensorThresholdValue Sensorthreshold; //声明传感器阈值结构体变量uint8_t menu = 1; //显示菜单变量
uint8_t OLED_Clear_Flag; //阈值设置界面的清屏标志位
uint8_t mode = 0; //系统模式uint8_t displayPageNum; //主页面显示页面uint8_t valveLockFlag; //阀门自锁标志位enum
{display_page1 = 1,display_page2,settingsPage}MenuPages;/*** @brief 显示菜单1的固定内容* @param 无* @retval 无*/
void OLED_Menu1(void)
{//显示“温度: C”OLED_ShowChinese(1, 1, 0);OLED_ShowChinese(1, 2, 1);OLED_ShowChar(1, 5, ':');OLED_ShowChar(1, 8, 'C');//显示“湿度: %”OLED_ShowChinese(1, 5, 2);OLED_ShowChinese(1, 6, 3);OLED_ShowChar(1, 13, ':'); OLED_ShowChar(1, 16, '%'); //显示“烟雾浓度: ”OLED_ShowChinese(2, 1, 6);OLED_ShowChinese(2, 2, 7);OLED_ShowChinese(2, 3, 32);OLED_ShowChinese(2, 4, 33);OLED_ShowChar(2, 9, ':');OLED_ShowString(2, 14, "ppm");//显示“一氧化碳: ”OLED_ShowChinese(3, 1, 42);OLED_ShowChinese(3, 2, 43);OLED_ShowChinese(3, 3, 44);OLED_ShowChinese(3, 4, 45);OLED_ShowChar(3, 9, ':');OLED_ShowString(3, 14, "ppm");//显示“系统模式:”OLED_ShowChinese(4, 1, 24);OLED_ShowChinese(4, 2, 25);OLED_ShowChinese(4, 3, 26);OLED_ShowChinese(4, 4, 27); OLED_ShowChar(4, 9, ':');
}/*** @brief 显示菜单2的固定内容* @param 无* @retval 无*/
void OLED_Menu2(void)
{//显示“火焰信号:”OLED_ShowChinese(1, 1, 8);OLED_ShowChinese(1, 2, 9);OLED_ShowChinese(1, 3, 10);OLED_ShowChinese(1, 4, 11); OLED_ShowChar(1, 9, ':');//显示“人体信号:%”OLED_ShowChinese(2, 1, 12);OLED_ShowChinese(2, 2, 13);OLED_ShowChinese(2, 3, 14);OLED_ShowChinese(2, 4, 15); OLED_ShowChar(2, 9, ':');}/*** @brief 显示菜单1的传感器数据* @param 无* @retval 无*/
void SensorDataDisplay1(void)
{//显示温度数据OLED_ShowNum(1, 6, sensorData.temp, 2);//显示湿度数据OLED_ShowNum(1, 14, sensorData.humi, 2);//显示烟雾浓度数据OLED_ShowNum(2, 10, sensorData.smog, 4);//显示甲烷浓度数据OLED_ShowNum(3, 10, sensorData.methane, 4);//显示系统状态数据if (!mode){OLED_ShowChinese(4, 6, 30);OLED_ShowChinese(4, 7, 31); }else{OLED_ShowChinese(4, 6, 28);OLED_ShowChinese(4, 7, 29); }
}/*** @brief 显示菜单2的传感器数据* @param 无* @retval 无*/
void SensorDataDisplay2(void)
{if (!sensorData.flame){OLED_ShowChinese(1, 6, 36);OLED_ShowChinese(1, 7, 37); }else{OLED_ShowChinese(1, 6, 34);OLED_ShowChinese(1, 7, 35); }if (!sensorData.people){OLED_ShowChinese(2, 6, 40);OLED_ShowChinese(2, 7, 41); }else{OLED_ShowChinese(2, 6, 38);OLED_ShowChinese(2, 7, 39); }
}/*** @brief 显示阈值设置界面1的固定内容* @param 无* @retval 无*/
void OLED_settingsPage1(void)
{//显示“温度阈值:”OLED_ShowChinese(1, 2, 0);OLED_ShowChinese(1, 3, 1);OLED_ShowChinese(1, 4, 18);OLED_ShowChinese(1, 5, 19); OLED_ShowChar(1, 11, ':');//显示“火焰阈值:”OLED_ShowChinese(2, 2, 8);OLED_ShowChinese(2, 3, 9);OLED_ShowChinese(2, 4, 18);OLED_ShowChinese(2, 5, 19); OLED_ShowChar(2, 11, ':');//显示“烟雾阈值:”OLED_ShowChinese(3, 2, 6);OLED_ShowChinese(3, 3, 7);OLED_ShowChinese(3, 4, 18);OLED_ShowChinese(3, 5, 19); OLED_ShowChar(3, 11, ':');//显示“一氧阈值:”OLED_ShowChinese(4, 2, 42);OLED_ShowChinese(4, 3, 43);OLED_ShowChinese(4, 4, 18);OLED_ShowChinese(4, 5, 19); OLED_ShowChar(4, 11, ':');
}/*** @brief 显示阈值界面1的传感器数据* @param 无* @retval 无*/
void settingsThresholdDisplay1(void)
{//显示温度阈值数据OLED_ShowNum(1, 13, Sensorthreshold.tempValue, 2);//显示火焰阈值数据OLED_ShowNum(2, 13, Sensorthreshold.flameValue, 2);//显示烟雾阈值数据OLED_ShowNum(3, 13, Sensorthreshold.smogValue, 3);//显示甲烷阈值数据OLED_ShowNum(4, 13, Sensorthreshold.methaneValue, 3);
}/*** @brief 显示阈值界面的选择符号* @param num 为显示的位置* @retval 无*/
void OLED_Option(uint8_t num)
{switch(num){case 1: OLED_ShowChar(1,1,'>');OLED_ShowChar(2,1,' ');OLED_ShowChar(3,1,' ');OLED_ShowChar(4,1,' ');break;case 2: OLED_ShowChar(1,1,' ');OLED_ShowChar(2,1,'>');OLED_ShowChar(3,1,' ');OLED_ShowChar(4,1,' ');break;case 3: OLED_ShowChar(1,1,' ');OLED_ShowChar(2,1,' ');OLED_ShowChar(3,1,'>');OLED_ShowChar(4,1,' ');break;case 4: OLED_ShowChar(1,1,' ');OLED_ShowChar(2,1,' ');OLED_ShowChar(3,1,' ');OLED_ShowChar(4,1,'>');break;default: break;}
}/*** @brief 记录阈值界面下按KEY1的次数* @param 无* @retval 返回次数*/
uint8_t SetSelection(void)
{static uint8_t count = 1;if(KeyNum == KEY_1){KeyNum = 0;count++;if (count > 4){count = 1;}}return count;
}/*** @brief 对阈值界面的传感器阈值进行修改* @param num 为当前用户需要更改的传感器阈值位置* @retval 无*/
void ThresholdModification(uint8_t num)
{switch (num){case 1:if (KeyNum == 3){KeyNum = 0;Sensorthreshold.tempValue++;if (Sensorthreshold.tempValue > 99){Sensorthreshold.tempValue = 0;}}else if (KeyNum == 4){KeyNum = 0;Sensorthreshold.tempValue--;if (Sensorthreshold.tempValue > 99){Sensorthreshold.tempValue = 99;} }break;case 2:if (KeyNum == 3){KeyNum = 0;Sensorthreshold.flameValue++;if (Sensorthreshold.flameValue > 99){Sensorthreshold.flameValue = 0;}}else if (KeyNum == 4){KeyNum = 0;Sensorthreshold.flameValue--;if (Sensorthreshold.flameValue > 99){Sensorthreshold.flameValue = 99;} } break;case 3:if (KeyNum == 3){KeyNum = 0;Sensorthreshold.smogValue++;if (Sensorthreshold.smogValue > 500){Sensorthreshold.smogValue = 0;}}else if (KeyNum == 4){KeyNum = 0;Sensorthreshold.smogValue--;if (Sensorthreshold.smogValue > 500){Sensorthreshold.smogValue = 500;} }break;case 4:if (KeyNum == 3){KeyNum = 0;Sensorthreshold.methaneValue++;if (Sensorthreshold.methaneValue > 500){Sensorthreshold.methaneValue = 0;}}else if (KeyNum == 4){KeyNum = 0;Sensorthreshold.methaneValue--;if (Sensorthreshold.methaneValue > 500){Sensorthreshold.methaneValue = 500;} }break;default: break; }
}/*** @brief 系统自动模式下的运行* @param 无* @retval 无*/
void AutomaticMode()
{if (mode){/*当系统检测到有人时会开启LED灯,没人时自动关闭*/if (sensorData.people){currentDataPoint.valueLED = 1;LED_ON();}else{currentDataPoint.valueLED = 0;LED_OFF();}/*系统检测到温度高于阈值时会自动开启风扇*/if (sensorData.temp > Sensorthreshold.tempValue){currentDataPoint.valuefan = 1;Relay_ON(1);Buzzer_ON();}/*系统检测到火焰时,会自动开启水泵进行灭火并且关闭阀门*/if (sensorData.flame){Relay_ON(0);currentDataPoint.valuevalve = 1;currentDataPoint.valuewaterPump = 1;systemState.flameAlarm = 1;Buzzer_ON();}else{systemState.flameAlarm = 0;currentDataPoint.valuewaterPump = 0;currentDataPoint.valuevalve = 0;}/*系统检测到烟雾浓度高于阈值,会自动开启风扇并且关闭阀门*/if (sensorData.smog > Sensorthreshold.smogValue){currentDataPoint.valuefan = 1;systemState.smogAlarm = 1;Relay_ON(1); currentDataPoint.valuevalve = 1;Buzzer_ON();}else{systemState.smogAlarm = 0;}/*系统检测到甲烷浓度高于阈值,会自动开启风扇并且关闭阀门*/if (sensorData.methane > Sensorthreshold.methaneValue){currentDataPoint.valuefan = 1;systemState.methaneAlarm = 1;Relay_ON(1);currentDataPoint.valuevalve = 1; Buzzer_ON();}else{systemState.methaneAlarm = 0;}/*控制舵机运行*/if ((sensorData.flame || sensorData.smog > Sensorthreshold.smogValue || sensorData.methane > Sensorthreshold.methaneValue)&& valveLockFlag == 0){valveLockFlag = 1;Servo_SetAngle(90);}else if (valveLockFlag && !sensorData.flame && (sensorData.smog ) < Sensorthreshold.smogValue && (sensorData.methane ) < Sensorthreshold.methaneValue){valveLockFlag = 0;Relay_OFF(1);Relay_OFF(0);currentDataPoint.valuevalve = 0;Servo_SetAngle(0);} /*控制风扇停止*/if (sensorData.temp < Sensorthreshold.tempValue && (sensorData.smog ) < Sensorthreshold.smogValue && (sensorData.methane ) < Sensorthreshold.methaneValue){currentDataPoint.valuefan = 0;Relay_OFF(1);}/*控制蜂鸣器停止*/if (sensorData.temp < Sensorthreshold.tempValue && !sensorData.flame && (sensorData.smog ) < Sensorthreshold.smogValue && (sensorData.methane ) < Sensorthreshold.methaneValue){Buzzer_OFF();}}
}/*** @brief 传感器数据扫描* @param 无* @retval 无*/
void SensorScan(void)
{DHT11_Read_Data(&sensorData.humi, &sensorData.temp);HC_SR501_Input(&sensorData.people);Get_Average_MQ2_PPM(&sensorData.smog);Get_Average_MQ4_PPM(&sensorData.methane);if (Get_Average_Flame_Percent() < Sensorthreshold.flameValue){sensorData.flame = 0;}else{sensorData.flame = 1;}
}int main(void)
{ADCX_Init();Timer2_Init(9,14398);Uart2_Init(9600);Uart1_Init(115200);Uart3_Init();IWDG_Init(); //初始化看门狗PWM_Init();OLED_Init();DHT11_Init();LED_Init();Buzzer_Init();Relay_Init();Key_Init();HC_SR501_Init();Servo_Init();Sensorthreshold.tempValue = FLASH_R(FLASH_START_ADDR); //从指定页的地址读FLASHSensorthreshold.flameValue = FLASH_R(FLASH_START_ADDR+2); //从指定页的地址读FLASHSensorthreshold.smogValue = FLASH_R(FLASH_START_ADDR+4); //从指定页的地址读FLASHSensorthreshold.methaneValue = FLASH_R(FLASH_START_ADDR+6); GENERAL_TIM_Init();userInit(); //完成机智云初始赋值gizwitsInit(); //开辟一个环形缓冲区gizwitsSetMode(WIFI_AIRLINK_MODE);Delay_ms(1000);Servo_SetAngle(135);Buzzer_ON();Delay_ms(1000);Buzzer_OFF();Servo_SetAngle(45);KeyNum = 0;gizwitsSetMode(WIFI_AIRLINK_MODE);Delay_ms(1000);while (1){/*阈值上传至机智云云平台*/do{currentDataPoint.valuetempValue = Sensorthreshold.tempValue;currentDataPoint.valueflameValue = Sensorthreshold.flameValue;currentDataPoint.valuesmogValue = Sensorthreshold.smogValue;currentDataPoint.valuemethaneValue = Sensorthreshold.methaneValue;}while(0);IWDG_ReloadCounter(); switch (menu){case display_page1:SensorScan(); //获取传感器数据if (!displayPageNum){SensorDataDisplay1(); //显示传感器1数据OLED_Menu1(); //显示主页面1固定信息 }else{SensorDataDisplay2(); //显示传感器2数据 OLED_Menu2(); //显示主页面2固定信息 }AutomaticMode();if (KeyNum == KEY_1){Delay_ms(10);if(KeyNum == 1){KeyNum = 0;OLED_Clear(); //清屏menu = settingsPage;}}if (KeyNum == KEY_2) //是否按下按键2{KeyNum = 0;OLED_Clear(); //清屏displayPageNum = !displayPageNum; }break;case settingsPage:settingsThresholdDisplay1(); //显示传感器阈值1数据 OLED_settingsPage1(); //显示阈值设置界面1固定信息ThresholdModification(SetSelection()); //调节传感器阈值OLED_Option(SetSelection()); //获取按键次数,从而判断“>”显示位置if (KeyNum == KEY_2) //判断用户是否按下退出按键{KeyNum = 0;OLED_Clear(); //清屏menu = display_page1; //回到主页面1//存储修改的传感器阈值至flash内FLASH_W(FLASH_START_ADDR, Sensorthreshold.tempValue, Sensorthreshold.flameValue,Sensorthreshold.smogValue, Sensorthreshold.methaneValue);currentDataPoint.valuetempValue = Sensorthreshold.tempValue;currentDataPoint.valueflameValue = Sensorthreshold.flameValue;currentDataPoint.valuesmogValue = Sensorthreshold.smogValue;currentDataPoint.valuemethaneValue = Sensorthreshold.methaneValue;}break;default: break;}/*机智云阈值更改后保存至Flash*/if (valueFlashFlag){valueFlashFlag = 0;FLASH_W(FLASH_START_ADDR, Sensorthreshold.tempValue, Sensorthreshold.flameValue,Sensorthreshold.smogValue, Sensorthreshold.methaneValue); }userHandle(); //更新机智云数据点变量存储的值gizwitsHandle((dataPoint_t *)¤tDataPoint); //数据上传至机智云 }
}
六、实验效果
七、资料内容