項目成品圖片:

01
—
項目簡介
1.功能詳解
功能如下:
STM32F103C8T6單片機作為主控芯片
檢測功能:檢測環境溫濕度、煙霧濃度、一氧化碳、火焰信號和人體信號
顯示功能:OLED顯示環境參數
手動控制:通過手機APP控制水泵、風扇、LED燈和閥門(舵機模擬)的開關
自動模式:系統檢測到有人開啟LED,溫度高于閾值開啟風扇,煙霧和一氧化碳超過閾值開啟風扇并關閉閥門,發生火災時關閉閥門、開啟水泵
模式切換:可以在APP上切換模式
閾值調節:按鍵可調節閾值
機智云APP:接入機智云APP查看數據與控制下發
2.材料清單
STM32F103C8T6單片機
OLED 屏幕
DHT11溫濕度傳感器
MQ2煙霧傳感器
MQ7一氧化碳傳感器
火焰傳感器
ESP8266模塊(WIFI)
繼電器
有源蜂鳴器
水泵
風扇模塊
舵機
02
—
原理圖設計

03
—
PCB硬件設計
PCB圖


04
—
程序設計
#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"
#defineKEY_11#defineKEY_22#defineKEY_33#defineKEY_44
#defineFLASH_START_ADDR0x0801f000//寫入的起始地址
SystemStatesystemState;//聲明系統狀態結構體變量SensorModules sensorData;//聲明傳感器數據結構體變量SensorThresholdValue Sensorthreshold;//聲明傳感器閾值結構體變量
uint8_tmenu =1;//顯示菜單變量uint8_tOLED_Clear_Flag;//閾值設置界面的清屏標志位uint8_tmode =0;//系統模式
uint8_tdisplayPageNum;//主頁面顯示頁面
uint8_tvalveLockFlag;//閥門自鎖標志位
enum{display_page1 =1,display_page2,settingsPage
}MenuPages;
/** * @brief 顯示菜單1的固定內容 * @param 無 * @retval 無 */voidOLED_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 無 */voidOLED_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 無 */voidSensorDataDisplay1(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 無 */voidSensorDataDisplay2(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 無 */voidOLED_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 無 */voidsettingsThresholdDisplay1(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 無 */voidOLED_Option(uint8_tnum){switch(num){case1:OLED_ShowChar(1,1,'>');OLED_ShowChar(2,1,' ');OLED_ShowChar(3,1,' ');OLED_ShowChar(4,1,' ');break;
case2:OLED_ShowChar(1,1,' ');OLED_ShowChar(2,1,'>');OLED_ShowChar(3,1,' ');OLED_ShowChar(4,1,' ');break;
case3:OLED_ShowChar(1,1,' ');OLED_ShowChar(2,1,' ');OLED_ShowChar(3,1,'>');OLED_ShowChar(4,1,' ');break;
case4:OLED_ShowChar(1,1,' ');OLED_ShowChar(2,1,' ');OLED_ShowChar(3,1,' ');OLED_ShowChar(4,1,'>');break;
default:break;}}
/** * @brief 記錄閾值界面下按KEY1的次數 * @param 無 * @retval 返回次數 */uint8_tSetSelection(void){staticuint8_tcount =1;if(KeyNum == KEY_1){KeyNum =0;count++;if(count >4){count =1;}}returncount;}
/** * @brief 對閾值界面的傳感器閾值進行修改 * @param num 為當前用戶需要更改的傳感器閾值位置 * @retval 無 */voidThresholdModification(uint8_tnum){switch(num){case1:if(KeyNum ==3){KeyNum =0;Sensorthreshold.tempValue++;if(Sensorthreshold.tempValue >99){Sensorthreshold.tempValue =0;}}elseif(KeyNum ==4){KeyNum =0;Sensorthreshold.tempValue--;if(Sensorthreshold.tempValue >99){Sensorthreshold.tempValue =99;}}break;
case2:if(KeyNum ==3){KeyNum =0;Sensorthreshold.flameValue++;if(Sensorthreshold.flameValue >99){Sensorthreshold.flameValue =0;}}elseif(KeyNum ==4){KeyNum =0;Sensorthreshold.flameValue--;if(Sensorthreshold.flameValue >99){Sensorthreshold.flameValue =99;}}break;
case3:if(KeyNum ==3){KeyNum =0;Sensorthreshold.smogValue++;if(Sensorthreshold.smogValue >500){Sensorthreshold.smogValue =0;}}elseif(KeyNum ==4){KeyNum =0;Sensorthreshold.smogValue--;if(Sensorthreshold.smogValue >500){Sensorthreshold.smogValue =500;}}break;
case4:if(KeyNum ==3){KeyNum =0;Sensorthreshold.methaneValue++;if(Sensorthreshold.methaneValue >500){Sensorthreshold.methaneValue =0;}}elseif(KeyNum ==4){KeyNum =0;Sensorthreshold.methaneValue--;if(Sensorthreshold.methaneValue >500){Sensorthreshold.methaneValue =500;}}break;
default:break;}}
/** * @brief 系統自動模式下的運行 * @param 無 * @retval 無 */voidAutomaticMode(){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);
}elseif(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 無 */voidSensorScan(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;}}
intmain(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){casedisplay_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;
casesettingsPage:
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);//數據上傳至機智云}}
05
—
實驗效果


-
STM32
+關注
關注
2309文章
11162瀏覽量
373399 -
安全系統
+關注
關注
0文章
419瀏覽量
67804 -
智能廚房
+關注
關注
0文章
25瀏覽量
5459
發布評論請先 登錄
STM32項目分享:智能廚房安全系統(機智云)
評論