目录

一、项目概述

二、实现功能

1、功能详解:

2、项目清单:

3、演示视频:哔哩哔哩视频链接点击观看:https://www.bilibili.com/video/BV1TCMg6AEmk/?share_source=copy_web&vd_source=f4437c8e4429101e5bf1054c39d5474f

三、硬件介绍

PCB硬件设计:

四、程序设计

五、项目成品效果

六、项目总结

七、包含资料



一、项目概述

本项目使用STM32F103C8T6单片机开发,整体设计简洁明了,没有复杂的操作系统和多线程逻辑。主要实现基础的数据采集、数据显示和智能控制功能,上手零压力。
系统搭载DHT11温湿度传感器采集环境温湿度,声音传感器侦测婴儿啼哭,雨滴传感器检测尿床状态,震动传感器监测撞击震动。所有数据实时显示在OLED屏幕上。系统支持自动与手动两种模式:自动模式下,温湿度超标自动调节风扇与加热片,侦测到啼哭自动播放安抚音乐并启动摇床,尿床或撞击时通过蓝牙App推送报警并触发蜂鸣器;手动模式下,用户可通过按键分别控制加热片、风扇、摇床及音乐播放。设备通过BT04A蓝牙模块连接手机App,可实时查看数据与报警信息,并远程下发控制指令。

二、实现功能

  • 1、功能详解:

  • 环境采集:实时采集环境温湿度、婴儿啼哭声音、尿床状态以及撞击震动情况。

  • 显示功能:通过OLED显示屏实时呈现环境参数、当前工作模式、预设阈值及各执行器运行状态。

  •  阈值调节:支持用户自定义温度上限、温度下限及湿度阈值。

  •  模式切换:支持通过按键在自动模式和手动模式之间切换。

  • 自动模式:系统依据传感器数据自动执行控制逻辑:超温时启动风扇降温,低温时启动加热片升温,湿度过高时启动风扇除湿;侦测到啼哭时自动播放安抚音乐并启动摇床;侦测到尿床时通过蓝牙推送报警信息;侦测到撞击时通过蓝牙推送报警信息并触发蜂鸣器报警。

  •  手动模式:用户可通过按键分别控制加热片、风扇、摇床及音乐播放功能的开启与关闭。

  • 蓝牙APP:支持通过蓝牙APP实时查看所有环境数据与报警信息,并可远程下发控制指令。

  • 2、项目清单:

  • STM32F103C8T6最小系统板

  • OLED显示屏(0.96)

  • DHT11温湿度传感器

  • 声音传感器

  • 震动传感器

  • 雨滴传感器

  • JR6001语音模块

  • BT04A蓝牙模块

  • 扬声器

  • 步进电机

  • PTC加热片

  • 风扇模块

  • 有源蜂鸣器

  • 大功率LED灯模块

  • 继电器

  • 3、演示视频:哔哩哔哩视频链接点击观看:https://www.bilibili.com/video/BV1TCMg6AEmk/?share_source=copy_web&vd_source=f4437c8e4429101e5bf1054c39d5474f

三、硬件介绍

  • PCB硬件设计:

四、程序设计

#include "delay.h"
#include "sys.h"
#include "bmp.h"
#include "usart.h"
#include "dht11.h"
#include "control.h"
#include "key.h"
#include "timer.h"
#include "oled.h"
#include "uln2003.h"
#include "adc.h"
#include "IoData.h"
#include "aliyun.h"
#include "esp8266.h"

/****  数据变量  ****/
int temp_shang = 35;	//温度上限
int temp_xia = 20;		//温度下限
int humi_door = 60;		//湿度阈值

int step_flag = 0;		//摇床开关

int step_status = 0;	//摇床开关状态
int wind_status = 0;	//风扇开关状态
int hate_status = 0;	//加热开关状态
int music_status = 0;	//音乐开关状态
int music_auto = 0;		//音乐开关自动模式
int music_time = 0;		//音乐时间

int auto_mode = 0;		//自动模式开关	0关闭	1开启


/****  菜单变量  ****/
uint8_t keu_num = 0;		//按键赋值
uint8_t page_num = 1;		//页面ID
uint8_t option = 0;			//阈值、控制选项
uint8_t net_flag    = 1;

