【STM32项目】智能家居(版本1)
✌️✌️大家好,这里是5132单片机毕设设计项目分享,今天给大家分享的是基于《基于STM32的智能家居设计》。
目录
1、系统功能
2.1、硬件清单
2.2、功能介绍
2.3、控制模式
2、演示视频和实物
3、系统设计框图
4、软件设计流程图
5、原理图
6、主程序
7、总结
1、系统功能
2.1、硬件清单
STM32+OLED+BH1750 光照传感器 + 温湿度传感器 + 空气质量传感器 + PM2.5 传感器 + 补光灯 + 风扇 + 蜂鸣器 + WIFI + 继电器模块 + 按键模块
2.2、功能介绍(下面视频有详细讲解)
(1)ESP8266 WIFI 模块:用于连接远程云平台,可在手机 APP 实现对设备的远程控制,实时查看温度、湿度、空气质量、PM2.5、光照强度等传感器数据。
(2)BH1750 光照传感器(I2C 通讯协议):用于检测环境光照强度,在自动模式下,当光照强度小于设定阈值时自动打开补光灯。
(3)温湿度传感器(DHT11):用于检测房间温度和湿度,在自动模式下,若湿度大于设定阈值,会触发继电器模块打开空调。
(4)空气质量传感器和 PM2.5 传感器:分别用于监测空气质量参数及空气中 PM2.5 浓度,在自动模式下,空气质量大于设定阈值会触发空调开启,PM2.5 浓度大于设定阈值会启动风扇进行排风。
(5)0.96 寸显示屏(OLED):用于实时显示时间、温度、湿度、PM2.5、光照强度等传感器数据及系统工作模式,时间准确性在不拔下后备电池时可得到保证。
(6)按键模块(4 个按键):在不同模式下功能不同,包括模式切换(远程 / 手动 / 自动)、阈值设置(通过按键加减调整各传感器阈值,可通过按键进入阈值设置界面)、手动控制外设(风扇、空调、补光灯等),因传感器采集耗时,操作时需按下停顿一秒再放开以确保响应。
(7)继电器模块:用于控制空调,在自动模式下,当湿度或空气质量检测值大于设定阈值时自动开启空调;在手动模式下,可通过按键控制空调开关。
(8)补光灯:用于环境补光,在自动模式下,根据光照强度传感器检测值与设定阈值对比,当光照强度小于阈值时自动打开。
(9)风扇:在自动模式下,若温度或 PM2.5 浓度大于对应设定阈值,自动启动进行排风;在手动模式下,可通过按键直接控制风扇开关。
(10)蜂鸣器模块:用于声音报警,当检测到的声音强度大于设定阈值时触发报警,可通过调整阈值或对着麦克风大声说话触发。
2.3、控制模式
- 手动模式:通过按键或蓝牙连接的手机 APP 直接控制各区域灯光的开关及暖光 / 白光模式切换,OLED 屏实时显示当前模式及操作状态。
- 语音模式:通过唤醒词 “小智” 激活语音交互,支持语音指令控制各区域灯光的开关、暖光 / 白光切换(如 “打开厨房暖光灯”“关闭卧室灯”),语音指令执行结果通过语音反馈及 OLED 屏显示。
- 自动模式:需通过按键或 APP 开启,仅在人体识别传感器检测到有人时生效,系统根据光敏传感器检测的光照强度自动调节对应区域灯光亮度(光照强度低于阈值时逐级增强亮度,高于阈值时关闭灯光),实现无人时自动关灯、有人时智能调光。
2、演示视频和实物
基于STM32的智能家居控制(版本1)(PM2.5+温湿度+光照强度)-(远程+自动+手动模式)
3、系统设计框图
4、软件设计流程图
5、原理图
6、主程序
#include \"main.h\"uint16_t AD0, AD1; //存储5路ADC值uint8_t KeyNum;// 存储按键值u8 t = 0;// 传感器读取时间间隔uint16_t RTC_Time[] = {0, 0, 0};// RTC时间uint16_t RTC_Time1[] = {7, 0, 0};// 定时时间---开uint16_t RTC_Time2[] = {19, 0, 0};// 定时时间---关u8 S_Mode; // 按键状态标志u8 S_Shou_1 ; //手动模式控制设备1u8 S_Shou_2; //手动模式控制设备2u8 S_Shou_3; //手动模式控制设备3u8 S_YuZhi; //阈值设置里用的,用来切换阈值// 其他状态标志u8 qingping = 1; //清屏标志u8 S_ShiShi_Time_1; //设置实时时间用,用来切换时间显示和设置时间u8 S_ShiShi_Time_2; //设置实时时间用,用来切换设置的时分秒u8 S_DingShi_Switch; //设置定时时间里用到,切换时分秒uint32_t bufe[10];// 定义传感器数据和阈值结构体变量SensorDataAndThreshold sensorData;// 初始化相关硬件和机智云void System_Init(){ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(9600); // 串口初始化为9600 delay_init(); // 延时函数初始化 LED_Init(); // 初始化与LED连接的硬件接口 DHT11_Init(); Buzzer_Init(); // 外设初始化 OLED_Init(); PM25_Init(); //里面包含了AD_Init(); BH1750_Init(); Key_Init(); MyRTC_Init(); sensorData.GuangYu = 100; sensorData.KongQiYu = 80; sensorData.PM25Yu = 500; sensorData.ShengYinYu = 20; sensorData.HumiYu = 50; sensorData.TempYu = 35; MY_Gizwits_Init(); // 机智云初始化}int main(void){ System_Init(); while (1) { userHandle(); // 数据上传 gizwitsHandle((dataPoint_t *)¤tDataPoint); // 后台处理,必须放在while里 ReadSensorData(); HandleModes(); }}// 读取传感器数据void ReadSensorData(){ if(t%10==0){ DHT11_Read_Data(&sensorData.Temp, &sensorData.Humi); // 读取温湿度并显示在OLED上 sensorData.Guang = bh_data_read(); AD1 = AD_GetValue(ADC_Channel_1); //空气质量传感器 if (AD1 > 4000)AD1 = 4000; sensorData.KongQi = (u8)(80 - (AD1 / 40)); sensorData.ShengYin = 100 - TS_GetData(ADC_Channel_0); // 声音传感器 PA0 sensorData.PM25 = Get_PM25_Average_Data();}}// 处理不同模式void HandleModes(){ KeyNum = Key_GetNum(); if (KeyNum == 1 && DebounceKey(1)) { qingping = 0; S_Shou_2 = 2; //每次初始化手动模式的标志,这样进入手动模式是一样的 S_Mode = (S_Mode + 1) % 4; } switch (S_Mode) { case 0: // 远程模式 if (qingping == 0) { OLED_Clear(); qingping = 1; } TimeRead(); ChuangGan(); OLED_ShowChinese(1, 7, 49); OLED_ShowChinese(1, 8, 50); break; case 2: // 自动模式 OLED_ShowChinese(1, 7, 51); OLED_ShowChinese(1, 8, 52); TimeRead(); zhidong(); ChuangGan(); break; case 1: // 手动模式 OLED_ShowChinese(1, 7, 18); OLED_ShowChinese(1, 8, 52); TimeRead(); ChuangGan(); shoudong(); break; case 3: // 阈值设置 if (qingping == 0) { OLED_Clear(); qingping = 1; } YuZhiSet(); break; }}// 手动模式函数void shoudong(){ if (qingping == 0) { OLED_Clear(); qingping = 1; } if (KeyNum == 2 && DebounceKey(2)) { S_Shou_1 = (S_Shou_1 + 1) % 2; } if (S_Shou_1 == 0) { FENG_OFF();// 外设操作 } if (S_Shou_1 == 1) { FENG_ON();// 外设操作 } if (KeyNum == 3 && DebounceKey(3)) { S_Shou_2 = (S_Shou_2 + 1) % 2; } if (S_Shou_2 == 1) { LED_ON(); // 外设操作 } if (S_Shou_2 == 0) { LED_OFF(); // 外设操作 } if (KeyNum == 4 && DebounceKey(4)) { S_Shou_3 = (S_Shou_3 + 1) % 2; } if (S_Shou_3 == 1) { KONG_ON(); // 外设操作 } if (S_Shou_3 == 0) { KONG_OFF(); // 外设操作 }}// 自动模式函数void zhidong(){ if (qingping == 0) { OLED_Clear(); qingping = 1; } if ((sensorData.PM25 > sensorData.PM25Yu) || (sensorData.Temp > sensorData.TempYu)) { FENG_ON(); } else { FENG_OFF(); } if ((sensorData.KongQi > sensorData.KongQiYu) || (sensorData.Humi > sensorData.HumiYu)) { KONG_ON(); } else { KONG_OFF(); } if (sensorData.Guang sensorData.ShengYinYu) { Buzzer_Turn(); } else { Buzzer_OFF(); }}// 设置阈值函数void YuZhiSet(){ if (qingping == 0) { OLED_Clear(); qingping = 1; } zhidong(); OLED_ShowChinese(1, 3, 72); OLED_ShowChinese(1, 4, 73); OLED_ShowChinese(1, 5, 74); OLED_ShowChinese(1, 6, 75); OLED_ShowString(2, 1, \"G:\"); OLED_ShowNum(2, 3, sensorData.GuangYu, 3); OLED_ShowString(2, 7, \"K:\"); OLED_ShowNum(2, 9, sensorData.KongQiYu, 2); OLED_ShowString(2, 12, \"T:\"); OLED_ShowNum(2, 14, sensorData.TempYu, 2); OLED_ShowString(3, 12, \"H:\"); OLED_ShowNum(3, 14, sensorData.HumiYu, 2); OLED_ShowString(3, 1, \"PM2.5:\"); OLED_ShowNum(3, 7, sensorData.PM25Yu, 3); OLED_ShowString(4, 1, \"ShengYin:\"); OLED_ShowNum(4, 10, sensorData.ShengYinYu, 2); if (KeyNum == 2 && DebounceKey(2)) { S_YuZhi = (S_YuZhi + 1) % 6; } switch (S_YuZhi) { case 0: if (KeyNum == 3) sensorData.GuangYu++; if (KeyNum == 4) sensorData.GuangYu--; break; case 1: if (KeyNum == 3) sensorData.KongQiYu++; if (KeyNum == 4) sensorData.KongQiYu--; break; case 3: if (KeyNum == 3) sensorData.PM25Yu += 100; if (KeyNum == 4) sensorData.PM25Yu -= 100; break; case 5: if (KeyNum == 3) sensorData.ShengYinYu ++; if (KeyNum == 4) sensorData.ShengYinYu --; break; case 2: if (KeyNum == 3) sensorData.TempYu ++; if (KeyNum == 4) sensorData.TempYu --; break; case 4: if (KeyNum == 3) sensorData.HumiYu ++; if (KeyNum == 4) sensorData.HumiYu --; break; }}// 定时模式函数void DingShiMoShi(){ if (qingping == 0) { OLED_Clear(); qingping = 1; } // 定时模式判断 if ((MyRTC_Time[3] == RTC_Time1[0]) && (MyRTC_Time[4] == RTC_Time1[1]) && (MyRTC_Time[5] == RTC_Time1[2])) { // 外设操作 } if ((MyRTC_Time[3] == RTC_Time2[0]) && (MyRTC_Time[4] == RTC_Time2[1]) && (MyRTC_Time[5] == RTC_Time2[2])) { // 外设操作 } // 显示定时时间 OLED_ShowChinese(3, 1, 31); OLED_ShowString(3, 3, \":\"); OLED_ShowNum(3, 5, RTC_Time1[0], 2); OLED_ShowString(3, 7, \":\"); OLED_ShowNum(3, 8, RTC_Time1[1], 2); OLED_ShowString(3, 10, \":\"); OLED_ShowNum(3, 11, RTC_Time1[2], 2); OLED_ShowChinese(4, 1, 32); OLED_ShowString(4, 3, \":\"); OLED_ShowNum(4, 5, RTC_Time2[0], 2); OLED_ShowString(4, 7, \":\"); OLED_ShowNum(4, 8, RTC_Time2[1], 2); OLED_ShowString(4, 10, \":\"); OLED_ShowNum(4, 11, RTC_Time2[2], 2); // 修改定时时间操作 if (KeyNum == 2 && DebounceKey(2)) { S_DingShi_Switch = (S_DingShi_Switch + 1) % 6; } switch (S_DingShi_Switch) { case 0: // 时 if (KeyNum == 3) RTC_Time2[0]++; if (KeyNum == 4) RTC_Time2[0]--; break; case 1: // 分 if (KeyNum == 3) RTC_Time2[1]++; if (KeyNum == 4) RTC_Time2[1]--; break; case 2: // 秒 if (KeyNum == 3) RTC_Time2[2]++; if (KeyNum == 4) RTC_Time2[2]--; break; case 3: // 时 if (KeyNum == 3) RTC_Time1[0]++; if (KeyNum == 4) RTC_Time1[0]--; break; case 4: // 分 if (KeyNum == 3) RTC_Time1[1]++; if (KeyNum == 4) RTC_Time1[1]--; break; case 5: // 秒 if (KeyNum == 3) RTC_Time1[2]++; if (KeyNum == 4) RTC_Time1[2]--; break; }}void YuYingMode() //先说小杰唤醒,然后说打开窗户和关闭窗户{// if (qingping == 0)// {// OLED_Clear();// qingping = 1;// }// if (Serial2_RxFlag == 1) //串口接收到数据包的标志位,若是收到数据包,会置1// {// if (strcmp(Serial2_RxPacket, \"JIASHI_ON\") == 0)// {// // 外设操作// }// else if (strcmp(Serial2_RxPacket, \"JIASHI_OFF\") == 0)// {// // 外设操作// }// Serial2_RxFlag = 0; //将标志位清零,不清零就接收不到下一个数据包了// }}// 机智云初始化函数void MY_Gizwits_Init(void){ TIM3_Int_Init(9, 7199); // 1MS系统定时 usart3_init(9600); // WIFI初始化 memset((uint8_t *)¤tDataPoint, 0, sizeof(dataPoint_t)); // 设备状态结构体初始化 gizwitsInit(); // 环形缓冲区初始化 gizwitsSetMode(2); // 设置模式 userInit();}// 按键消抖函数uint8_t DebounceKey(uint8_t key){ delay_ms(20); return KeyNum == key;}// 设置时间函数void TimeSet(){ if (KeyNum == 2 && DebounceKey(2)) { S_ShiShi_Time_1 = (S_ShiShi_Time_1 + 1) % 3; } if (S_ShiShi_Time_1 == 0) // 时间显示模式 { MyRTC_ReadTime(); OLED_ShowNum(1, 5, MyRTC_Time[3], 2); // 时 OLED_ShowString(1, 7, \":\"); OLED_ShowNum(1, 8, MyRTC_Time[4], 2); // 分 OLED_ShowString(1, 10, \":\"); OLED_ShowNum(1, 11, MyRTC_Time[5], 2); // 秒 RTC_Time[0] = MyRTC_Time[3]; RTC_Time[1] = MyRTC_Time[4]; RTC_Time[2] = MyRTC_Time[5]; } else if (S_ShiShi_Time_1 == 1) // 修改时间 { if (KeyNum == 5 && DebounceKey(5)) { S_ShiShi_Time_2 = (S_ShiShi_Time_2 + 1) % 3; } switch (S_ShiShi_Time_2) { case 0: // 修改时 if (KeyNum == 4) { RTC_Time[0] = (RTC_Time[0] + 1) % 24; // 加 1 后取模 24,确保在 0 - 23 范围内 } if (KeyNum == 3) { if (RTC_Time[0] == 0) { RTC_Time[0] = 23; // 当为 0 时,减操作变为 23 } else { RTC_Time[0]--; } } OLED_ShowNum(1, 5, RTC_Time[0], 2); // 时 break; case 1: // 修改分 if (KeyNum == 4) { RTC_Time[1] = (RTC_Time[1] + 1) % 60; // 加 1 后取模 60,确保在 0 - 59 范围内 } if (KeyNum == 3) { if (RTC_Time[1] == 0) { RTC_Time[1] = 59; // 当为 0 时,减操作变为 59 } else { RTC_Time[1]--; } } OLED_ShowNum(1, 8, RTC_Time[1], 2); // 分 break; case 2: // 修改秒 if (KeyNum == 4) { RTC_Time[2] = (RTC_Time[2] + 1) % 60; // 加 1 后取模 60,确保在 0 - 59 范围内 } if (KeyNum == 3) { if (RTC_Time[2] == 0) { RTC_Time[2] = 59; // 当为 0 时,减操作变为 59 } else { RTC_Time[2]--; } } OLED_ShowNum(1, 11, RTC_Time[2], 2); // 秒 break; } } else if (S_ShiShi_Time_1 == 2) { MyRTC_Time[3] = RTC_Time[0]; MyRTC_Time[4] = RTC_Time[1]; MyRTC_Time[5] = RTC_Time[2]; MyRTC_SetTime(); S_ShiShi_Time_1 = 0; }}// 读取时间函数void TimeRead(){ MyRTC_ReadTime(); OLED_ShowNum(1, 5, MyRTC_Time[3], 2); // 时 OLED_ShowString(1, 7, \":\"); OLED_ShowNum(1, 8, MyRTC_Time[4], 2); // 分 OLED_ShowString(1, 10, \":\"); OLED_ShowNum(1, 11, MyRTC_Time[5], 2); // 秒}// 显示传感器信息void ChuangGan(){ OLED_ShowChinese(2, 1, 53); OLED_ShowChinese(2, 2, 54); OLED_ShowString(2, 5, \":\"); OLED_ShowNum(2, 6, sensorData.Guang, 4); OLED_ShowString(2, 10, \"%\"); OLED_ShowString(2, 12, \"T:\"); OLED_ShowNum(2, 14, sensorData.Temp, 2); OLED_ShowString(3, 12, \"H:\"); OLED_ShowNum(3, 14, sensorData.Humi, 2); OLED_ShowString(3, 1, \"PM2.5:\"); OLED_ShowNum(3, 7, sensorData.PM25, 4);// OLED_ShowNum(3, 7, bufe[0], 4); OLED_ShowChinese(4, 1, 64); OLED_ShowChinese(4, 2, 65); OLED_ShowString(4, 5, \":\"); OLED_ShowChinese(4, 5, 78); OLED_ShowChinese(4, 6, 79); OLED_ShowString(4, 13, \":\"); OLED_ShowNum(4, 6, sensorData.KongQi, 2); OLED_ShowNum(4, 14, sensorData.ShengYin, 2);}
7、总结
本文介绍了一个基于STM32的智能家居系统设计,支持远程控制、手动操作和自动调节三种模式。系统硬件包括STM32主控、OLED显示屏、温湿度传感器、光照传感器、空气质量传感器、PM2.5传感器等模块,通过ESP8266 WIFI模块连接云平台实现手机APP远程监控。自动模式下能根据环境参数智能控制补光灯、风扇和空调;手动模式可通过按键或APP直接操作;还支持语音控制功能。软件设计采用模块化编程,包含传感器数据采集、阈值设置、模式切换等功能模块。该系统实现了家居环境的智能监测与调控,具有实用性和可扩展性。