FFT が汚れる前に — AD コンバータの手前で、4 次 LPF を E12 と E24 でどう組むか

  • 電子回路
  • spice
  • python
  • 信号処理
  • 組み込み

加速度センサで振動を測って、Python に取り込んで FFT をかけたら、何かが乗っている。気になって、デジタル側で平均をかけたり、ソフトのローパスを足したりしてみる。けれど、ある種のノイズはどうしても消えてくれない——そういう経験、ないでしょうか。私はあります。

一つ前の記事 の終盤で、サンプリングがズレると速い波が遅い波に化けてしまう話(折り返し/エイリアシング)を書きました。今回の話の前提は、ぜんぶそこに帰着します。AD コンバータでデジタルに落とした後では、折り返してしまったノイズはもう取れない。元の信号と幽霊が、同じ帯域で見分けがつかなくなっているからです。

なので、AD する手前のアナログ側で、ある程度まで落としておくしかない。これがアンチエイリアシング・フィルタ(AAF)と呼ばれるものです。今回は、この AAF を 4 次 まで上げて、入手しやすい E12 / E24 部品の値で組む話を、SPICE で確かめながら書きます。前 2 本(回路図を Python でngspice の壁)で道具立てまで揃えた、その続編にあたります。

道具より、現場でどう値を選ぶかのほうに紙幅を多く取りました。設計式の暗記より、選び方のクセを覚えるほうが、私には現場で効いた気がしているからです(と書きつつ、私自身もしょっちゅう間違えるので、いまでも手探りです)。それから、記事の最後に、ここで使った設計手順をコマンドラインから叩ける Python ツールにして公開しています。「自分の用途で値だけ振ってみたい」という方の手元でも、すぐ試せるはずです。

どれくらい落とせばいいのか

ナイキスト周波数(サンプリング周波数の半分)以上の成分は、AD した瞬間に折り返します。だから AAF の役目は、ナイキストの所で、AD の分解能のノイズフロアより下まで落としておくことです。

理屈の上の上限は単純で、AD の有効ビット数を NN とすると、フルスケールに対する LSB(Least Significant Bit、AD が刻める最小 1 ステップ)の振幅比は約 6.02N-6.02N dB です(1 ビット増えるごとに約 6 dB 細かくなる、と覚えています)。12 bit: −72 dB / 14 bit: −84 dB / 16 bit: −96 dB。これは「LSB 1 個分の単音レベル」のことで、厳密には理想 ADC の量子化ノイズ床そのもの(正弦波フルスケール基準で SNR 6.02N+1.76\approx 6.02N + 1.76 dB、量子化ノイズの RMS は LSB の 1/121/\sqrt{12})とは別物です。ただ、設計の入口の指標として頭に置いておくと、後の調整で大きく外しにくいと感じています。ナイキスト超にフルスケール相当のノイズが乗っている最悪ケースを想定した、いちばん厳しい設計目安、という位置付けです。

ただし実務でこの厳しい線を取ると、たいてい過剰設計になります。現場では、信号帯域外に乗っている実際のノイズ密度と、AD 後に許容できる S/Nから逆算して、「ナイキストで何 dB あれば実用」を決めることが多い——私の経験的な感覚だと、−40 dB から −60 dBくらいの間で折り合うことが多かった気がします。本当の AAF 要件は「ナイキスト一点のゲイン」ではなく、ナイキスト超のノイズ密度を信号帯域に折り返したときに積分される全量で決まるので、ここの数字は計測対象と現場の電磁環境でけっこう動きます。絶対値は控えめに見てください。

1 次・2 次では足りないことがある

具体的なお題で考えます。加速度センサで 20 kHz まで通したい。AD のサンプリングを 80 kHz(ナイキスト 40 kHz)に取ります。LPF のカットオフは信号帯域の上端、20 kHz に置きます。

このとき、ナイキストの 40 kHz で、フィルタは何 dB 落とせているか。理想 Butterworth で計算するとこうなります。

次数 ロールオフ(dB/dec:周波数 10 倍ごとに何 dB 落ちるか) 40 kHz でのゲイン
1 次 −20 dB/dec −7.0 dB
2 次 −40 dB/dec −12.3 dB
4 次 −80 dB/dec −24.1 dB

同じカットオフ (20 kHz) で次数だけ変えた Bode 線図。-3dB 点はどれも 20kHz だが、ナイキスト 40kHz での減衰量は次数で大きく違う

