【Proteus仿真】【STM32单片机】智能语音家居陪护机器人


一、功能简介

本项目使用Proteus8仿真STM32单片机控制器,使用OLED显示模块、红外传感器、蜂鸣器、DS18B20温度传感器,风扇LED、语音识别模块等。

主要功能:
系统运行后,OLED显示动画效果,一段时间后静止。当到达指定时间时开启闹钟,系统需感应到有人后,此时可通过K4键或语音关闭闹铃。系统感应到有人后,OLED显示测量的人体体温、时间、LED和风扇的开关状态;此时可通过语音开关LED和风扇;可通过按键K3进入闹钟设置界面,通过K3键切换不同时间位置,K1和K2键加减调节,设置后按下K4键保存并退出,返回测温和时钟显示界面。
语音识别指令(十六进制数):
开灯–>0X01
关灯–>0X02
开风扇–>0X11
关风扇–>0X12
关闹铃–>0X22


二、软件设计

/*
作者:嗨小易(QQ:3443792007)

*/



//系统数据获取
void sys_data_get(void)
{
	static u8 i=0;
	static u8 oneflag=1;

	while(1)
	{	
		//人体红外检测
		if(IRED==0)
		{
			//温度获取
			i++;
			if(i%1==0)
			{
				TIM_Cmd(TIM2,DISABLE); //关闭定时器
				sys_ctrl.temp=DS18B20_GetTemperture()*10;
				TIM_Cmd(TIM2,ENABLE); //打开定时器
			}
			sys_ctrl.man=1;
		}
		else sys_ctrl.man=0;
		
		//界面状态显示
		if(sys_ctrl.man==0)
		{
			sys_ctrl.window=0;
			if(oneflag==0)
			{
				oneflag=1;
				sys_open_show();//系统开机界面显示	
			}			
		}
		else 
		{
			sys_ctrl.window=1;
			if(oneflag==1)
			{
				oneflag=0;
				sys_parm_show();//系统数据参数显示界面	
			}		
		}		

		break;
	}
}

