チーム16B1
課題名
平均化フィルタを用いたLPFとHPF
研究者名
Kohei Suzuki
Kohei Tajima
説明
可変抵抗を使用して信号を入力し、それを出力した後に信号にHPFを1度、2度、3度かけたものをそれぞれ順番に表示し、その後同様にLPFを1度、2度、3度にかけたものをそれぞれ順に表示することで、フィルターがかかっていく様子を視覚化する。
すべて表示し終えた後に、スイッチを押すことによって見逃した値をもう一度見直すことができるようにした。
ソースコード
#include <device.h>
#include <math.h>
#define N 20
int16 adcResult = 0;
//データ配列を受け取り、それを波として視覚化するための関数
void draw(double data[]){
LCD_Char_1_ClearDisplay(); double max=0; int i; for(i=0;i<16;i++){ if(max<data[i]) max=data[i]; } for(i=0;i<16;i++){ LCD_Char_1_DrawVerticalBG(1, i, 2,data[i]); }
}
//文字を受け取り、LCDに出力するための関数
void print(char *m){
char *msg; msg=m; LCD_Char_1_ClearDisplay(); LCD_Char_1_Position(0,0); LCD_Char_1_PrintString(msg); CyDelay(1000u);
}
void main(){
LCD_Char_1_Start(); ADC_DelSig_1_Start(); ADC_DelSig_1_StartConvert();
int i=0; int j=0; int data=0; double hpf1[N]; double lpf1[N]; double ini[16]; double tmp[N]; double adc[N]; double hpf2[N],hpf3[N],lpf2[N],lpf3[N]; int d=0; //データ入力をする時のカウントダウン print("data input 3"); print("data input 2"); print("data input 1");
LCD_Char_1_ClearDisplay(); //最初に、ADCを使って可変抵抗の値をデジタル値として受け取る。 //この時、出力の関係上最大値が16、最小値が0になるように調整しておく for(;;){ if(ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_WAIT_FOR_RESULT)){ LCD_Char_1_Position(0, 0); adcResult = ADC_DelSig_1_GetResult16(); LCD_Char_1_PrintNumber((uint16)adcResult); data=adcResult; //値の調整 //可変抵抗の値を小さくしすぎると以上に高い数値が出てしまう問題をここで取り除いておく if(data>4100){ data=0; } else{ data=data/256; }
LCD_Char_1_Position(0, 6); LCD_Char_1_PrintNumber(data); adc[j]=data; j++; if(j>=20) break; CyDelay(500u); LCD_Char_1_ClearDisplay(); } } //受け取った値を、出力、計算のためにほかの配列に入れる。 for(i=0;i<20;i++){ hpf1[i]=adc[i]; lpf1[i]=adc[i]; } for(i=0;i<16;i++){ ini[i]=adc[i]; }
//入力された信号を出力 print("initial value"); draw(ini); CyDelay(1000u); LCD_Char_1_ClearDisplay(); //HPF for(i=0;i<20;i++){ tmp[i]=(hpf1[i]-hpf1[i-1])/2.0; tmp[i]=tmp[i]+8; } for(i=0;i<20;i++){ hpf1[i]=tmp[i]; } print("1st HPF"); draw(hpf1); CyDelay(1000u); LCD_Char_1_ClearDisplay(); for(i=0;i<20;i++){ tmp[i]=(hpf1[i]-hpf1[i-1])/2.0; tmp[i]=tmp[i]+8; } for(i=0;i<20;i++){ hpf2[i]=tmp[i]; } print("2nd HPF"); draw(hpf2); CyDelay(1000u); LCD_Char_1_ClearDisplay();
for(i=0;i<20;i++){ tmp[i]=(hpf2[i]-hpf2[i-1])/2.0; tmp[i]=tmp[i]+8; } for(i=0;i<20;i++){ hpf3[i]=tmp[i]; } print("3rd HPF"); draw(hpf3); CyDelay(1000u); LCD_Char_1_ClearDisplay(); //LPF for(i=0;i<N;i++){ lpf1[i] = ( lpf1[i] + lpf1[i+1] + lpf1[i+2] + lpf1[i+3] ) / 4.0; } print("1st LPF"); draw(lpf1); CyDelay(1000u); LCD_Char_1_ClearDisplay();
for(i=0;i<N;i++){ lpf2[i] = ( lpf1[i] + lpf1[i+1] + lpf1[i+2] + lpf1[i+3] ) / 4.0; } print("2nd LPF"); draw(lpf2); CyDelay(1000u); LCD_Char_1_ClearDisplay(); for(i=0;i<N;i++){ lpf3[i] = ( lpf2[i] + lpf2[i+1] + lpf2[i+2] + lpf2[i+3] ) / 4.0; } print("3rd HPF"); draw(lpf3); CyDelay(1000u); LCD_Char_1_ClearDisplay(); //見落としたデータを見直すための部分 for(;;){ //dの値によって出力するものを変える //dは、スイッチによって値を変えることができる //ここでの出力のため、作成したデータ配列は擦れずれ別の名前で保存しておく必要がある if(d==0){ print("initial value"); draw(ini); } else if(d==1){ print("1st HPF"); draw(hpf1); } else if(d==2){ print("2nd HPF"); draw(hpf2); } else if(d==3){ print("3rd HPF"); draw(hpf3); } else if(d==4){ print("1st LPF"); draw(lpf1); } else if(d==5){ print("2nd LPF"); draw(lpf2); } else if(d==6){ print("3rd LPF"); draw(lpf3); } //dの値が想定外(負の値や大きすぎる値)になった時には表示を終了する else{ print("END"); break; } //ボタンを連続で押す判定にならないように少し入力を待つ CyDelay(300u); //ボタンの入力判定 for(;;){ if(!SW_2_Read()){ d--; break; } else if(!SW_3_Read()){ d++; break; } } }
}
結果
図1.入力した信号
図2.HPFを2回かけた信号
図3.LPFを2回かけた信号
考察
図より、HPFは波をとがらせ、LPFは波をなだらかにしていることがわかる。このことからHPFは高い周波数の波を通し、LPFは低い周波数の波を通すことがわかる。
今回は、PSoCを使用して波を視覚化した。しかし、あまり多くのデータを取り扱うことができず、その点で視覚的にわかりにくい部分があったため、連続したデータを視覚化するためにWaveSpectraなどを利用してより分かりやすくすればよかったが、時間の都合で実装することができなかった。
また、4タップのアベレージフィルタを利用してLPFを実現したが、様々なタップ数のアベレージフィルタを実装すれば、LPFのかかり方にも違いが出ると考えられる。
今回作成したフィルタを何度も重ねてかけると、どちらも交流成分を完全に消してしまう。そのため、LPFであっても低い周波数成分を少しずつ減らしていることになるので、改善が求められる部分であると考えられる。
- 最終更新:2016-06-06 16:33:20