1 次の −7 dB は少し心許ないです。2 次の −12 dB もまだ薄い。4 次まで上げて、ようやく「ナイキストで −24 dB」まで来ます。実はこの −24 dB ですら、上で書いた「実用 −40〜−60 dB」のラインにはまだ届いていません。「4 次にすれば AAF として完成」ではなく、まだ続きがある、ということです。

そこで、現実解は 二つの合わせ技 になります。

  1. フィルタの次数を上げる — 1 次・2 次で足りないところを、4 次まで持ち上げる
  2. オーバーサンプリング — サンプリングを 80 kHz から 160 kHz、320 kHz と上げていく。ナイキストが信号帯域から遠くなるので、同じフィルタでもナイキスト点でのゲインがぐっと下がる。ただし AD のレートとデータ転送、ストレージ、後段の処理がぜんぶ重くなる

たとえば 4 次・fc=20kHzf_c = 20\,\mathrm{kHz} のまま fsf_s を 80 kHz → 160 kHz に上げると、ナイキストが 40 → 80 kHz に移ります。Butterworth は漸近的に 1 オクターブごとに約 −24 dB 落ちるので、ナイキスト点のゲインは −24 → 約 −48 dB(厳密には −48.2 dB)と一気に深くなり、ようやく実用の谷に入ります。「4 次まで上げる + 適度にオーバーサンプリング」が、現場での標準の組み合わせになるのは、こういう事情からです。どちらか一方に寄せると、必ずどこかで無理が出ます。

今回は次数を上げる側の話です。1 次までなら、抵抗 1 本とコンデンサ 1 本の受動 CR で素直に組めます。ところが 4 次となると、受動 RC を 4 段つなぐだけでは現場で使い物にならないことが多くて、実務では OP アンプを使ったアクティブフィルタに切り替えます。なぜそうなるのかを、まず受動側で目で見てから、本命の OP アンプ構成に進みます。

4 次の「特性カーブ」を選ぶ

「4 次の LPF」と一口に言っても、通過帯域や遷移帯域の振る舞いが違う性格を、設計のときに選ぶことになります。代表的なのが次の三つ。

  • Butterworth — 通過帯域がいちばん平ら(最平坦特性と呼ばれます。「バターのように平ら」と言われることもありますが、考案したイギリスの物理学者 Stephen Butterworth さんの姓に由来します)。通過帯域の平坦性と遷移帯域の鋭さのバランスを取った定番
  • Bessel — 群遅延が低周波側で最大平坦になるよう設計されていて、通過帯域内では位相がほぼ直線、群遅延がほぼ一定です。だから矩形波やパルスのような信号でも波形の形が崩れにくい。代わりに遷移帯域は Butterworth より緩い
  • Chebyshev (I) — 遷移帯域がいちばん鋭い。代わりに通過帯域に小さなリプルが乗る(設計時に指定して許容する)

同じカットオフ 20 kHz で並べると、性格の違いがはっきり見えます。

4次 LPF の特性カーブ比較。通過帯域の平らさと、遷移帯域の鋭さの折り合いが、特性ごとに違う

左が通過帯域の拡大、右が全域です。AAF として どれを選ぶか は、AD 後にやりたい処理で変わります。

  • AD 後に振幅スペクトルだけ見たい(位相は使わない) → Butterworth が無難。通過帯域の平坦さは振幅 FFT の使い勝手と相性がいい
  • AD 後にも時間波形の形を保ちたい(FIR で線形位相を仕上げるなら別ですが、アナログ段で位相を歪ませたくないとき) → Bessel
  • 遷移帯域を最大限に鋭くしたい、通過帯域に小リプルは許せる → Chebyshev

ここで一つ、率直に書いておきたいことがあります。この三つの特性は、純粋な受動 RC だけでは厳密には作れません。理由は少しだけ数学の話になるのですが——フィルタの特性は「極(pole、伝達関数の分母がゼロになる ss の値)」の配置で決まり、Butterworth や Bessel は 実部と虚部を持つ "複素極" を要求します。ところがインダクタや能動素子を使わない純 RC 網で作れるのは、実数極(複素平面の負の実軸上にしか出てこない極)に限られます。これが「RC だけでは Butterworth にならない」の中身です(LC を含む受動回路なら複素極も作れますが、低周波の AAF ではコイルが現実的でないので、そちらは選択肢から外れます)。だから本来は OP アンプを使ったアクティブフィルタ(Sallen-Key 等)で作ります。「受動 RC を 4 段つないで Butterworth」は紙の上の話で、現場ではそうはならない——これを次の段で SPICE で見ます。

