やっつけな日常(76) Maxima on Android、パッシブ・フィルタの計算

Joseph Halfmoon

パッシブ・フィルタの計算。別な「電子回路用電卓」をスマホに載せてあるので、わざわざMaxima様にお願いしなくても、と思っていたのです。しかし「その先」を計算するためには避けていられませぬ。機能重複しますがMaxima用のソースも作る(第72回のソースに継ぎ足し)ことにいたしました。鰻屋さんの秘伝のタレ式?

※「やっつけな日常」投稿順 Index はこちら

※動作確認は、パソコン上の wxMaxima 22.04.0 および Androidスマホ上の Maxima on Android 3.2.1 で行っています。

別な「電子回路用電卓」

スマホに載せてある「別な電子回路用電卓」はElectrodoc Pro(有料版)です。各種電卓に加えピン配その他、忘却力の年寄が自分じゃ計算できね~あるいは、覚えていられない各種の事柄を教えてくれる逸品であります。RLCフィルタ用の電卓画面が以下に。ElectrodocPro_filter

 

これがあるので、わざわざ同じような機能をMaxima on Android用にこさえることもないか、と思っておりました。が、しかし「その先」を計算するとなると、重複機能部分とは言え、実装せざるを得ませんな。今回は先を考えて、重複機能を実装っと。

計算対象のフィルタ

フィルタといってもいろいろあり。まずは、

    • デジタル
    • アナログ

の区別があります。今回はアナログねたです。DSPじゃありません。さてアナログ・フィルタにも大きく2種類の区別あり。

    • パッシブ
    • アクティブ

今回は受動素子のみでフィルタを構成するパッシブ・フィルタです。アクティブ・フィルタの設計は何度かURLを貼り付けさせていただいているアナログ権化のアナデバさまの「アナログ・フィルター・ウィザード」をどうぞ。魔法使いが助けてくれることでしょう。知らんけど。

さてパッシブ・フィルタには、

    • 1次のRCフィルタ、RLフィルタ
    • 2次のLCフィルタ(RLC)フィルタ

ありです。今回はRC、RLフィルタに加えて、L型のLCフィルタ「まで」実装してみてます。π型フィルタ、T型フィルタなどはまた後で(いつやるのだ自分?)ほぼほぼ Electrodoc Pro がカバーしている範囲です。フィルタ機能としては、以下中心です。

    • ローパスフィルタ
    • ハイパスフィルタ

最後のRLCフィルタでは、

    • バンドパスフィルタ

もやってます。なお、Electrodoc Pro以外に、『Analogista』様の以下のページも参考にさせていただきました。ありがとうございます。

LCフィルタの設計方法

Maximaソース

Windows上のMaxima、Android上のMaxima on Android共通に使用できるソースが以下に。(第72回のソースに継ぎ足し)

