心率监控及反馈系统 终稿要点.docx
《心率监控及反馈系统 终稿要点.docx》由会员分享,可在线阅读,更多相关《心率监控及反馈系统 终稿要点.docx(27页珍藏版)》请在冰点文库上搜索。
![心率监控及反馈系统 终稿要点.docx](https://file1.bingdoc.com/fileroot1/2023-5/19/15e32037-1fd8-4199-8cc8-ff225f156ef4/15e32037-1fd8-4199-8cc8-ff225f156ef41.gif)
心率监控及反馈系统终稿要点
第四届“含弘杯”学生课外学术科技作品竞赛
心率监控及反馈系统
作品类别:
科技发明制作信息技术类
二〇一四年十月
目录
目录1
摘要1
关键词1
一、前言1
二、工作原理1
1、硬件部分1
1.1信号采集模块2
1.2数据处理模块3
1.3人机交互模块3
1.4数据传输模块3
1.5数据存储模块4
1.6报警模块4
1.7数据接收模块5
2、软件设计部分5
2.1心率采集算法原理及相关C语言程序5
2.1.1心率采集算法原理5
2.1.2心率采集算法相关C语言程序7
2.2程序代码(见附录)8
三、测试方法与误差分析8
1、测试方法9
2、误差分析9
四、市场应用及价值11
五、作品实际图片11
参考文献12
附录:
13
摘要:
心率一项能够比较准确反映人体身体状况的生理指标,通过对心率数值的连续测量来获得准确而客观的数据分析,同时通过模块化的设计将相关的数据进行智能化分析存入SD卡中,同时通过NRF2401A模块或GSM模块进行数据的传输,有效地提高了心率测量仪器的应用范围和分析的准确性。
关键词:
心率测定MSP430单片机NRF2401A模块GSM模块
1、前言
随着人们生活水平的提高,人们对于健康的关注程度也在逐渐上升。
我国的医疗设备市场存在着很大的发展空间,拥有巨大的市场潜力。
心率是指心脏每分钟跳动的次数,是一项能够比较准确的反映出一个人身体状况的生理指标。
通过心率的测量和连续心率数据的处理发掘,可以较客观的获得个体的身体状况分析。
根据模块化设计的思想,可以依照用户的需求进行差异化的定制,从而得到相应所需的产品,极大的扩展了产品的使用范围。
同时通过程序的设计使其能够对于数据进行优化处理,使设备更加智能化,操作更加简便快捷。
2、工作原理
1、硬件部分
硬件部分采用了模块化的设计方案,通过不同的模块与基础测量部分的搭配,从而达到扩展功能的目的。
硬件部分分为信号采集模块、数据处理模块、人机交互模块、数据传输模块、数据存储模块、报警模块、数据接收模块七个部分。
信号采集模块将采集到的信号输入到MSP430单片机中,然后经过单片机的处理,显示在屏幕上,同时将数据存储进SD卡中。
在安装数据传输模块后可以选择将数据通过NRF2401A模块或GSM模块进行传输,一旦心率超出正常范围,报警模块将开始工作,同时将报警信息通过数据传送模块发送到数据接收端。
系统框图如图一所示:
图一系统框图
1.1信号采集模块
信号采集模块采用的是PulseSensor生物传感器。
该传感器采用光电容积法来测量。
当光束透过人体外周血管,由于动脉搏动充血容积变化导致这束光的透光率发生改变,此时由光电变换器接收经人体组织反射的光线,转变为电信号并将其放大和输出。
其价格低廉,精度高,体积较小,工作状态稳定性好,可以使用微处理器进行数据分析处理,用以分析脉搏变化以及实时自我调节心率,维持较为稳定的健康的心率状态。
工作电压在+3~+5V,作品采用+5V供电。
图二传感器波形图
1.2数据处理模块
数据处理模块选择的是德州仪器生产的MSP430单片机,其工作速度快,片内存储空间大,同时具备64个通用IO口,具备优良的数据处理和控制性能。
将PulseSensor传感器采集到的数据进行处理后再传输给下一级硬件部分。
下图为MSP430单片机:
图三MSP430单片机
1.3人机交互模块
人机交互模块采用的了10.1英寸的TFT触摸彩屏,同时对控制部分进行优化。
通过运用工业化集成屏幕,使用触摸进行操作,使系统操作更加便捷。
大屏幕增强了图形显示的效果,使人机交互的功能得到增强。
1.4数据传输模块
为了适应不同的数据传输需求,数据传输模块采用了两种方式。
近距离的数据传输采用NRF2401A无线传输模块。
该模块能够工作在2.4~2.5GHZ的公共频段,工作晶振为16MHZ,采用3.3V电压供电,分为配置模式,直接发送模式,突发模式等多种模式,该模块选择的是突发模式,在该模式下无线通信模块可以直接将从单片机获得的8位二进制数据传送给同一频段的接收端,空旷地区实测传输距离可达400米,接收端再将8位数据校验完成后输出。
图四NRF2401A无线传输模块原理图
远距离的数据传输采用华为的GTM900GSM\GPRS通信模块,其能够在接收到MSP430传递的数据后通过2G网络将数据以短信的形式发送到绑定的手机,工作性能稳定。
1.5数据存储模块
在数据存储模块部分采用的是大容量SD卡存储设备。
其通过SPI总线与MSP430单片机相连,在数据采集后能够迅速完成数据的存入和读取,同时体积较小,具备极高的兼容性,方便数据的转移。
同时扩大了数据的存储空间和存储效果。
1.6报警模块
报警模块采用了蜂鸣器和屏幕共同工作的方式。
当报警模块工作时,蜂鸣器开始工作同时屏幕开始间歇性点亮熄灭,从而起到发出警报的效果。
1.7数据接收模块
在远距离数据传输中,采用手机作为数据接收端;在近距离的数据传输中,由于使用了NRF2401A无线通信模块,所以接收端采用了相同的通信模块和STC89C52RC单片机来构成,其能够将接收到的数据显示在LCD1602的屏幕上,同时在发送端发出警报信号时,在接收端的蜂鸣器工作进行报警。
下图为接收端LCD1602的电路原理图:
图五LCD1602显示部分原理图
2、软件设计部分
2.1心率采集算法原理及相关C语言程序
2.1.1心率采集算法原理
NN
YY
Y
N
Y
N
Y
Y
N
BPM用于保存脉冲速率
IBI持有次之间的时间
Pulse脉冲波高,真;假时,低
QS为真时,发现了一拍心跳节拍
Signal持有传入的原始数据
其中最主要的是BPM和IBI两个字。
IBI是连续两个心拍之间的时间差,而BMP是心率值,表示心脏每分钟跳几下,BMP=60/IBI。
采样:
主要通过ADC12采样脉搏模拟信号,采样频率为500Hz。
滤波:
由于脉搏波在动脉中的反射,往往会出现一个重脉波。
为了避免这个重脉波的干扰,在程序中每隔0.6个IBI值跟踪脉搏上升。
心率的计算根据两个相邻脉搏波的上升段的中间差值确定IBI值,由此可以推算BMP数值。
图六心率采集算法图一
计算:
心率的计算根据两个相邻脉搏波的上升段的中间差值确定IBI值,由此可以推算BMP数值
图七心率采集算法图二
2.1.2心率采集算法相关C语言程序
unsignedintrate[10];//数组来保存最后十个IBI值
unsignedintamp=120;//用于保存脉冲波形的振幅,发送
//unsignedinttemp=0;//温度
unsignedintBPM=600;//用于保存脉冲速率
unsignedintIBI=600;//持有次之间的时间
unsignedintPeak=512;//初始化心跳峰值
unsignedintTrough=512;//用来寻找脉搏波最小值,发送
unsignedintthresh=512;//初始化心跳最小值
_BoolPulse=false;//脉冲波高,真。
假时,低
_BoolfirstBeat=true;//用于启动发送速率数组
_BoolsecondBeat=false;//用于启动发送速率数组
_BoolQS=false;//为真时,发现了一拍心跳节拍。
unsignedintSignal;//持有传入的原始数据
unsignedlongsampleCounter=0;//当前时间
unsignedlonglastBeatTime=0;//上个心跳时间
unsignedlongtime;//用于记录时间
采样:
主要通过ADC12采样脉搏模拟信号,采样频率为500Hz。
voidinit_adc12(void)
{
P6SEL=0x01;//p6.0ADC输入
ADC12CTL0&=~ENC;
ADC12CTL0=ADC12ON+MSC+SHT0_0;
ADC12CTL1=SHP+CONSEQ_1+ADC12SSEL1;
ADC12MCTL0|=INCH_0+MSC;
ADC12IE=0x03;
ADC12CTL0|=ENC;
}
#pragmavector=ADC12_VECTOR//ADC数据
__interruptvoidADC12(void)
{
Signal=ADC12MEM0/4;
}
2.2程序代码(见附录)
三、测试方法与误差分析
1、测试方法
1、通过USB给系统供给5V直流电
2、确认电源指示灯点亮系统正常工作
3、将传感器通过绑带绑在指尖,需指尖感到一定的压迫感即可。
4、将程序从电脑加载到单片机进行调试
5、通过液晶屏幕获得相应的心率测量数据,并模拟心率失常环境,检测警报信号是否正常发出。
2、误差分析
经过大量的反复的测量,获得该设备心率测量数据与参考设备测量数据之间的误差(参考设备选用IHEALTH生产腕式血压计,误差在6%)下面对部分采样结果和计算方法进行介绍。
令设备测得的心率数值为
(
),参考设备测得的心率数值为
(
),
(1)
其中
设样本的平均值为
,方差为
,则通过方差的计算公式知:
(2)
其中
(3)
其中
下图为三次随机测量的结果的统计图:
图八误差统计图一
图九误差统计图二
图十误差统计图三
经过大量的实验,使现有的心率采集算法能够达到与参考设备获得数据相比4%以内的误差。
四、市场应用及价值
本产品可以广泛的适用于家庭远距离监护、中小型医疗机构的检测网络的构建、体育运动分析和一些关于人体状况的研究,比如人体情感控制类的科研数据采集等方面。
在国内的相关产品中,功能类似的产品存在着价格昂贵,体积巨大,测定时间过长,数据传输距离有限,操作繁琐,显示的数值只是离散的单位时间点,没有横向的数据分析功能,存储空间有限等缺点。
随着老龄化社会到来以及国内医疗科研领域的热门化,其具备的市场空间正在急剧扩大,通过这种智能化,灵活性高的产品来构成的相关医疗设备会更加得到消费者的青睐。
例如老年人口增多,年轻人无法在身边长时间陪护;部分中小型医疗机构缺乏资金购置昂贵的设备;对于运动员运动过程中全程的心率数据分析;应用到科学研究中,如人体情感控制需要大量的数据分析而相关的产品功能缺失或性能低等等问题,都可以得到有效的解决,其能够拥有很大的经济效益,并且在未来还可以通过模块的增加为其提供更多的发展空间和市场前景。
五、作品实际图片
图十一作品实际图片
参考文献
[1]洪利,李世宝,章扬.MSP430单片机原理与应用实例详解[M].北京:
北京航空航天大学出版社
[2]谭浩强.C程序设计(第三版)[M].北京:
清华大学出版社
[3]康华光.电子技术基础·模拟部分(第五版)[M].北京:
高等教育出版社
[4]SteveSummit.CProgrammingFAQs—frequentlyaskedquestions[M].CommonwealthofMassachusetts,Boston:
AddisonWesley
附录:
软件主程序
#include
#include"driver.c"
#include"Config.h"//配置msp430头文件,与硬件相关的配置在这里更改
#include"LCM-DRV_CFG.h"
#include"LCM-DRV_DISP.h"
#include"LCM-DRV_TOUCH.h"
#include"LCM-DRV_CAN.h"
#include"uart.h"
unsignedchari,j,k=0,count=0,n=0;
unsignedshortcout[2],a[48][2],b[6][2]=
{
{10,270-250},{10,270},{10+350,270},{10+350,270-1},{10+1,270-1},{10+1,270-250}
};//坐标轴6点原点(10,270)
ucharDisBuff[4]={0};//显示心率数据值
//***********************************************************************
//系统时钟初始化,外部8M晶振
//***********************************************************************
voidClock_Init()
{
uchari;
BCSCTL1&=~XT2OFF;//打开XT2振荡器
BCSCTL2|=SELM1+SELS;//MCLK为8MHZ,SMCLK为8MHZ
do{
IFG1&=~OFIFG;//清楚振荡器错误标志
for(i=0;i<100;i++)
_NOP();
}
while((IFG1&OFIFG)!
=0);//如果标志位1,则继续循环等待
IFG1&=~OFIFG;
}
//*************************************************************************
//主函数
//*************************************************************************
voidmain(void)
{
WDTCTL=WDTPW+WDTHOLD;//关闭看门狗
Clock_Init();//系统时钟设置
UART_Init();//串口设置初始化TFT与单片机通信方式232
init_adc12();//adc心率采集初始化
TACCTL0=CCIE;
TACCR0=16000;
TACTL=TASSEL_2+MC_1+TACLR;
/***********************驱动测试*************************/
//重启液晶
LCDDispText(HZLIB_24X24,CHAR_FB_MODE,0,0,"LCDRESET.");
delayms(1500);
LCDReset();LCDClearScreen();delayms(1500);
LCDDispSolidRectangle(0xF800,0x07E0,10,10,400,270);//画填充矩形
LCDClearScreen();
LCDDispDot(0x00,6,b);//delayms(1500);//画点
LCDDispLines(0x00,6,b);delayms(1500);
/*LCDDispSolidRectangle(0xF800,0x07E0,10,330,400,590);//画填充矩形
LCDDispSolidRectangle(0xF800,0x07E0,440,10,800,270);//画填充矩形
delayms(1500);LCDClearScreen();
for(i=0;i<=8;i++)
for(j=0;j<=6;j++){a[k][0]=100*i;a[k][1]=50*j;k+=1;if(k>=48)k=0;}
LCDDispDot(0x00,48,a);
LCDDispLines(0x00,48,a);delayms(1500);LCDClearScreen();
LCDDispArcSector(0x00,0xF800,0x0064,0x0030,0x0032,0x0000,0x00B4);//画圆弧或扇形
delayms(1500);LCDClearScreen();
LCDDispFreeLines(0x0005,0x0020,0x0135,0x001F,2,FreeLineCordn);//动态曲线显示
delayms(1500);LCDClearScreen();
LCDDispSpectrum(0x0020,0x0135,3,0x0128,SpectrumHigh);
delayms(1500);LCDClearScreen();
LCDDrawPolylineByFixedXoffset(0x0020,0x0008,3,OffsetDotYposi);
delayms(1500);LCDClearScreen();
LCDDrawPolylineByAnyOffset(0x0020,0x0008,3,OffsetDotposi);
delayms(1500);LCDClearScreen();
LCDDispTextSimply(0,0x00F0,0x0088,"Hello!
");
delayms(1500);LCDClearScreen();
LCDDispAscii(0x01,0x00,0x00F0,0x0088,AsciiBuf,sizeof(AsciiBuf));
delayms(1500);LCDClearScreen();
LCDDispDot(0x00,80,DotCordn);//画点
delayms(1500);LCDClearScreen();
*/
_EINT();//开中断
while
(1)
{
if(QS==true)
{
count++;
LCDDispAscii(0x01,0,100,100,DisBuff,4);
if(count==0){cout[0]=270-BPM;}
elseif(count==1){cout[1]=270-BPM;}
else
{
cout[0]=cout[1];cout[1]=270-BPM;
LCDDrawPolylineByFixedXoffset(15+n*20,20,2,cout);n++;
}
if(n>18)
{
n=0;
LCDSetFillWithGroundColor(0x00,0x11,0x20,0x360,0x269);
}
QS=false;
}
}
}
#pragmavector=ADC12_VECTOR
__interruptvoidADC12(void)
{
Signal=ADC12MEM0/4;
}
#pragmavector=TIMERA0_VECTOR
__interruptvoidTIMER1_A0_ISR(void)
{
unsignedintrunningTotal=0;
unsignedchari=0;
ADC12CTL0|=ADC12SC;
_DINT();
sampleCounter+=2;
time=sampleCounter-lastBeatTime;
if((Signal(IBI/5)*3)){
if(SignalTrough=Signal;//取最小值
}
}
if((Signal>thresh)&&(Signal>Peak)){
Peak=Signal;//取最大值
}
if(time>250)
{
if((Signal>thresh)&&(Pulse==false)&&(time>(IBI/5)*3))
{
Pulse=true;
IBI=sampleCounter-lastBeatTime;
lastBeatTime=sampleCounter;
if(secondBeat)
{
secondBeat=false;
for(i=0;i<=9;i++)
{
rate[i]=IBI;
}
}
if(firstBeat)
{
firstBeat=false;
secondBeat=true;
_EINT();
return;
}
for(i=0;i<=8;i++)
{
rate[i]=rate[i+1];
runningTotal+=rate[i];
}
rate[9]=IBI;
runningTotal+=rate[9];
runningTotal/=10;
BPM=60000/runningTotal;
if(BPM>200)BPM=200;
if(BPM<30)BPM=30;
/*****************************************/
DisBuff[2]=BPM%10+48;//取个位数
DisBuff[1]=BPM%100/10+48;//取十位数
DisBuff[0]=BPM/100+48;//取百位数
if(DisBuff[0]==48)
DisBuff[0]=32;
/****************************************/
QS=true;
}
}
if((Signal{
Pulse=false;
amp=Peak-Trough;
thresh=amp/2+Trough;
Peak=thresh;
Trough=thresh;
}
if(time>2500)
{
thresh=512;
Peak=512;
Trough=512;
lastBeatTime=sampleCounter;
firstBeat=true;
secondBeat=false;
}
_EINT();
}