low pass filter는 말 그대로 저주파를 통과시키는 필터이다.
예를들어 sampling rate가 250Hz에서 10Hz미만의 성분만 보고싶다 그러면 LPF를 사용하면 된다.
푸리에 변환을 통해 10Hz성분 미만만 역 푸리에 변환을 해도 되긴하지만 cost가 더 많이 나올것이다.
자세한 설명은 다른 블로그를 참조 바라며, 이 글에서는 LPF를 C로 구현한 소스코드를 공유할 것이다.
먼저 아래 차트와 같이 sampling rate가 250Hz인 데이터 280point가 있다.
데이터는 아래와 같다.
-2.000359297 -2.174054623 -2.35839057 -2.507937431 -2.658874989 -2.78489852 -2.877093792 -2.909906149 -2.907539129 -2.937593699 -2.827812433 -2.690007925 -2.546804667 -2.392328024 -2.21248436 -2.015531301 -1.793585896 -1.563929677 -1.325000048 -1.079359412 -0.831492186 -0.586148441 -0.42007032 -0.144992188 0.092226565 0.263468742 0.429539055 0.416757822 0.53262502 0.630937517 0.691570342 0.772828102 0.629304707 0.774874985 0.806195319 0.655210912 0.471523434 0.36916405 0.270898432 0.127007812 -0.068875 -0.269171864 -0.467968762 -0.813125014 -1.146039009 -1.432148457 -1.73896873 -2.059898376 -2.338007927 -2.525742292 -2.661421776 -2.7732265 -2.840250015 -2.865140676 -2.847640514 -2.848711014 -2.792609453 -2.636093855 -2.481937408 -2.355070353 -2.234999895 -2.108062506 -1.950406194 -1.764906287 -1.562687516 -1.365570307 -1.161453128 -1.008117199 -0.789039075 -0.54219532 -0.331617177 -0.148312494 -0.021695312 0.077593751 0.165726557 0.147898436 0.213874996 0.255742192 0.260015637 0.256117195 0.262156248 0.134218752 0.252695322 0.271320313 0.167570308 0.109742187 0.097070314 0.069085941 -0.048140626 0.033109374 -0.08910156 -0.329359382 -0.502343774 -0.534539044 -0.691710949 -0.943640649 -1.163335919 -1.331562519 -1.489703178 -1.674289107 -1.832992196 -1.959609389 -2.113632917 -2.182625055 -2.261710882 -2.351234436 -2.396953106 -2.42303133 -2.4449296 -2.52601552 -2.414085865 -2.344320297 -2.295562506 -2.256546974 -2.161414146 -2.052265644 -1.959125042 -1.871031284 -1.773031235 -1.69217968 -1.514945269 -1.32571876 -1.10216403 -0.865499973 -0.625703096 -0.386039048 -0.280257821 -0.069914065 0.109304689 0.1605625 0.292874992 0.446937501 0.46265626 0.745437503 0.772367179 0.69853127 0.643203139 0.690132797 0.559656262 0.689281225 0.585460961 0.285804689 0.0425625 -0.027671875 -0.216843754 -0.500554681 -0.752054691 -0.958437502 -1.177835941 -1.407039046 -1.579789042 -1.738976598 -1.915171862 -2.100664139 -2.267031193 -2.384734392 -2.457664013 -2.509851456 -2.5463202 -2.571703196 -2.582914114 -2.584343672 -2.554718733 -2.482843637 -2.363773346 -2.212007761 -2.059499979 -1.895585895 -1.711500049 -1.563703179 -1.375921845 -1.176585913 -0.997718751 -0.832906246 -0.666460931 -0.508429706 -0.364976555 -0.214132816 -0.108101562 -0.066781253 0.029945312 0.034125 0.125671878 0.15045312 0.101632811 0.098242186 0.284015626 0.310632825 0.237570316 0.151328132 0.245398432 0.106375001 0.031570312 0.11110156 -0.031515624 -0.269585937 -0.314718753 -0.351375014 -0.521132827 -0.744414091 -0.917148411 -1.046429634 -1.147304654 -1.26858592 -1.41814065 -1.55799222 -1.732531309 -1.83027339 -1.951093793 -2.075718641 -2.195859432 -2.28751564 -2.360492229 -2.413351536 -2.539414167 -2.463015556 -2.400062561 -2.382968664 -2.316937447 -2.237421989 -2.1956954 -2.157210827 -2.083374977 -1.94097662 -1.736617208 -1.5039922 -1.255507827 -1.02369535 -0.797984362 -0.595109403 -0.434656262 -0.444523424 -0.206812501 -0.10302344 -0.044242188 0.080179684 0.054929689 0.391234368 0.480953127 0.463007808 0.476460934 0.505054712 0.418437511 0.581453145 0.521531224 0.357890636 0.284031242 0.196085945 0.019648438 -0.167007819 -0.297500014 -0.454773426 -0.639414072 -0.803546846 -0.945109367 -1.083359361 -1.217484355 -1.361624956 -1.518867135 -1.654859424 -1.820046902 -1.995585918 -2.168671846 -2.299382925 -2.389531136 -2.456804752 -2.51266408 -2.544703007 -2.561906338 -2.528382778 -2.453234434 -2.353968859 -2.23029685 -2.099882841 -1.962406278 -1.86474216 -1.701679707 -1.520601511 -1.350796819 -1.198937535
low pass filter의 계수는 아래와 같이 구한다.
double *lowpassfilter(double f, double fs, int N)
{
double *filter = NULL;
double fc = 0;
double omega = 0;
int i = 0;
int middle = 0;
if (f <= 0 || fs <= 0 || N <= 0)
return NULL;
filter = (double*)malloc(N*sizeof(double));
if (!filter)
return NULL;
memset(filter, 0, N*sizeof(double));
middle = (int)(N / 2);
fc = f / fs;
omega = 2 * PI*fc;
for (i = 0; i < N; i++)
{
if (i == middle)
{
filter[i] = 2 * fc;
}
else
{
filter[i] = sin(omega*(i - middle)) / (PI*(i - middle));
}
}
return filter;
}
파라미터는 각각 아래와 같다
- f: cut off frequency
- fs: sampling rate
- N: data count
lpf를 하기 위해 샘플을 뒤집어주어야한다.
void reverce_array(double *arr, int n_data)
{
double temp;
for (int i = 0, j = n_data - 1; i < n_data / 2; i++, j--) {
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
그 후 아래와 같이 DC offset을 제거해 주고, 합성곱을 하면 된다.
int main(void)
{
double *lpf_coefficient;
double sum = 0;
double avg;
lpf_coefficient = lowpassfilter(10.0, 250, 30);
reverce_array(test_dat, 280);
for (int i = 0; i < 280; i++) {
sum += test_dat[i];
}
avg = sum / 280;
for (int i = 0; i < 280; i++) {
test_dat[i] -= avg;
}
reverce_array(test_dat, 280);
for (int j = 0; j < 250; j++) {
sum = 0;
for (int i = 0; i < 30; i++) {
sum += test_dat[i + j] * lpf_coefficient[i];
}
test_dat[j] = sum;
printf("%lf\n",test_dat[j]);
}
}
그러면 아래와 같이 고주파 성분이 사라진 그래프를 확인 할 수 있다.
정확하게 확인을 위해 fft를 해보자면,
10Hz이상의 성분이 제거된 것을 확인 할 수 이다.
'FW' 카테고리의 다른 글
STM32CubeIDE개발환경 구축하기 (0) | 2022.09.01 |
---|---|
stm32 HAL timer(2) (0) | 2021.12.04 |
stm32 HAL timer(1) (0) | 2021.10.30 |
IAR Heap Stack size 조절 (0) | 2021.09.19 |
Hanning window (0) | 2021.09.19 |