/****  功能函数声明  ****/
void get_all_sensor_data();		//传感器数据采集
void Sensor_Data_Handle();		//不同模式下控制效果
void Key_event_handle(void);	//按键功能函数

void OLED_Show_FirstPage();		//第一屏显示内容
void OLED_Show_SecondPage();	//第二屏显示内容
void OLED_Show_ThirdPage();		//第三屏显示内容s
void OLED_Show_FourthPage();	//第四屏显示内容
void net_page();

int main(void)
{
	delay_init();		//系统延时函数初始化
	OLED_Init();		//屏幕初始化
	uart3_init(115200);	//串口3初始化,波特率115200
	uart1_init(115200);	//串口1初始化,波特率115200
	uart2_init(9600);	//串口2初始化,波特率9600
	DHT11_Init();		//DHT11温湿度初始化
	Control_Init();		//声光报警,风扇、水泵、照明初始化
	KEY_Init();			//按键初始化
	Uln2003_Init();
	TIME_Config();		//定时器初始化
	IoData_Init();
	Adc_Init();
	net_page();
	while(net_flag){
		keu_num = KEY_Scan(0);		//按键扫描赋值
		if(keu_num==1){net_flag=0;}
		else if(keu_num==2){net_flag=0;ESP8266_Init();}
	}
	OLED_Clear();
//	JQ6500_SendBuff(sound1_buf,6);
	while(1)
	{
		if(Time_Period[1]>1000)		//Time_Period[1] 在定时器中累加
		{
			get_all_sensor_data();	//传感器数据采集
			Mqtt_Publiash_Aliyun();
			Time_Period[1] = 0;
		}

		Key_event_handle();			//按键监测
		Sensor_Data_Handle();		//数据处理
		if(page_num == 1){			//屏幕更新
			OLED_Show_FirstPage();
		}else if(page_num == 2){
			OLED_Show_SecondPage();
		}else if(page_num == 3){
			OLED_Show_ThirdPage();
		}
	}
}

void Key_event_handle(void)
{
	keu_num = KEY_Scan(0);		//按键扫描赋值
	switch(keu_num)
	{
		case 1:		//按键1按下
			if(page_num==1){
				page_num=2;option=0;
				OLED_Clear();OLED_Show_SecondPage();
			}else if(page_num==2){
				page_num=3;option=0;
				OLED_Clear();OLED_Show_ThirdPage();
			}else if(page_num==3){
				page_num=1;option=0;
				OLED_Clear();OLED_Show_FirstPage();
			}
			break;
		case 2:		//按键2按下
			if(page_num==1){
				
			}else if(page_num==2){
				option++;
				if(option>3)option=0;
			}else if(page_num==3){
				option++;
				if(option>4)option=0;
			}
			break;
		case 3:		//按键3按下
			if(page_num==1){
				auto_mode = 1;
			}else if(page_num==2){
				if(option==1)temp_shang++;
				else if(option==2)temp_xia++;
				else if(option==3)humi_door++;
			}else if(page_num==3){
				if(auto_mode==0){
					if(option==1){
//						step_flag=1;
						step_status = 1;
					}else if(option==2){
						Wind = 1;
						wind_status = 1;
					}else if(option==3){
						Hate = 1;
						hate_status = 1;
					}else if(option==4){
						music_status = 1;
						music_time = 0;
					}
				}
			}
			break;
		case 4:		//按键4按下
			if(page_num==1){
				auto_mode = 0;
			}else if(page_num==2){
				if(option==1)temp_shang--;
				else if(option==2)temp_xia--;
				else if(option==3)humi_door--;
			}else if(page_num==3){
				if(auto_mode==0){
					if(option==1){
//						step_flag=1;
						step_status = 0;
					}else if(option==2){
						Wind = 0;
						wind_status = 0;
					}else if(option==3){
						Hate = 0;
						hate_status = 0;
					}else if(option==4){
						music_status = 0;
						JQ6500_SendBuff(sound2_buf,6);
					}
				}
			}
			break;
	}
}

void get_all_sensor_data()
{
	DHT11_Read_Data(&temp,&hum);    //获取温湿度数据
	Get_Bed_Value(&Bed_Value);		//检测是否尿床
//	Get_CO2_Data();					//获取CO2浓度数据
}

