一、前言

实物项目成品:
在这里插入图片描述

仿真项目成品:
在这里插入图片描述

哔哩哔哩开源视频链接(复制浏览器打开):
https://www.bilibili.com/video/BV1Ften65Ene/?vd_source=10da4d04d580bd6b34f7298120737c50

(资料分享见文末)

二、项目功能简介

【开源】STM32单片机智能除湿衣柜控制系统(代码 + 原理图 + 仿真)-编号:CY26043
功能介绍:

  1. 自动除湿控制:采用 DHT11 数字温湿度传感器采集衣柜内部温湿度数据,当湿度达到设定阈值,继电器驱动风扇启动进行除湿;湿度回落至阈值以下自动停止除湿。
  2. 人体存在检测:搭载 HC‑SR501 红外热释电传感器,实时检测衣柜附近是否有人体活动。
  3. PWM 自动调光补光:检测到有人时,根据环境光照强度自动调节 LED 灯 PWM 输出占空比,将衣柜内部照明维持在设定光照区间(300‑500Lux),实现智能补光。
  4. OLED 状态显示:OLED 显示屏实时展示当前温湿度、温湿度阈值等系统参数。
  5. 超限声光报警:当衣柜内温湿度超出预设阈值,触发蜂鸣器 + LED 声光报警提示。
  6. 按键参数配置:独立按键可设置温湿度上下限阈值,同时支持手动控制 LED 照明灯的开启与关闭
  7. APP远程监控:手机蓝牙APP可以实时监控温湿度、光照等传感器数据,可以设置阈值,远程控制风扇和灯光

三、PCB设计

在这里插入图片描述

四、原理图设计

在这里插入图片描述

五、程序设计

代码如下():

#include "sys.h"
#include "adc.h"
#include "delay.h"
#include "OLED.h"
#include "ds18b20.h"
#include "esp8266.h"
#include "timer.h"
#include "dht11.h"
#include "PWM.h"
#include "gpio.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


unsigned int  light=0;
unsigned char temperature=0;
unsigned char  Humi;

unsigned char setTempValue=35;       
unsigned int  setHumiValue=70;	
unsigned int setLightValue=900;       
unsigned int LightValue=0;       

bool usart_send_flag = 0;
bool mode = 0;               
bool shuaxin  = 0;
bool shanshuo = 0;
bool sendFlag = 1;

u8 buff[30];//参数显示缓存数组
u8 count;
uint8_t Ren;		// 人
unsigned char setn=0;
void Red_Init(void)		
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
}

uint8_t Red_Rdata(void)//获取有人无人的数据
{
	return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4);
}
void displayLight(void)
{
		u16 test_adc=0;
		static u16 last_light[5] = {0}; // 保存最近5次的光照值,用于滑动平均滤波
		static u8 filter_index = 0;     // 当前滤波数组索引
		u16 sum = 0;                    // 用于计算平均值的总和
	  
	  // 增加采样次数,从20次增加到30次
	  test_adc = Get_Adc_Average(ADC_Channel_0,30);
		
		// 计算当前光照值
		u16 current_light = test_adc*1000/4096;
		//current_light = 99 - current_light;
		
		// 更新滑动窗口数组
		last_light[filter_index] = current_light;
		filter_index = (filter_index + 1) % 5; // 循环更新索引
		
		// 计算滑动平均值
		for(u8 i = 0; i < 5; i++) {
			sum += last_light[i];
		}
		
		// 如果是初始状态(前几次采样),使用当前值
		if(last_light[4] == 0) {
			light = current_light;
		} else {
			// 使用滑动平均值,但对新值赋予更高权重
			// 新值占20%,历史平均值占80%
			light = (current_light * 2 + (sum / 5) * 8) / 10;
		}
		
		// 确保值在合理范围内
		light = light >= 1000? 1000: (light <= 0? 0: light);
		
	  if(light<=setLightValue && shanshuo)
		{
			//   OLED_ShowString(16*6,32,"   ",16);
		}
		else
		{
			//OLED_ShowNum(3, 13, light, 4);
			sprintf((char*)buff,"%2d Luz",light);
			OLED_ShowString(3,7,(char*)buff);	//显示光照
		}
}
void displayTemp_Humierature(void)
{
		DHT11_Read_Data(&Humi,&temperature);

	  if(temperature>=setTempValue && shanshuo)
		{
			 //OLED_ShowString(16*6,16,"  ",16);
		}
		else
		{
			 if(temperature!=0)
			 {
				 sprintf((char*)buff,"%2d C",temperature);
				OLED_ShowString(1,7,(char*)buff);	
					
			 }
		}
		if(Humi<=setHumiValue && shanshuo)
		{
			// OLED_ShowString(16*6,0,"   ",16);
		}
		else
		{
			sprintf((char*)buff,"%2d %%",Humi);
			OLED_ShowString(2,7,(char*)buff);	//显示温度
			
		}
}