//系统数据显示
void sys_data_show(void)
{
	u8 buf[9];

	while(1)
	{	
		//显示数据界面
		if(sys_ctrl.window==1)
		{	
			//正常模式下
			if(sys_ctrl.mode==0)
			{
				//温度显示
				buf[0]=sys_ctrl.temp/100+0x30;
				buf[1]=sys_ctrl.temp%100/10+0x30;
				buf[2]='.';
				buf[3]=sys_ctrl.temp%100%10+0x30;
				buf[4]='C';
				buf[5]='\0';
				OLED_ShowString(3*16,0,buf,16);	
	
				//时间显示
				buf[0]=sys_ctrl.hour/10+0x30;
				buf[1]=sys_ctrl.hour%10+0x30;
				buf[2]=':';
				buf[3]=sys_ctrl.min/10+0x30;
				buf[4]=sys_ctrl.min%10+0x30;
				buf[5]=':';
				buf[6]=sys_ctrl.sec/10+0x30;
				buf[7]=sys_ctrl.sec%10+0x30;
				buf[8]='\0';
				OLED_ShowString(3*16,2,buf,16);
	
				//灯状态显示
				if(sys_ctrl.led==1)OLED_ShowString(2*16,4,"ON ",16);
				else OLED_ShowString(2*16,4,"OFF",16);
				//风扇状态显示
				if(sys_ctrl.motor==1)OLED_ShowString(6*16+8*1,4,"ON ",16);
				else OLED_ShowString(6*16+8*1,4,"OFF",16);
			}
			//时间设置模式下
			else
			{
			   	//吃药时间显示
				buf[0]=sys_ctrl.stime[0][0]/10+0x30;
				buf[1]=sys_ctrl.stime[0][0]%10+0x30;
				buf[2]=':';
				buf[3]=sys_ctrl.stime[0][1]/10+0x30;
				buf[4]=sys_ctrl.stime[0][1]%10+0x30;
				buf[5]=':';
				buf[6]=sys_ctrl.stime[0][2]/10+0x30;
				buf[7]=sys_ctrl.stime[0][2]%10+0x30;
				buf[8]='\0';
				OLED_ShowString(3*16,0,buf,16);
				//运动时间显示
				buf[0]=sys_ctrl.stime[1][0]/10+0x30;
				buf[1]=sys_ctrl.stime[1][0]%10+0x30;
				buf[2]=':';
				buf[3]=sys_ctrl.stime[1][1]/10+0x30;
				buf[4]=sys_ctrl.stime[1][1]%10+0x30;
				buf[5]=':';
				buf[6]=sys_ctrl.stime[1][2]/10+0x30;
				buf[7]=sys_ctrl.stime[1][2]%10+0x30;
				buf[8]='\0';
				OLED_ShowString(3*16,3,buf,16);
				//休息时间显示
				buf[0]=sys_ctrl.stime[2][0]/10+0x30;
				buf[1]=sys_ctrl.stime[2][0]%10+0x30;
				buf[2]=':';
				buf[3]=sys_ctrl.stime[2][1]/10+0x30;
				buf[4]=sys_ctrl.stime[2][1]%10+0x30;
				buf[5]=':';
				buf[6]=sys_ctrl.stime[2][2]/10+0x30;
				buf[7]=sys_ctrl.stime[2][2]%10+0x30;
				buf[8]='\0';
				OLED_ShowString(3*16,6,buf,16);

				switch(sys_ctrl.mode)
				{
					case 1://吃药-时
						OLED_ShowString(3*16,0,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[0][0]/10+0x30;
						buf[1]=sys_ctrl.stime[0][0]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16,0,buf,16);
						break;
					case 2://吃药-分
						OLED_ShowString(3*16+3*8,0,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[0][1]/10+0x30;
						buf[1]=sys_ctrl.stime[0][1]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16+3*8,0,buf,16);
						break;
					case 3://吃药-秒
						OLED_ShowString(3*16+6*8,0,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[0][2]/10+0x30;
						buf[1]=sys_ctrl.stime[0][2]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16+6*8,0,buf,16);
						break;
					case 4://运动-时
						OLED_ShowString(3*16,3,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[1][0]/10+0x30;
						buf[1]=sys_ctrl.stime[1][0]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16,3,buf,16);
						break;
					case 5://运动-分
						OLED_ShowString(3*16+3*8,3,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[1][1]/10+0x30;
						buf[1]=sys_ctrl.stime[1][1]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16+3*8,3,buf,16);
						break;
					case 6://运动-秒
						OLED_ShowString(3*16+6*8,3,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[1][2]/10+0x30;
						buf[1]=sys_ctrl.stime[1][2]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16+6*8,3,buf,16);
						break;
					case 7://休息-时
						OLED_ShowString(3*16,6,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[2][0]/10+0x30;
						buf[1]=sys_ctrl.stime[2][0]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16,6,buf,16);
						break;
					case 8://休息-分
						OLED_ShowString(3*16+3*8,6,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[2][1]/10+0x30;
						buf[1]=sys_ctrl.stime[2][1]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16+3*8,6,buf,16);
						break;
					case 9://休息-秒
						OLED_ShowString(3*16+6*8,6,"  ",16);
						delay_ms(50);
						buf[0]=sys_ctrl.stime[2][2]/10+0x30;
						buf[1]=sys_ctrl.stime[2][2]%10+0x30;
						buf[2]='\0';
						OLED_ShowString(3*16+6*8,6,buf,16);
						break;
				}
			}	
		}
		
		break;		
	}
}