void Sensor_Data_Handle()
{
	//自动模式
	if(auto_mode == 1)  //如果开启了自动模式则可以实现根据数据的自动控制
	{
		//温度大于阈值,打开风扇
		if(temp > temp_shang || hum > humi_door){
			Wind = 1;wind_status = 1;
		} else {
			Wind = 0;wind_status = 0;
		}
		
		//温度低于阈值,打开加热
		if(temp < temp_xia){
			Hate = 1;hate_status = 1;
		} else {
			Hate = 0;hate_status = 0;
		}
		
		if(Shock_Value==1){
			Beep=1;
		}else Beep=0;
		
		if(Sound_Value==1){
			if(music_auto==0){
				music_auto=1;
				JQ6500_SendBuff(sound1_buf,6);
			}
			Stepper_RotateByLoop(1,1,1);
			Stepper_RotateByLoop(0,1,1);
			Stepper_RotateByLoop(0,1,1);
			Stepper_RotateByLoop(1,1,1);
		}else music_auto=0;
		
//		//湿度小于阈值,打开加湿器
//		if(hum < humi_door){
//			Hate = 1;water_status = 1;
//		} else {
//			Hate = 0;water_status = 0;
//		}
		
//		//CO2浓度大于阈值,打开通风并蜂鸣器报警
//		if(Kqzl.CO2 > co2_door){
//			if(step_status==0){
//				step_status=1;
//				Stepper_RotateByLoop(step_status,1,1);
//			}
//			Beep = 1;
//		} else {
//			if(step_status==1){
//				step_status=0;
//				Stepper_RotateByLoop(step_status,1,1);
//			}
//			Beep = 0;
//		}
		
	}else{
		Beep = 0;	//手动模式下,关闭蜂鸣器
		music_auto=0;
	}
	
	if(step_status==1){
		step_flag++;
		switch(step_flag%4)
		{
			case 1:
				Stepper_RotateByLoop(1,1,1);
				break;
			case 2:
				Stepper_RotateByLoop(0,1,1);
				break;
			case 3:
				Stepper_RotateByLoop(0,1,1);
				break;
			case 0:
				Stepper_RotateByLoop(1,1,1);
				break;
		}
		if(step_flag==20)step_status=0;
	}else step_flag = 0;
	
}