void displaySetValue(void)
{
		if(setn == 1)
		 {
			 
			 if(shanshuo)
			 {
				OLED_ShowString(2,11,"  ");
			 }
			 else
			 {
				 sprintf((char*)buff,"%2dC",setTempValue);
				 
				OLED_ShowString(2,11,(char*)buff);	
				sprintf((char*)buff,"%2d%%",setHumiValue);
				OLED_ShowString(3,11,(char*)buff);	
				sprintf((char*)buff,"%2dLux",setLightValue);
				OLED_ShowString(4,11,(char*)buff);	
				 
				
			 }
			
		 }
		 if(setn == 2)
		 {
				if(shanshuo)
			 {
				OLED_ShowString(3,11,"  ");
			 }
			 else
			 {
				 sprintf((char*)buff,"%2dC",setTempValue);
				 
				OLED_ShowString(2,11,(char*)buff);	
				  sprintf((char*)buff,"%2d%%",setHumiValue);
				OLED_ShowString(3,11,(char*)buff);	
				 sprintf((char*)buff,"%2dLux",setLightValue);
				OLED_ShowString(4,11,(char*)buff);	
				 
				  
			 }
		 }
		 if(setn == 3)
		 {
				if(shanshuo)
			 {
				OLED_ShowString(4,11,"  ");
			 }
			 else
			 {
				sprintf((char*)buff,"%2dC",setTempValue);
				 
				OLED_ShowString(2,11,(char*)buff);	
				sprintf((char*)buff,"%2d%%",setHumiValue);
				OLED_ShowString(3,11,(char*)buff);	
				sprintf((char*)buff,"%2dLux",setLightValue);
				OLED_ShowString(4,11,(char*)buff);	 
			 }
		 }
}

void keyscan(void)
{
	if(KEY1 == 0)
	{
	 	delay_ms(20);
		if(RELAY2==1)delay_ms(50);
		if(KEY1 == 0)
		{
		 	while(KEY1 == 0);
			if(setn == 0)
			 {
				  mode = !mode;
					 if(mode==0)
					  {
						  OLED_ShowChinese(4,4,19);
						  OLED_ShowChinese(4,5,20);
					  }
					  else 
					  {
						  RELAY1=0;  
						  RELAY2=0;  
						  RELAY3=0;  
						  OLED_ShowChinese(4,4,21);
						  OLED_ShowChinese(4,5,22);
					  }
			 }
		}
	}
	if(KEY2 == 0)
	{
	 	delay_ms(20);
		
		if(KEY2 == 0)
		{
			while(KEY2 == 0);
			 BEEP=0;
			if(mode==0)
			{
				setn ++;
				PWM_SetCompare2(0);  
				RELAY2=0; 
				
			}
			if(setn == 0 && mode==1)
			 {
					PWM_SetCompare2(0);  
			 }
			if(setn == 1)
			{
				OLED_Clear();
			}
			if(mode==1)
			{
				RELAY3=~RELAY3;;
			}
			
			 if(setn == 1||setn == 2||setn == 3)
			 {
				OLED_ShowChinese(1,3,16);
				OLED_ShowChinese(1,4,17);
				OLED_ShowChinese(1, 5, 23);
				OLED_ShowChinese(1, 6, 24);	
				 
				//显示“温度阈值:”
				OLED_ShowChinese(2, 1, 2);
				OLED_ShowChinese(2, 2, 3);
				OLED_ShowChinese(2, 3, 23);
				OLED_ShowChinese(2, 4, 24);	
				OLED_ShowChar(2, 9, ':');
				
				//显示“湿度阈值:”
				OLED_ShowChinese(3, 1, 6);
				OLED_ShowChinese(3, 2, 7);
				OLED_ShowChinese(3, 3, 23);
				OLED_ShowChinese(3, 4, 24);	
				OLED_ShowChar(3, 9, ':');

				//显示”光照阈值:“
				OLED_ShowChinese(4, 1, 10);
				OLED_ShowChinese(4, 2, 11);	
				OLED_ShowChinese(4, 3, 23);
				OLED_ShowChinese(4, 4, 24);	
				OLED_ShowChar(4, 9, ':');
			 }
			
			 displaySetValue();
			 if(setn >= 4)
			 {
					OLED_Clear();
					setn = 0;
					//显示"温度:"
					OLED_ShowChinese(1, 1, 2);
					OLED_ShowChinese(1, 2, 3);
					OLED_ShowChar(1, 5, ':');
					
					//显示“湿度:”
					OLED_ShowChinese(2, 1, 6);
					OLED_ShowChinese(2, 2, 7);	
					OLED_ShowChar(2, 5, ':');

					//显示”光照:“
					OLED_ShowChinese(3, 1, 8);
					OLED_ShowChinese(3, 2, 9);	
					OLED_ShowChar(3, 5, ':');
								 
					//显示”工作模式:“
					OLED_ShowChinese(4,1,14);
					OLED_ShowChinese(4,2,15);
					OLED_ShowChar(4, 5, ':');
		
				  if(mode==0)
					  {
						  OLED_ShowChinese(4,4,19);
						  OLED_ShowChinese(4,5,20);
					  }
					  else 
					  {
						  OLED_ShowChinese(4,4,21);
						  OLED_ShowChinese(4,5,22);
					  }
			 }
		}
	}
	if(KEY3 == 0)//加
	{
		delay_ms(20);//
		
		if(KEY3 == 0 )
		{
			while(KEY3 == 0);
			if(setn == 0 && mode==1)
			 {
					if(LightValue==0)
					{
						LightValue=setLightValue;
					}
					LightValue+=100;
					if(LightValue>=1000)
						LightValue=10;
					PWM_SetCompare2(LightValue);
			 }
			if(setn == 2)
			 {
					if(setHumiValue<99)setHumiValue++;
			 }
			 if(setn == 1)
			 {
					if(setTempValue<99)setTempValue++;
			 }
			 if(setn == 3)
			 {
				 if(setLightValue<999)setLightValue+=100;
			 }
			 displaySetValue();
		}
	}
	
	if(KEY4 == 0)//减
	{
		delay_ms(20);//
		if(RELAY2==1)delay_ms(50);
		if(KEY4 == 0 )
		{
			while(KEY4 == 0);
			if(setn == 0 && mode==1)
			 {
					RELAY2=~RELAY2;
			 }
      if(setn == 2)
			 {
					if(setHumiValue>0)setHumiValue--;
			 }
			 if(setn == 1)
			 {
					if(setTempValue>0)setTempValue--;
			 }
			 if(setn == 3)
			 {
				 if(setLightValue>0)setLightValue-=100;
			 }
			 displaySetValue();
		}
	}
}

