製作モジュール一覧

ラベル デジタルフィルタ の投稿を表示しています。 すべての投稿を表示
ラベル デジタルフィルタ の投稿を表示しています。 すべての投稿を表示

2017年5月28日日曜日

デジタルフィルタ MicroModeler DSPを使ってみる

デジタルフィルタは、リズムマシンを作った時PSoC5 LPのDFBを使ったことがある。(参考:「PSoC 5LPのデジタル・フィルタを使ってみる」「PSoC 5LPのデジタル・フィルタを使ってみる CPUで波形生成」)

PSoC 5LPのDFBはPSoC CreatorのFilterコンポーネントを使うとかんたんにデジタルフィルタを実装できるが、コアがCortex-M3なので浮動小数点演算がなかなかしにくい。(もうすぐPSoC6(Cortex-M4 & Cortex-M0+)が出そうなので期待しています。)

デジタルフィルタの設計ツールとして「MicroModeler DSP」というツールを見つけたので試してみた。コミュニティ版は非商用なら無償で使える。

デジタルフィルタの種類


「音遊び!Blackfin DSP基板でディジタル信号処理初体験」の付録についているAnalog DevicesのBlackfinを使ったボードでデジタルフィルタを試したことがある。



この本はDSPの使い方入門といった感じで、信号処理の理論的なことにはあまり触れられていないが、DSPとはいかなるもので、どうやってプログラミングすればいいのか?という取っ掛かりにはちょうどいいと思う。

DSPの実行環境はなかなかないので付録基板ですぐに試せるのが大きなメリット。

<追記:2017.05.31>
amazonの転売はふっかけすぎですが、marutsuでは新品を定価販売されているようです。
</追記>

最初の方の三章を使って、移動平均、FIR(有限インパルス応答)、IIR(無限インパルス応答)の説明がなされている。

これにしたがって、MicroModeler DSPで3つのフィルターを試してみた。

MicroModeler DSPではコードを自動生成してくれるので、Visual StudioでWindowsのコンソールプログラムを作り、出力をExcelでグラフ化してみた。

デジタルフィルタの方式が変わっても、インターフェイスは変わらないようなので、

#define LOOP    (2)
#define PERIOD  (50)

int _tmain(int argc, _TCHAR* argv[])
{
    filter1Type* filter = filter1_create();

    printf("Sample\tInput\tOutput\n");
    int count = 0;
    for (int i = 0; i < LOOP; i++) {
        float in = 1.0f;
        for (int j = 0; j < PERIOD / 2; j++) {
            filter1_writeInput(filter, in);
            float out = filter1_readOutput(filter);
            printf("%d\t%f\t%f\n", count, in, out);
            count++;
        }
        in = 0.0f;
        for (int j = 0; j < PERIOD / 2; j++) {
            filter1_writeInput(filter, in);
            float out = filter1_readOutput(filter);
            printf("%d\t%f\t%f\n", count, in, out);
            count++;
        }
    }

    return 0;
}

というコードで矩形波を入力してフィルタ応答を出力してみた。

移動平均


一番かんたんなLPFで実装が楽で高速。パラメータは前の値を保持しておくバッファ長のみ。


横軸が時間で、縦軸が出力値。かんたんなだけあって過渡応答も線形。

FIR(Lth Band Filter)


フィードバックなしのデジタルフィルタ。フィードバックしないので安定的で発振しない。カットオフ周波数がサンプリング周波数の1/Nに限定される。


スマホのファンクションジェネレータ等、デジタル機器の矩形波出力によく似た応答だと思う。

IIR(バターワース特性)


フィードバックありでアナログフィルタに近い応答をする。設計をミスると発振する。


Orderが4の場合の過渡応答で、4次LPFに相当すると思う。FIRに比べるとアナログ回路で見慣れた波形。

Orderを1にしてみる


Orderを1にした場合は、多少きれいすぎるがCRの1次LPFの過渡応答にそっくりさんだ。

Github:
https://github.com/ryood/DigitalFilterTest

