【STM32项目开源】基于STM32的独居老人监护系统
目录
一、设计背景和意义
1.1设计背景
1.2设计意义
二、实物效果展示
2.1实物图片
2.2实物演示视频
三、硬件功能简介
3.1项目功能详解
3.2元器件清单
四、主框图与软件流程图
五、硬件PCB展示
六、软件程序设计
七、项目资料包内容
资料获取:查看主页介绍“充哥单片机设计”
一、设计背景和意义
1.1设计背景
随着医疗技术的进步与人均寿命的提高,全球人口老龄化问题日益严峻。据国家统计局数据显示,中国60岁及以上老年人口已接近3亿,占全国总人口的比重持续上升,预计在2035年前后将进入“深度老龄化”社会。在这一背景下,传统的家庭照护与机构养老服务日益显现出人力紧张、响应不及时、监护盲区等诸多现实问题,尤其是针对独居、高龄、慢性病患者等重点老年群体,其突发性健康事件(如高热、低血氧、心律异常、意外摔倒)极具风险,若未能及时发现与干预,极易造成严重后果。
1.2设计意义
本课题的研究不仅具有突出的技术整合与工程实现价值,更体现了信息技术在社会民生领域的广泛应用前景。通过构建低成本、可部署、功能完备的养老监护系统,不仅能够有效填补传统养老方式在安全监护方面的不足,还可为社区居家养老、智慧医疗、远程健康管理等更广泛的应用场景提供技术支撑,具有较高的社会价值与推广潜力。
二、实物效果展示
2.1实物图片
2.2实物演示视频
【开源】基于STM32的智能独居老人监护系统
三、硬件功能简介
3.1项目功能详解
- 传感器检测:检测体温、心率、血氧等健康相关数据
- 跌倒检测:ADXL345检测老人是否跌倒
- GPS定位:实时检测老人的定位坐标的经纬度数据
- 数据显示:0.96OLED屏幕显示全部的传感器数据以及传感器的阈值等数据
- App远程监控:通过蓝牙模块连接App远程监控全部传感器数据
- 阈值数据设定:系统通过按键设定阈值
- 报警:检测到体温超过阈值、心率超过阈值、血氧低于阈值会开启或检测到老人摔倒蜂鸣器报警,JQ6500语音提醒
3.2元器件清单
- 主控STM32F103C8T6最小系统板
- 0.96OLED显示屏幕
- ESP8266联网WIFI(ESP01S)
- DS18B20温度传感器
- MAX30102心率血氧传感器
- ADXL345三轴加速度传感器
- GPS定位模块
- 按键
四、主框图与软件流程图
主框图
流程图
五、硬件PCB展示
六、软件程序设计
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "string.h"
#include "max30102.h"
#include "ds18b20.h"
#include "beep.h"
#include "key.h"
#include "timer.h"
#include "oled.h"
#include "adxl345.h"
#include "iic.h"double lat_minutes = 32.138118;
double lon_minutes = 116.447290;#define GPS_STR_LEN 48unsigned char display[16];/**** 数据变量 ****/int temp_door = 38;
int oxy_door = 90;
int heart_door = 100;uint8_t send_time = 3;
uint8_t printd_flag = 0;float adx,ady,adz;
float acc,acc2;
uint8_t tiltFlag = 0;
uint8_t fallTime = 0;/**** 菜单变量 ****/
uint8_t option = 0; //阈值选项
uint8_t key_num = 0; //按键赋值
uint8_t page_id = 1; //页面ID/**** 功能函数声明 ****/
void oled_show_onepage(); //第一屏显示内容
void oled_show_twopage(); //第二屏显示内容void get_all_sensor_data(); //传感器数据采集
void Sensor_Data_Handle(); //不同模式下控制效果
void FallDetection(void); //摔倒检测int main(void)
{delay_init(); //系统延时函数初始化OLED_Init(); //OLED初始化uart2_init(9600); //串口2初始化,波特率9600USART1_Config(); //串口1初始化,波特率9600uart3_init(9600); //串口3初始化,波特率9600DS18B20_Init(); //DS18B20温度检测初始化MAX30102_Init(); //心率血氧检测初始化un_min=0x3FFFF;un_max=0;Max30102_right_data();BEEP_Init(); //蜂鸣器初始化beep = 0;KEY_Init(); //按键初始化 IIC_init(); //ADXL345摔倒检测初始化adxl345_init(); TIME_Config(); //定时器初始化while(1){get_all_sensor_data(); //传感器数据采集if(Time_Period[1]>1000) //Time_Period[1] 在定时器中累加{Time_Period[1] = 0;if(page_id == 1){ //屏幕更新oled_show_onepage();}else if(page_id == 2){oled_show_twopage();}if(tiltFlag==1){ //摔倒后,每隔一段时间进行语音播报提醒send_time++;if(send_time>=5){send_time=0;BY_U2_SendBuff(sound_buf,7);}}printd_flag = !printd_flag;if(printd_flag==1){ //蓝牙消息发送printf("\r\n\r\n\r\n\r\n"); printf("*********************\r\n");printf("心率:%d次/分钟 血氧:%d%%\r\n",dis_hr,dis_spo2);printf("体温:%d℃\r\n",body_temp);if(tiltFlag==1)printf("老人摔倒\r\n");else printf("活动正常\r\n");printf("经度:%10.6f\r\n",lon_minutes);printf("纬度:%10.6f\r\n",lat_minutes);printf("*********************\r\n");} }Sensor_Data_Handle(); //数据处理}
}void Sensor_Data_Handle()
{//体温超过阈值 或 心率超过阈值 或 血氧低于阈值且大于0,蜂鸣器报警提醒if(body_temp>temp_door||dis_hr>heart_door||(dis_spo2<oxy_door&&dis_spo2>0)||tiltFlag==1)beep=1;else beep=0;
}
void get_all_sensor_data() //获取数据
{body_temp = DS18B20_Get_Temp(); //获取DS18B20体温数据Get_Max30102_Data(); //获取心率血氧数据FallDetection(); //摔倒检测}
// 心(0) 率(1) 血(2) 氧(3) 体(4) 温(5) ℃(6) 宠(7) 物(8) 状(9) 态(10) 正(11) 常(12) 经(13) 纬(14) 度(15) 阈(16) 值(17)
// 活(18) 动(19) 老(20) 人(21) 摔(22) 倒(23)
void oled_show_onepage(){OLED_ShowChinese(16*0,0,0,16,1); //心OLED_ShowChinese(16*1,0,1,16,1); //率OLED_ShowChar(16*2,0,':',16,1);OLED_ShowNum(16*2+8,0,dis_hr,3,16,1); //心率数据OLED_ShowChinese(16*4,0,2,16,1); //血OLED_ShowChinese(16*5,0,3,16,1); //氧OLED_ShowChar(16*6,0,':',16,1);OLED_ShowNum(16*6+8,0,dis_spo2,3,16,1); //血氧数据OLED_ShowChinese(16*0,16,4,16,1); //体OLED_ShowChinese(16*1,16,5,16,1); //温OLED_ShowChar(16*2,16,':',16,1);OLED_ShowNum(16*2+8,16,body_temp,2,16,1); //体温数据if(tiltFlag==1){OLED_ShowChinese(16*4,16,20,16,1);OLED_ShowChinese(16*5,16,21,16,1);OLED_ShowChinese(16*6,16,22,16,1);OLED_ShowChinese(16*7,16,23,16,1);}else {OLED_ShowChinese(16*4,16,18,16,1);OLED_ShowChinese(16*5,16,19,16,1);OLED_ShowChinese(16*6,16,11,16,1);OLED_ShowChinese(16*7,16,12,16,1); }sprintf((char *)display,"%10.6f ",lon_minutes);OLED_ShowChinese(16*0,32,13,16,1); //经OLED_ShowChinese(16*1,32,15,16,1); //度OLED_ShowChar(16*2,32,':',16,1);OLED_ShowString(16*3,32,(u8*)display,16, 1);//显示经度sprintf((char *)display,"%10.6f ",lat_minutes);OLED_ShowChinese(16*0,48,14,16,1); //纬OLED_ShowChinese(16*1,48,15,16,1); //度OLED_ShowChar(16*2,48,':',16,1);OLED_ShowString(16*3,48,(u8*)display,16, 1);//显示纬度OLED_Refresh();
}void oled_show_twopage(){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 {a=1;b=1;c=1;d=1;}OLED_ShowChinese(16*0,0,0,16,1); // “心”OLED_ShowChinese(16*1,0,1,16,1); // “率”OLED_ShowChinese(16*2,0,16,16,1); // “阈”OLED_ShowChinese(16*3,0,17,16,1); // “值”OLED_ShowChar(16*4,0,':',16,1); // “:”OLED_ShowNum(16*4+8,0,heart_door,3,16,a); // heart_doorOLED_ShowChinese(16*0,16,2,16,1); // “血”OLED_ShowChinese(16*1,16,3,16,1); // “氧”OLED_ShowChinese(16*2,16,16,16,1); // “阈”OLED_ShowChinese(16*3,16,17,16,1); // “值”OLED_ShowChar(16*4,16,':',16,1); // “:”OLED_ShowNum(16*4+8,16,oxy_door,3,16,b); // oxy_doorOLED_ShowChinese(16*0,32,4,16,1); // “体”OLED_ShowChinese(16*1,32,5,16,1); // “温”OLED_ShowChinese(16*2,32,16,16,1); // “阈”OLED_ShowChinese(16*3,32,17,16,1); // “值”OLED_ShowChar(16*4,32,':',16,1); // “:”OLED_ShowNum(16*4+8,32,temp_door,3,16,c); // temp_doorOLED_Refresh();
}void TIM3_IRQHandler(void)
{if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //检测更新中断是否发生{key_num = KEY_Scan(0); //按键扫描赋值switch(key_num){case 1: //按键1按下if(page_id==1){page_id=2;OLED_Clear();oled_show_twopage();}else if(page_id==2){option++;if(option>3){option=0;page_id=1;OLED_Clear();oled_show_onepage();}else oled_show_twopage();}break;case 2: //按键2按下if(page_id==2){if(option==1)heart_door+=1;else if(option==2)oxy_door+=1;else if(option==3)temp_door+=1;oled_show_twopage();}break;case 3: //按键3按下if(page_id==2){if(option==1)heart_door-=1;else if(option==2)oxy_door-=1;else if(option==3)temp_door-=1;oled_show_twopage();}break;case 4: //按键4按下
// BY_U2_SendBuff(sound_buf,7);lanya_flag = 0;break;}Time_Period[0]++;Time_Period[1]++;TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清楚更新中断标志位,如果不清除,会一直进中断}
}void FallDetection(void)//倾斜检测
{u8 i;adxl345_read_average(&adx,&ady,&adz,10);//获取数据acc=ady;acc2=adx;if(acc<0)acc=-acc;if(acc2<0)acc2=-acc2;if(((u16)acc)>=190 || ((u16)acc2)>=190)//检测到倾斜{tiltFlag=1;}else{tiltFlag=0;}}