今回は AAF として一番素直な Butterworth で進めます。

受動 RC 4 段は、思ったより緩い

「RC を 4 つつなぐだけ」で 4 次のはずです。各段の伝達関数 Hi(s)=1/(1+sRiCi)H_i(s) = 1/(1+sR_iC_i) を 4 つ重ねれば、漸近的には −80 dB/dec のロールオフは出る。

ところが、ここにロード効果という落とし穴があります。受動 RC は、次段に何かをつなぐと、次段の R-C 網がそのまま前段の出力を負荷します。各段はもう「独立した一次遅れ」のようには振る舞えなくなり、カスケード全体の極が Butterworth 配置から外れて、実数軸の上に広く散ってしまう——結果として、漸近線の −80 dB/dec までたどり着くのが遠くなります。段間にバッファを挟まない素の RC カスケードは、各段が独立した 4 次にはなりません。

実際に試してみます。同じ R と同じ C を 4 段つなぐ素朴な構成で、カスケード全体の −3 dB を 20 kHz に合わせると、各値は R=428Ω,C=2.2nFR = 428\,\Omega, C = 2.2\,\mathrm{nF} になります。バッファ付きの独立 4 段なら、−3 dB は単段の約 0.435 倍に下がるので 46 kHz 設計でちょうど合う——というのが教科書の数字です。ところがバッファ無しのカスケードは関係が変わってしまい、SPICE で合わせると、単段の単体カットオフを 169 kHz くらいまで持ち上げないと、全体の −3 dB が 20 kHz に着地しません。

これを理想 4 次 Butterworth(同じ −3 dB = 20 kHz)と並べると、こうなります。

同じカットオフ -3dB=20kHz で揃えても、理想 Butterworth と受動 RC 4段(同一 R, C)では遷移帯域の落ち方がまるで違う

数値で並べると、もっと衝撃です。

周波数 理想 4 次 Butterworth 受動 RC 4 段(同一 RC)
20 kHz −3.0 dB −3.0 dB
40 kHz −24.1 dB −7.1 dB
100 kHz −55.9 dB −15.7 dB
200 kHz −80.0 dB −25.1 dB

ナイキスト 40 kHz の所で、理想 Butterworth なら −24 dB 落ちているのに、受動 RC 4 段(同一 RC)はまだ −7 dB しか落ちていない。1 次の Butterworth とほぼ同じ値です。漸近線の −80 dB/dec はずっと先で初めて効いてきて、200 kHz でようやく −25 dB。

これは、各段の極が(Butterworth で要求される複素極の配置から外れて)実数軸の上で広く散らばってしまうのが原因です。「4 段つなげば 4 次」と思っていると、実用範囲では肩透かしを食らう。私自身、これを最初に SPICE で見たときは「あれ、こんなはず…」と二度見しました。

受動でも、組み方で少しは改善できる(けれど限界はある)

ロード効果は「次段の入力 Z が、前段の出力 C と並列に見える」ことで起きるので、段を進むごとに R を大きくしていく——インピーダンス階段——にすると、次段が前段にぶら下がる重さがじわっと軽くなります。3 倍刻みで E24 / E12 から値を拾うとこうなります。

R C RC
1 470 Ω 4.7 nF 2.21 µs
2 1.5 kΩ 1.5 nF 2.25 µs
3 4.7 kΩ 470 pF 2.21 µs
4 15 kΩ 150 pF 2.25 µs

受動 RC 4段は組み方で性格が変わる。インピーダンス階段は同一 RC より遷移帯域の落ち方が明らかに鋭い

周波数 理想 Butterworth 同一 RC インピーダンス階段
100 kHz −55.9 dB −15.7 dB −22.2 dB
200 kHz −80.0 dB −25.1 dB −39.5 dB

100 kHz で 同一 RC より 7 dB、200 kHz で 14 dB 良くなりました。部品の数は同じ、並び順と値だけでここまで動く。

