TNJ-052:LTspice でやってみるデジタル・フィルタ解析(前編)平均化フィルタの周波数応答と連続信号・離散信号
はじめに
これまで使っていなかったLTspice。リニアテクノロジーとの統合により、晴れて使えるようになり、学習しながら/探究しながら何とか使いつつも、最近は逆に「どうすれば変な(?)テクニックを編み出せるだろうか」などと、怪しい方向に走りつつあります(笑)。
今回の技術ノートでは、ΣΔADC で使われているsinc フィルタ(cardinal sine function filter)がどんなもので、そしてその周波数応答特性を、どうすればLTspice を用いてシミュレーションできるのかについて検討をしてみます。また今回編み出した怪しいLTspice テクニック(?)もご紹介していきたいと思います。なお次回は、ΣΔADC で用いられている、「sinc フィルタに見えない」sinc フィルタを探究してみます。
デジタル・フィルタの理論的考え方
デジタル・フィルタは図1 のように、遅延させた離散時間ごとの各数値を演算して、入力値から出力値としての数値伝達関数で「フィルタ」を実現するものです。
この図は4 タップのFIR(Finite Impulse Response; 有限インパルス応答)フィルタとよばれるものです。
すべては(たとえばAD コンバータ)でサンプルされた定時間間隔ごとのサンプル数値となっています。このサンプル数値を各タップ[「タップ」とは数値取り出し位置のことを示します。水道の蛇口も英語では「タップ」と呼び、学校の校庭にある水のみ場の複数の蛇口(図2)をイメージしてもらうと良いです]ごとに、ある定数(これを「タップ係数」と呼びます)と乗算し、それらを足し合わせることによって、フィルタ出力を得るものです。


すべて定時間間隔でということなので、この図の一番左側の1タップ目についても時間遅延ボックスの出力から出てきているものと考えることもできます。現実的にこの各段の時間遅延ボックスは、デジタル回路としてはデータがラッチされたフリップ・フロップ出力として考えることができます。ソフトウェアならメモリ上に並んでいるデータという感じでしょうか。
FIR フィルタのタップ係数を一定にしたものが平均化フィルタ
株価の変動や企業業績を分析したりするときに「移動平均」というものを用います。これはたとえば「ある日を基準として、その日までの過去5 日間(稼働日で考えました)の数値を平均化して、基準日を変えて(横軸として)グラフとし、数週間から数ヶ月オーダの変化トレンドを見るというものです。
エンジニアらしく、これを式で書いてみると、
と表すことができます。また和記号で表せば、
となりますが…、こんなかたちで別に難しく考えることもなく、この移動平均という操作は、図1 のFIR フィルタにおいて各タップのタップ係数を1にしてあるものと全く同じです[式(1)、式(2)は「平均」ということで0.2倍していますが]。
つまり移動平均というものはFIRフィルタなわけです。そしてこの移動平均というものは、ここまでの説明から構成がお分かりになるとおり、平均化フィルタとなります。つまり平均化フィルタはFIRフィルタなのですね。以降は「平均化フィルタ」として説明していきます。とはいえこれがsincフィルタなのですが…。
LTspiceで平均化フィルタの周波数応答特性を得る
LTspiceを使って、この平均化フィルタの周波数応答特性をどうすれば得ることができるでしょうか。ここでは二つのアプローチを考えて行きたいと思います。なお、以降で紹介するものにタップ係数を加えるだけで、FIRフィルタやIIR(Infinite Impulse Response; 無限インパルス応答)フィルタの周波数応答特性もシミュレーションすることができます。
直球でBモデルのDELAY関数を利用して計算する
LTspiceには便利に使えるBモデルというものがあります。これは「Arbitrary Behavioral Voltage or Current Sources」というものです。ここではいろいろな関数を定義することができて、
delay(x,t)
で信号遅延を作ることができます。ここでxはいずれかのネットの信号(電圧でも電流でも可)、tは遅延させる時間です。


