사실... 저역통과필터는 뭐 원체 많이들 사용하고 있는거라 어려울게 없습니다만.... 그걸 저는 또 구지~~~ C Code로 구현하는 것에 대해 한 번 다룬적[바로가기]이 있었죠... 그리고는 그걸 다시 Python으로 구현하는 법을 이야기[바로가기]를 했구요. 또.. MATLAB으로 구현하는 것도 각각 FFT까지 수행해 가면서 다루었지요.[바로가기] 심지어는 엑셀에서 구현하는 방법마저도... 또 다루었습니다^^[바로가기] 이제 끝나나 하셨겠지만~~~^^ 이번에는 ChebyShev 체비세프 저역통과필터를 한 번 이야기해볼려고 합니다. 이 글을 쓰는 카테고리가 Program Language로... MATLAB에서 그냥 간편히 빠르게 어떻게 구현할 것인가가 목적입니다. 그러니 뭐 유도과정 원리... 등등의 복잡한 이야기는 [바로가기]로 패스~~~하고 시작하죠^^
일단 체비세프 필터의 주파수 특성은
출처 : 위키백과 Chebyshev filter 항목의 그림
와 같습니다. 통과를 시키는 저역부분에 리플(ripple)이 존재한다는 단점이 있지만...
출처 : 위키백과의 Chebyshev필터
Butterworth에 비해 주파수를 자르는(cut-off) 기울기가 아주 가파르게 잘 자르는 특성을 알 수 있습니다. 오늘 다루는 것이 체비세프 1형이고.. 2형의 경우는 통과대역의 ripple은 없지만.. 차단된 대역에 ripple이 있다는 단점이 있습니다.
체비세프 필터를 MATLAB에서 설계하는 간편한 절차는 위와 같습니다. passband와 stopband를 정하고... ripple의 정도를 설정한 후~~ cheb1ord를 실행하면 필터의 차수와 가중치를 계산해 줍니다. 그것과 통과대역의 ripple정도를 설정한 후에 cheby1을 실행하면 필터의 계수를 정해 줍니다. 이를 filter라는 함수를 통해 원 신호에 필터를 적용한 결과를 알 수 있게 해 줍니다. filter라는 함수를 나중에 C든... 뭐든 코드로 구현하면 되는데요... 그 원리는
출처 : MATLAB filter 명령의 설명 문서
입니다. 이산 시간에서의 개념이므로 차수에 맞게 이전 값을 저장해서 계산해 주면 됩니다. 일단 오늘은 MATLAB~~~이니까.. 예제 전체를 설명해야죠~~^^. 더불어 [바로가기]에서 했던 1차 LPF를 가지고 비교해볼까 합니다.^^
% create rawData sampleTime = 0.0001; endTime = 2; time = 0:sampleTime:endTime; freq = [1 2 3 4 10 70 80 90 100 200 300 400 500 1000 1100 1200 1300 2000]; testYtmp = zeros(length(freq), length(time)); for i=1:length(freq) eval(['testYtmp(' num2str(i) ', :) = sin(2*pi*freq(i)*time); ']) end testYtmp(1,:) = testYtmp(1,:)*5; refSignal = testYtmp(1, :) + testYtmp(2, :) + testYtmp(3, :) + testYtmp(4, :) + testYtmp(5, :); testY = sum(testYtmp, 1);
이 부분은 시험 신호를 만드는 부분입니다. 먼저 1, 2 Hz 대역의 신호 몇 개와 10 70 등등의 신호들... 수백 Hz 신호들을 조합해서 test 신호를 만들었습니다. 제 목적은 10Hz까지는 확실히 복원하고 나머지는 버리는 필터를 설계하고 싶은거구요. 그래서 refSignal이라는 것에서 10Hz까지를 따로 두고 나중에 비교할려고 합니다.
%% simple 1st LPF tau = 0.018; resultLPF = zeros(1, length(time)); for i = 2:length(time) resultLPF(i) = (tau*resultLPF(i-1) + sampleTime*testY(i))/(tau + sampleTime); end
이 부분은 이전에도 이야기한 1차 LPF를 적용한 결과이구요.... 저~~ 필터 계수 tau는 오늘 세팅할 체비세프 필터와 응답 시간을 최대한 맞출려고 그냥 막 잡은 겁니다. 비교를 위해서이죠~~~^^
%% ChebyShev LPF passband = 0.01; stopband = 0.029; passrip = -20*log10(0.99); stopatten = -20*log10(0.0001); [Nc1, Wnc1] = cheb1ord(passband, stopband, passrip, stopatten); [Bc1, Ac1] = cheby1(Nc1, passrip, Wnc1); resultCheby = filter(Bc1, Ac1, testY);
오늘의 핵심인 체비세프 필터입니다. 위에서 설명했습니다만~~~^^
%% Draw the result figure; plot(time, testY, 'LineWidth', 0.1) grid on hold on plot(time, refSignal, 'c', 'LineWidth', 1.5) plot(time, resultLPF, 'k', 'LineWidth', 1.5) plot(time, resultCheby, 'r', 'LineWidth', 1.5) hold off set(gcf, 'Color', [1,1,1]) legend('rawData', 'refSignal', '1stLPF', 'ChebyShev') eval(['title(''1st LPF coef = ' num2str(tau) ', ChebyShev''''s order = ' num2str(Nc1) ' '');'])
이제 원신호(testY)와 1차 LPF(resultLPF)와 체비세프 필터(resultCheby)를 비교하기 위해 그래프로 그려보죠~~^^
위 결과와 같습니다. 파란색은 노이즈를 잔뜩 실어준 원 데이터이구요. 하늘색은 딱 저 모양으로 복원되었으면 하는 바램(^^)이구요. 까망색은 1차 LPF, 빨간색이 체비세프 필터의 결과입니다. 두 필터는 성능 비교를 위해 지연된 시간을 대충 눈으로(^^) 일치시켜서 보는겁니다.
이 것만 봐도 체비세프가 잔 진동 없이.. 이말은 다른 주파수 영역없이 상대적으로 깔끔하게 잘 필터링 된 것이라고 볼 수 있는데요...
%% FFT sampleFreq = 1/sampleTime; lenData = length(time); NFFT = 2^nextpow2(lenData); Y1 = fft(testY, NFFT)/lenData; Y2 = fft(resultLPF, NFFT)/lenData; Y3 = fft(resultCheby, NFFT)/lenData; f = sampleFreq/2*linspace(0,1,NFFT/2+1); figure; plot(f, 2*abs(Y1(1:NFFT/2+1)), ... f, 2*abs(Y2(1:NFFT/2+1)), 'c', ... f, 2*abs(Y3(1:NFFT/2+1)), 'r', 'LineWidth', 1.5 ) grid on set(gcf, 'Color', [1,1,1]) legend('rawData', '1stLPF', 'ChebyShev')
좀더 정확히 알기 위해 FFT를 수행해보죠. 위 코드는 뭐 이미 제가 이야기한 적이 있는 FFT코드이구요..
결과가 위와 같습니다. 원신호는 제가 의도한 것 처럼 주파수가 잘 버무려진듯 보이네요...
확실히 하늘색(1차 LPF)는 점점 주파수 성분이 깍여가는 것이 보이네요. 좀 더 보면
1차 LPF는 자르고 싶은 주파수 대역이 확실히 깔끔하게 자르지 못하고 남은 영역이 보이지만. 빨간색 체비세프 필터는 상대적으로 잘 잘려진것이 확인됩니다.^^
다시 원 신호를 더 자세히 보면... 이 의미를 확인할 수 있습니다.^^. 잘 잘라서 10Hz까지만 유지를 하고.. 나머지는 잘 잘렸네요~~~^^
'Software > MATLAB' 카테고리의 다른 글
MATLAB에서 벡터를 3D로 표현하는 quiver3와 화면 보기 각도를 조절하는 view 함수 익히기 (6) | 2015.11.23 |
---|---|
MATLAB에서 벡터나 공간을 표현하고 연습하기 좋은 drawLA Toolbox (8) | 2015.09.16 |
칼만 필터를 이용하여 위치에서 속도 구하는 예제 - 김성필 저, 칼만필터의 이해 - (43) | 2015.08.20 |
MATLAB에서 1차 저역통과필터를 구현해보자 (41) | 2015.06.11 |
MATLAB에서 직접 2차 미방을 풀어 진자 운동 구현하기 (28) | 2014.10.22 |
MATLAB에서 4차 Runge Kutta를 이용하여 1차 혹은 2차 미분방정식을 푸는 예제 (55) | 2014.10.10 |
MATLAB/Simulink에서 If - else문 구현과 유용한 scope 세팅 (12) | 2014.10.02 |