ただし、ここまで頑張っても理想 Butterworth には届きません。100 kHz で −22 dB 対 −56 dB、ナイキスト 40 kHz でも −8 dB 止まり。受動 RC は実数極しか持てない、という根本のところで頭打ちです。だから、現場で 4 次が本当に必要になったら、私は受動を諦めて OP アンプに切り替えてきました。

本命 — OP アンプの Sallen-Key 2 段カスケード

実務で 4 次 Butterworth を組むときの定石は、Sallen-Key と呼ばれる 2 次のアクティブセクションを 2 段カスケードして構成するやり方です。

Sallen-Key 1 段(2 次)は、抵抗 2 本(R1=R2=RR_1 = R_2 = R)とコンデンサ 2 本(C1,C2C_1, C_2)と、OP アンプを使った利得 1 の非反転バッファで作ります。コンデンサ 2 本の比 C2/C1C_2/C_1 で Q を決め、RRC1C2\sqrt{C_1 C_2}ω0\omega_0 を決める——これが核です。

ここで出てくる QQ は「フィルタの共振の鋭さを表す数」だと思ってください。大きいほど通過帯域のカットオフ近辺で山(ピーキング)が出やすく、小さいほど平らに落ちます。ω0\omega_0 はフィルタの固有角周波数で、f0=ω0/(2π)f_0 = \omega_0/(2\pi) がいわゆる中心の周波数の場所です。

unity-gain Sallen-Key の伝達関数(R1=R2=RR_1 = R_2 = RC1C_1 は非反転入力から GND、C2C_2 は OP アンプ出力から R1R_1-R2R_2 中間ノードへ戻る帰還側、という割り当てを前提):

H(s)=1s2R2C1C2+2sRC1+1,ω0=1RC1C2,Q=12C2C1H(s) = \frac{1}{s^2 R^2 C_1 C_2 + 2 s R C_1 + 1}, \qquad \omega_0 = \frac{1}{R\sqrt{C_1 C_2}}, \quad Q = \frac{1}{2}\sqrt{\frac{C_2}{C_1}}

文献によっては C1C_1C2C_2 の名前が逆になっているものがあるので、回路図のノードと式の対応を見ながら使ってください。

4 次 Butterworth にするには、2 段の Q をそれぞれ次のように選びます(同じ ω0\omega_0 で、Q だけ違う 2 つの極ペア)。

  • 段 1: Q1=12cos(π/8)0.541Q_1 = \dfrac{1}{2\cos(\pi/8)} \approx 0.541
  • 段 2: Q2=12cos(3π/8)1.307Q_2 = \dfrac{1}{2\cos(3\pi/8)} \approx 1.307

値そのものは、4 次 Butterworth の正規化分母が (s2+1.848s+1)(s2+0.765s+1)(s^2 + 1.848\,s + 1)(s^2 + 0.765\,s + 1) と二つの 2 次に因数分解できて、各 2 次標準形 s2+s/Q+1s^2 + s/Q + 1 と見比べると Q=1/1.8480.541Q = 1/1.848 \approx 0.541Q=1/0.7651.307Q = 1/0.765 \approx 1.307 が出てきます(Butterworth の極を単位円左半平面に等角配置し、複素共役対ごとに 2 次セクションへまとめた、と言い換えてもいいです)。

段 1 は控えめ(通過帯域でゲインを上げない)、段 2 は強め(通過帯域で少しピーキングする)。この二つを直列にすると、ピーキングが他方のロールオフで抑え込まれて、全体としてフラットな 4 次 Butterworth になる——という、よくできた仕組みです。

E12 / E24 で実際に作ってみます。各段の C1C_1 を 1 nF(E12 で取りやすい値)に固定して、C2C_2 を E12、RR を E24 で丸めると、こうなりました。C1C_1 は OP アンプの非反転入力から GND へ、C2C_2 は OP アンプの出力から R1R_1R2R_2 の中間ノードへ戻る帰還側、という割り当てです(文献によって C1C_1C2C_2 の名前が逆になっていることがあるので、念のため)。

R1=R2R_1 = R_2 C1C_1 (GND側) C2C_2 (帰還側) f0f_0 QQ
段 1 7.5 kΩ 1 nF 1.2 nF 19.4 kHz 0.548(目標 0.541, +1.2%)
段 2 3.0 kΩ 1 nF 6.8 nF 20.3 kHz 1.304(目標 1.307, −0.2%)

