Modules

circuits.py: Circuit synthesis module

This module is used for constructing filters from the transfer function specifications. It is intended for use with mrfilter, but can be used standalone.

Note

This file documents only those functions and methods with complicated math. Its purpose is to make verification of the math easy. Most equations reference one of the sources, but for some the full derivation is given. For general API documentation, import the module and study the docstrings.

circuits.pbgain(Z, P, k)

Returns the passband gain of the given transfer func in ZPk format

For a filter with z zeros and p poles, the transfer function in [b, a] format will be

T(s) = \frac{b_z s^z + b_{z-1} s^{z-1} + ... + b_1 s + b_0}
            {a_p s^z + a_{p-1} s^{p-1} + ... + a_1 s + a_0}, 
            \text{for } s = j \omega

For low-pass filters, the passband gain will be

\lim_{x \rightarrow 0} T(s) = \frac{b_0}{a_0}

For high-pass filters, the passband gain will be

\lim_{x \rightarrow \inf} T(s) = \left\{
\begin{array}{rl}
\pm \infty       & \text{if } z > p \\
\frac{b_z}{a_p}  & \text{if } z = p \\
0                & \text{if } z < p \\
\end{array} \right.

Todo

passband gain for band-pass, band-stop, all-pass

class circuits.Biquad(Z, P, k)

General representation of a filter with a biquadratic transfer function

get_q()

Return the filter’s Q factor.

From [1], Figure 5.2

get_w0()

Return the filter’s ѡ0

From [1], Figure 5.2

synth_q()

Calculate the q from synthesized component values

Relevant equations:

  • low-pass: [1], eq 6.56
  • band-pass: [1], eq 7.30
  • high-pass: TODO: check the TI app note
  • band-stop: [1], eq 12.33

In all cases, the s^1 term of the denominator equals \omega_0 / Q

synth_w0()

Calculate the w0 from synthesized component values.

The equations are the same as for synth_q

In all cases, the s^0 term of the denominator equals \omega_0^2

class circuits.Cascade(approx, topology)

Represent a cascade connection of multiple filters

synth_tf()

Return the transfer function of the entire cascade from calculated component values.

From [2], §9.8.1

class circuits.OnePole(Z, P, k)

One pole R-C filter

get_sens(property, refdes)

Return the Bode sensitvity of property wrt refdes.

Supported properties: ѡ0, h

ѡ0 and h are identically defined for low-pass and high-pass filters. So their sensitivities are also identical. Q = \frac{1}{2}, from [1], eq. 5.9 .

\omega_0 = \frac{1}{R1 C1} &= R1^{-1} C1^{-1} \\
\therefore S_{R1}^{\omega_0} &= S_{C1}^{\omega_0} = -1

Using eq 9.32 from [1]:

h &= 1 + \frac{R3}{R2} = 1 + R3 R2^{-1} \\
S_{R2}^h &= \frac{1 \cdot S_{R2}^1 + 
\frac{R3}{R2} S_{R2}^{R3/R2}}{1 + \frac{R3}{R2}} = -1  \\
S_{R3}^h &= \frac{0 + \frac{R3}{R2} \cdot 1}{1 + \frac{R3}{R2}} = 
\frac{1}{1 + \frac{R2}{R3}}

synth_tf()

Return the transfer function of the entire cascade from calculated component values.

Low pass case from [1], eq. 3.3

_synthesize()

Perform the circuit synthesis.

The equations to satisfy are:

\omega_0 &= \frac{1}{R1 C1} \\
h &= 1 + \frac{R3}{R2}

class circuits.SallenKey(Z, P, k)

Generalized Sallen-Key filter, without resistive gain enhancement

get_sens(property, refdes)

Return the Bode sensitvity of property wrt refdes.

Supported properties: w0, q, h.

For low-pass filters, the equations are from [1], pp 269-270. However, note that eq. 9.58 contains an error. The correct equation is

S_{R1}^Q = -\frac{1}{2} + Q \sqrt{\frac{R2 C2}{R1 C1}}

The high-pass SallenKey transfer function is (from page 67 of my notebook)

T(s) &= \frac{h s^2}{s^2 + (\frac{1}{C2 R2} + \frac{1}{C1 R2} + \frac{1}{C1 R1} - \frac{h}{C1 R1}) s + 1 / (C1 C2 R1 C2)} \\
\omega_0 &= 1 / \sqrt{C1 C2 R1 R2}

So S_x^{\omega_0} is the same as for low-pass filters, for all x. Similarly, S_x^h is the same for all shapes of SallenKey filter. To find the sensitivities of Q, we use the same strategy as used in §9.2 of [1].

Y &= \frac{\omega_0}{Q} = \frac{1}{C2 R2} + \frac{1}{C1 R2} + \frac{1 - h}{C1 R1} \\
S_x^Q &= S_x^{\omega_0} - S_x^Y \\
S_x^Y &= \frac{x}{Y}\frac{\partial Y}{\partial x} = 
  x\frac{Q}{\omega_0}\frac{\partial Y}{\partial x}\\
S_{C2}^Y &= C2 \frac{Q}{\omega_0}\frac{\partial Y}{\partial C2} 
  = C2 \frac{Q}{\omega_0} \frac{-1}{R2 {C2}^2}
  = -Q \frac{\sqrt{R1 R2 C1 C2}}{R2 C2}
  = -Q \sqrt{\frac{R1 C1}{R2 C2}} \\
\Rightarrow S_{C2}^Q &= -\frac{1}{2} + Q \sqrt{\frac{R1 C1}{R2 C2}} \\
S_{R2}^Y &= R2 \frac{Q}{\omega_0} \frac{\partial Y}{\partial C2}
  = R2 \frac{Q}{\omega_0} 
    \left(\frac{-1}{C2 {R2}^2} - \frac{1}{C1 {R2}^2}\right)
  = -Q \left(\frac{\sqrt{R1 R2 C1 C2}}{C2 R2} + 
    \frac{\sqrt{R1 R2 C1 C2}}{C1 R2}\right)
  = -Q  \left(\sqrt{\frac{R1 C1}{R2 c2}} + 
    \sqrt{\frac{C2 R1}{C1 R2}}\right) \\
\Rightarrow S_{R2}^Q &= -\frac{1}{2} +
    Q \left(\sqrt{\frac{R1 C1}{R2 c2}} + 
    \sqrt{\frac{C2 R1}{C1 R2}}\right) \\
S_{R1}^Y &= R1 \frac{Q}{\omega_0} \frac{h-1}{C1 {R1}^2}
  = Q (h-1) \sqrt{\frac{C2 R2}{C1 R1}} \\
\Rightarrow S_{R1}^Q &= -\frac{1}{2} - 
    Q(h-1)\sqrt{\frac{C2 R2}{C1 R1}} \\
S_{C1}^Y &= C1 \frac{Q}{\omega_0} \left(\frac{-1}{R2 {C1}^2} + 
  \frac{h-1}{R1 {C1}^2} \right)
  = Q \left( -\sqrt{\frac{R1 C2}{R2 C1}} + 
    (h-1)\sqrt{\frac{R2 C2}{R1 C1}}\right)\\
\Rightarrow S_{C1}^Q &= -\frac{1}{2}  - 
    Q \left( -\sqrt{\frac{R1 C2}{R2 C1}} + 
    (h-1)\sqrt{\frac{R2 C2}{R1 C1}}\right)

To find the sensitivities of h, first rewrite Y in terms of R3 and R4.

Y &= \frac{1}{C2 R2} + \frac{1}{C1 R2} - \frac{R3}{R4 C1 R1} \\
S_{R4}^Y &= R_4 \frac{Q}{\omega_0} 
    \left(\frac{-R_3}{{R_4}^2 R1 C1} \right)
  = -\frac{Q R_3}{\omega_0 R_4 R1 C1}
  = - Q (1-h) \sqrt{\frac{R2 C2}{R1 C1}} \\
\Rightarrow S_{R4}^Q &= -Q (h-1) \sqrt{\frac{R2 C2}{R1 C1}} \\
S_{R3}^Y &= R_3 \frac{Q}{\omega_0} \left(\frac{1}{R_4 C1 R1} \right)
  = Q (1-h) \sqrt{\frac{C2 R2}{C1 R1}} \\
\Rightarrow S_{R3}^Q &= Q (h-1) \sqrt{\frac{C2 R2}{C1 R1}}

Todo

Derive sensitivities for bandpass, bandstop, and allpass

synth_tf()

Calculate the transfer function from synthesize component values.

The low-pass case is given in [1] eq 6.55 . The high-pass case is given in [3], eq 11. Note that [3] uses a different convention for resistor numbering than is used in this program. Rearranging eq 11 gives the transfer function as used here:

T(s) = \frac{h s^2}{s^2 + \left(\frac{1}{C2 R2} + \frac{1}{C1 R2} +
    \frac{1}{C1 R1} - \frac{h}{R1 C1}\right) + 
    \frac{1}{C1 C2 R1 R2}}

Todo

band-pass, band-stop, and allpass

_synthesize()

Perform the componenet value calculations.

Strategy is from [3]:

  1. try simplification 4 (R1=R2, C1=C2)
  2. if that fails, try simplification 3 (C1=C2)
  3. if that fails, try simplification 1, the most general case

Simplification 2 is not used here because it is just a special case of simplification 1.

_simplification4(w0, q, h)

Attempt to synthesize using simplification 4 from SLOA024B.

Simplification 4 sets R1=R2 and C1=C2

_simplification3(w0, q, h)

Attempt to synthesize using simplification 3 from SLOA024B.

Simplification 3 sets C1=C2 and R2 = m*R1

_simplification1(w0, q, h)

Attempt to synthesize using simplification 1 from SLOA024B.

Simplification 1 is the most general. It sets R2=m*R1 and C2=n*C1

[1](1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) M. E. VanValkenburg, Analog Filter Design. New York, 1982
[2]Alan V. Oppenheim, Alan S. Willsky, S. Hamid Nawab, Signals & Systems 2nd edition. New Jersey, 1983
[3](1, 2, 3) Texas Instruments, “Analysis of the Sallen-Key Architecture (Rev. B)” , Texas Instruments, SLOA024B, September 2002. [Online]. Available: http://focus.ti.com/general/docs/litabsmultiplefilelist.tsp?literatureNumber=sloa024b . [Accessed: May, 2009].