c51实现老人跌倒,心率异常报警系统

简介: c51实现老人跌倒,心率异常报警系统

本设计硬件部分:由OLED液晶显示屏,ADXL345角度传感器,SIM800C短信模块,GPS定位模块。以及心形脉搏测量,以及蜂鸣器报警电路再加上按键电路组成。


设计可实现:


心率的测量,按键1,即可开始心率的测量,测量结束,数据会显示到OLED液晶上,若心率超过阈值,同时还会发送报警短信用以提醒。

可检测是否摔倒,如若摔倒,则液晶可显示摔倒提示。并产生报警提醒,同时会通过GSM模块获取经纬度信息,发送含有经纬度的报警短信到绑定的手机。如果摔倒后直立,则会发送直立提示短信。

同时还可以进行手动的取消摔倒报警,按下按键2,则可以取消本次的摔倒报警。

按下按键3,则可以发送含有当前具体经纬度的求助短信。

OLED液晶,可以显示出当前状态,心率数据,以及具体的经纬度数据。


发送短信的手机号,只需第一次使用时发送连接短信,单片机会自动将手机号进行保存。后期不需要再次进行发送。


器件选型:


mcu单片机: STC12C5A60S2

GSM/GPRS:  SIM800C

加速度模块: ADXL345

心率: PulseSensor


主程序代码:

#include <STC12C5A60S2.H>
#include "eeprom12.H"
#include "ADXL345.h"
#include "OLED.H"
#include "usercode.H"
#include "SIM800.H"
#include "key.H"
//=====================================================================================================================  保存经纬度
void Memory_data()
{
    IapEraseSector(0x0400);
    IapProgramByte(0x0401,jing_du/100000000%10);
    IapProgramByte(0x0402,jing_du/10000000%10);
    IapProgramByte(0x0403,jing_du/1000000%10);
    IapProgramByte(0x0404,jing_du/100000%10);
    IapProgramByte(0x0405,jing_du/10000%10);
    IapProgramByte(0x0406,jing_du/1000%10);
    IapProgramByte(0x0407,jing_du/100%10);
    IapProgramByte(0x0408,jing_du/10%10);
    IapProgramByte(0x0409,jing_du/1%10);
    IapProgramByte(0x0412,wei_du/10000000%10);
    IapProgramByte(0x0413,wei_du/1000000%10);
    IapProgramByte(0x0414,wei_du/100000%10);
    IapProgramByte(0x0415,wei_du/10000%10);
    IapProgramByte(0x0416,wei_du/1000%10);
    IapProgramByte(0x0417,wei_du/100%10);
    IapProgramByte(0x0418,wei_du/10%10);
    IapProgramByte(0x0419,wei_du/1%10);
    IapProgramByte(0x040A,SIM800_Heat);
}
void Read_data()
{
    jing_du = IapReadByte(0x0401)*100000000 + IapReadByte(0x0402)*10000000 + IapReadByte(0x0403)*1000000 + IapReadByte(0x0404)*100000 +
          IapReadByte(0x0405)*10000 + IapReadByte(0x0406)*1000 + IapReadByte(0x0407)*100 + IapReadByte(0x0408)*10 +
          IapReadByte(0x0409) ;
    wei_du = IapReadByte(0x0412)*10000000 + IapReadByte(0x0413)*1000000 + IapReadByte(0x0414)*100000 + IapReadByte(0x0415)*10000 + 
          IapReadByte(0x0416)*1000 + IapReadByte(0x0417)*100 + IapReadByte(0x0418)*10 + IapReadByte(0x0419) ;
    SIM800_Heat=IapReadByte(0x040A);
}
//=====================================================================================================================  读取角度数据,判断跌倒
/*****************************************************************************************************************
    角度判断跌倒函数:
      读取出角度数据后,然后去比较这个角度数据,有没有超过一定值,如果超过一定值则判定为跌倒。
*****************************************************************************************************************/
void Read_ADXL345()
{   
    static char cs=0; //-- 定义静态局部变量   角度连续5次数据判断
    if(Read_dat)
    {
        Read_dat=0;
        duqujiaodu();  
        if(Y_dat<=0)  Y_dat=0; //-- 平放时,避免角度出现0度以下
        if(Y_dat>=300)  Y_dat=0; //-- 保证数据合理性。
        if(Fall_Flag==0)
        {  //-- 未检测到摔倒情况时
            if(cs!=5)   
            {
                if(Y_dat<190 || Y_dat>300)  cs++;
                else            cs=0;
            }else //-- 连续5次数据都判定为摔倒,此时系统确定当前为摔倒状态
            {
                cs=0;
                Fall_Flag=1;
            }
        }else//-- 检测到摔倒情况时
        {
            if(cs!=5)   
            {
                if(Y_dat<300 && Y_dat>=190) cs++;
                else            cs=0;
            }else //-- 连续5次数据都判定为未摔倒,此时系统确定当前为正常状态
            {
                cs=0;
                Fall_Flag=0;
            }
        }
    }
}
//=====================================================================================================================  角度报警
void police_ADXL345()
{
    if(Fall_Flag)//-- 确认摔倒后       
    {
        Up_Time=0;
        if(Fall_Time!=Fall_Cnt)     
        {     //-- 摔倒一定时间内,可手动取消
            if(Hand_Close==0)   Fall_Time++;  //-- 没有手动取消时,计时++
            else          Fall_Time=0;  //-- 在摔倒一定时间内,手动取消报警,计时清零 
        }else   //-- 时间到,报警发短信
        {
            if(Beep_Flag==0)            //-- 计时时间到报警标志为1,产生报警
            {                   //-- 发送摔倒短信
                Beep_Flag=1;
                GSM_Send=1;
                GSM_Send_Num=1;
                GSM_Send_Time=0;
            }
        }
    }else //-- 老人没有摔倒           
    {
        if(Up_Time!=0)        Up_Time--;      //-- 如果手动时间不等于0, 手动取消报警时间清零
        else            Hand_Close=0;     //-- 清零后,取消手动标志
        Fall_Time=0;//-- 摔倒时间清零
        if(Beep_Flag)                 //-- 直立后取消报警
        {                       //-- 发送直立短信
            Beep_Flag=0;
            GSM_Send=1;
            GSM_Send_Num=2;
            GSM_Send_Time=0;
        }           
    }  
}
//=====================================================================================================================  心率检测
/*****************************************************************************************************************
    心率检测函数:
      心率检测方法,就是先检测出第一次心跳的时候,将时间清零,开始计时,当再次检测到心跳后,停止计时
    读取出,时间数据,这个时间就是两次心跳之间的间隔时间,然后用1分钟除以这个时间,就可以得到1分钟之内
    对应的心跳数,循环测量多次,然后取平均值即可。
*****************************************************************************************************************/
bit OnceFlag=1;
void Xinlv_dispose()
{
    unsigned int pules=0;
    static bit Send_Flag=1;
    if(Start_Flag && Heat_Time==0)
    {
        if(Xinlv==0)
        {
            if(OnceFlag)
            {
                OnceFlag=0;
                if(Heat_State==0)   Heat_State=1;
                else if(Heat_State==1)  Heat_State=2;
            }
        }else OnceFlag=1;
        if(Heat_State==1)           TR1=1;  //-- 开始计时
        else if(Heat_State==2)
        {
            Heat_State=0;
            TR1=0;              //-- 停止计时,准备计算
            if((6000/Heat_ms) > 50 && (6000/Heat_ms) < 150)
            {
                if(Heat_Cnt<7)
                {
                    Heat_Cnt++;
                    if(Heat_Cnt>=3) 
                    {
                        pules = 6000/Heat_ms;         //Heat_dat = 
                        Heat_Total = Heat_Total+pules;
                        pules=0;
                    }
                }else
                {
                    SIM800_Heat = Heat_dat   = Heat_Total/5;
                    Heat_Total = Heat_Cnt=0;
                    Heat_Time  = xinlv_Time;   //-- 显示2分钟
                    Beep_Num=4;
                      Memory_data();         //-- 存储心率数据  
                }
            }
            Heat_ms = TH1 = TL1=0;
        }
    }
    if(Heat_Time!=0)    //-- 心跳测量完成
    {
        if(Heat_dat>Heat_H || Heat_dat<Heat_L)    
        {
            if(Send_Flag)
            {
                Send_Flag=0;
                Beep_Num = 100;
                GSM_Send=1;
                GSM_Send_Num=3; //-- 发送心率报警短信   SIM800_Heat
                GSM_Send_Time=0;
            }
        }
    }else Send_Flag=1;
}
uchar dis_Cnt=0;
//=====================================================================================================================  OLED液晶显示
void OLED_display_Init()
{
    display_GB2312_string(0,0,"                ");
    display_GB2312_string(0,1,"                ");
    display_GB2312_string(0,2,"  初 始 化");
    switch(dis_Cnt)
    {
        case  0:  display_GB2312_string(10,2,"       ");    break;
        case  1:  display_GB2312_string(10,2,".      ");    break;
        case  2:  display_GB2312_string(10,2,"..     ");    break;
        case  3:  display_GB2312_string(10,2,"...    ");    break;
        default:  break;
    }
    display_GB2312_string(0,3,"                ");
}
//=====================================================================================================================  OLED液晶显示
void OLED_display()
{
    display_GB2312_string(0,0,"当前状态:"); //------------------------------------------->第一行显示温度数据
    if(Fall_Flag==0)            display_GB2312_string(11,0," 正常");
    else                  display_GB2312_string(11,0," 摔倒");
    display_GB2312_string(0,1,"心率:"); //------------------------------------------->第二行显示心率数据
    if(Start_Flag==0)           display_GB2312_string(5,1,"---");
    else 
    {
        if(Heat_dat>99)           display_buff(5,1,Heat_dat/100%10);
        else                display_GB2312_string(5,1," ");
        if(Heat_dat>9)              display_buff(6,1,Heat_dat/10%10);
        else                display_GB2312_string(6,1," ");
        display_buff(7,1,Heat_dat/1%10);
    }
    display_GB2312_string(8,1,"次/分  ");
    display_GB2312_string(0,2,"经度:");//------------------------------------------->第三行  显示经度
    display_buff(5,2,jing_du/100000000%10);
    display_buff(6,2,jing_du/10000000%10);
    display_buff(7,2,jing_du/1000000%10);
    display_GB2312_string(8,2,"."); 
    display_buff(9,2,jing_du/100000%10);              
    display_buff(10,2,jing_du/10000%10);
    display_buff(11,2,jing_du/1000%10);
    display_buff(12,2,jing_du/100%10);
    display_buff(13,2,jing_du/10%10);
    display_buff(14,2,jing_du/1%10);
    if(BaseFlag==0)             display_GB2312_string(15,2," ");
    else                  display_GB2312_string(15,2,"*");
    display_GB2312_string(0,3,"纬度:");//------------------------------------------->第三行  显示纬度
    display_buff(5,3,wei_du/10000000%10);
    display_buff(6,3,wei_du/1000000%10);
    display_GB2312_string(7,3,"."); 
    display_buff(8,3,wei_du/100000%10);
    display_buff(9,3,wei_du/10000%10);
    display_buff(10,3,wei_du/1000%10);
    display_buff(11,3,wei_du/100%10);
    display_buff(12,3,wei_du/10%10);
    display_buff(13,3,wei_du/1%10);
}
//=====================================================================================================================  定时器初始化
void Time_Init()//初始化函数
{
    TMOD=0x11;    //-- 配置定时器0和定时器1
    TH0=0x4C;
    TL0=0x00;   //-- 定时器0,初值50ms
    ET0=1;      //-- 开启定时器0
    TR0=1;      //-- 开启定时器0中断
    TH1=0xDC;
    TL1=0x00;     //-- 10ms中断  
    ET1=1;       
    TR1=0;          //-- 关闭定时器1中断
      EA=1;           
}
//=====================================================================================================================  程序主函数
void main()
{
      Time_Init();    //-- 初始化
    Uart_Init();  //-- 串口初始化配置波特率
    EA=1;     //-- 开总中断 
    initial_lcd();  //-- 屏幕初始化
    Init_ADXL345(); //-- 角度初始化
    Read_data();  //-- 读取存储的经纬度数据
    Read_Phone();   //-- 读取手机号
    while(1)
    {   
        if(GSM_Send_Time==0)      SIM800_Send_Message();  
        if(Quest_flag==1)       OLED_display_Init();
        else              
        {
            OLED_display(); //---------------------->OLED 液晶显示
            Read_ADXL345(); //-- 读取角度数据 
            Xinlv_dispose();//-- 心率测量
        }
        if(GPS_Buff[0]=='$'&&GPS_Buff[1]=='G'&&GPS_Buff[2]=='P'&&GPS_Buff[3]=='G'&&GPS_Buff[4]=='L'&&GPS_Buff[5]=='L'&&GPS_Buff[18]=='N'&&GPS_Buff[32]=='E')
        {
            if(((GPS_Buff[30]-0x30)*100+(GPS_Buff[31]-0x30)*10+(GPS_Buff[32]-0x30))>=0&&((GPS_Buff[30]-0x30)*100+(GPS_Buff[31]-0x30)*10+(GPS_Buff[32]-0x30))<=180)   //经度0°——180°  纬度0°——90°
            {
                jing_du=  (((GPS_Buff[20]-0x30)*100000000)+((GPS_Buff[21]-0x30)*10000000)+((GPS_Buff[22]-0x30)*1000000))
                      +(((((GPS_Buff[23]-0x30)*10)+(GPS_Buff[24]-0x30))*100000)/6)
                      +(((((GPS_Buff[26]-0x30)*1000)+((GPS_Buff[27]-0x30)*100)+((GPS_Buff[28]-0x30)*10)+(GPS_Buff[29]-0x30))*10)/6);      
                wei_du= ((GPS_Buff[7]-0x30)*10000000+(GPS_Buff[8]-0x30)*1000000)
                      +(((((GPS_Buff[9]-0x30)*10)+(GPS_Buff[10]-0x30))*100000)/6)
                      +(((((GPS_Buff[12]-0x30)*1000)+((GPS_Buff[13]-0x30)*100)+((GPS_Buff[14]-0x30)*10)+(GPS_Buff[15]-0x30))*10)/6); 
                GPS_Flag=1;
                GPS_Time = GPS_Cnt; //-- 赋值存储  GPS接收到卫星定位
                Memory_data();    //-- 存储经纬度数据
                BaseFlag=0; //-- 取消基站定位
            }
        }
        if(Quest_flag==0 && GPS_Time==0)//-- GSM初始化完成后
        {
            if(GPS_Flag==0)//--- GPS 未接收到卫星定位   
            {
                if(GSM_Send==0 && GSM_Send_Time==0)//-- 未执行AT指令
                {
                    Uart1_Count=0;
                    Uartdat_byte("AT+CLBS=1,1\r\n"); //-- 获取经纬度
                    GSM_Send_Time=200;
                }
            }
        }
    }                         
}
//=====================================================================================================================  定时器0中断  50ms
unsigned char Time0_ms=0;     //-- 定时器计时变量
void Time_0 ()interrupt 1   //----50MS       
{
      TH0=0x4C;
      TL0=0x00; 
    Time0_ms++;
    Scan_keyscan();               //-- 50ms进行1次按键扫描
    if(GSM_Send_Time!=0)    GSM_Send_Time--;//-- AT指令间隔倒计时
    if(Beep_Flag!=0 || Beep_Num!=0)         //--蜂鸣器产生报警
    {
        if(Beep_Num!=0)   Beep_Num--;
        Beep=!Beep;
    }else Beep=1;
    if(Time0_ms%5==0)       
    {
        Read_dat=1;   // 对4取余 200ms 读取一次角度数据
        dis_Cnt=(dis_Cnt+1)%4;  
    }
    if(Time0_ms>=20)          
    {
        Time0_ms=0;
        police_ADXL345(); //-- 1s中检测角度报警
        if(Heat_Time!=0)  
        {
            Heat_Time--;
            if(Heat_Time<=5)
            {
                Heat_Time=0;
                Start_Flag=0;
            }
        }
        if(GPS_Time!=0)   GPS_Time--;
        else        GPS_Flag=0;
    }                    
}     
//=================================================================================================================   定时器1 心率计时
void Time_1 () interrupt 3
{ 
      TH1=0xDC;
      TL1=0x00;  //-- 重载10ms初值  
    Heat_ms++;  
}
//=====================================================================================================================  串口2中断 GPS定位
void Uart_2 () interrupt 8
{
    if (S2CON & S2RI)
    {
        S2CON &= ~S2RI;
        if(S2BUF=='$')      GPS_Num=0;
        GPS_Buff[GPS_Num]=S2BUF;
        GPS_Num=(GPS_Num+1)%100;
    }
}