ここで f0=ω0/(2π)f_0 = \omega_0/(2\pi) は 固有周波数で、段単体の −3 dB 点とは一致しません(特に高 Q 段はピーキングするので、単体では f0f_0 より上で −3 dB が出ます)。カスケード全体の −3 dB は、2 段を直列に通した結果で決まります。

段 2 の C2=6.8nF,C1=1nFC_2 = 6.8 \mathrm{nF}, C_1 = 1 \mathrm{nF} は E12 比が気持ちよく Q に乗ります(6.8 という数字は 4Q26.834 Q^2 \approx 6.83 を E12 から拾うとほぼぴったりです)。段 1 は E12 の中で「比 1.17」に近い値が無くて、1.2 で代用するため Q が 1.2% ほど高めにずれます。

それから、正直に書いておきたい誤差を一つ。本来の 4 次 Butterworth は「同じ ω0\omega_0 を持つ Q の違う 2 段」を要求しますが、上の実装は f0f_0 が 段 1: 19.4 kHz / 段 2: 20.3 kHz と約 5 % ずれています。E24 / E12 で離散値しか取れないので、完全な ω0\omega_0 一致は無理です。この f0f_0 のズレが、通過帯域の平坦性にどれだけ顔を出すかは、最後にカスケード Bode を見て判断する話で——後ろの図 7 を見るとわかるように、通過帯域は理想 Butterworth から ±0.1 dB 以内に収まっていて、今回の用途では実用的な範囲、と言える結果でした。これも「離散値で作っているのだから完全一致は無理、許容内かを毎回 SPICE で確認する」という、設計の心構えの話に帰着します。

回路はこれです。

Sallen-Key 4次 Butterworth (unity-gain × 2段)。OP アンプは利得1の非反転バッファ。電源と基準電位は省略

そして Bode 線図。受動 RC 4 段(同一 RC)と理想 Butterworth と並べると、こう見えます。

Sallen-Key 4次 Butterworth は E24/E12 で組んでも理想 Butterworth とほぼ重なる。受動同一 RC とは 40 dB 以上の差

数字で見ると、もう一段気持ちが良いです。

周波数 理想 Butterworth 受動 4 段(同一 RC) Sallen-Key(E24/E12)
40 kHz −24.1 dB −7.1 dB −24.1 dB
100 kHz −55.9 dB −15.7 dB −56.1 dB
200 kHz −80.0 dB −25.1 dB −80.2 dB

E12 と E24 の市販部品で組んでも、Sallen-Key は 40 kHz / 100 kHz / 200 kHz の 3 点いずれでも理想 Butterworth と 0.3 dB 以内に収まりました。受動 4 段に比べると 同じ周波数で 40 dB 以上の差。これが「現場で 4 次は OP アンプ」という慣れの中身です。

OP アンプは利得 1 の非反転バッファとして使うので、大袈裟な高速品は不要です。ただ、「汎用品なら何でも OK」というほどラフでもありません。少なくとも以下は確認しています:

  • GBW(利得帯域積) — 信号帯域の十分上。20 kHz 信号でも、Q1.3Q \approx 1.3 の Sallen-Key の段で阻止域までしっかり出したいなら、1 MHz 級では通過帯域の概形しか保証できない印象です。10 MHz 級以上を候補にして、候補品の SPICE マクロモデルで AC・過渡・安定性まで一度確認するのが、後で困らないやり方かなと思っています
  • スルーレート(SR) — 入力の急変に追従できるか。SR ≥ 2π · f_signal · V_p が目安
  • 入出力電圧範囲(Rail-to-Rail かどうか含む) — 単電源で使うときは特に。出力が信号のピークに余裕を持って届くか
  • 容量負荷安定性 — Sallen-Key の C2C_2 そのものは「周波数依存の正帰還/フィードフォワード要素」で、いわゆる「出力にぶら下がる容量負荷」とは少し性格が違います。注意したいのは Sallen-Key の出力が直接駆動する ADC のサンプリング容量・配線容量・後段入力容量のほうで、必要なら出力直列抵抗や ADC 推奨の RC スナバを入れて発振余裕を確保します
  • AD 直前のドライブ能力 — 後段の SAR ADC が容量サンプリングで電荷を引き抜く場合、その引き抜きに追従できるか
  • 入力雑音密度 — 微弱信号系では効きます