// 温(0) 湿(1) 度(2) ℃(3) 阈(4) 值(5) 风(6) 扇(7) 通(8) 风(9) 加(10) 湿(11) 自(12) 手(13) 动(14) 模(15)
// 式(16) 浓(17) 度(18) 开(19) 关(20) 摇(21) 床(22) 热(23) 上(24) 下(25) 限(26)
// 啼(27) 哭(28) 尿(29) 床(30) 撞(31) 击(32) 有(33) 无(34) 播(35) 放(36) 音(37) 乐(38)
void OLED_Show_FirstPage(){
	
	OLED_ShowChinese(16*0,0,0,16,1);		//	“温”
	OLED_ShowChinese(16*1,0,2,16,1);		//	“度”
	OLED_ShowChar(16*2,0,':',16,1);			//	“:”
	OLED_ShowNum(16*2+8,0,temp,2,16,1);		//	temp
	OLED_ShowChinese(16*3+8,0,3,16,1);		//	“℃”
	
	OLED_ShowChinese(16*0,16,1,16,1);		//	“湿”
	OLED_ShowChinese(16*1,16,2,16,1);		//	“度”
	OLED_ShowChar(16*2,16,':',16,1);		//	“:”
	OLED_ShowNum(16*2+8,16,hum,2,16,1);		//	hum	
	OLED_ShowString(16*3+8,16,"%RH",16,1);
	
	OLED_ShowChinese(16*0,32,29,16,1);		//	“尿”
	OLED_ShowChinese(16*1,32,30,16,1);		//	“床”
	OLED_ShowChar(16*2,32,':',16,1);			//	“:”
	if(Bed_Value == 1){
		OLED_ShowChinese(16*2+8,32,33,16,1);			//	“有”
	}else{
		OLED_ShowChinese(16*2+8,32,34,16,1);			//	“无”
	}
	
	OLED_ShowChinese(16*0,48,27,16,1);		//	“啼”
	OLED_ShowChinese(16*1,48,28,16,1);		//	“哭”
	OLED_ShowChar(16*2,48,':',16,1);			//	“:”
	if(Sound_Value == 1){
		OLED_ShowChinese(16*2+8,48,33,16,1);			//	“有”
	}else{
		OLED_ShowChinese(16*2+8,48,34,16,1);			//	“无”
	}
	
	OLED_ShowChinese(16*4,48,31,16,1);		//	“撞”
	OLED_ShowChinese(16*5,48,32,16,1);		//	“击”
	OLED_ShowChar(16*6,48,':',16,1);			//	“:”
	if(Shock_Value == 1){
		OLED_ShowChinese(16*6+8,48,33,16,1);			//	“有”
	}else{
		OLED_ShowChinese(16*6+8,48,34,16,1);			//	“无”
	}
	
//	OLED_ShowString(16*0,32,"CO2",16,1);	//	“CO2”
//	OLED_ShowChinese(16*1+8,32,17,16,1);		//	“浓”
//	OLED_ShowChinese(16*2+8,32,18,16,1);		//	“度”
//	OLED_ShowChar(16*3+8,32,':',16,1);		//	“:”
////	OLED_ShowNum(16*4,32,Kqzl.CO2,4,16,1);	//	CO2_Value
	
//	OLED_ShowChinese(16*0,48,15,16,1);		//	“模”
//	OLED_ShowChinese(16*1,48,16,16,1);		//	“式”
//	OLED_ShowChar(16*2,48,':',16,1);		//	“:”
	if(auto_mode == 1){
		OLED_ShowChinese(16*7,0,12,16,1);			//	“自”
		OLED_ShowChinese(16*7,16,14,16,1);			//	“动”
	}else if(auto_mode == 0){
		OLED_ShowChinese(16*7,0,13,16,1);			//	“手”
		OLED_ShowChinese(16*7,16,14,16,1);			//	“动”
	}
//	
	OLED_Refresh();
}

void OLED_Show_SecondPage(){
	
	uint8_t a,b,c,d;
	if(option==1){a=0;b=1;c=1;d=1;}
	else if(option==2){a=1;b=0;c=1;d=1;}
	else if(option==3){a=1;b=1;c=0;d=1;}
	else if(option==4){a=1;b=1;c=1;d=0;}
	else{a=1;b=1;c=1;d=1;}
	
	OLED_ShowChinese(16*0,0,0,16,1);		//	“温”
	OLED_ShowChinese(16*1,0,2,16,1);		//	“度”
	OLED_ShowChinese(16*2,0,24,16,1);		//	“上”
	OLED_ShowChinese(16*3,0,26,16,1);		//	“限”
	OLED_ShowChar(16*4,0,':',16,1);			//	“:”
	OLED_ShowNum(16*4+8,0,temp_shang,3,16,a);		//	temp_door
	
	OLED_ShowChinese(16*0,16,0,16,1);		//	“温”
	OLED_ShowChinese(16*1,16,2,16,1);		//	“度”
	OLED_ShowChinese(16*2,16,25,16,1);		//	“下”
	OLED_ShowChinese(16*3,16,26,16,1);		//	“限”
	OLED_ShowChar(16*4,16,':',16,1);			//	“:”
	OLED_ShowNum(16*4+8,16,temp_xia,3,16,b);		//	temp_door
	
	OLED_ShowChinese(16*0,32,1,16,1);		//	“湿”
	OLED_ShowChinese(16*1,32,2,16,1);		//	“度”
	OLED_ShowChinese(16*2,32,4,16,1);		//	“阈”
	OLED_ShowChinese(16*3,32,5,16,1);		//	“值”
	OLED_ShowChar(16*4,32,':',16,1);			//	“:”
	OLED_ShowNum(16*4+8,32,humi_door,3,16,c);		//	hum_door_value
	

	
	OLED_Refresh();
}

