一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用HC05/06蓝牙模块、IIC OLED液晶、DHT11温湿度传感器、按键模块、ASRONE语音识别模块、
光敏传感器模块、有源蜂鸣器模块、28BYJ48步进电机模块等。
主要功能:
系统运行后,OLED液晶显示当前检测温湿度、工作模式、光线强度、温度和光线阈值、
窗帘开关状态;系统默认处于自动控制模式,可通过K4键选择自动/手动
控制模式;在自动控制模式下,可通过K3键进入阈值设置界面,可设置光线强度和
温度阈值,K3键切换阈值位置,K1和K2调节,K4确认退出;
如果检测温度在温度阈值范围内,光线低于下限,窗帘打开,高于上限窗帘关闭。
如果温度高于温度上限,则打开窗帘,温度低于温度下限,则关闭窗帘。
在手动模式下,可通过K1键手动开关窗帘;同时还可以通过手机蓝牙app控制
窗帘开关以及工作模式;手动模式既可按键控制,也可语音控制;
在语音模式下,可通过语音“小智”唤醒语音模块,通过指令“打开窗帘”、“关闭窗帘”
进行控制;

蓝牙控制命令
#define LY_KEY1_VALUE 0X01
#define LY_KEY2_VALUE 0X02
#define LY_KEY3_VALUE 0X03
#define LY_KEY4_VALUE 0X04


二、软件设计

/*
作者:嗨小易(QQ技术交流群:570487280)

*/



//系统数据获取
void sys_data_get(void)
{
	while(1)
	{
		//获取环境温湿度
		DHT11_Read_Data(&sys_ctrl.temp,&sys_ctrl.humi);
		//获取光照强度
		sys_ctrl.light=99-Get_ADC_Value(ADC_Channel_9,5)/41;
		
		break;
	}
}

//系统数据显示
void sys_data_show(void)
{
	static u8 i=0;
	
	while(1)
	{
		//正常模式显示
		if(sys_ctrl.mode==0)
		{
			//温度
			OLED_ShowNum(16*2+8,16,sys_ctrl.temp,2,16);
			//温度阈值
			OLED_ShowxNum(16*2+8*6,16,sys_ctrl.templ,2,16,0,1);
			OLED_ShowxNum(16*2+8*9,16,sys_ctrl.temph,2,16,0,1);
			
			//湿度
			OLED_ShowNum(16*2+8,32,sys_ctrl.humi,2,16);
			//窗帘开关标志
			if(sys_ctrl.onoff==0)OLED_ShowFontHZ(16*4+8,32,17,16,1);
			else OLED_ShowFontHZ(16*4+8,32,16,16,1);
			//自动手动模式
			if(sys_ctrl.auto_flag==0)
			{
				//自动
				OLED_ShowFontHZ(16*6,32,13,16,1);
				OLED_ShowFontHZ(16*7,32,15,16,1);
			}
			else
			{
				//手动
				OLED_ShowFontHZ(16*6,32,14,16,1);
				OLED_ShowFontHZ(16*7,32,15,16,1);
			}
			
			//光线
			OLED_ShowNum(16*2+8,48,sys_ctrl.light,2,16);
			//光线阈值
			OLED_ShowxNum(16*2+8*6,48,sys_ctrl.lightl,2,16,0,1);
			OLED_ShowxNum(16*2+8*9,48,sys_ctrl.lighth,2,16,0,1);
			
			
			//将数据传输到蓝牙
			i++;
			if(i%10==0)
			{
				u3_printf("\r\n温度:%d°C 湿度:%d%%\r\n",sys_ctrl.temp,sys_ctrl.humi);
				u3_printf("光线:%d%%\r\n",sys_ctrl.light);
				if(sys_ctrl.onoff==0)u3_printf("窗帘:关\r\n");
				else u3_printf("窗帘:开\r\n");
				if(sys_ctrl.auto_flag==0)u3_printf("模式:自动\r\n");
				else u3_printf("模式:手动\r\n");
			}
		}
		//参数设置模式显示
		else
		{
			switch(sys_ctrl.mode)
			{
				case 1://温度下
					OLED_ShowxNum(16*2+8*9,48,sys_ctrl.lighth,2,16,0,1);
					OLED_ShowxNum(16*2+8*6,16,sys_ctrl.templ,2,16,0,0);
					break;
				case 2://温度上
					OLED_ShowxNum(16*2+8*6,16,sys_ctrl.templ,2,16,0,1);
					OLED_ShowxNum(16*2+8*9,16,sys_ctrl.temph,2,16,0,0);
					break;
				case 3://光线下
					OLED_ShowxNum(16*2+8*9,16,sys_ctrl.temph,2,16,0,1);
					OLED_ShowxNum(16*2+8*6,48,sys_ctrl.lightl,2,16,0,0);
					break;
				case 4://光线上
					OLED_ShowxNum(16*2+8*6,48,sys_ctrl.lightl,2,16,0,1);
					OLED_ShowxNum(16*2+8*9,48,sys_ctrl.lighth,2,16,0,0);
					break;
			}
		}
		
		OLED_Refresh_Gram();//刷新显示缓存
		break;
	}
}

