这是2020年江苏省电赛A题的一部分设计要求,计算ADS1292模块传出的心电信号值,找到QRS坐标,ADS1292是一个24位高精度的ADC,通过两路的差分放大接收激励引脚产生的电压变化(心电信号的变化)。
ECG信号为准周期信号,R为一个波段的最大值,Q为R前的最小值,S为整个波段最小值(R后最小值),信号建议使用SG滤波,可以保留信号变化的一种类似于最小二乘法的滤波,然后对数组取差值,前后差值最大的点为R,R前差值为正,直到Q点,R后插值为负,直到S点。
提示:这是对一组250个采样点,分区间找最大值,判断组内有效心电信号波段个数,计算相应QRS坐标的简易算法,用的一组处理后的心电数据txt里的。
#include <stdio.h> #include <math.h> int main(void) { int i,j,max_piont[6]={0},min1_piont[6]={0},min2_piont[6]={0},sz[461],max[6]={0},min1[6]={0},min2[6]={0}; int len = 85;//real = 85 , org = 461(460) int base = 500;//651:b,1563:c ,, real = 0 int a[85]={0}; int max_buf[5] = {0}; int max_buf_val[5] = {0}; int box[250] ={0}; int box_len = 250; int window = 50; int window_cnt =0; int max_temp=0; int temp; int ture=0; float xinglv=0, time = 0.004 ,xinglv_jiange1=0,xinglv_jiange2=0;//time要按采样时间算 //从TXT中读250个数字 FILE *fpRead=fopen("box2.txt","r");//b,c ,, real = real_1 if(fpRead==NULL) { return 0; } for(i=0;i<box_len;i++) { fscanf(fpRead,"%d ",&box[i]); //printf("%d ",a[i]); } //把250分成5个区间,取最大值 for(i=0;i<5;i++) { max_temp = 0; for(j = i*window;j < i*window+window;j++) { max_temp=(max_temp>box[j])?max_temp:box[j]; if(max_temp==box[j]) { max_buf[i]=j; max_buf_val[i]=box[j]; } } window_cnt = window_cnt + 1; } //排序 for(i=0;i<5;i++) { for(j=i+1;j<5;j++) { if(max_buf_val[i]<max_buf_val[j]) { temp=max_buf_val[i]; max_buf_val[i]=max_buf_val[j]; max_buf_val[j]=temp; temp=0; temp=max_buf[i]; max_buf[i]=max_buf[j]; max_buf[j]=temp; } } } for(i=0;i<5;i++)//计算有效的波峰 { if(max_buf_val[i]>max_buf_val[0]-5) ture++; } //取前有效个,算qs for(i=0;i<ture;i++) { for(j=max_buf[i];j<max_buf[i]+10;j++) { min1[i]=(min1[i]<box[i])?min1[i]:box[j]; if(min1[i]==box[j]) min1_piont[i]=j;//S } for(j=max_buf[i]-12;j<max_buf[i];j++) { min2[i]=(min2[i]<box[j])?min2[i]:box[j]; if(min2[i]==box[j]) min2_piont[i]=j;//R } } //算心率,心律不齐 xinglv = 60/(((max_buf[1]-max_buf[0])+(max_buf[2]-max_buf[1]))/2*time); // (time)not have value !!! just test xinglv_jiange1 = max_buf[1]-max_buf[0]; xinglv_jiange2 = max_buf[2]-max_buf[1]; //输出 printf(" %d %d %d %d %d , %d\n",max_buf[0],max_buf[1],max_buf[2],max_buf[3],max_buf[4],window_cnt); printf(" %d %d %d %d %d , %d\n",max_buf_val[0],max_buf_val[1],max_buf_val[2],max_buf_val[3],max_buf_val[4],window_cnt); printf(" R-R间距 %f %f \n",xinglv_jiange1,xinglv_jiange2); printf(" 心率 %f 间隔误差 %f \n",xinglv,(max_buf[1]-max_buf[0])/(max_buf[2]-max_buf[1])); for(i=0;i<ture;i++) { printf(" 输入%d个整数中Q%d是:%d \n其数组下标是:%d 是第:%d个\n",box_len,i,min2[i],min2_piont[i],min2_piont[i]+base); printf(" 输入%d个整数中R%d是:%d \n其数组下标是:%d 是第:%d个\n",box_len,i,max_buf_val[i],max_buf[i],max_buf[i]+base); printf(" 输入%d个整数中S%d是:%d \n其数组下标是:%d 是第:%d个\n",box_len,i,min1[i],min1_piont[i],min1_piont[i]+base); } ture = 0; return 0; }结果对于处理过的数据还是比较准的
提示:还是需要处理两最大值采样点x坐标过近的问题,滤除可能的误差。