それから、Sallen-Key の AAF として大事な現場知見を一つ。OP アンプの出力インピーダンス ZoutZ_\text{out} は高周波で上がります(GBW を超えたあたりから、出力 Z が抵抗成分として顔を出してくる)。Sallen-Key の C2C_2 は OP アンプ出力から中間ノードへの帰還ですが、高周波では「OP アンプを通る帰還経路」が機能しづらくなり、C2C_2 を介して入力から出力へ直接抜けるような形で、阻止域のロールオフが頭打ち(平坦化)になる現象が知られています。これがひどいと、せっかくの −80 dB/dec が高い周波数で平坦に張り付いて、AAF として効かなくなる。本気で阻止域の深さが必要な AAF 用途では、Sallen-Key を諦めて多重帰還型(MFB: Multiple Feedback、OP アンプの "−" 側に帰還を集める別構成)に切り替える——これも実務でよく取る選択肢です。今回の構成は scipy の解析計算ベースで「200 kHz で −80 dB」が出ていますが、これは理想 OP アンプ前提の値で、実機では OP アンプの GBW や出力 Z の影響でこの深さからは少し劣化する方向に動きます。もっと先まで深く落としたいときは MFB を検討する、と頭の片隅に置いてください。

値の選び方の、いくつかのコツ

ここまでの設計で、無意識に使っているコツをいくつか言葉にしておきます。私自身、誰かに教わったというより、現場で何度か失敗してから身についたものなので、書いておくと自分のためにもなります。

  1. R を先に決めない。C 起点で R を合わせ込む
    R は E24(5%)や E96(1%)で精度を上げられますが、C は E12(一般的に 10%、セラミックの温度特性込みだともっと暴れる)が普通です。精度が低い側に合わせて R を選ぶほうが、組み合わせが収束しやすい。だから手順は「目標 ω0\omega_0 と Q → C 比から C1,C2C_1, C_2 を E12 で決める → RR を逆算して E24 に丸める」。

  2. R は 10k〜100k の中庸帯に置きたい
    低すぎると前段に電流負荷が重く、OP アンプの出力電流能力にも効きます。高すぎると、抵抗の許容差そのものが絶対量で大きくなる(例: 1 MΩ ±5% は ±50 kΩ)。ほかにも、OP アンプの 入力バイアス電流 IbI_b(OP アンプの入力端子に微小に流れ込む / 流れ出す電流。データシートで pA〜nA オーダの値がある)による DC オフセット誤差は、入力端子から見た等価抵抗 × IbI_b に比例して大きくなるので、高い R ほど効きやすい(熱雑音も同様に効きます)。ちょうどよく効く帯域が、経験的に 10k〜100k あたりにある気がします(今回の例は 3 k〜7.5 kΩ と少し低めですが、OP アンプの IbI_b 仕様と要求される DC 精度を見て妥当と判断できれば、これくらいまで下げても実用に困りません)。

  3. C は 5% より細かい精度を求めても効きが頭打ち
    セラミック(C0G / NP0 以外)では温度・電圧で容量が動きます。フィルム品にすると 5% 切れますが、サイズと値段が跳ねます。「R を E96 で揃えても、C が 10% ならカットオフのばらつきは C が支配」というのは、よくある罠です。

  4. Sallen-Key の高 Q 段(Q1.3Q \approx 1.3)は、通過帯域でわずかにピーキングが出る
    段 2 単体で見ると、f0f_0 近辺で +2.4 dB ほど持ち上がります(f0f_0 ちょうどでは 20log10Q+2.320\log_{10} Q \approx +2.3 dB、ピーク最大は f0f_0 より少し下で約 +3.0 dB という形)。これは段 1 のロールオフで打ち消されて、全体としてフラットに見えるようにできています。組み立てる段順序は、伝達関数の出口だけで見ればどちらが先でも結果は同じですが、慣習的には 段 1 → 段 2(低 Q → 高 Q)の順に並べることが多い、という程度に書いておきます。前段で帯域外成分が先に少し落ちると、後段の高 Q ノードの振幅が抑えられて飽和余裕が取りやすい——という説明をよく見るのですが、実際に有利かどうかは入力信号スペクトルと過渡条件で変わるので、本気で詰めるときは両順序を SPICE で見比べるのが安全です(私もこれを「定石」と書き切るほどの確信は持っていなくて、毎回シミュレーションで確認する派です)。