//系统数据设置
void sys_data_set(void)
{
	u8 key=0;
	
	key=KEY_Scan(0);
	if(key!=0)BEEP_Alarm(2,2000);
	
	
	//设置
	if(key==KEY3_PRESS || USART3_RX_BUF[0]==LY_KEY3_VALUE)
	{
		sys_ctrl.mode++;
		if(sys_ctrl.mode>4)sys_ctrl.mode=1;
	}
	//加
	else if(key==KEY1_PRESS || USART3_RX_BUF[0]==LY_KEY1_VALUE)
	{
		switch(sys_ctrl.mode)
		{
			case 1://温度下限
				sys_ctrl.templ++;
				if(sys_ctrl.templ>99)sys_ctrl.templ=0;
				break;
			case 2://温度上限
				sys_ctrl.temph++;
				if(sys_ctrl.temph>99)sys_ctrl.temph=0;
				break;
			case 3://光线下限
				sys_ctrl.lightl++;
				if(sys_ctrl.lightl>99)sys_ctrl.lightl=0;
				break;
			case 4://光线上限
				sys_ctrl.lighth++;
				if(sys_ctrl.lighth>99)sys_ctrl.lighth=0;
				break;
		}
	}
	//减
	else if(key==KEY2_PRESS || USART3_RX_BUF[0]==LY_KEY2_VALUE)
	{
		switch(sys_ctrl.mode)
		{
			case 1://温度下限
				sys_ctrl.templ--;
				if(sys_ctrl.templ<0)sys_ctrl.templ=99;
				break;
			case 2://温度上限
				sys_ctrl.temph--;
				if(sys_ctrl.temph<0)sys_ctrl.temph=99;
				break;
			case 3://光线下限
				sys_ctrl.lightl--;
				if(sys_ctrl.lightl<0)sys_ctrl.lightl=99;
				break;
			case 4://光线上限
				sys_ctrl.lighth--;
				if(sys_ctrl.lighth<0)sys_ctrl.lighth=99;
				break;
		}
	}
	//确定
	else if(key==KEY4_PRESS || USART3_RX_BUF[0]==LY_KEY4_VALUE)
	{
		if(sys_ctrl.mode!=0)sys_ctrl.mode=0;
		else sys_ctrl.auto_flag=!sys_ctrl.auto_flag;
	}	
	
	//手动模式
	if(sys_ctrl.auto_flag==1)
	{	
		//窗帘开关
		if(key==KEY1_PRESS || USART3_RX_BUF[0]==LY_KEY1_VALUE)
		{
			sys_ctrl.onoff=!sys_ctrl.onoff;
		}
	}
	
	if(USART3_RX_BUF[0]!=0)USART3_RX_BUF[0]=0;
}

//系统功能控制
void sys_fun_ctrl(void)
{
	static u8 oneflag=0;
	
	//自动模式
	if(sys_ctrl.auto_flag==0)
	{
		//如果温度高于上限值,打开窗帘
		if(sys_ctrl.temp>sys_ctrl.temph)
		{
			sys_ctrl.onoff=1;
		}
		//如果温度低于下限,关闭窗帘
		else if(sys_ctrl.temp<sys_ctrl.templ)
		{
			sys_ctrl.onoff=0;
		}
		//如果在阈值范围内
		else 
		{
			//光线高于上限,关闭窗帘
			if(sys_ctrl.light>sys_ctrl.lighth)
			{
				sys_ctrl.onoff=0;
			}
			//光线低于下限,打开窗帘
			else if(sys_ctrl.light<sys_ctrl.lightl)
			{
				sys_ctrl.onoff=1;
			}
		}
	}
	
	
	//语音识别模块控制
	switch(USART2_RX_BUF[0])
	{
		case 0x01://自动模式
			sys_ctrl.auto_flag=0;
			break;
		case 0x02://手动模式
			sys_ctrl.auto_flag=1;
			break;
		case 0x09://语音模式
			sys_ctrl.auto_flag=1;
			break;
	}
	//手动模式控制
	if(sys_ctrl.auto_flag==1)
	{
		switch(USART2_RX_BUF[0])
		{
			case 0x03://打开窗帘
				sys_ctrl.onoff=1;
				break;
			case 0x04://关闭窗帘
				sys_ctrl.onoff=0;
				break;
		}
	}
	if(USART2_RX_BUF[0]!=0)USART2_RX_BUF[0]=0;
	
	
	//原本关闭窗帘,开窗帘
	if(sys_ctrl.onoff==1)
	{
		if(oneflag==0)
		{
			oneflag=1;
			Step_Motor_Run(8,sys_ctrl.onoff,STEPMOTOR_MAXSPEED,180,1);
		}
	}
	//原本打开窗帘,关闭窗帘
	else
	{
		if(oneflag==1)
		{
			oneflag=0;
			Step_Motor_Run(8,sys_ctrl.onoff,STEPMOTOR_MAXSPEED,180,1);
		}
	}
}






三、实验现象

B站演示视频:https://space.bilibili.com/444388619
在这里插入图片描述
在这里插入图片描述

联系作者

视频地址:https://space.bilibili.com/444388619/video
专注于51单片机、STM32、国产32、DSP、Proteus、arduino、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