少し触っただけだが、デジタルフィルタについてほとんど知識がなくても使えた。←画面に出てくる「Z-Plane」や「Transfer Fuction」が何なのかわからないレベル(^q^;

ゼロや極で特性を決めることもできるようだ。←これは制御工学でやったので名前だけは知ってるレベル(^q^:

生成されるコードは、標準Cの他に、ARMのCMSISのライブラリを使ったものも出力できる。(IIRだとオプションでBuiquadsをDirect Form1にしてやる必要がある。)

「ARM + CMSIS」で生成されたコードを見ると

float32_t filter1_coefficients[10] =
{
// Scaled for floating point

    0.0979448726126829, 0.1958897452253658, 0.0979448726126829, 0.7973802425733677, -0.17423867505153404,// b0, b1, b2, a1, a2
    0.125, 0.25, 0.125, 0.8219434348269887, -0.34174007022989955// b0, b1, b2, a1, a2

};

//<中略>

 void filter1_init( filter1Type * pThis )
{
    arm_biquad_cascade_df1_init_f32(    &pThis->instance, filter1_numStages, filter1_coefficients, pThis->state );
    filter1_reset( pThis );

}

//<中略>

 int filter1_filterBlock( filter1Type * pThis, float * pInput, float * pOutput, unsigned int count )
{
    arm_biquad_cascade_df1_f32( &pThis->instance, pInput, pOutput, count );
    return count;

}

となっていてフィルターの演算はCMSISにまかせている。もしかしたらDSP付きのARMならDSPを使うようになってるのかもしれない?

また、標準Cでもfloat型だけではなく整数型(固定小数点型)のコードも出力してくれるようだ。FPUが付いていないCoretex-M0やM3で演算速度を上げたい場合にも使えるかも?

メモ:


デジタル的な波形をアナログチックにするために、(1- e^(-t/τ))みたいな関数を使って変換しようかと漠然と考えていたが、この用途にはIIRが使えるかもしれない。

多分IIRの方が速度的に有利な気がする。積分を数式で解くのはしんどいが、コンピューターを使って数値積分すれば近似的に解けるみたいな。

エンベロープ波形をMPU内部でアナログチックにするのに一度使ってみようか?

2015年11月20日金曜日

リズムマシン デジタルフィルタ処理

リズムマシンのメイン基板のPSoC 5LPにデジタルフィルタの処理を追加してみた。

今のところ8kHzのサンプリング・レートでやっている。

サンプリング間隔のうちどれぐらい時間がかかっているかオシロで見てみた。

PSoC Creaatorのプロジェクト
https://github.com/ryood/RhythmMachine/tree/master_DFB_test/Master_PSoC5LP_Test/PSoC/Sequencer_Master/Sequencer_Master_PSoC5LP_ProtoKit_HD44780.cydsn

波形生成の処理時間


ch1:ISR_Check ch2:Timer_Sampling_TC

ch2はサンプリング周期でパルスを発生させて補足したもの。ch1は波形生成処理の前後でH/Lさせている。

サンプリング周期は0.126ms(126us)で波形生成は60.400us。8kHzだと約半分で処理が完了しているようだ。

プログラムはほとんど最適化していないので最終的にはサンプリング周波数をもう少しあげられるかもしれない。

デジタル・フィルターの処理時間



ch1:ISR_Check ch2:Ext_Check

ch2はデジタル・フィルタの処理の前後でH/Lさせたもの。2usで済んでいるようだ。

メモ:


  • 8kHzのサンプリング周波数だとカットオフ周波数は4kHzに制限される。ナイキスト周波数だからしかたない。ノイズにHPFをかけてみたがかなり変な音になってしまった(^q^;
  • PSoC 5LPのFilterコンポーネントは実行時にパラメータをいじれないようだ。カットオフ周波数ぐらいは変化させたかったので残念。
  • 自力でDFBをいじればできるかもしれないが、DSPプログラミングはやったことがないので保留。BlackFinをいじってからまた考えよう。
  • フィルターをCPUでプログラミングすればパラメータをいじれそうだが、確実に小数点演算なので実行時間がどれ位かかるか・・・
    →固定小数点演算でできれば現実的な範囲かな?


2015年11月17日火曜日

PSoC 5LPのデジタル・フィルタを使ってみる CPUで波形生成

今作りかけのリズムマシンのWhite Noiseで作っている波形にフィルターをかけたいのでデジタルフィルタをもう少しやってみた。

デジタルフィルタなんてMatlabでもやったことがないし(あ?やったかな?覚えてない(^q^;)手探り状態ですが、PSoCのFilterコンポーネントはz変換とか行列すらも出てこないので見た目通りに試してみた。

前回やったExampleでは外部入力された波形をFilterで加工しているが、リズムマシンはCPUで波形を作っているのでCPUからFilterを通さないといけいない。

サンプリング間隔ごとに逐次波形を計算しているのでDMAは不要だ。(←とおもう)

PSoC Creatorのプロジェクト
https://github.com/ryood/PSoC_5LP_DigitalFilter_Test


TopDesign


CPUで波形を生成して、「Filter」コンポーネントを通して「VDAC8_1」と「Opamp_1」のボルテージフォロワを通して出力する。

「VDAC8_2」と「Opamp_2」はフィルターを通す前の波形の出力用。

「Timer」はサンプリング周波数で割り込みをかけるものだ。

「Pin_Timer_TC」はタイマーがオーバーフローした時(サンプリング間隔で)にパルスを発生、「Pin_ISR_Check」は割り込みルーチン内のタイミング計測用だ。

FilterのConfigureダイアログ


前回やったExampleからFilter TypeをHigh Passに、Cutoffを8kHzに変更した。

ソースコード

 #include <device.h>  
 #include <VDAC8.h>  
 #include <stdlib.h>  
 volatile uint8 cnt = 0;  
 CY_ISR(Timer_interrupt_handler)  
 {  
   uint16 v, fv;  
   /* Read Status register in order to clear the sticky Terminal Count (TC) bit   
      * in the status register. Note that the function is not called, but rather   
      * the status is read directly.  
      */  
       Timer_STATUS;  
   cnt++;  
   v = rand() % UINT16_MAX;  
   // Filterをかける前の波形を出力    
   VDAC8_2_SetValue(v >> 8);  
   Pin_ISR_Check_Write(1u);  
   Filter_Write16(Filter_CHANNEL_A, v);  
   /* Poll waiting for the holding register to have data to read */  
   while (Filter_IsInterruptChannelA() == 0) ;  
   fv = Filter_Read16(Filter_CHANNEL_A);  
     Pin_ISR_Check_Write(0u);  
   VDAC8_1_SetValue(fv >> 8);  
 }  
 int main()  
 {  
   /* Start all components used on schematic */  
   VDAC8_1_Start();  
   VDAC8_2_Start();  
   Opamp_1_Start();  
   Opamp_2_Start();  
   Filter_Start();  
   Timer_Start();  
   ISR_Timer_StartEx(Timer_interrupt_handler);  
     /* Enable the interrupt register bit to poll  
    Value 1 for Channel A, Value 2 for Channel B */  
   Filter_INT_CTRL_REG |= (1 << Filter_CHANNEL_A);  
   CyGlobalIntEnable;  
   for(;;)  
   {  
     //CyDelay(10);  
   }  
 } /* End of main */  


FilterをCPUから直接アクセスするにはFilter_Write**()とFilter_Read**()というAPIを使えば済むようだ。 ※**は引数のデータ型

rand()関数でWhite Noiseを作ってHPFを通してみた。

出力波形

PCのWavegeneでFFTしてみた。

Filterに入れる前

Filterを通した後

実行時間


Filterの演算が終わるまでCPUがWaitしているのでどれぐらい時間がかかっているか見てみた。


ch1:Pin_ISR_Check ch2:Pin_Timer_TC

Master_Clockを74.7MHzに設定。サンプリング周波数48kHz。

PWはデューティーの+側の時間で2.800us。周波数にすると357kHzぐらいだ。

メモ:


  • Filterの設定の「Filter gain:」を「1」にするとほとんどFilterが効かなくなる模様
  • PSoC 5LP Prototyping Kitで使われているCY8C5888LTI-LP097は最大クロックが80MHzだが内蔵クロックを使うとうまく設定できない。(クロックの誤差で80MHzを超えるため)
  • PSoC 5LPはPSoC4にくらべるとかなり強力。Cortex M0とCortexM3の差+UDBいっぱい+DFB+メモリもいっぱい(^q^/

2015年11月16日月曜日

PSoC 5LPのデジタル・フィルタを使ってみる

ExampleのFilter_ADC_VDAC_pollをやってみた。

TopDesign


デルタ・シグマADCで入力を受けて、DMA経由でFilterコンポーネントに送り、VDAC8で出力する。
vdda/2とOpampで仮想グランドを作っているようだ。これは便利に使えるかも?

ブレッドボード図



TopDesignの通りブレッドボードで回路を組んで、自作の矩形波だけのファンクションジェネレーターで矩形波を出力してPCのWaveSpectraでFFTしてみた。

入力波形(100Hz)


出力波形(100Hz)



出力波形(500Hz)



出力波形(1000Hz)


出力波形(2000Hz)


出力電圧が低くてオーディオインタフェースの入力ボリュームをかなりあげて測定した。

6kHzのLPFなのでFFTのグラフを見るとだいたい6kHzあたりで減衰しているようなのでLPFは効いていそう。

ソフト・オシロだとややこしいので(測定できるまで結構悩んだ)やっぱりそろそろAnalog Discoveryがほしいな~(^q^;

デジタルフィルタの使い方はまだいまいちよくわかってないけど中身はDSPらしい。フィルターはプログラムでやるとかなりCPU時間を食いそうなので、使えたら使ってみたい。