これらは「正解」ではなく、だいたいこの辺りに収めると、後で痛みが少ないという線です。

公開ツール — 自分の用途で値を振ってみる

ここまでの設計手順を、コマンドラインから叩ける Python ツール examples/05_aaf_design.py にしました。手元の AD の有効ビット数や、信号帯域、サンプリング周波数に合わせて、ご自分の用途で値を振ってみてください。

# Sallen-Key 4 次 Butterworth, fc=20 kHz, 各段 C1 を 1 nF 固定, R は E24, C は E12 で丸める
python examples/05_aaf_design.py --topology sallenkey --fc 20e3 --fix-c1 1e-9 \
                     --series-r e24 --series-c e12

# R を 10 kΩ 固定で振りたい場合 (高入力 Z OP アンプ前段、熱雑音の都合など)
python examples/05_aaf_design.py --topology sallenkey --fc 20e3 --fix-r 10e3 --series-c e12

# 受動 RC インピーダンス階段で C 列を指定
python examples/05_aaf_design.py --topology passive-ladder --fc 20e3 \
                     --c-list 4.7e-9,1.5e-9,470e-12,150e-12 --series-r e24

--fix-c1--fix-r のどちらを使うか、という所だけ少しだけ補足しておきます。既定は --fix-c1(C を先に決めて R を逆算)にしています。これは「精度の低い側を先に確定する」という設計のコツを、ツールの既定挙動に染み込ませた格好です。OP アンプの入力バイアス電流や、熱雑音の都合などで R を先に決めたいときだけ、--fix-r を使う、という運用が現実的です。

出力には、理論値・E シリーズに丸めた値・丸め後の実 fcf_c と Q・カスケード全体の実 −3 dB と帯域別ゲインが並びます。手元で振ってみて「これくらいの精度で済むか」「もう一段切り詰められるか」を確かめる、設計の入り口として使えるはずです(ソースは公開リポに置いています。記事末にリンクします)。

許容差の話 — Monte Carlo で振れを見る

設計が決まったら、最後に R と C の許容差で、カットオフ周波数がどれくらい振れるかを見ます。SPICE の AC 解析を許容差付きで何百回か回す、いわゆる Monte Carlo です。

これは受動 4 段で先に試した結果ですが、Sallen-Key でも傾向は近い(むしろ Q が C 比に依存するので、C の許容差がより素直に効きます)ので参考になります。

ケース カットオフ中央値 P5–P95
A: R±5%, C±10% 20.0 kHz ±1.16 kHz(約 ±6%)
B: R±1%, C±5% 20.0 kHz ±0.55 kHz(約 ±2.8%)

受動 RC 4段の許容差ばらつき。R 5% + C 10% でも、カットオフの中央値からの振れは P5-P95 で約 ±1.2kHz

E24 抵抗と E12 セラミックの組み合わせでも、カットオフは ±6% くらいに収まります。それで構わない用途なら、無理に E96 や高精度フィルムに行く必要はない。「どこまでの精度が必要か」を先に決めて、許容差を買う——精度はタダではないので、必要な分だけ買えばいい。これも「効果が見える」良い場面で、SPICE で測ってから決められる種類の判断です。

SPICE で検証する — PySpice の使い所

ここまでの分析は、scipy の状態空間と Sallen-Key の解析式で解いてきました。実回路として組んだときに同じ結果になるか、PySpice で AC 解析しても確かめられます(前回の ngspice の壁 で sudo 無しで通した、あの環境です)。受動 4 段の例を載せます。

from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import u_V, u_Ohm, u_F, u_Hz

c = Circuit("Passive RC 4-stage (impedance ladder)")
# AC 解析用に振幅 1V を明示
c.V("in", "vin", c.gnd, "DC 0 AC 1")
c.R(1, "vin", "n1", 470 @ u_Ohm)
c.C(1, "n1", c.gnd, 4.7e-9 @ u_F)
c.R(2, "n1", "n2", 1500 @ u_Ohm)
c.C(2, "n2", c.gnd, 1.5e-9 @ u_F)
c.R(3, "n2", "n3", 4700 @ u_Ohm)
c.C(3, "n3", c.gnd, 470e-12 @ u_F)
c.R(4, "n3", "vout", 15000 @ u_Ohm)
c.C(4, "vout", c.gnd, 150e-12 @ u_F)