//

image.png

目录
相关文章
|
7月前
|
机器学习/深度学习 传感器 人工智能
植保机器人在生长监测与分析以及病虫害预警与防控方面
植保机器人在生长监测与分析以及病虫害预警与防控方面
113 2
|
7月前
|
监控 安全 自动驾驶
基于python的室内老人实时摔倒智能监测系统-跌倒检测系统(康复训练检测+代码)
基于python的室内老人实时摔倒智能监测系统-跌倒检测系统(康复训练检测+代码)
|
传感器 安全 前端开发
井下空气质量检测预警系统学习
随着现代化煤矿深入开采,井下空气质量监测已成为重要的安全问题。煤矿通常有大量地瓦斯、煤尘等气体,如果空气质量不良,无疑会给矿工的健康和安全带来极大的威胁。因此,煤矿必须配备有效的井下空气质量检测预警系统,用来监测空气质量,预警可能的问题,为矿工提供更安全的工作环境。
井下空气质量检测预警系统学习
|
7月前
|
安全
ADR药物不良反应智能监测预警系统源码:辅助医务人员发现不良反应
ADR是英文Adverse Drug Reaction的缩写,意为药物不良反应。是指按规定剂量正常应用药品的过程中产生的有害、而非所期望的与药品应用有因果关系的反应。
78 1
|
传感器 监控 安全
井下空气质量检测预警系统,煤矿生产、事故应急检测和实时监测
井下空气质量检测预警系统,主要用于煤矿生产、事故应急检测和实时监测
井下空气质量检测预警系统,煤矿生产、事故应急检测和实时监测
地震监测系统
地震监测系统
|
机器学习/深度学习 算法 数据可视化
项目实践 | 行人跟踪与摔倒检测报警(文末获取完整源码)
项目实践 | 行人跟踪与摔倒检测报警(文末获取完整源码)
190 0
|
存储 传感器 数据采集
基于单片机的智能健康监护仪的设计(心电、心音、体温、脉搏、血压采集)
基于单片机的智能健康监护仪的设计(心电、心音、体温、脉搏、血压采集)
385 0
基于单片机的智能健康监护仪的设计(心电、心音、体温、脉搏、血压采集)
|
C# 数据安全/隐私保护
|
存储 前端开发 算法
复杂场景下的跌倒行为检测系统
跌倒是生活中较为常见的危险行为,随着人工智能技术的发展,研究人员尝试利用更先进的技术对跌倒行为进行检测,减少人力成本并尽可能减轻跌倒带来的危害。由于摄像头等监控设备的普及,使用计算机视觉的方法对跌倒行为进行分析和检测具有重要的研究价值和意义。然而传统的基于视觉的跌倒检测大多基于简单场景,面对多人或更复杂的场景时检测效果就会大大折扣。
782 0
复杂场景下的跌倒行为检测系统