Programming을 이용한 ECG증폭기 설계 6조
- 목차 - 과제 순위 생체신호의 실시간DSP 신호처리의 순서도 Digital Filter 신호처리부의 중요개념 신호처리부분의 프로그래밍
과제 순위 2004200459 장재필 2004200456 임명준 2007102856 임영민 2007102854 이준관 2005200439 이지민
생체신호의 실시간 DSP - “Setting” + Embedded Software : 특정한 기능을 하는 전자제품에 ECG 증폭기 ADC Micro processor Start Stop H.R : 75bpm Embedded Software : 특정한 기능을 하는 전자제품에 ( = Firmware) 들어있는 Software
Digital Signal Processing 신호처리의 순서도 START Initialization Key? Mode = Key Digital Signal Processing Display Yes No
Digital Filter * Digital filter H[n] X[n] Y[n] (1) FIR필터의 특징 ⓐ 선형위상특성을 정확히 그리고 용이하게 실현할 수 있다. 이러한 성질은 데이터 전송과 같은 파형정보를 중요시하는 응용에 필수적인 성질. ⓑ 귀환이 없기 때문에 항상 안정하다. ⓒ 주파수 영역에서 급 준한 감쇠특성을 실현할 때는 높은 차수의 필터 필요 (2) IIR필터의 특징 ⓐ FIR필터보다 적은 차수로 급 준한 감쇠특성을 실현할 수 있다. ⓑ 선형위상특성을 실현하기 어렵다. ⓒ 귀환이 있기 때문에 항상 안정하다고는 할 수 없다. 그러므로 시스템이 안정한가를 항상 판별해야 한다. 목적 : 신호처리의 가장 기본적인 목적의 하나로 본래의 신호에 잡음이 첨가될 경우 주어진 측정신호로부터 본래의 신호를 찾아내고자 하는 경우 정의 : 관측된 신호에 어떠한 처리를 하여 그 중에서 필요한 성분만 추출해 내어야 하는데 이와 같은 필터링(filtering) 종류 : 임펄스 응답이 유한인가 무한인가라는 관점에서 FIR(Finite Impulse Response)과 IIR(Infinite Impulse Response)디지털필터로 분류 Y[n]=a0x[n]+a1x[n-1]+…+anx[n-n] -b1y[n-1]-b2y[n-2]-…-bny[n-n] 위의 식에서 bi의 값이 모두 0이면 =>FIR bi의 값이 하나라도 0이 아니면 =>IIR
프로그램에 쓰이는 파일 monitor.c GetADC.c Dsp.c my_def.h Initialization.c Key.c
Monitor.c & GetADC.c // monitor.c #include my_def.h Int main(){ Init(); while(1){ mode = Key(); switch(mode){ case start; d = GetADCData(); dn = Dsp(d); Display signal(d); Display HR(dn); break; default : } return 0; //GetADC.c #include my_def.h Int GetADCData(void) { int d; // Read Data from ADC … return 0; } // my_def.h # define START 0xff; # define STOP 0x00; # define FALSE 0; # define TRUE 1; // 자주 쓰이는 값들을 하나의 헤더파일에 저장
Initialization.c & Key.c & Dsp.c Void Init(void) { … } // 프로그램의 초기값들을 저장 // Dsp.c #include my_def.h Int Dsp(int d) { int d1, d2, d3, d4; d1 = lpf(d); d2 = hpf(d1); d3 = differentiate(d2); d4 = absolute(d3); d5 = mwi(d4); d6 = threshould(d5); d7 = RR_interval(d6); d8 = computeHR(d7); return (d8); } //데이터를 처리해주는 부분, 각각의 함수를 호출하여 연산을 거친 값을 반환한다. // Key.c #inlcude my_def.h Unsigned char key(void) { if(key_value == 1) return (START); else return (STOP); } 새로 키가 눌려지기 전에는 이전의 키 값으로 return 해주는 program을 짜야한다.
lpf() & hpf() h[n] x[n] y[n] h[n] x[n] y[n] y[n] = {x[n] + 2x[n-1] + x[n-2]} / 4 y[n]=x[n]-2y[n-1] //lpf() Int lpf(int x) { Int y; static int x1,x2; // x1, x2는 함수 호출시 마다 저장 y={x+(x1<<1)+x2}>>2; // 프로그램의 성능을 빠르게 하기 위하여 << 시프트 연산자 사용 x2=x1; x1=x; return (y); } //hpf() int hpf(int d) { Int y; static int y1; y=d-(y1<<1); y1=y; return (d); } 왼쪽의 함수는 High Pass Filter로 왼쪽함수에서 사용된 식은 Y[n]=x[n]-2y[n-1] 의 식이다. 위의 함수는 Low Pass Filter로 왼쪽함수에서 사용된 식은 Y[n]={X[n]+2X[n-1]+X[n-2]}/4 의 식이다.
Differentiate() & absolute() *미분 Sampling interval ex) y[n] = x[n] – x[n-1] // Differentiate() Int differentiate (int d) { int y; static int d1; y=d-d1; d1=d; return (y); } 왼쪽의 함수는 Data값을 받아 미분하는 함수이다. 왼쪽의 미분치 식을 보면 Ts는 고정된 값이므로 미분을 f(n) – f(n-1)로 표현할 수 있는 것을 볼 수 있다. //Absolute() Int absolute (int d) { if(d<0) return (-d); else return (d); } 왼쪽의 함수는 Data의 값이 음의 값을 가지게 되면 그값에 음수를 취하여 줌으로써 모든 Data의 값을 양의 값을 가지도록 하는 함수이다. Ts는 고정된 값
mwi() y[n] = ∑x[n-i] = x[n] + x[n-1] + … + x[n-29] // i=0 ~ 29 Int mwi(int x) { int y1; static int y, p, x[30]; if(++p==30) P=0; y=y-x[p]+x; // y:running sum x[p] = x; return(y); } y[n] = ∑x[n-i] = x[n] + x[n-1] + … + x[n-29] // i=0 ~ 29 //mwi() – moving window integral Int mwi(int x) { int y; static int x1, x2, x3, … x29; y = x + x1 + x2 + … + x29; x29 = x28; x28 = x27; …. x2 = x1; x1 = x; return (y); } 제일 예전 Data P 제일 예전의 Data에 새로운 Data를 넣는 Program -> Ring buffer 위의 함수는 최근 30개의 Data의 값을 더하여 주는 함수이다. x6 x5 … x
threshould() & computeHR() Int computeHR(int r){ static int hr; if(r==0) return(hr); else{ hr=12000/r; return(hr); } // threshould() Int threshould(int d) { int Th = x; if(d>Th) return 1; else return 0; } 위의 함수는 심장 박동수를 계산하는 함수이다. 이 함수는 전 함수에서부터 입력받은 R-R interval값을 가지고 의 식에 의해 HR을 계산하게 된다. 여기서 시간은 data r값이 1상승하는데 걸리는 시간이라고 할 수 있다. 이 시간을 1분에 대하여 나누어 주면 HR의 값을 얻을 수 있게 된다. 위의 함수는 이 다음에 행하여질 R-R interval을 계산하기 위해 필요로 하는 R파형을 나타내는 함수이다. 입력 받은 Data의 값이 특정값 (Threshold값)보다 크게되면 1의 값을 다음 함수에 넘겨 줌으로써 다음 함수에서 이 1의 값을 넘겨받는 시간을 계산하여 R-R interval의 값을 계산하도록 하여주는 함수이다.
RR_interval() * QRS 파형 검출 int RR_interval(int t) { int r; static int t1,c; If(t1==0 & t==1){ r = ++c; c = 0; t1=t; return(r); } else{ ++c; t1 = t; Return(0); //RR_interval() int r; int RR_interval(int t) { static int t1,count; If(!(t1==0&t==1)){ ++count; t1=t; return(0); } else{ r=++count; count=0; return(r); 왼쪽의 함수는 이전의 함수로부터 data의 값을 입력받아 그 입력 받은 값이 1이 되는 두 입력사이의 시간을 계산함으로써 R-R interval의 시간을 계산하여 다음의 함수로 넘겨주게 된다. 그 원리로는 처음에 1을 입력받은 시점으로부터 다음의 1의 data값을 받을 때까지 count의 값을 증가시킴으로써 이 count 값을 다음의 함수로 넘겨주어 HR(심장 박동수)을 계산하도록 하여주는 함수이다.
감사합니다.