ac = c.simulator().ac(
    start_frequency=100 @ u_Hz, stop_frequency=1_000_000 @ u_Hz,
    number_of_points=20, variation="dec",
)

中身は、ただ R と C を vin → n1 → n2 → n3 → vout と素直に並べているだけです。.ac 解析を回すと、上で scipy で解いたのと同じ Bode が出ます。Sallen-Key 版も OP アンプモデル(理想 OP アンプの簡易記述、または実際に使う候補 OP アンプの SPICE マクロモデルを PySpice の SubCircuit で読み込む形)を入れて同じ流儀で書けます。設計は scipy の式で、検証は PySpice の実回路で、というワークフローが、いま私が一番落ち着いて使える組み合わせです。

1 次なら受動、4 次なら Sallen-Key

最後にもう一度。1 次の AAF(簡単なノイズ落とし)なら受動 CR で十分です。抵抗 1 本とコンデンサ 1 本、電源も基準電位も要らない、いちばん素直な解。

4 次まで本気で必要になったら、Sallen-Key(OP アンプ)に切り替える——これがいまの私の現場感です。受動 RC 4 段は紙の上では「4 次」ですが、実回路のロード効果で −80 dB/dec の漸近線が遠くにあって、実用範囲では肩透かしを食らうことが多い。インピーダンス階段で少しは戻せますが、それでも理想 Butterworth には届きません。OP アンプを 2 個使う手間を惜しんで、結局帯域で苦しむより、Sallen-Key で素直に組んでしまうほうが、後の自分が楽できます。

それから、最初の方で書いておいたことを一つだけ回収します。受動 1 次や Sallen-Key の入り口に、いきなり 数 kΩ の抵抗をぶら下げて大丈夫なのは、センサが「低インピーダンスで電圧を出せる」前提です。電荷出力のピエゾや、高インピーダンスのソースを直接そこに繋ぐと、信号源側が引っ張られて出力が大きく落ちる。その場合は、入り口にもう 1 個ボルテージフォロワを入れて、低 Z 化してから AAF に渡す、というのが標準形になります。

まとめ

  • AD 後のデジタル処理では取れないノイズの正体は、サンプリング前のナイキスト超え成分の折り返し。これは AD 前のアナログで落とすしかない
  • 1 次・2 次の LPF では、AD の有効ビット数が要求する減衰量に届かないことが多い。4 次まで上げる + 適度なオーバーサンプリングの組み合わせが現実
  • 4 次の特性は Butterworth / Bessel / Chebyshev で性格が違う。用途で選ぶ(FFT 振幅 → Butterworth、時間波形 → Bessel、鋭く落としたい → Chebyshev)
  • 受動 RC 4 段カスケードは、ロード効果で漸近線が遠くにあり、実用範囲では肩透かし。インピーダンス階段で少し改善できるが、理想 Butterworth には届かない
  • 現場の 4 次は Sallen-Key 2 段カスケード。OP アンプ 2 個と E12 / E24 の市販部品で、理想 Butterworth と 0.3 dB 以内
  • 値選びのコツ: C 起点で R を合わせ込む / R は中庸帯 / 精度は必要なぶんだけ買う
  • 受動で済むのは入り口の信号源インピーダンスが低い前提。微弱信号は素直にボルテージフォロワを挟む

私自身、ここに書いたコツは「正解」のつもりではありません。何度か外しながら、だいたいこの辺りに置いておくと痛みが少ないという線をなぞっただけです。SPICE と Python があるおかげで、思いつきで組んだ回路の Bode を一晩で確かめられる時代になったので、迷ったらまず手元のスクリプトに値を振ってみる、というのが私の最近のやり方です。

公開ツールと、すべての図を生成したスクリプトは、リポジトリにまとめて置きました。
📦 https://github.com/logicia32/lab-circuit-python


記事中の Bode 線図と Monte Carlo の分布は、scipy.signal で受動 RC カスケードの状態空間モデル と Sallen-Key の解析的伝達関数 を直接解いた結果です(PySpice の AC 解析でも、理想的には同じ結果が得られます)。回路図は schemdraw による説明用の概念図で、実機の写真ではありません。Sallen-Key の OP アンプは、回路図では極性の論理関係を示すのみで、電源端子と基準電位は省略しています。

この記事は Zenn に初出したものを加筆・補足したものです ── Zenn の元記事を見る