これで4タップの平均化フィルタ(話しを株価に戻せば、4日間の株価変動を移動平均したもの)を構成したものを図3に示します。時間を1, 2, 3, 4として4タップに相当する時間遅延をさせ、その周波数応答特性をみてみるというものです。
シミュレーション結果を図4に示します。おのおののdelay関数の遅延時間(サンプリング間隔)は1secです。これはサンプリング周波数1Hzに相当しますので、サンプリング定理と同じように、ナイキスト周波数0.5Hzで折り返しが生じ、1Hzごとにそれが繰り返されています。あとで説明していきますが、これがsinc関数の特性になっています(より厳密には、折り返しがあるので、sinc関数そのものではありませんが)。
怪しいテクニックを使って計算する(その前処理)
以降が「今回編み出した怪しいLTspiceテクニック」といえるものです(笑)。こんなことをLTspiceでやる人は世界中でもほとんど居ないでしょう…(汗)。
これを説明すると長くなりますので、実際の詳細計算は次の節にゆずり、ここではその計算のために必用な知識を確認しておきましょう。
図1で各タップ係数を1としたものが平均化フィルタなわけですが、この遅延は、図3で示したdelay関数と同じものとなります。これをZ変換というもので、図5のように表すことができます。図5は図3で示した4タップの平均化フィルタに相当します。ここでz-1というものが、1タップの遅延(図3とすれば1secの遅延)に相当します。
1タップの遅延時間を𝑇、入力信号の時間軸波形を𝑔(𝑡)とすると、この1タップ遅延回路出力の時間軸波形は
この出力の周波数スペクトルは「ラプラス変換の推移則」というもの
を使って、
として表すことができます。式(3)の右辺、式(4)の左辺は時間遅延に相当し、式(4, 5)の右辺はラプラス変換された式です。は ラプス変換対を意味します。 これら右辺の変数「𝑠」は、ここでは難しいことを考えずに、角周波数𝜔だとしてかまいません。式中では虚数単位𝑗を付加して𝑠=𝑗𝜔となります(かなり乱暴な展開ですがお許しを…。入力が定常状態の信号なので𝑠=𝑗𝜔としています)。また「𝑈(𝑡−𝑇)」はステップ関数というものですが、これはラプラス変換として有効な領域を示すだけのものなので無視すると、

- 𝑔(𝑡)の周波数スペクトルが𝐺(𝑠)=𝐺(𝑗𝜔)
- 𝑔(𝑡)を𝑧−1倍した𝑧−1𝑔(𝑡)は、𝑔(𝑡)を𝑇だけ時間遅延したもので
- この周波数(角周波数𝜔)スペクトルは式(4)の推移則からexp(−𝑗𝑇𝜔)𝐺(𝜔)となり、
- もともとの信号の周波数スペクトル𝐺(𝜔)に対して、出力はexp(−𝑗𝑇𝜔)倍されたものになる
- つまり𝑧−1という時間遅延は、exp(−𝑗𝑇𝜔)という周波数応答特性をもつフィルタに相当する
図5の式を以下に再掲しますが、
上記の説明から、このFIRフィルタの周波数応答特性𝐻(𝜔)を得るには、この式(6)に
として代入すればよいことになります。
ちなみにデジタル信号処理の教科書では、(正規化のため)𝑇=1としてexp(−𝑗𝜔)と表しています。実際の電子回路で実現するには、時間遅延はサンプリング・レートなどに影響されますので、ここではわざと式中に𝑇を入れてあります。
怪しいテクニックを使って計算する(Bモデルを使ってオイラーの公式で計算をする)
上記のことから平均化フィルタの周波数(角周波数)特性
は
として得られることになります。ようやくこれで計算するための基本式が得られることとなりました。
しかしexp(−𝑗𝑇𝜔)は複素数です…。LTspiceと少し格闘してみましたが、MATLABなどの科学技術計算ソフトと違い、複素数を直接取り扱える機能は無いようです。なお波形表示機能のほうでは複素数を一部取り扱えます。しかし今回の目的は実現できなさそうでした。
そこで以下のように分解してみました。オイラーの公式を使い、
このようにすると𝐻(𝜔)は
と分解でき、さらに
として考えることで、LTspiceで複素数を直接扱うことなく計算できそうなところまでたどり着きました。

