巷にあるデジタルフィルタの書籍では周波数特性や位相特性に重きを置いたものは
沢山あるけれども、セトリング特性に関する記述はあまり見掛けないように思う。
異常検出など、セトリング特性が大事な用途もあるので簡単に使えるものを書いておくのも良いかなと、ここに紹介しておくことにした。
温度や電圧などを A/D 変換器で取り込むときに雑音低減のために簡易なデジタルフィルタをかけたいことがよくある。
異常検出用途などでは、オーバーシュートが発生せずリアルタイム処理に向いていて、
また、組み込み用プロセッサでは処理能力の余裕が少ないので、演算量や使用する変数が少ない方式が望ましい。
デジタルフィルタには様々な方式のものがあるが、ここでは必要な変数領域が少なく
除算が不要な 2次 あるいは 3次の IIR (Infinite Impulse Response) LPF (Low Pass Filter) を、
状態変数フィルタ(State variable filter) *fig.4 等の過渡応答から直接変換して実現した
ものを紹介する。下にダイアグラム*fig.1 とそのプログラム例を示す。
fig.1 2次 IIR LPF ダイアグラム (状態変数型)
Listing.1 Cプログラム例 (状態変数型)
float iirlpf(in, reset) float in; int reset; { float t; static float d1, d2; static float k = 0.125; /* 0 < k < 1 */ if (!reset) { t = d1; d1 += (d2 - in) * k; d2 -= (t + d2 * 2.0) * k; /* Q = 0.5 */ return d2; }else{ d1 = -2.0 * in; d2 = in; return d2; } }この例では浮動小数点演算を行っているが、プログラム中の乗算箇所は時定数 k を 2の倍数、例えば 1/8 に選ぶことにより整数演算版にも簡単に修正できるはずである。
fig.2 は上述のデジタルフィルタの過渡応答の例である。 オーバーシュートが発生していないのが見てとれる。また、fig.3 のアナログ フィルタの過渡応答とほぼ同等な過渡応答になっていることも分かる。
fig.2 2次 IIR LPF のステップレスポンス
fig.3 は、変換元のアナログフィルタ(fig.4) の過渡応答特性の SPICE シミュレーション例である。 Q = 0.5, 自然周波数 ωn = 2/3 に選んである。
fig.3 2次 状態変数型 LPF のステップレスポンス
参考のため、 2次の状態変数型アクティブフィルタの回路例を fig.4 に示す。 各積分器のコンデンサの電圧が IIR デジタルフィルタでのレジスターの値に 相当する。
fig.4 2次 状態変数型フィルタ
fig.5 は、「1/f雑音生成アルゴリズム」で紹介している アルゴリズムで生成したピンクノイズと、それに 2次 IIR LPF をかけた波形を表示している。
Run PinkNoise/IIR filter Demo [5kB, Java Web Start]
![]()
fig.5 ピンクノイズと LPF 出力波形 (k=0.250)
fig.1 は、状態変数型フィルタから変換したものであったが、 バイカッド型フィルタ (Bi-quad filter) *fig.8 から変換することもできる。 そのダイアグラムを fig.6 に示す。
fig.6 2次 IIR LPF ダイアグラム (バイカッド型)
Listing.2 Cプログラム例 (バイカッド型)
float iirlpf(in, reset) float in; int reset; { float t; static float d1, d2; static float k = 0.125; /* 0 < k < 1 */ if (!reset) { t = d1; d1 -= (d1 * 2.0 + in - d2) * k; /* Q = 0.5 */ d2 -= t * k; return d2; }else{ d1 = 0.0; d2 = in; return d2; } }
fig.7 は、変換元のアクティブフィルタ *fig.8 の過渡応答特性の SPICE シミュレーション例である。Q=0.5, 自然周波数 ω=2/3 に選んである。 バイカッド型の場合、出力段は完全積分回路なので、即ちその前段は 出力の微分になっている。出力の変化が知りたい時などには便利であるし、 初期値を0とすれば良いのも便利な点である。
fig.7 2次 バイカッド型 LPF のステップレスポンス
fig.8 2次 バイカッドフィルタ
…実は 2次フィルタを Q = 0.5 でしか使わないのであれば1次 のフィルタのカスケード接続の方が簡単にできる。
fig.9 2次 IIR LPF ダイアグラム (1次×2段)
Listing.3 Cプログラム例 (1次 LPF 2段カスケード)
float iirlpf(in, reset) float in; int reset; { static float r1, r2; static float k = 0.125; /* 0 < k < 1 */ if (!reset) { r2 += (r1 - r2) * k; r1 += (in - r1) * k; return r2; }else{ r2 = r1 = in; return r2; } }
このままでは特に面白いところも無いので 12 bit 程度のシステム用に若干(100 ppm 程度)の セトリング時の振幅リプルを許容してセトリング特性を改善した 3次 LPF を、伝達関数の係数を直接指定して設計してみた。
各係数はハードウェア化が容易になるように係数の除算が 2 の冪になるようにしている。 fig.10 に、帰還係数 k = 1 / 256 の場合の特性例を示す。k= 1 / 256 の場合、ステップ入力に対し、1908 tick 後に 100 ppm、3351 tick 後に 10 ppm、3754 tick 後に 1 ppm 以内にセトリングしている。
周波数特性はベッセル特性的ななだらかな特性となる。 サンプリング周波数 fs = 20 kHz のとき カットオフ周波数 fc は約 8.86 Hz となる。
fig.10 3次 IIR LPF の特性例 (k = 1/256)
[Prog.4 Cプログラム例 ( 3次 振幅リプル有り、高速セトリング )]
double iirlpf3(double in, double k, int reset) { double f, k; static double r1, r2, r3; const double a = 3.0; const double b = 7.0 / 2 - 1.0 / 128; const double c = 3.0 / 2; if (!reset) { f = r3; r3 += (r2 - a * f) * k; r2 += (r1 - b * f) * k; r1 += (in - f) * c * k; return r3; }else{ r1 = in * b; r2 = in * a; return r3 = in; } }
fig.11 は、アナログ回路で状態変数型アクティブ LPF を構成した場合の回路図である。 2次の状態変数型を 3次に拡張したものである。
fig.11 3次 状態変数型フィルタ
伝達関数
この回路はダイナミックレンジやオペアンプの個数、安定度等の問題もあり、実際に 使用される事は少ないと思うが、この構成の回路例の SPICE シミュレーション結果を fig.12 に載せておく。
IIR フィルタとアナログフィルタのシミュレーション結果で過渡応答に違いが見られるのは E24 系列に丸めた素子値に係数の違いや、 オペアンプの特性の話もあるが、本質的なところでは、 IIR フィルタが積分の 0次の近似で構成されているためというのも大きい。 サンプリングレートが低い場合には誤差が増大して違いが顕著になる。
fig.12 3次 状態変数型 LPF のステップレスポンス
fig.13 3次 状態変数型 LPF の周波数特性
3次状態変数型フィルタ
清水さんの xmbmon-2.04 - このプログラムではバイカッド型 LPF*fig.6 を使用している。