#import os
from sympy import *
import numpy as np
from tabulate import tabulate
from scipy import signal
import matplotlib.pyplot as plt
import pandas as pd
import SymMNA
from IPython.display import display, Markdown, Math, Latex
init_printing()
16 Test 12
The circuit in Figure 16.1 is a 7th order low pass filter, Chebyshev response, 0.1 dB of ripple from Zverev (1967). This test circuit is a ladder filter realization of a Chebyshev filter.
The netlist generated by LTSpice:
C3 2 0 3.7642
I1 0 1 AC 1
C5 3 0 4.015
C7 4 0 3.0182 Rser=0
L2 1 2 0.7529 Rser=0
L4 2 3 0.9276 Rser=0
L6 3 4 0.9142 Rser=0
Rs 1 0 0.5
Rl 4 0 1
C1 1 0 1.5948
16.1 Load the net list
= '''
net_list C3 2 0 3.7642
I1 0 1 1
C5 3 0 4.015
C7 4 0 3.0182
L2 1 2 0.7529
L4 2 3 0.9276
L6 3 4 0.9142
Rs 1 0 0.5
Rl 4 0 1
C1 1 0 1.5948
'''
16.2 Call the symbolic modified nodal analysis function
= SymMNA.smna(net_list) report, network_df, i_unk_df, A, X, Z
Display the equations
# reform X and Z into Matrix type for printing
= Matrix(X)
Xp = Matrix(Z)
Zp = ''
temp for i in range(len(X)):
+= '${:s}$<br>'.format(latex(Eq((A*Xp)[i:i+1][0],Zp[i])))
temp
Markdown(temp)
\(I_{L2} + v_{1} \left(C_{1} s + \frac{1}{Rs}\right) = I_{1}\)
\(C_{3} s v_{2} - I_{L2} + I_{L4} = 0\)
\(C_{5} s v_{3} - I_{L4} + I_{L6} = 0\)
\(- I_{L6} + v_{4} \left(C_{7} s + \frac{1}{Rl}\right) = 0\)
\(- I_{L2} L_{2} s + v_{1} - v_{2} = 0\)
\(- I_{L4} L_{4} s + v_{2} - v_{3} = 0\)
\(- I_{L6} L_{6} s + v_{3} - v_{4} = 0\)
16.2.1 Netlist statistics
print(report)
Net list report
number of lines in netlist: 10
number of branches: 10
number of nodes: 4
number of unknown currents: 3
number of RLC (passive components): 9
number of inductors: 3
number of independent voltage sources: 0
number of independent current sources: 1
number of Op Amps: 0
number of E - VCVS: 0
number of G - VCCS: 0
number of F - CCCS: 0
number of H - CCVS: 0
number of K - Coupled inductors: 0
16.2.2 Connectivity Matrix
A
\(\displaystyle \left[\begin{matrix}C_{1} s + \frac{1}{Rs} & 0 & 0 & 0 & 1 & 0 & 0\\0 & C_{3} s & 0 & 0 & -1 & 1 & 0\\0 & 0 & C_{5} s & 0 & 0 & -1 & 1\\0 & 0 & 0 & C_{7} s + \frac{1}{Rl} & 0 & 0 & -1\\1 & -1 & 0 & 0 & - L_{2} s & 0 & 0\\0 & 1 & -1 & 0 & 0 & - L_{4} s & 0\\0 & 0 & 1 & -1 & 0 & 0 & - L_{6} s\end{matrix}\right]\)
16.2.3 Unknown voltages and currents
X
\(\displaystyle \left[ v_{1}, \ v_{2}, \ v_{3}, \ v_{4}, \ I_{L2}, \ I_{L4}, \ I_{L6}\right]\)
16.2.4 Known voltages and currents
Z
\(\displaystyle \left[ I_{1}, \ 0, \ 0, \ 0, \ 0, \ 0, \ 0\right]\)
16.2.5 Network dataframe
network_df
element | p node | n node | cp node | cn node | Vout | value | Vname | Lname1 | Lname2 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | C3 | 2 | 0 | NaN | NaN | NaN | 3.7642 | NaN | NaN | NaN |
1 | I1 | 0 | 1 | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
2 | C5 | 3 | 0 | NaN | NaN | NaN | 4.015 | NaN | NaN | NaN |
3 | C7 | 4 | 0 | NaN | NaN | NaN | 3.0182 | NaN | NaN | NaN |
4 | L2 | 1 | 2 | NaN | NaN | NaN | 0.7529 | NaN | NaN | NaN |
5 | L4 | 2 | 3 | NaN | NaN | NaN | 0.9276 | NaN | NaN | NaN |
6 | L6 | 3 | 4 | NaN | NaN | NaN | 0.9142 | NaN | NaN | NaN |
7 | Rs | 1 | 0 | NaN | NaN | NaN | 0.5 | NaN | NaN | NaN |
8 | Rl | 4 | 0 | NaN | NaN | NaN | 1.0 | NaN | NaN | NaN |
9 | C1 | 1 | 0 | NaN | NaN | NaN | 1.5948 | NaN | NaN | NaN |
16.2.6 Unknown current dataframe
i_unk_df
element | p node | n node | |
---|---|---|---|
0 | L2 | 1 | 2 |
1 | L4 | 2 | 3 |
2 | L6 | 3 | 4 |
16.2.7 Build the network equation matrix
# Put matrices into SymPy
= Matrix(X)
X = Matrix(Z)
Z
= Eq(A*X,Z) NE_sym
Turn the free symbols into SymPy variables.
str(NE_sym.free_symbols).replace('{','').replace('}','')) var(
\(\displaystyle \left( Rl, \ L_{4}, \ v_{1}, \ I_{L2}, \ v_{4}, \ v_{3}, \ I_{1}, \ I_{L6}, \ v_{2}, \ C_{3}, \ C_{1}, \ I_{L4}, \ s, \ C_{5}, \ C_{7}, \ L_{2}, \ Rs, \ L_{6}\right)\)
16.3 Symbolic solution
= solve(NE_sym,X) U_sym
Display the symbolic solution
= ''
temp for i in U_sym.keys():
+= '${:s} = {:s}$<br>'.format(latex(i),latex(U_sym[i]))
temp
Markdown(temp)
\(v_{1} = \frac{C_{3} C_{5} C_{7} I_{1} L_{2} L_{4} L_{6} Rl Rs s^{6} + C_{3} C_{5} I_{1} L_{2} L_{4} L_{6} Rs s^{5} + C_{3} C_{5} I_{1} L_{2} L_{4} Rl Rs s^{4} + C_{3} C_{7} I_{1} L_{2} L_{4} Rl Rs s^{4} + C_{3} C_{7} I_{1} L_{2} L_{6} Rl Rs s^{4} + C_{3} I_{1} L_{2} L_{4} Rs s^{3} + C_{3} I_{1} L_{2} L_{6} Rs s^{3} + C_{3} I_{1} L_{2} Rl Rs s^{2} + C_{5} C_{7} I_{1} L_{2} L_{6} Rl Rs s^{4} + C_{5} C_{7} I_{1} L_{4} L_{6} Rl Rs s^{4} + C_{5} I_{1} L_{2} L_{6} Rs s^{3} + C_{5} I_{1} L_{2} Rl Rs s^{2} + C_{5} I_{1} L_{4} L_{6} Rs s^{3} + C_{5} I_{1} L_{4} Rl Rs s^{2} + C_{7} I_{1} L_{2} Rl Rs s^{2} + C_{7} I_{1} L_{4} Rl Rs s^{2} + C_{7} I_{1} L_{6} Rl Rs s^{2} + I_{1} L_{2} Rs s + I_{1} L_{4} Rs s + I_{1} L_{6} Rs s + I_{1} Rl Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
\(v_{2} = \frac{C_{5} C_{7} I_{1} L_{4} L_{6} Rl Rs s^{4} + C_{5} I_{1} L_{4} L_{6} Rs s^{3} + C_{5} I_{1} L_{4} Rl Rs s^{2} + C_{7} I_{1} L_{4} Rl Rs s^{2} + C_{7} I_{1} L_{6} Rl Rs s^{2} + I_{1} L_{4} Rs s + I_{1} L_{6} Rs s + I_{1} Rl Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
\(v_{3} = \frac{C_{7} I_{1} L_{6} Rl Rs s^{2} + I_{1} L_{6} Rs s + I_{1} Rl Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
\(v_{4} = \frac{I_{1} Rl Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
\(I_{L2} = \frac{C_{3} C_{5} C_{7} I_{1} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} I_{1} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} I_{1} L_{4} Rl Rs s^{3} + C_{3} C_{7} I_{1} L_{4} Rl Rs s^{3} + C_{3} C_{7} I_{1} L_{6} Rl Rs s^{3} + C_{3} I_{1} L_{4} Rs s^{2} + C_{3} I_{1} L_{6} Rs s^{2} + C_{3} I_{1} Rl Rs s + C_{5} C_{7} I_{1} L_{6} Rl Rs s^{3} + C_{5} I_{1} L_{6} Rs s^{2} + C_{5} I_{1} Rl Rs s + C_{7} I_{1} Rl Rs s + I_{1} Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
\(I_{L4} = \frac{C_{5} C_{7} I_{1} L_{6} Rl Rs s^{3} + C_{5} I_{1} L_{6} Rs s^{2} + C_{5} I_{1} Rl Rs s + C_{7} I_{1} Rl Rs s + I_{1} Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
\(I_{L6} = \frac{C_{7} I_{1} Rl Rs s + I_{1} Rs}{C_{1} C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl Rs s^{7} + C_{1} C_{3} C_{5} L_{2} L_{4} L_{6} Rs s^{6} + C_{1} C_{3} C_{5} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{4} Rl Rs s^{5} + C_{1} C_{3} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{3} L_{2} L_{4} Rs s^{4} + C_{1} C_{3} L_{2} L_{6} Rs s^{4} + C_{1} C_{3} L_{2} Rl Rs s^{3} + C_{1} C_{5} C_{7} L_{2} L_{6} Rl Rs s^{5} + C_{1} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{1} C_{5} L_{2} L_{6} Rs s^{4} + C_{1} C_{5} L_{2} Rl Rs s^{3} + C_{1} C_{5} L_{4} L_{6} Rs s^{4} + C_{1} C_{5} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{2} Rl Rs s^{3} + C_{1} C_{7} L_{4} Rl Rs s^{3} + C_{1} C_{7} L_{6} Rl Rs s^{3} + C_{1} L_{2} Rs s^{2} + C_{1} L_{4} Rs s^{2} + C_{1} L_{6} Rs s^{2} + C_{1} Rl Rs s + C_{3} C_{5} C_{7} L_{2} L_{4} L_{6} Rl s^{6} + C_{3} C_{5} C_{7} L_{4} L_{6} Rl Rs s^{5} + C_{3} C_{5} L_{2} L_{4} L_{6} s^{5} + C_{3} C_{5} L_{2} L_{4} Rl s^{4} + C_{3} C_{5} L_{4} L_{6} Rs s^{4} + C_{3} C_{5} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{2} L_{4} Rl s^{4} + C_{3} C_{7} L_{2} L_{6} Rl s^{4} + C_{3} C_{7} L_{4} Rl Rs s^{3} + C_{3} C_{7} L_{6} Rl Rs s^{3} + C_{3} L_{2} L_{4} s^{3} + C_{3} L_{2} L_{6} s^{3} + C_{3} L_{2} Rl s^{2} + C_{3} L_{4} Rs s^{2} + C_{3} L_{6} Rs s^{2} + C_{3} Rl Rs s + C_{5} C_{7} L_{2} L_{6} Rl s^{4} + C_{5} C_{7} L_{4} L_{6} Rl s^{4} + C_{5} C_{7} L_{6} Rl Rs s^{3} + C_{5} L_{2} L_{6} s^{3} + C_{5} L_{2} Rl s^{2} + C_{5} L_{4} L_{6} s^{3} + C_{5} L_{4} Rl s^{2} + C_{5} L_{6} Rs s^{2} + C_{5} Rl Rs s + C_{7} L_{2} Rl s^{2} + C_{7} L_{4} Rl s^{2} + C_{7} L_{6} Rl s^{2} + C_{7} Rl Rs s + L_{2} s + L_{4} s + L_{6} s + Rl + Rs}\)
16.4 Construct a dictionary of element values
= SymMNA.get_part_values(network_df)
element_values
# display the component values
for k,v in element_values.items():
print('{:s} = {:s}'.format(str(k), str(v)))
C3 = 3.7642
I1 = 1.0
C5 = 4.015
C7 = 3.0182
L2 = 0.7529
L4 = 0.9276
L6 = 0.9142
Rs = 0.5
Rl = 1.0
C1 = 1.5948
16.5 DC operating point
= NE_sym.subs(element_values)
NE = NE.subs({s:0}) NE_dc
Display the equations with numeric values.
= ''
temp for i in range(shape(NE_dc.lhs)[0]):
+= '${:s} = {:s}$<br>'.format(latex(NE_dc.rhs[i]),latex(NE_dc.lhs[i]))
temp
Markdown(temp)
\(1.0 = I_{L2} + 2.0 v_{1}\)
\(0 = - I_{L2} + I_{L4}\)
\(0 = - I_{L4} + I_{L6}\)
\(0 = - I_{L6} + 1.0 v_{4}\)
\(0 = v_{1} - v_{2}\)
\(0 = v_{2} - v_{3}\)
\(0 = v_{3} - v_{4}\)
Solve for voltages and currents.
= solve(NE_dc,X) U_dc
Display the numerical solution
Six significant digits are displayed so that results can be compared to LTSpice.
= ['unknown', 'mag']
table_header = []
table_row
for name, value in U_dc.items():
str(name),float(value)])
table_row.append([
print(tabulate(table_row, headers=table_header,colalign = ('left','decimal'),tablefmt="simple",floatfmt=('5s','.6f')))
unknown mag
--------- --------
v1 0.333333
v2 0.333333
v3 0.333333
v4 0.333333
I_L2 0.333333
I_L4 0.333333
I_L6 0.333333
The node voltages and current through the sources are solved for. The Sympy generated solution matches the LTSpice results:
--- Operating Point ---
V(2): 0.333333 voltage
V(1): 0.333333 voltage
V(3): 0.333333 voltage
V(4): 0.333333 voltage
I(C3): 1.25473e-12 device_current
I(C5): 1.33833e-12 device_current
I(C7): 1.00607e-12 device_current
I(C1): 5.316e-13 device_current
I(L2): 0.333333 device_current
I(L4): 0.333333 device_current
I(L6): 0.333333 device_current
I(I1): 1 device_current
I(Rs): 0.666667 device_current
I(Rl): 0.333333 device_current
The results from LTSpice are slightly different in some cases starting at the 2nd decimal place.
16.5.1 AC analysis
Solve equations for \(\omega\) equal to 1 radian per second, s = 1j. V1 is the AC source, magnitude of 10
= NE_sym.subs(element_values)
NE = NE.subs({s:1j}) NE_w1
Display the equations with numeric values.
= ''
temp for i in range(shape(NE_w1.lhs)[0]):
+= '${:s} = {:s}$<br>'.format(latex(NE_w1.rhs[i]),latex(NE_w1.lhs[i]))
temp
Markdown(temp)
\(1.0 = I_{L2} + v_{1} \cdot \left(2.0 + 1.5948 i\right)\)
\(0 = - I_{L2} + I_{L4} + 3.7642 i v_{2}\)
\(0 = - I_{L4} + I_{L6} + 4.015 i v_{3}\)
\(0 = - I_{L6} + v_{4} \cdot \left(1.0 + 3.0182 i\right)\)
\(0 = - 0.7529 i I_{L2} + v_{1} - v_{2}\)
\(0 = - 0.9276 i I_{L4} + v_{2} - v_{3}\)
\(0 = - 0.9142 i I_{L6} + v_{3} - v_{4}\)
Solve for voltages and currents.
= solve(NE_w1,X) U_w1
Display the numerical solution
Six significant digits are displayed so that results can be compared to LTSpice.
= ['unknown', 'mag','phase, deg']
table_header = []
table_row
for name, value in U_w1.items():
str(name),float(abs(value)),float(arg(value)*180/np.pi)])
table_row.append([
print(tabulate(table_row, headers=table_header,colalign = ('left','decimal','decimal'),tablefmt="simple",floatfmt=('5s','.6f','.6f')))
unknown mag phase, deg
--------- -------- ------------
v1 0.247674 43.979099
v2 0.596900 -119.590485
v3 0.467235 71.054634
v4 0.235668 -81.486420
I_L2 1.112227 -34.389344
I_L4 1.142319 155.081675
I_L6 0.749319 -9.817657
--- AC Analysis ---
frequency: 0.159155 Hz
V(2): mag: 0.5969 phase: -119.59° voltage
V(1): mag: 0.247674 phase: 43.9791° voltage
V(3): mag: 0.467235 phase: 71.0546° voltage
V(4): mag: 0.235668 phase: -81.4864° voltage
I(C3): mag: 2.24685 phase: -29.5905° device_current
I(C5): mag: 1.87595 phase: 161.055° device_current
I(C7): mag: 0.711294 phase: 8.51358° device_current
I(C1): mag: 0.394991 phase: 133.979° device_current
I(L2): mag: 1.11223 phase: -34.3893° device_current
I(L4): mag: 1.14232 phase: 155.082° device_current
I(L6): mag: 0.749319 phase: -9.81766° device_current
I(I1): mag: 1 phase: 0° device_current
I(Rs): mag: 0.495349 phase: 43.9791° device_current
I(Rl): mag: 0.235668 phase: -81.4864° device_current
16.5.2 AC Sweep
Looking at node 4 voltage and comparing the results with those obtained from LTSpice. The frequency sweep is from 0.01 Hz to 1 Hz.
= NE_sym.subs(element_values) NE
Display the equations with numeric values.
= ''
temp for i in range(shape(NE.lhs)[0]):
+= '${:s} = {:s}$<br>'.format(latex(NE.rhs[i]),latex(NE.lhs[i]))
temp
Markdown(temp)
\(1.0 = I_{L2} + v_{1} \cdot \left(1.5948 s + 2.0\right)\)
\(0 = - I_{L2} + I_{L4} + 3.7642 s v_{2}\)
\(0 = - I_{L4} + I_{L6} + 4.015 s v_{3}\)
\(0 = - I_{L6} + v_{4} \cdot \left(3.0182 s + 1.0\right)\)
\(0 = - 0.7529 I_{L2} s + v_{1} - v_{2}\)
\(0 = - 0.9276 I_{L4} s + v_{2} - v_{3}\)
\(0 = - 0.9142 I_{L6} s + v_{3} - v_{4}\)
Solve for voltages and currents.
= solve(NE,X) U_ac
16.5.3 Plot the voltage at node 2
= U_ac[v4] H
= fraction(H) #returns numerator and denominator
num, denom
# convert symbolic to numpy polynomial
= np.array(Poly(num, s).all_coeffs(), dtype=float)
a = np.array(Poly(denom, s).all_coeffs(), dtype=float)
b = (a, b) system
#x = np.linspace(0.01*2*np.pi, 1*2*np.pi, 2000, endpoint=True)
= np.logspace(-2, 0, 200, endpoint=False)*2*np.pi
x = signal.bode(system, w=x) # returns: rad/s, mag in dB, phase in deg w, mag, phase
Load the csv file of node 10 voltage over the sweep range and plot along with the results obtained from SymPy.
= 'test_12_v1.csv' # data from LTSpice
fn = np.genfromtxt(fn, delimiter=',') LTSpice_data
# initaliaze some empty arrays
= np.zeros(len(LTSpice_data))
frequency = np.zeros(len(LTSpice_data)).astype(complex)
voltage
# convert the csv data to complez numbers and store in the array
for i in range(len(LTSpice_data)):
= LTSpice_data[i][0]
frequency[i] = LTSpice_data[i][1] + LTSpice_data[i][2]*1j voltage[i]
Plot the results.
Using
np.unwrap(2 * phase) / 2)
to keep the pahse plots the same.
0] frequency[
\(\displaystyle 0.01\)
-1] frequency[
\(\displaystyle 1.0\)
= plt.subplots()
fig, ax1 'magnitude, dB')
ax1.set_ylabel('frequency, Hz')
ax1.set_xlabel(
20*np.log10(np.abs(voltage)),'-r') # Bode magnitude plot
plt.semilogx(frequency, /(2*np.pi), mag,'-b') # Bode magnitude plot
plt.semilogx(w
='y')
ax1.tick_params(axis#ax1.set_ylim((-30,20))
plt.grid()
# instantiate a second y-axes that shares the same x-axis
= ax1.twinx()
ax2 = 'tab:blue'
color
2*np.angle(voltage)/2)*180/np.pi,':',color=color) # Bode phase plot
plt.semilogx(frequency, np.unwrap(/(2*np.pi), phase,':',color='tab:red') # Bode phase plot
plt.semilogx(w
'phase, deg',color=color)
ax2.set_ylabel(='y', labelcolor=color)
ax2.tick_params(axis#ax2.set_ylim((-5,25))
'Magnitude and phase response')
plt.title( plt.show()
The SymPy and LTSpice results overlay each other.
= plt.subplots()
fig, ax1 'magnitude difference')
ax1.set_ylabel('frequency, Hz')
ax1.set_xlabel(
0:-1], np.abs(voltage[0:-1]) - 10**(mag/20),'-r') # Bode magnitude plot
plt.semilogx(frequency[#plt.semilogx(w/(2*np.pi), mag,'-b') # Bode magnitude plot
='y')
ax1.tick_params(axis#ax1.set_ylim((-30,20))
plt.grid()
# instantiate a second y-axes that shares the same x-axis
= ax1.twinx()
ax2 = 'tab:blue'
color
0:-1], np.unwrap(2*np.angle(voltage[0:-1])/2)*180/np.pi - phase,':',color=color) # Bode phase plot
plt.semilogx(frequency[#plt.semilogx(w/(2*np.pi), phase,':',color='tab:red') # Bode phase plot
'phase difference, deg',color=color)
ax2.set_ylabel(='y', labelcolor=color)
ax2.tick_params(axis#ax2.set_ylim((-5,25))
'Magnitude and phase response difference')
plt.title( plt.show()
The SymPy and LTSpice results overlay each other, but not to the same precision as in previous tests.
16.6 Poles and zeros of the transfer function
The poles and zeros of the transfer function can easly be obtained with the following code:
= fraction(H) #returns numerator and denominator
H_num, H_denom
# convert symbolic to numpy polynomial
= np.array(Poly(H_num, s).all_coeffs(), dtype=float)
a = np.array(Poly(H_denom, s).all_coeffs(), dtype=float)
b = signal.TransferFunction(a,b) sys
= np.roots(sys.num)
sys_zeros = np.roots(sys.den) sys_poles
16.6.0.1 Low pass filter pole zero plot
The poles and zeros of the preamp transfer function are plotted.
'ob', markerfacecolor='none')
plt.plot(np.real(sys_zeros), np.imag(sys_zeros), 'xr')
plt.plot(np.real(sys_poles), np.imag(sys_poles), 'Zeros', 'Poles'], loc=1)
plt.legend(['Pole / Zero Plot')
plt.title('real part, \u03B1')
plt.xlabel('imaginary part, j\u03C9')
plt.ylabel(
plt.grid() plt.show()
Poles and zeros of the transfer function plotted on the complex plane. The units are in radian frequency.
Printing these values in Hz.
print('number of zeros: {:d}'.format(len(sys_zeros)))
for i in sys_zeros:
print('{:,.2f} Hz'.format(i/(2*np.pi)))
number of zeros: 0
print('number of poles: {:d}'.format(len(sys_poles)))
for i in sys_poles:
print('{:,.2f} Hz'.format(i/(2*np.pi)))
number of poles: 7
-0.01+0.16j Hz
-0.01-0.16j Hz
-0.04+0.12j Hz
-0.04-0.12j Hz
-0.05+0.07j Hz
-0.05-0.07j Hz
-0.06+0.00j Hz
16.7 Impulse and step response
Use the SciPy functions impulse2 and step2 to plot the impulse and step response of the system.
The impulse and step response of the filter are plotted below. Any linear, time-invariant is completely characterized by its impulse response. The transfer function is the Laplace transform of the impulse response. The impulse response defines the response of a linear time-invariant system for all frequencies.
In electronic engineering and control theory, step response is the time behavior of the outputs of a general system when its inputs change from zero to one in a very short time.
1,2,figsize=(15, 5))
plt.subplots(
# using subplot function and creating
# plot one
1, 2, 1)
plt.subplot(
# impulse response
= signal.impulse2(sys,N=500)
t, y /1e-3, y)
plt.plot(t'Impulse response')
plt.title('volts')
plt.ylabel('time, msec')
plt.xlabel(
plt.grid()
# using subplot function and creating plot two
1, 2, 2)
plt.subplot(
= signal.step2(sys,N=500)
t, y /1e-3, y)
plt.plot(t'Step response')
plt.title('volts')
plt.ylabel('time, msec')
plt.xlabel(
plt.grid()
# show plot
plt.show()
16.7.1 Low pass filter group delay
The following python code calculates and plots group delay. Frequency components of a signal are delayed when passed through a circuit and the signal delay will be different for the various frequencies unless the circuit has the property of being linear phase. The delay variation means that signals consisting of multiple frequency components will suffer distortion because these components are not delayed by the same amount of time at the output of the device.
Group delay: \(\tau _{g}(\omega )=-\frac {d\phi (\omega )}{d\omega }\)
#w_preamp, mag_preamp, phase_preamp = bp_sys.bode(w=x_axis_range)
'group delay')
plt.title(/(2*np.pi), -np.gradient(phase*np.pi/180)/np.gradient(w),'-',label='group delay')
plt.semilogx(w
'Group delay, sec')
plt.ylabel('Frequency, Hz')
plt.xlabel(
plt.legend()
plt.grid() plt.show()