「Bモデル+オイラーの公式」シミュレーション回路の動作
この考え方を用いて、図3の4タップの平均化フィルタ回路に相当する回路を構成したものを図6に示します。このシミュレーション回路について説明しておきましょう。
まず図5での遅延時間(サンプリング間隔に相当します)は、𝑇= 1secです。サンプリング周波数は1Hzになります。そこで2Hzまでシミュレーションできるようにしてあります。
「2Hz」とはいえ、シミュレーションは2 secのトランジェント・シミュレーションです。つまり時間軸です。ここにまず注目してみてください。
シミュレーションの結果として、周波数応答特性がシミュレーションできればいいわけですから、周波数(実際は角周波数𝜔)という変数を定義し、これをスイープ(掃引/変化)させていけばいいわけです。
そこで図6の信号源B9を、現在時間を示すパラメータTimeを用いて
V=2*PI*TIME
で角周波数𝜔を発生させるものとしてみました。
また図6にあるように、シンボルB1~B7のBモデルは電流出力にしてあります。それにより、𝐻𝑅𝐸𝐴𝐿(ω), 𝐻𝐼𝑀𝐴𝐺(ω)それぞれでタップごとの足し算に相当するぶんを、抵抗R1, R2(1Ω)に流れ込む複数の電流源として構成することができます。
最後にシンボルB8を使って式(12)の計算を行い、𝐻(ω)を得るようにしています。
シミュレーション結果を図7に示します。この結果は図4と同じになっていることが分かります。
平均化フィルタの周波数応答特性はsinc形状になっている
図4および図7の周波数応答形状は「sinc形状」というものになっています。ΣΔADCのデータシートでよく出てくるsincフィルタが、これらの図での周波数応答と同じものです。
sincフィルタの周波数応答形状は
という式で表されます。この形状を図7に重ね合わせてみましょう。この計算はLTspiceのWaveform Viewer上でAdd TraceからExpression(s) to addのダイヤログに式を記載することで実現できます。
ここでLTspiceの不思議なこと(?)に気が付きました。Bモデルを使ってのシミュレーションでは角度の単位はradian(弧度法)になっていますが、このWaveform Viewer上での計算式ではdegree(度数法)になっています…。図6のシミュレーションでは変数OMEGAを定義し、これをsin/cosの変数としていましたから、間違いなく弧度法になっていました…。


さて、ということで気を取り直して、
abs(4*sin(360*2*time)/(2*pi*2*time))
という式を設定してみます。
sinc関数においてはsinのカッコの中が0~πradianで一山に相当します(πradianで最初のヌル点、つまりゼロになります)。図5、式(6)相当では、timeが0~0.25secでヌル点に到達しますので、上記のように係数2として360*2*timeという式にしてあります。
この計算式を図7のうえに重ね合わせたものを図8に示します。計算式が赤のプロットです。0.25Hzまでは図6の回路のシミュレーション結果とsinc関数の計算結果がほぼ一致していることが分かります。平均化フィルタはsinc形状になっているのですね。
また0.25Hzから上は、0.5Hzでの折り返しにより、シミュレーション結果のほうが大きくなっていることが分かります。平均化フィルタでは離散処理が入っているために、このような結果の差異になるわけですね。
4タップの平均化フィルタがサンプリング周波数の1/4でヌルが出ることを確認してみる
ここまで示した図4や図7、図8のように、サンプリング間隔が1secだと、0.25Hzのところにヌル点(周波数応答がゼロ)が出来ています。これはどう考えればよいのでしょうか。非常に簡単な視点でみてみましょう。
図9は図3を改造した4タップかつサンプリング間隔1secの平均化フィルタです。図3の回路に、各タップに相当する電圧出力のBモデルを追加しています。入力には0.25Hzの(ヌルになる周波数である)正弦波信号を加えています。
シミュレーション結果を図10に示します。正弦波信号は1周期が4secで、その信号が1secごとに遅延されますから(1周期を4ポイントでサンプリングし、1タップごとに遅延していることと同じですから)、この4点をピックアップして足し算した結果は「ゼロ」です。つまりこの平均化フィルタで、確かに0.25Hzのところにヌルができることが分かります。
この整数倍の周波数でも同じ条件(ゼロ)になりますから、図4、図7や図8のように0.5Hz, 0.75Hz, 1Hz…とヌルが出来ていることになるわけですね。