int main(void)
{	
	delay_init();	   
	NVIC_Configuration();
	delay_ms(500);      
	Adc_Init();          //光照adc初始化
	KEY_GPIO_Init();     //按键初始化
	DHT11_Init();				//DHT11初始化
	Red_Init();         //人体检测
	PWM_Init();         //PWM初始化
	OLED_Init();				//OLED初始化
	OLED_Clear();		
	OLED_ShowString(2,1,"   Loading...   ");
	delay_ms(1000);
	OLED_Clear();
	
	//显示"温度:"
	OLED_ShowChinese(1, 1, 2);
	OLED_ShowChinese(1, 2, 3);
	OLED_ShowChar(1, 5, ':');
	
	//显示“湿度:”
	OLED_ShowChinese(2, 1, 6);
	OLED_ShowChinese(2, 2, 7);	
	OLED_ShowChar(2, 5, ':');

	//显示”光照:“
	OLED_ShowChinese(3, 1, 8);
	OLED_ShowChinese(3, 2, 9);	
	OLED_ShowChar(3, 5, ':');
				 
	//显示”工作模式:“
	OLED_ShowChinese(4,1,14);
	OLED_ShowChinese(4,2,15);
	OLED_ShowChar(4, 5, ':');
			
	TIM3_Init(99,719);  
		
		while(1)
		{  
			 keyscan();
			 if(setn == 0)
			 {
				   if(shuaxin == 1)
					 {
						   shuaxin = 0;
							 displayLight();   
							 displayTemp_Humierature(); 
							 Ren=Red_Rdata();
							 if(Ren==1)   
							 {
								  OLED_ShowChinese(1,7,25);
									OLED_ShowChinese(1,8,27);
							 }
							 else
							 {
									 
								  OLED_ShowChinese(1,7,26);
									OLED_ShowChinese(1,8,27);
							 }
							 if(mode==0)   
							 {
								 if(Ren==1)      //有人
								 {
										if(light<=setLightValue)
											PWM_SetCompare2(1000-light);
										else
											PWM_SetCompare2(0); 
								 }
								 else         //无人自动关灯
								 {
										PWM_SetCompare2(0); 
								 }             
								 if(temperature>=setTempValue||Humi>=setHumiValue)RELAY2=1;else RELAY2=0;                
								 if(temperature>=setTempValue||Humi>=setHumiValue)BEEP=1;else BEEP=0;  
								 OLED_ShowChinese(4,4,19);
								 OLED_ShowChinese(4,5,20);
							 }
							 else
							 {
									BEEP=0;
									OLED_ShowChinese(4,4,21);
									OLED_ShowChinese(4,5,22);
							 }
					 }
			 }
			  if(setn!=0)
				 {  
					displaySetValue();  
				 }
			 delay_ms(10);
		}	
}


void TIM3_IRQHandler(void)   
{
		static u16 timeCount1 = 0;
	
		if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  
		{
				TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  
        timeCount1++;
        if(timeCount1 >= 300)  //300ms
				{
						timeCount1 = 0;
					  shanshuo = !shanshuo;
					  shuaxin = 1;
				}
		}
} 

六、包含内容

在这里插入图片描述

七、资料分享

资料获取:请查看主页介绍搜索或观看开源视频获取

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