【STM32项目】智能婴儿床
目录
一、项目概述
本项目使用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可查看实时数据与报警信息,远程下发控制指令正常
七、包含资料
本资料免费分享,获取全套资料请看主页,并将告诉助手需要资料的项目编号,助手收到消息后,会发送资料。
资料获取:查看主页介绍“充哥单片机设计“
文章若对你有所帮助,期待点赞收藏,后续会持续分享各类单片机实战案例。
内容仅作为学习参考,有任何不妥之处,欢迎大家一起探讨!
更多推荐

所有评论(0)