//系统数据设置
void sys_data_set(void)
{
	u8 key=0;
	static u8 oneflag=0;
	//有人的时候
	if(sys_ctrl.window==1)
	{
		key=KEY_Scan(1);
		//语音识别
		if(USART1_RX_BUF[0]==LED_ON_CMD)//开灯
		{
			USART1_RX_BUF[0]=0;
			LED=0;
			sys_ctrl.led=1;	
		}
		else if(USART1_RX_BUF[0]==LED_OFF_CMD)//关灯
		{
			USART1_RX_BUF[0]=0;
			LED=1;
			sys_ctrl.led=0;	
		}
		else if(USART1_RX_BUF[0]==MOTOR_ON_CMD)//开风扇
		{
			USART1_RX_BUF[0]=0;
			MOTOR=0;
			sys_ctrl.motor=1;	
		}
		else if(USART1_RX_BUF[0]==MOTOR_OFF_CMD)//关风扇
		{
			USART1_RX_BUF[0]=0;
			MOTOR=1;
			sys_ctrl.motor=0;
		}
		else if(USART1_RX_BUF[0]==ALARM_OFF_CMD)//关闹铃
		{
			USART1_RX_BUF[0]=0;
			sys_ctrl.alarm=0;
			OLED_ShowString(0,6,"        ",16);
		}	
	}	
	//模式设置
	if(key==KEY3_PRESS)
	{
		sys_ctrl.mode++;
		if(sys_ctrl.mode>9)sys_ctrl.mode=1;	
		if(oneflag==0)//时间设置界面仅显示1次
		{
			oneflag=1;
			sys_time_set_show();//系统时间设置界面显示	
		}
	}
	//在设置模式下,加
	else if(key==KEY1_PRESS)
	{
		switch(sys_ctrl.mode)
		{
			case 1://吃药-时
				sys_ctrl.stime[0][0]++;
				if(sys_ctrl.stime[0][0]>23)sys_ctrl.stime[0][0]=0; 
				break;
			case 2://吃药-分
				sys_ctrl.stime[0][1]++;
				if(sys_ctrl.stime[0][1]>59)sys_ctrl.stime[0][1]=0; 
				break;
			case 3://吃药-秒
				sys_ctrl.stime[0][2]++;
				if(sys_ctrl.stime[0][2]>59)sys_ctrl.stime[0][2]=0; 
				break;
			case 4://运动-时
				sys_ctrl.stime[1][0]++;
				if(sys_ctrl.stime[1][0]>24)sys_ctrl.stime[1][0]=0; 
				break;
			case 5://运动-分
				sys_ctrl.stime[1][1]++;
				if(sys_ctrl.stime[1][1]>59)sys_ctrl.stime[1][1]=0; 
				break;
			case 6://运动-秒
				sys_ctrl.stime[1][2]++;
				if(sys_ctrl.stime[1][2]>59)sys_ctrl.stime[1][2]=0; 
				break;
			case 7://休息-时
				sys_ctrl.stime[2][0]++;
				if(sys_ctrl.stime[2][0]>24)sys_ctrl.stime[2][0]=0; 
				break;
			case 8://休息-分
				sys_ctrl.stime[2][1]++;
				if(sys_ctrl.stime[2][1]>59)sys_ctrl.stime[2][1]=0; 
				break;
			case 9://休息-秒
				sys_ctrl.stime[2][2]++;
				if(sys_ctrl.stime[2][2]>59)sys_ctrl.stime[2][2]=0; 
				break;		
		}		
	}
	//在设置模式下,减
	else if(key==KEY2_PRESS)
	{
		switch(sys_ctrl.mode)
		{
			case 1://吃药-时
				sys_ctrl.stime[0][0]--;
				if(sys_ctrl.stime[0][0]<0)sys_ctrl.stime[0][0]=23; 
				break;
			case 2://吃药-分
				sys_ctrl.stime[0][1]--;
				if(sys_ctrl.stime[0][1]<0)sys_ctrl.stime[0][1]=59; 
				break;
			case 3://吃药-秒
				sys_ctrl.stime[0][2]--;
				if(sys_ctrl.stime[0][2]<0)sys_ctrl.stime[0][2]=59; 
				break;
			case 4://运动-时
				sys_ctrl.stime[1][0]--;
				if(sys_ctrl.stime[1][0]<0)sys_ctrl.stime[1][0]=23; 
				break;
			case 5://运动-分
				sys_ctrl.stime[1][1]--;
				if(sys_ctrl.stime[1][1]<0)sys_ctrl.stime[1][1]=59; 
				break;
			case 6://运动-秒
				sys_ctrl.stime[1][2]--;
				if(sys_ctrl.stime[1][2]<0)sys_ctrl.stime[1][2]=59; 
				break;
			case 7://休息-时
				sys_ctrl.stime[2][0]--;
				if(sys_ctrl.stime[2][0]<0)sys_ctrl.stime[2][0]=23; 
				break;
			case 8://休息-分
				sys_ctrl.stime[2][1]--;
				if(sys_ctrl.stime[2][1]<0)sys_ctrl.stime[2][1]=59; 
				break;
			case 9://休息-秒
				sys_ctrl.stime[2][2]--;
				if(sys_ctrl.stime[2][2]<0)sys_ctrl.stime[2][2]=59; 
				break;		
		}	
	}
	//确定
	else if(key==KEY4_PRESS)
	{	
		if(oneflag==1)
		{
			sys_ctrl.mode=0;
			oneflag=0;
			sys_parm_show();//系统数据参数显示界面	
		}
		//闹铃
		if(sys_ctrl.alarm==1)
		{
			sys_ctrl.alarm=0;
			OLED_ShowString(0,6,"        ",16);	
		}	
	}
}

//应用控制系统
void appdemo_show(void)
{
	u8 i=10;
	KEY_Init();
	ctrl_pin_init();
	BEEP_Init();
	DS18B20_Init();
	//等待温度数据稳定
	while(i--)
	{
		sys_ctrl.temp=DS18B20_GetTemperture()*10;
		delay_ms(100);	
	}
	OLED_Init();
	USART1_Init(9600);
	printf("USART1_Init OK\r\n");
	TIM2_Init(400-1,70);//定时10ms
	sys_parm_init();//系统参数初始化
	sys_open_show();//系统初始界面显示
	TIM_Cmd(TIM2,ENABLE); //打开定时器
	while(1)
	{
		sys_data_get();//系统数据获取
		sys_data_show();//系统数据显示
		sys_data_set();//系统数据设置
		sys_fun_ctrl();//系统功能控制		
	}
}









三、实验现象

B站演示视频:https://space.bilibili.com/444388619

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


联系作者

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

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值