void OLED_Show_ThirdPage(){

	uint8_t a,b,c,d;
	if(option==1){a=0;b=1;c=1;d=1;}
	else if(option==2){a=1;b=0;c=1;d=1;}
	else if(option==3){a=1;b=1;c=0;d=1;}
	else if(option==4){a=1;b=1;c=1;d=0;}
	else{a=1;b=1;c=1;d=1;}
	
	OLED_ShowChinese(16*0,0,21,16,1);	//摇
	OLED_ShowChinese(16*1,0,22,16,1);	//床
	OLED_ShowChar(16*2,0,':',16,1);		
	if(step_status==1)OLED_ShowChinese(16*2+8,0,19,16,a);	//开
	else OLED_ShowChinese(16*2+8,0,20,16,a);	//关

	OLED_ShowChinese(16*0,16,6,16,1);	//风
	OLED_ShowChinese(16*1,16,7,16,1);	//扇
	OLED_ShowChar(16*2,16,':',16,1);		
	if(wind_status==1)OLED_ShowChinese(16*2+8,16,19,16,b);	//开
	else OLED_ShowChinese(16*2+8,16,20,16,b);	//关

	OLED_ShowChinese(16*0,32,10,16,1);	//加
	OLED_ShowChinese(16*1,32,23,16,1);	//热
	OLED_ShowChar(16*2,32,':',16,1);
	if(hate_status==1)OLED_ShowChinese(16*2+8,32,19,16,c);	//开
	else OLED_ShowChinese(16*2+8,32,20,16,c);	//关
	
	OLED_ShowChinese(16*0,48,37,16,1);	//音
	OLED_ShowChinese(16*1,48,38,16,1);	//乐
	OLED_ShowChar(16*2,48,':',16,1);
	if(music_status==1)OLED_ShowChinese(16*2+8,48,19,16,d);	//开
	else OLED_ShowChinese(16*2+8,48,20,16,d);	//关
	
	OLED_Refresh();
}

void net_page(){

	uint8_t a,b,c,d,i;
	if(option==1){a=0;b=1;c=1;d=1;}
	else if(option==2){a=1;b=0;c=1;d=1;}
	else if(option==3){a=1;b=1;c=0;d=1;}
	else {a=1;b=1;c=1;d=1;}
	
	i = 39;
	OLED_ShowChinese(16*2,16,i,16,1);			//	“是”
	OLED_ShowChinese(16*3,16,i+1,16,1);			//	“否”
	OLED_ShowChinese(16*4,16,i+2,16,1);			//	“配”
	OLED_ShowChinese(16*5,16,i+3,16,1);			//	“网”
	OLED_ShowChar(16*6,16,'?',16,1);				//	“:”
	
	OLED_ShowString(16*0,32,"KEY1        KEY2",16,1);
	OLED_ShowChinese(16*0,48,i+4,16,1);		//	“跳”
	OLED_ShowChinese(16*1,48,i+5,16,1);		//	“过”
	
	OLED_ShowChinese(16*6,48,i+6,16,1);		//	“确”
	OLED_ShowChinese(16*7,48,i+7,16,1);		//	“认”
	
	OLED_Refresh();
}

五、项目成品效果

六、项目总结

本系统各项功能均已实现并稳定运行,具体成果如下:

  • 环境感知:DHT11采集温湿度准确,声音传感器对啼哭识别灵敏,雨滴传感器可有效检测尿床,震动传感器响应迅速,OLED屏幕实时刷新显示。

  • 自动模式:超温开风扇、低温开加热片、湿度过高开风扇除湿、啼哭播放音乐并启动摇床、尿床及撞击触发蓝牙报警和蜂鸣器,五项联动逻辑准确,响应及时。

  • 手动模式:按键控制加热片、风扇、摇床、音乐播放均响应正常,操作流畅。

  • 阈值调节:按键进入设置界面修改温度上下限及湿度阈值功能正常,参数掉电保存。

  • 蓝牙监控:BT04A蓝牙模块通信稳定,手机App可查看实时数据与报警信息,远程下发控制指令正常

七、包含资料

本资料免费分享,获取全套资料请看主页,并将告诉助手需要资料的项目编号,助手收到消息后,会发送资料。
资料获取:查看主页介绍“充哥单片机设计“
文章若对你有所帮助,期待点赞收藏,后续会持续分享各类单片机实战案例。
内容仅作为学习参考,有任何不妥之处,欢迎大家一起探讨!

更多推荐