チーム18A2
課題名
1.AD変換したwavegeneの信号をFFTしてLCDに表示
2.アベレージフィルタの追加
研究者名
石原 詢大
ハードウェア設計
使用したモジュールと設定
Delta Sigma ADC
Character LCD
Analog Pin
Delta Sigma ADCの設定
Conversion Mode 2 - Continuous
Resolution 12 bits
Conversion Rate 10000 SPS
Clock Frequency 320.000 kHz
Input Mode Single
Input Range Vssa to 2.048V(0.0 to 2*Vref)
Vref Internal 1.024 Volts
Character LCDの設定
Vertical Bargraph
Pinの設定
Analog
また、Analog PinとLCDのポートはそれぞれ
Analog Pin P3[5] OpAmp+
LCD P2[6 : 0]
とした.
ソフトウェア設計
1. FFTした結果をLCDに表示するコード(main文)
#include <device.h>
#include <fft.h> //FFT64のヘッダファイルをインクルード
void main()
{
/* Place your initialization/startup code here (e.g. MyInst_Start()) */ int i = 0; /*for文のループ用*/ //unsigned char j = 5; /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */ LCD_Char_1_Start(); /*LCDモジュールの開始*/ LCD_Char_1_ClearDisplay(); /*LCDモジュール画面からデータをクリアする*/ ADC_DelSig_1_Start(); /*ADCモジュールの開始*/ ADC_DelSig_1_StartConvert(); /*変換の開始*/ for(;;) { /* Place your application code here. */ /*N_points = 64 *64ビットでデータを受け取る *ポーリング */ for(i = 0; i < N_points; i++) { /*変換完了時にif文を実行する*/ if(ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_WAIT_FOR_RESULT)) { /*配列data_reに64ビットのデータを代入する *data_imは0 */ data_re[i] = (double)ADC_DelSig_1_GetResult16(); //data_imm[i] = (double)ADC_DelSig_1_GetResult16(); } } FFT(1, exponent, data_re, data_imm); /*FFTの結果がmodに入る*/ for(i = 0; i < 16; i++) { LCD_Char_1_DrawVerticalBG(1, i, 2, mod[i]); //CyDelay(j); } }
}
2.アベレージ・フィルタを追加したコード
#include <device.h>
#include <fft.h> //FFT64のヘッダファイルをインクルード
/*AverageFilterの関数
*ADCから受け取った値を4タップで平均化する. */
void AverageFilter()
{
int i = 0; double averagedata[N_points] = {0}; //4タップで平均化した値を受け取る for(i = 0; i < N_points; i++) { //4タップを平均化すると元のデータが足りなくなるので //足りない分は配列の最初にもどり平均化を行う averagedata[i] = (data_re[i] + data_re[(i+1)%N_points] + data_re[(i+2)%N_points] + data_re[(i+3)%N_points]) / 4; } //平均化したデータの配列をdata_reに渡す for(i = 0; i < N_points; i++){ data_re[i] = averagedata[i]; }
}
void main()
{
/* Place your initialization/startup code here (e.g. MyInst_Start()) */ int i = 0; /*for文のループ用*/ //unsigned char j = 5; /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */ LCD_Char_1_Start(); /*LCDモジュールの開始*/ LCD_Char_1_ClearDisplay(); /*LCDモジュール画面からデータをクリアする*/ ADC_DelSig_1_Start(); /*ADCモジュールの開始*/ ADC_DelSig_1_StartConvert(); /*変換の開始*/ for(;;) { /* Place your application code here. */ /*N_points = 64 *64ビットでデータを受け取る *ポーリング */ for(i = 0; i < N_points; i++) { /*変換完了時にif文を実行する*/ if(ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_WAIT_FOR_RESULT)) { /*配列data_reに64ビットのデータを代入する *data_imは0 */ data_re[i] = (double)ADC_DelSig_1_GetResult16(); } } AverageFilter(); FFT(1, exponent, data_re, data_imm); /*FFTの結果がmodに入る*/ for(i = 0; i < 16; i++) { LCD_Char_1_DrawVerticalBG(1, i, 2, mod[i]); //CyDelay(j); } }
}
結果[#v525b1bc]
1.FFTした値をLCDに表示するほうの出力結果
2.アベレージ・フィルタを追加した出力結果
考察
1.ではADCで変換したデータをFFTを使ってLCDにスペクトルを表示させたところグラフが激しく変動するのが観察できた.これはADCが受け取るときのノイズのためである.このノイズを除去するためにはLPF(ローパスフィルタ)ををかける必要がある
2.では値がLPFとしてアベレージフィルタを実装した.今回は4タップの入力を平均化するアベレージフィルタを実装した.出力結果はFFTだけのときに比べスペクトルが少なくなった.よって高周波のスペクトルが除去できたとみなせる.しかし,この出力結果でもグラフの激しい変動がみられた.この変動を除去するにはアベレージフィルタでの高周波の除去でなくFIRによるローパスフィルタの実装が必要だと考える.
また,グラフの激しい変動とは別にwavegeneの音を停止しているときにスペクトルが一本だけ立ってしまう状態になってしまった.これは,音を停止した状態でも何かしらの音が出ているのか,私の作った仕様がそのようになってしまっているのか原因がわかりませんでした.
- 最終更新:2018-05-21 17:13:49