平均化フィルタに入力される信号が連続時間信号と離散時間信号で答えがどう異なるか
ここまでのところで疑問が脳裏をよぎった方もいらっしゃるのではないでしょうか。「いや、ちょっとまてよ。図3、図6、図9では入力は連続時間信号だよな」「この技術ノートの最終目的は、デジタル・フィルタとして離散時間信号をどう取り扱うか、だよな?」「でもここまでの説明は、連続時間信号についてではないか!」
ごもっともです…。これを少し考えてみましょう。
連続時間信号(以降「アナログ信号」と呼びます)でも離散時間信号(以降「デジタル信号」と呼びます)でも平均化フィルタは同じ構成になると考えることができます。この平均化フィルタのやっていることは「遅延」ですので、以降は「遅延型平均化フィルタ」と表現することで、遅延型という用語を付記してその動作を明確にしておきましょう。
これをLTspiceのシミュレーションでデモしてみます。図9の入力の信号源部分をインパルス波形とした、シミュレーション回路(信号源部分のみ)を図11に示します。
遅延型平均化フィルタに入力される信号はS1(図中右上)ですが、その信号S1は0.125Hzの正弦波である信号源V2(ネットSRC)と、1secごとでサンプリング・パルスを生成する信号源V1(ネットSMP)との掛け算
V(SMP)*V(SRC)
になっています。
シミュレーション結果を図12に示します。波形は実時間で動いていますが、サンプリング間隔ごとで値が各タップに到来しているとみなせることが分かります。つまりデジタル・フィルタそのものの動作ということが分かります。
システムという視点では、同じ遅延型平均化フィルタに連続的な信号が加わるか、インパルス的な信号が加わるかの違いだけということなのですね。
アナログ信号とデジタル信号のスペクトルは異なる
一方でそれぞれの入力信号を周波数スペクトルとして表してみると、図13のようになります。連続時間であるアナログ信号ならば、本来のアナログ信号としての周波数𝑓𝐴だけにしかスペクトルはありません。一方でこの信号をサンプリング周波数𝑓𝑆でサンプリングしたデジタル信号の場合、𝑓𝐴は折り返されて同図のように
に現れることになります。これはサンプリング定理の話題でよく出てくる話ですから、多くの方が理解されていることと思います。



アナログ信号の場合はアナログ信号のスペクトルがフィルタ出力に現れる
図4や図7のsinc形状の周波数応答特性をもつ遅延型平均化フィルタ(サンプリング周波数を𝑓𝑆 = 1Hz、ヌル周波数を𝑓𝑁 = 0.25Hzとします)に、周波数𝑓𝐴 = 0.1Hzの「アナログ信号」が加わったことを考えてみます。これを図14に示します。この遅延型平均化フィルタの周波数応答特性は図7のとおりです。なお図7のsinc形状の周波数応答特性は、連続時間信号を加えたものと仮定してシミュレーションしたものでありました。
このsinc形状の周波数応答特性で周波数𝑓𝐴 = 0.1Hzの(連続時間の)入力アナログ信号がフィルタリングされるわけですので、それが出力として周波数𝑓𝐴(0.1Hz)上に現れることになります。
デジタル信号の場合もデジタル信号の折り返されたスペクトルがフィルタ出力に現れる
つづいてサンプリング周波数𝑓𝑆 = 1Hzでサンプリングされた周波数𝑓𝐴 = 0.1Hzのデジタル信号が図4や図7の特性の遅延型平均化フィルタに加わったことを考えてみます。この出力スペクトルを図15に示します。
遅延型平均化フィルタの動作自体はアナログ信号でも離散時間信号(デジタル信号)でも同じになります。つまり周波数特性は図7となります。これが離散時間信号(デジタル信号)のスペクトルをフィルタリングするわけですが、丁度遅延型平均化フィルタの特性繰り返しと、デジタル信号のスペクトルの現れる周波数繰り返しポイントが同じピッチになっています。
これは遅延型平均化フィルタの遅延時間の逆数(これまでサンプリング周波数と説明してきたもの)と信号のサンプリング周波数が等しいからです。
結局は何事もなかったように、デジタル信号での遅延型平均化フィルタ出力のスペクトルも、サンプリング周波数𝑓𝑆 = 1Hzを周期として繰り返されるスペクトルになるわけです。
まとめと予告
今回はLTspiceを使って平均化フィルタについて考えてみました。平均化フィルタはsincフィルタになることがご理解いただけたかと思いますし、LTspiceでの怪しいテクニックも「ふーん」とご高覧いただけたものかと思います。
次回はこの理解と怪しいLTspiceテクニックをツールとして、ΣΔADCで用いられているsincフィルタについて考えてみます。これが実は回路構成としては「平均化フィルタ」には見えないものなのですが…、これを深く解析していきたいと思います。


著者について
デジタル回路(FPGAやASIC)からアナログ、高周波回路まで多...
この記事に関して
{{modalTitle}}
{{modalDescription}}
{{dropdownTitle}}
- {{defaultSelectedText}} {{#each projectNames}}
- {{name}} {{/each}} {{#if newProjectText}}
-
{{newProjectText}}
{{/if}}
{{newProjectTitle}}
{{projectNameErrorText}}