/* Maxima BATCH FILE 2024/05/31 J.Halfmoon       */
/* Passive Filters                               */
algebraic:true$
/*- Utilities -----------------------------------*/
log10(x) := log(x)/log(10)$
roundF(x, p) := float(round(x*10^p)/10^p)$
dB(Vout, Vin) := float(20*log10(Vout/Vin))$
phase(z) := 180*carg(z)/%pi$
vec2(x, y) := matrix([x],[y])$
mat22(a11, a12, a21, a22) := matrix([a11, a12],[a21, a22])$
vecP(v2) := vector([0, 0], [v2[1, 1], v2[2, 1]])$
vecLis(lis) := if listp(lis) then map(vecP, lis) else [vecP(lis)] $
vi: vec2(1, 0);
vj: vec2(0, 1);
I: mat22(1, 0, 0, 1);
/*- impedance calculation -----------------------*/
define(ser ([Lis]), '(apply ("+", Lis)))$
define(par ([Lis]), '(1 / (apply ("+", 1/Lis))))$
ci(C):= 1/(%i*2*%pi*f*C)$
ii(L):= %i*2*%pi*f*L$
/*- plot impedance vector -----------------------*/
plotImp(vP1, vP2, xR, yR) := draw2d(
  xrange=xR, yrange=yR, proportional_axes=xy,
  xaxis=true, yaxis=true, grid=true,
  title = "Impedance Z",
  xlabel = "Real", ylabel = "Imag",
  color = blue, head_length = 0.2, head_angle = 20,
  color = blue, 
  vecLis(vP1),
  color = red,
  vecLis(vP2)
)$
prSub(z) := ceiling(max(realpart(z), imagpart(z)) * 1.2)$
plotImpedance(z) := block([tmp],
  tmp: prSub(z),
  XR: [-0.1, tmp],
  YR: [-tmp, tmp],
  vZ: [vec2(realpart(z), 0), vec2(0, imagpart(z))],
  vY: vec2(realpart(z), imagpart(z)),
  plotImp(vZ, vY, XR, YR)
)$
/*- magnitude plot ------------------------------*/
plotMag(zf, fR) := draw2d(
  xrange=fR,
  xaxis=true, yaxis=true, grid=true, logx=true, logy=true,
  title = "Magnitude plot",
  xlabel = "Frequency[log(Hz)]", ylabel = "Magnitude[log(Z)]",
  explicit(abs(ev(zf, f=x)), x, fR[1], fR[2])
)$
/*- phase plot ----------------------------------*/
plotPhase(zf, fR) := draw2d(
  xrange=fR, yrange=[-180, 180],
  xaxis=true, yaxis=true, grid=true, logx=true, logy=false,
  title = "Phase plot",
  xlabel = "Frequency[log(Hz)]", ylabel = "phase[degree]",
  explicit(phase(ev(zf, f=x)), x, fR[1], fR[2])
)$
/*- Passive filter calculation ------------------*/
/*- L type filters                               */
/* RC LOW PASS   (IN)--R1--+--(OUT)              */
/*                         |                     */
/*                         C1                    */
/*                         V                     */
/* RC HIGH PASS  (IN)--C1--+--(OUT)              */
/*                         |                     */
/*                         R1                    */
/*                         V                     */
/* RL LOW PASS   (IN)--L1--+--(OUT)              */
/*                         |                     */
/*                         R1                    */
/*                         V                     */
/* RL HIGHPASS   (IN)--R1--+--(OUT)              */
/*                         |                     */
/*                         L1                    */
/*                         V                     */
/* LC LOW PASS   (IN)--L1--+--(OUT)              */
/*                         |                     */
/*                         C1                    */
/*                         V                     */
/* LC HIGH PASS  (IN)--+--C1--(OUT)              */
/*                     |                         */
/*                     L1                        */
/*                     V                         */
/* RLC BAND PASS (IN)--R1--+---+--(OUT)          */
/*                         |   |                 */
/*                         L1  C1                */
/*                         V   V                 */
/*-----------------------------------------------*/
Frc: Fc1 = 1/(2*%pi*R1*C1);
Frl: Fc1 = R1/(2*%pi*L1);
Fcl: Fc1 = 1/(2*%pi*sqrt(L1*C1));
FANS(Ftype, X1) := solve(Ftype, X1);
FVAL(Ftype, X1, Y1, YV, Z1, ZV) := float(at(FANS(Ftype, X1), [Y1=YV, Z1=ZV]));
Qpar(R, C, L) := R*sqrt(C/L);
/*- Example -------------------------------------*/
FVAL(Frc, Fc1, R1, 1, C1, 10e-6);
FVAL(Frl, Fc1, R1, 1, L1, 100e-6);
FVAL(Fcl, Fc1, C1, 10e-6, L1, 100e-6);
Qpar(1, 10e-6, 100e-6);

コメント部分に、想定している回路形式をキャラクタで描いてあります。実際にスマホ上のエディタ(monospaceフォントの11ポイント)で見るとこんな感じ。
editFilter_mac使い方は以下だけです。

FVAL(フィルタ、求める変数、既定変数1、1の値、既定変数2、2の値)

フィルタのところには、以下のどれかを指定します

    • Frc、RCフィルタ、LPFでもHPFでも同じ
    • Frl、RLフィルタ、LPFでもHPFでも同じ、
    • Fcl、LCフィルタ、LPFでもHPFでも同じ

RLCバンドパスフィルタのときには上記の3つとも使用します。

求める変数は、以下のどれかを指定します。

    • Fc1、遮断周波数[Hz]
    • R1、抵抗の値[Ω]
    • C1、コンデンサの値[F]
    • L1、コイルの値[H]

例えば、RCフィルタで遮断周波数を求めようとする場合は、Fc1と指定します。そのとき、R1とC1の値を以下のようにして与えれば、Fc1が求まります。

FVAL(Frc, Fc1, R1, 1, C1, 10e-6)

なお、RLCバンドパスフィルタの時は、以下の実施例のように3項目全てを使います。

MoA上での実行

実際にAndroid上で実行した結果が以下に。MoAfilter

 

LTspiceでRLCバンドパスフィルタをシミュレーション

念のため、以下にLTspiceシミュレーションの結果を掲げます。回路が以下に。LCbandpassCircuit

シミュレーション結果が以下に。LCbandpassSim

通過域付近を拡大したものが以下に。LCbandpassSim2

こんなもんかいな~。やっつけ。

やっつけな日常(75) Maxima on Android、ベクトルの外積、3次元表示 へ戻る