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月前
|
监控 安全 自动驾驶
基于python的室内老人实时摔倒智能监测系统-跌倒检测系统(康复训练检测+代码)
基于python的室内老人实时摔倒智能监测系统-跌倒检测系统(康复训练检测+代码)
|
传感器 安全 前端开发
井下空气质量检测预警系统学习
随着现代化煤矿深入开采,井下空气质量监测已成为重要的安全问题。煤矿通常有大量地瓦斯、煤尘等气体,如果空气质量不良,无疑会给矿工的健康和安全带来极大的威胁。因此,煤矿必须配备有效的井下空气质量检测预警系统,用来监测空气质量,预警可能的问题,为矿工提供更安全的工作环境。
井下空气质量检测预警系统学习
|
7月前
|
传感器 安全 芯片
雨滴检测报警电路设计与调试
雨滴检测报警电路设计与调试
73 1
|
7月前
|
传感器 数据采集 安全
振弦采集仪在岩土边坡监测中的实际应用效果评价
振弦采集仪在岩土边坡监测中的实际应用效果评价
振弦采集仪在岩土边坡监测中的实际应用效果评价
|
7月前
|
传感器 数据采集 安全
工程监测振弦采集仪是一种用于岩土安全监测的仪器设备
工程监测振弦采集仪是一种用于岩土安全监测的仪器设备。它主要用于监测岩土体的振动特性和变形情况,以评估岩土体的稳定性和安全性。
|
7月前
|
安全
ADR药物不良反应智能监测预警系统源码:辅助医务人员发现不良反应
ADR是英文Adverse Drug Reaction的缩写,意为药物不良反应。是指按规定剂量正常应用药品的过程中产生的有害、而非所期望的与药品应用有因果关系的反应。
78 1
|
传感器 监控 安全
井下空气质量检测预警系统,煤矿生产、事故应急检测和实时监测
井下空气质量检测预警系统,主要用于煤矿生产、事故应急检测和实时监测
井下空气质量检测预警系统,煤矿生产、事故应急检测和实时监测
|
机器学习/深度学习 算法 数据可视化
项目实践 | 行人跟踪与摔倒检测报警(文末获取完整源码)
项目实践 | 行人跟踪与摔倒检测报警(文末获取完整源码)
193 0
|
存储 传感器 数据采集
SLU闸坝监测预警系统
SLU闸门监测预警系统以各类传感器为数据源,自动进行数据采集、业务逻辑运算,使用数据库为数据载体,完成海量、快速数据存储及快速检索,可完成闸前水位、尾水水位、入出库、发电机负荷、总流量、降雨量等关键信息监测以及闸门反向控制、远程报警等功能,适用于机组工作闸门、泄洪闸门、冲沙洞闸门,以及水利、航运、供排水系统的节制闸、船闸等各种闸门的自动化控制与远方调度。
SLU闸坝监测预警系统
|
存储 传感器 安全
裂缝监测预警仪的监测预警
裂缝监测预警仪是专门为墙体裂缝、地表裂缝研发的监测预警仪器,低功耗设计,内置电池可长时间独立工作。
裂缝监测预警仪的监测预警
下一篇
DataWorks