1.標本化、量子化
2.離散フーリエ変換
3.ディジタルフィルタ
2.EZ-LABの奥に直流安定化電源を配置する。
3.EZ-LABの右横にファンクションジェネレータを配置する。
・オレンジ色のマークのついているプローブをCH1に取り付け、オシロスコープの測定モード(各CHの横のレバーAC、GND、DC)をGNDにしてGNDの位置を分かりやすいところに調節する。
・特に指定のない限り、測定モードはDCとする。
・測定状況(時間レンジ、電圧レンジ、測定モード)は必ず記録しておく事。
1.EZ-LABから直流電源への接続線の直流電源側をはずし、直流電源とACコンセントを接続する。
2.直流電源をオンにし、直流電源をそれぞれ+5V、−12V、+12Vに設定する。
EZ-LAB 直流電源 −−−−−−−−−−−−−−−−−−−−−−−− 黒 DGND GND(+6Vの側) 茶 AGND COM 赤 +5 +6V(5Vに設定) 橙 +12 +(+12Vを設定) 緑 −12 −(−12Vを設定) 黄 未接続 未接続4.RS-232Cケーブルを使用してホストPCとEZ-LABを接続する。 5.直流電源とコンピュータの電源を入れる。
1.コンピュータとディスプレイの電源を切る。
2.測定器類、直流安定化電源の順に電源を切る。
3.直流安定化電源から電源ケーブルをはずす。
5.EZ-LABボードとRS-232Cケーブルを指定された場所に片づける。
として、コンパイルしなさい。
/* DSPボードを使用するためのヘッダーファイルの読み込み */ #include<21020.h> /* FLAG0のプッシュボタンスイッチが押されるまで待つ */ poll_flag_in(READ_FLAG0、FLAG_IN_LO_TO_HI); /* FLAG0のプッシュボタンスイッチが離されるまでまで待つ */ poll_flag_in(READ_FLAG0、FLAG_IN_HI_TO_LO); /* LED1をオンにする */ set_flag(SET_FLAG1、SET_FLAG); /* LED1をオフにする */ set_flag(SET_FLAG1、CLR_FLAG); /* LED1をオンからオフ、オフからオンにトグルする */ set_flag(SET_FLAG1、TGL_FLAG);
/* 割り込み処理を使用するためのヘッダーファイルの読み込み */ #include<signal.h> /* timer_set(引数1、引数2)は、タイマー割り込み間隔を与える。引数1と引数2は同じ値を与える。 */ timer_set(33000000、33000000); /* 1秒間隔の割り込み */ timer_set(33000000/64000,33000000/64000); /* 1/64000秒間隔の割り込み */ /* 割り込み信号と実行する関数名の設定 */ interrupt(SIG_TMZ0、timer_isr); /* タイマー割り込みの開始 この宣言以降、timer_setで設定された時間間隔で、interruptで指定されたtimer_isr関数が実行される */ timer_on(); while(1); /* 割り込みのための無限ループ */ /* timer_isrの使い方 例えばLED1をトグル動作させるには */ void timer_isr(int interrupt_number) { set_flag(SET_FLAG1、TGL_FLAG); }
LED3 〇 〇 〇 〇 ● ● ● ● LED2 〇 〇 ● ● 〇 〇 ● ● LED1 〇 ● 〇 ● 〇 ● 〇 ● −−−−−−−−−−−−−−−−−−−−−−− 0→1→2→3→4→5→6→73つのLEDの取り扱いは、以下の関数を参考にしなさい。LEDのオフ、トグル動作については、【課題1】のCLR_FLAG、TGL_FLAGを使う。
/* turn on LED1 */ set_flag(SET_FLAG1、SET_FLAG); /* turn on LED2 */ set_flag(SET_FLAG2、SET_FLAG); /* turn on LED3 */ set_flag(SET_FLAG3、SET_FLAG);
与える16進数(32bit) vout_aの出力電圧 0xff000000 +4.0[V] 0x80000000 +2.5[V] 0x00000000 +1.0[V]の関係がある。AD7769のDA変換においては、与えられた32bitデータの上位8bitが有功となる。また、AD7769の出力は、次の値が書き込まれるまで、以前の値を保持している。(0次ホールドと呼ぶ)。
付録リスト1の説明
AD7769の出力端子vout_a、vout_bは、出力電圧範囲が+1.0[V]〜+4.0[V]であるため、cos波の負の値をそのまま出力 することはできない。そこで、付録リスト1の@の個所に示すようにcos波の値(buf[datano])に0x80000000(+2.5 [V]に相当)を加えて、出力電圧を+1.0[V]〜+4.0[V]になるようにしている。(最大0x80000000+0x7f000000 =0xff000000。0xff000000は+4.0[V]。最小0x80000000-0x7f000000=0x01000000。0x01000000は+1.0[V]。 ただし、最小電圧は正確に1.0[V]とはならない)また、cos波の値は、毎回計算させずに初期に1周期分 (64個で1周期になるように設定。したがって、1周期=1/64[msec]×64個=1[msec]、すなわち1[kHz]のcos波 としている)をbuf[datano]に蓄えておき、繰り返し用いることで連続的に出力している。
8bitの場合、付録リスト1の@の個所を
vout_a=0x80000000+buf[datano];とすれば、DSPボードのvout_a端子に元のcos波、vout_bに上位8bitの場合のcos波電圧が出力される。 buf[datano]&0xff000000とすると、buf[datano]と0xff000000との論理積が求まる。すなわち、 buf[datano]の上位8bit(16進数のffは2進数で11111111であるから8bit分の論理積)が取り出せれることになる。 同様にして、2、4、6bitの場合、0x??000000の??の部分をいくらにすればよいか考え、
vout_b=0x80000000+(buf[datano]&0xff000000);
vout_b=0x80000000 +(buf[datano]&0x??000000);として、オシロスコープで波形を観測し、概略をスケッチしなさい。
出力は、DSPボードのvout_aに元の波形、vout_bに振幅スペクトルを出力しているので、オシロスコープ のCH1にvout_aを、CH2にvout_bを接続して観測、スケッチを行いなさい。付録リスト2においてFFTを行う矩形波は 、0〜0.5[ms]において+1.0[V]、0.5[ms]〜1.0[ms]において-1.0[V]としている。
付録リスト2の説明
make_buf()関数で、矩形波を生成。Rect_buf[I]に電圧値を代入、buf[I]にオシロスコープ表示のためのスケーリン グ(オシロスコープ上ではあたかも1.0[V]と4.0[V]の矩形波で表示される)
rfft64(x、rx、ix)関数は、64点FFTと呼ばれ、入力信号系列x(n);n=0、1、2、……、63 を配列x[64]にいれておき、以下に述べるFFTを行い、計算結果(実数rxと虚数ixが計算せれる)がrx[64]、ix[64] に返される。この関数の結果(rxおよびix)を用いて、入力信号系列x(n)の振幅スペクトルX(k)は、
で計算される。ただし、プログラム中では、オシロスコープに表示するためのスケーリングを行っているので、 表示された振幅と計算結果の値は異なる。
フーリエ変換と逆フーリヘ変換
フーリヘ変換とは、対象とする信号がどのような周波数の分布になるのかという周波数特性を解析する手法である。 元のアナログ信号をx(t)とすれば、そのフーリエ変換X(ω)は、
と表わされる。ただし、ω=2πf。この式は、信号の周波数が、時間軸上の−∞から∞まで観測されないと決定され ない、ということを表している。また、元のアナログ信号x(t)は、そのフーリエ変換X(ω)を用いて、
と表わされ、可逆な変換となる。これをフーリエ逆変換と呼ぶ。この式では、周波数に正の周波数と負の周波数が存 在し、信号の時間変化は、周波数軸上の−∞から∞まで既知でないと決定されない、ということを表している。 実際には、負の周波数は観測されず、負と正の周波数が合成されて観測される。また、正負が対称となっている関係 から周波数の折り返しと呼ぶ。例えば、図1(a)に示す波形のフーリヘ変換は、図1(b)に示すようになる。また、 フーリヘ逆変換により、図1(b)から図1(a)に戻る。
DFTとFFT
ディジタル信号x(n)は、アナログ信号x(t)をサンプリング間隔Tで標本化した信号x(nT)で、時間的に飛び飛びの信号 となる。フーリヘ変換は、連続したアナログ信号x(t)の周波数解析に役立つ。一方、信号が時間的に飛び飛びである ディジタル信号に対しては、離散フーリヘ変換 (DFT:Discrete Fourier Transform)を用いることにより、周波数解析 が行える。このDFTは、周期系列x(n):n=0,1,2,3,……,N-1の離散信号を
である。ただし、WNは回転子と呼ばれ、と表わされる。 また、その逆変換である離散フーリエ逆変換(逆DFT)(IDFT:Inverse Discrete Fourier Transform)は、
となる。FFTは、高速フーリエ変換と呼ばれ、回転子の指数性、周期性を利用して、計算を高速化したものである。 同様に逆FFTは、逆DFTを高速化したものである。X(k)の絶対値|X(k)|を図示したものを振幅スペクトル、X(k)の位相 角∠X(k)を図示したものを位相スペクトルという。
volatile int vin_a segment(adc_a); /* ADC のvin_a端子の初期化 voltaile int vin_b segment(adc_b); /* ADC のvin_b端子の初期化 void main() { static int vin_a,input; input=vin_a; /* vin_a端子からの信号取り込み vin_a=input; /* 次入力のためのADC準備 }ファンクションジェネレータを用いて可変周波数のsin波をvin_aに入力し、FLAG0プッシュボタンによりサンプリン グを開始する。このサンプリングした信号を関数rfft64() を使用して、FFTの計算を行い、振幅スペクトルを vout_bに出力する。サンプリングした信号はvout_aに出力する。サンプリング周波数は64[kHz]、
timer_set((int)(33000000/64000)、(int)(33000000、64000));
入力のサンプル数はN=64としなさい。
まず、付録リスト3のプログラムを入力してみましょう。(この付録リスト3のプログラムが、FIR型ディジタルフィルタ (ローパスフィルタ)です。これだけでは、特性が分からないので、このリストに外部から信号を入力し、出力を 観測するプログラムを付け加えてあります。)次に、ファンクションジェネレータを+2.5[V]を中心に振幅が+1.0[V] 〜+4.0[V]になる正弦波を出力するように調整しましょう。この、出力を、DSPボードのvin_a端子に入力し、 ファンクションジェネレータの周波数を0.1[kHz]〜64[kHz]に変化させ、DSPボードの出力端子vout_aとvout_bを オシロスコープで観測し、それぞれ観測される波形の振幅電圧の値を周波数ごと (周波数間隔は後でグラフを書きやすい程度にしましょう)に記録しておきましょう。
フィルタについて
フィルタは、その周波数特性から、
の4種類に分類される。
一般に、フィルタの周波数特性を調べるためには、そのフィルタにインパルス関数(Δ関数)を入力し、 その出力特性を調べることでそのフィルタの特性が分かる。これは、インパルス関数が様々な周波数を 一様に持っていることから、その出力(インパルス応答)を解析することにより、すべての周波数に対する応答を 一度に観測できるためである。
ディジタルフィルタは、そのインパルス応答の長さから、インパルス応答長が有限の有限インパルス応答フィルタ (Finite Inpulse Response Filter: FIR型フィルタ)と、インパルス応答長が無限の無限インパルス応答フィルタ (Infinite Inpulse Response Filter: IIR型フィルタ)とに分類される。図3にFIR型フィルタとIIR型フィルタの構成 について示す。図中のz−1は遅延素子、+は加算器、∇は乗算器、a、bは乗数を表わす。
【課題1】コメント付きの作成したプログラム
【課題2】コメント付きの作成したプログラム
【課題3】コメント付きの作成したプログラム
【課題4】コメント付きの作成したプログラム
【課題5】コメント付きの作成したプログラムと観測波形のスケッチ
【課題6】オシロスコープ観測波形のスケッチ
【考察6】プログラムで使用した矩形波の理論的なDFT解析結果を求め、スケッチとの比較を行いなさい。
【課題7】コメント付きの作成したプログラム
【考察7】外部入力波形のスケッチとFFT後の観測波形スケッチ、理論的考察を行いなさい。
【課題8】オシロスコープ観測波形のスケッチ
【考察8】課題8で用いたディジタルフィルタの周波数特性を測定データからおおよそ求めなさい。
余力のある人へ
【考察9】課題8では、ローパスフィルタ(次数7のFIR型)を例として示したが、次数の異なるFIR型フィルタや、ハイパスフィルタの作成について考察してみなさい。
/* 必要なインクルードファイルの読み込み */ #include<21020.h>; #include<signal.h>; #include<macros.h>; /* initialization for 8bit ADC and 8bit DAC、 AD7769 */ volatile int vout_a segment(dac_a); volatile int vout_b segment(dac_b); /* 関数名の宣言 */ void timer_isr(int); void process_input(int); void make_buf(); int buf[64]; /* 出力波形データバッファ */ int datano=0; /* 出力データ番号の初期化 */ void main() { make_buf(); /* cos波データの作成 */ timer_set(33000/64,33000/64); /* 1/64[msec]間隔のタイマ割り込み */ interrupt(SIG_TMZ0,timer_isr); /* 割り込み処理関数名の設定 */ timer_on(); /* 無限ループ * while(1); } void timer_isr(int interrupt_number) /* 割り込み処理ルーチン */ { vout_a = 0x80000000 + buf[datano]; /* @ vout_a端子への出力 */ datano=(datano+1) & 63; /* バッファラベルの更新 */ } void make_buf() /* cos波形の生成 */ { int i=0; for (i=0 ; i<64 ; i++) /* 64個分のデータをバッファに記憶 */ buf[i] = cos(3.14159265*2*(float)i/64)*0x7fff0000; /* +1.0[V]〜+4.0[V]になるように調整 */ }
付録リスト2
#include<21020.h>; #include<signal.h>; #include<macros.h>; #include<trans.h>; /* volatile は、処理系による最適化を行わないよう指示する */ volatile int vout_a segment(dac_a); volatile int vout_b segment(dac_b); void timer_isr(int); void process_input(int); void make_buf(); float rect_buf[64]; float real_buf[64]; float imag_buf[64]; int buf[64]; int buf_b[64]; int da_ptr=0; void main() { int i; timer_set(33000/64,33000/64); interrupt(SIG_TMZ0,timer_isr); make_buf(); rfft64(rect_buf,real_buf,imag_buf); /* 64点FFT関数 */ for(I=0;I<64;I++) buf_b[I]=(int)(sqrt(real_buf[I]*real_buf[I]+img_buf[I]*img_buf[I]) *0x7fff0000*0.1)+0x40000000; timer_on(); while(1); void timer_isr(int interrupt_number) { vout_a = buf[da_ptr]; vout_b = buf_b[da_ptr]; da_ptr = (da_ptr+1) & 63; } void make_buf() { int i; /* 矩形波の生成 */ for(i=0;i<;32;i++) rect_buf[i]=1.0; for(;i<;64;i++) rect_buf[i]=-1.0; /* 矩形波を画面に表示するためのスケーリング */ for(i=0;i<;64;i++) buf[i]=(int)((rect_buf[i]*0x7f000000)); }
付録リスト3
#include<21020.h>; #include<signal.h>; #include<macros.h>; #include<trans.h>; #include<math.h>; volatile int vin_a segment(adc_a); volatile int vin_b segment(adc_b); volatile int vout_a segment(dac_a); volatile int vout_b segment(dac_b); void timer_isr(int); void main() { timer_set((int)(33000000/100000),(int)(33000000/100000)); interrupt(SIG_TMZ0,timer_isr); timer_on(); while(1) idle(); } void timer_isr(int interrupt_number) { static int vin_old; static int vin_now; static int x[8],out,i; static float w[8]; static float y; w[0]= 0.03489755821785150; w[1]=−0.01098301946252854; w[2]=−0.06286453934951963; w[3]= 0.223907720892568; w[4]= 0.556856993531445; w[5]= 0.357976304997285; w[6]=−0.02390027056113145; w[7]=−0.07594096379188282; for(i=6;i>=0;i--) x[i+1]=x[i]; x[0]=vin_a-0x80000000; vin_a=x[0]; y=0; for(i=0;i<8;i++) y+=x[i]*w[i]; out=(int)y; vout_a=x[0]+0x80000000; vout_b=out+0x80000000; }
付録4 EZ-LABの電気特性
アナログ入力
8-bit A/D 入力 : 0.0 〜 5.0 V マイクロフォン入力 : 100 mV p-p ライン入力 : 2.8 V p-p
アナログ出力
8-bit D/A 出力 : 1.0 〜 4.0 V スピーカー出力 : 6.0 V p-p ライン出力 : 2.0 V p-p
C言語
ANSI C 言語辞典 Page 259 volatile