commit 220fa85dfa51bb6de9b9074db7f4b3c44bb95e3c Author: Andrej Date: Wed Mar 10 16:04:43 2021 +0100 skripta za mikrotrakasto linijo in pasovno sito diff --git a/__pycache__/microstrip.cpython-37.pyc b/__pycache__/microstrip.cpython-37.pyc new file mode 100644 index 0000000..f8ea340 Binary files /dev/null and b/__pycache__/microstrip.cpython-37.pyc differ diff --git a/filter.py b/filter.py new file mode 100644 index 0000000..3b4bf86 --- /dev/null +++ b/filter.py @@ -0,0 +1,123 @@ +#!/usr/bin/python3 + +import numpy as np +import scipy.optimize as opt +import microstrip as ms + +def Butterworth(n): + ''' + Return koefficents of Butterworth n-th order filter + g0 and gn+1 are assumed to be 1 + + [g0, g1, ... gn, gn+1] = Buttherworth(n) + ''' + gi = 2*np.sin((2*np.arange(1,n+1)-1)*np.pi/2/n) + return np.hstack([1,gi,1]) + +def Tchebysheff(n, ripple): + ''' + Return coefficents of Tchebysheff n-th order filter + with specified ripple in passband. + + [g0, g1, ... gn, gn+1] = Tchebysheff(n, ripple) + n <- order of filter + ripple <- ripple in passband (dB) + ''' + b = np.log(1/np.tanh(ripple/17.37)) + k = np.sinh(b/2/n) + + g = np.ones(n+2) + g[1] = 2/k*np.sin(np.pi/2/n) + for i in range(2,n+1): + g[i] = 1/g[i-1]*4*np.sin((2*i-1)*np.pi/2/n)*np.sin((2*i-3)*np.pi/2/n)/\ + (k**2+np.sin((i-1)*np.pi/n)**2) + + if n % 2 == 0: + g[-1] = 1/np.tanh(b/4)**2 + + return g + +def mclBPF(h, e_r, fbw, gk, f0): + ''' + Calculate dimensions of microstrip coupled lines bandpass + filter. + + h <- height of substrate (mm) + e_r <- dielectric constant of substrate + fbw <- fractional bandwidth of bpf + gk <- filter coefficents + f0 <- central frequency (GHz) + ''' + + n = len(gk)-2 + J = np.ones(n+1) + J[0] = np.sqrt(np.pi*fbw/2/gk[0]/gk[1]) + J[-1] = np.sqrt(np.pi*fbw/2/gk[-2]/gk[-1]) + for j in range(1,n): + J[j] = np.pi*fbw/2/np.sqrt(gk[j]*gk[j+1]) + + Zo = np.zeros(n+1) + Ze = np.zeros(n+1) + + for j in range(n+1): + Ze[j] = 50*(1+J[j]+J[j]**2) + Zo[j] = 50*(1-J[j]+J[j]**2) + + lambda4 = 3e8/f0/1e9/4 *1e3 + W = np.zeros(n+1) + s = np.zeros(n+1) + l = np.zeros(n+1) + for j in range(n+1): + x = ms.get_mcl(Ze[j],Zo[j],h,e_r,f0) + W[j] = x[0] + s[j] = x[1] + dl = ms.open_end(W[j],h,e_r,f0) + eps = ms.mcl_eps(W[j],h,s[j],e_r,f0) + # popravek z upostevanjem disperzije + l[j] = lambda4/np.sqrt(np.sqrt(eps[0]*eps[1]))-dl + #print(l[j]) + # popravek s staticnim eps + l[j] = lambda4/np.sqrt(np.sqrt(eps[2]*eps[3]))-dl + #print(l[j]) + + return {'W':W, 's':s, 'l':l, 'f':f0, 'fbw':fbw} + +def prtmclBFP(bfp): + ''' + Print filter in readable format + ''' + n = len(bfp['W']) + print("Microstrip coupled line bandpass filter:\nAll dimensions in mm.") + print("\tW\ts\tl") + for i in range(n): + print("{}:\t{:.2f}\t{:.2f}\t{:.2f}".format(i+1,bfp['W'][i],\ + bfp['s'][i],bfp['l'][i])) + + print("Length of filter: {} mm".format(sum(bfp['l']))) + print("Width of filter: {} mm".format(sum(bfp['W'])+sum(bfp['s']))) + + +if __name__ == '__main__': + gk = Tchebysheff(7,0.05) + #bfp = mclBPF(1.54, 3.66, 0.1, gk, 10.2) + bfp = mclBPF(0.76, 3.66, 0.1, gk, 10.2) + #prtmclBFP(bfp) + + print(ms.getWf(50, 0.76, 3.66, 10.2)) + + print("=== interstage filter za bfp840 ===") + gk = Butterworth(7) + bfp = mclBPF(0.8, 3.66, 0.3, gk, 10.5) + prtmclBFP(bfp) + print("=== interstage filter za bfp840 ===") + gk = Butterworth(5) + bfp = mclBPF(0.8, 3.66, 0.3, gk, 10.5) + prtmclBFP(bfp) + print("=== interstage filter za bfp840 ===") + gk = Butterworth(5) + bfp = mclBPF(0.8, 3.66, 0.05, gk, 10.5) + prtmclBFP(bfp) + print("=== interstage filter za bfp840 ===") + gk = Butterworth(3) + bfp = mclBPF(0.8, 3.66, 0.05, gk, 10.5) + prtmclBFP(bfp) diff --git a/microstrip.py b/microstrip.py new file mode 100644 index 0000000..3993a5b --- /dev/null +++ b/microstrip.py @@ -0,0 +1,333 @@ +#!/usr/bin/python3 + +import numpy as np +import scipy.optimize as opt + +np.seterr(under='ignore') +### STATIC approx +def eps_re(u, e_r): + ''' + Calculate effective dielectric constant + using the expressions given in + E. Hammerstad and O. Jensen, "Accurate Models for + Microstrip Computer-Aided Design," 1980 IEEE MTT-S + International Microwave symposium Digest, Washington, + DC, USA, 1980, pp. 407-409. + doi: 10.1109/MWSYM.1980.1124303 + + e_re = eps_re(u, e_r): + u <- ratio W/h + e_r <- substrate relative dielectric constant + e_re -> effective relative dielectric constant + of microstrip line + ''' + a = 1 + np.log((u**4 + (u/52)**2)/(u**4+0.432))/49 +\ + np.log(1+(u/18.1)**3)/18.7 + b = 0.564*( (e_r-0.9)/(e_r+3) )**(0.053) + + e_re = 0.5*(e_r+1)+0.5*(e_r-1)*(1+10/u)**(-a*b) + return e_re + +def getZc(u, e_r): + ''' + Calculate characteristic impedance Zc + using the expressions given in + E. Hammerstad and O. Jensen, "Accurate Models for + Microstrip Computer-Aided Design," 1980 IEEE MTT-S + International Microwave symposium Digest, Washington, + DC, USA, 1980, pp. 407-409. + doi: 10.1109/MWSYM.1980.1124303 + (neglected thickness of copper) + + Zc = getZc(u, e_r) + u <- ratio W/h + e_r <- substrate relative dielectric constant + Zc -> characteristic impedance of microstrip line + ''' + F = 6 + (2*np.pi-6)*np.exp(-(30.666/u)**0.7528) + e_re = eps_re(u, e_r) + Zc = (120*np.pi)/(2*np.pi*np.sqrt(e_re))*np.log(\ + F/u + np.sqrt(1 + (2/u)**2)) + return Zc + +### Dispersion correction +def eps_f(W,h,e_r,f): + ''' + Calculate effective dieletric constant using formulas given by: + M. Kirschning and R. H. Jansen, "Accurate Model for Effective + Dielectric Constant of Microstrip with Validity up to Millimeter-Wave + Frequencies," Electronics Letters, vol. 8, no. 6, pp. 272-273, + Mar. 1982. + R. H. Jansen and M. Kirschning, "Arguments and an accurate Model + for the Power-Current Formulation of Microstrip Characteristic + Impedance," Archiv für Elektronik und Übertragungstechnik (AEÜ), + vol. 37, pp. 108-112, 1983. + http://qucs.sourceforge.net/tech/node75.html + + e_re = eps_f(W,h,e_r,f) + W <- width of microstrip (mm) + h <- height of substrate (mm) + e_r <- substrate relative dielectric cosntatn + f <- frequency (GHz) + e_re -> effective dielectric constant of microstrip line + ''' + fn = f*h + u = W/h + P1 = 0.27488 + (0.6315+0.525/(1+0.0157*fn)**20)*u - 0.065683*np.exp(\ + -8.7513*u) + P2 = 0.33622*(1-np.exp(-0.03442*e_r)) + P3 = 0.0363*np.exp(-4.6*u)*(1-np.exp(-(fn/38.7)**4.97)) + P4 = 1+2.751*(1-np.exp(-(e_r/15.916)**8)) + Pf = P1*P2*((0.1844+P3*P4)*fn)**1.5763 + eps0 = eps_re(u,e_r) + return e_r - (e_r - eps0)/(1+Pf) + +def getZcf(W,h,e_r,f,R=False): + ''' + Calculate characteristic impedance using formulas given by: + M. Kirschning and R. H. Jansen, "Accurate Model for Effective + Dielectric Constant of Microstrip with Validity up to Millimeter-Wave + Frequencies," Electronics Letters, vol. 8, no. 6, pp. 272-273, + Mar. 1982. + R. H. Jansen and M. Kirschning, "Arguments and an accurate Model + for the Power-Current Formulation of Microstrip Characteristic + Impedance," Archiv für Elektronik und Übertragungstechnik (AEÜ), + vol. 37, pp. 108-112, 1983. + http://qucs.sourceforge.net/tech/node75.html + + Zc = Zcf(W,h,e_r,f,R=False) + W <- width of microstrip (mm) + h <- height of substrate (mm) + e_r <- substrate relative dielectric cosntatn + f <- frequency (GHz) + R=False <- flag telling whether to return R17 or not + Zc -> characteristic impedance of microstrip line + R17 -> parameter used to calculate impedance and coupled line + return only if R=True + ''' + fn = f*h + u = W/h + ef = eps_f(W,h,e_r,f) + e0 = eps_re(u,e_r) + + R1 = 0.03891*e_r**1.4 + R2 = 0.267*u**7 + R3 = 4.766*np.exp(-3.228*u**0.641) + R4 = 0.016 + (0.0514*e_r)**4.524 + R5 = (fn/28.843)**12.0 + R6 = 22.20*u**1.92 + + R7 = 1.206-0.3144*np.exp(-R1)*(1-np.exp(-R2)) + R8 = 1+1.275*(1-np.exp(-0.004625*R3*e_r**1.674)*(fn/18.365)**2.745) + R9 = 5.086*R4*R5*np.exp(-R6)*(e_r-1)**6/\ + ((0.3838+0.386*R4)*(1+1.2992*R5)*(1+10*(e_r-1)**6)) + + R10 = 0.00044*e_r**2.136+0.0184 + R11 = (fn/19.47)**6/(1+0.0962*(fn/19.47)**6) + R12 = 1/(1+0.00245*u**2) + R13 = 0.9408*ef**R8-0.9603 + R14 = (0.9408-R9)*e0**R8-0.9603 + R15 = 0.707*R10*(fn/12.3)**1.097 + R16 = 1+0.0503*e_r**2*R11*(1-np.exp(-(u/15)**6)) + R17 = R7*(1-1.1241*R12*np.exp(-0.026*fn**1.15656-R15)/R16) + + Z0 = getZc(u,e_r) + Zc = Z0*(R13/R14)**R17 + if R: + return (Zc, R17) + else: + return Zc + +def getWf(Zk,h,e_r,f): + ''' + Calculate width of microstrip line when also + taking in to account dispersion. + + W = getWf(Zk,h,e_r,f) + Zk <- characteristic impedance (ohms) + h <- substrate height + e_r <- substrate relative di. costant + f <- frequency (GHz) + W -> widht of microstrip line (mm) + ''' + u = opt.root_scalar(lambda X: Zk-getZcf(X,h,e_r,f),x0=h,\ + method='brentq', bracket=[0.01,100]) + return u.root + +### coupled lines +def mcl_eps(W,h,s,e_r,f): + ''' + Calculate effective odd and even permittivity of parallel + coupled microstrip lines. + M. Kirschning, R. H. Jansen, and N. H. L. Koster, + "Coupled microstrip parallel-gap model for improved filter and coupler design," + Electronics Letters, vol. 19, no. 10, pp. 377–379, May 1983, + doi: 10.1049/el:19830261. + + even, odd = mcl_eps(W,h,s,e_r,f): + W <- width of microstrip (mm) + h <- height of substrate (mm) + s <- spacing between lines (mm) + e_r <- substrate relative dielectric cosntatn + f <- frequency (GHz) + even -> even mode dielectric constant + odd -> odd mode dielectric constant + ''' + u = W/h + g = s/h + fn = f*h + + eps0 = eps_re(u,e_r) + + v = u * (20+g**2)/(10+g**2)+ g*np.exp(-g) + ae = 1+np.log((v**4+(v/52)**2)/(v**4+0.432))/49+np.log(1+(v/18.1)**3)/18.7 + be = 0.564*((e_r-0.9)/(e_r+3))**0.053 + even0 = 0.5*(e_r+1)+0.5*(e_r-1)*(1+10/v)**(-ae*be) + + ao = 0.7287*(eps0-0.5*(e_r+1))*(1-np.exp(-0.179*u)) + bo = 0.747*e_r/(0.15+e_r) + co = bo - (bo-0.207)*np.exp(-0.414*u) + do = 0.593+0.694*np.exp(-0.562*u) + odd0 = (0.5*(e_r+1)+ao-eps0)*np.exp(-co*g**do)+eps0 + + P1 = 0.27488+(0.6315+0.525/(1+0.0157*fn)**20)*u-0.065683*np.exp(-8.7513*u) + P2 = 0.33622*(1-np.exp(-0.03442*e_r)) + P3 = 0.0363*np.exp(-4.6*u)*(1-np.exp(-(fn/38.7)**4.97)) + P4 = 1+2.751*(1-np.exp(-(e_r/15.916)**8)) + P5 = 0.334*np.exp(-3.3*(e_r/15)**3)+0.746 + P6 = P5*np.exp(-(fn/18)**0.368) + P7 = 1+4.069*P6*g**0.479*np.exp(-1.347*g**0.595-0.17*g**2.5) + Fe = P1*P2*((P3*P4+0.1844*P7)*fn)**1.5763 + even = e_r - (e_r - even0)/(1+Fe) + + P8 = 0.7168*(1+1.076/(1+0.0576*(e_r-1))) + P9 = P8-0.7913*(1-np.exp(-(fn/20)**1.424))*np.arctan(2.481*(e_r/8)**0.946) + P10 = 0.242*(e_r - 1)**0.55 + P11 = 0.6366*(np.exp(-0.3401*fn)-1)*np.arctan(1.263*(u/3)**1.629) + P12 = P9 + (1-P9)/(1+1.183*u**1.376) + P13 = 1.695 * P10/(0.414+1.605*P10) + P14 = 0.8928+0.1072*(1-np.exp(-0.42*(fn/20)**3.215)) + P15 = np.abs(1-0.8928*(1+P11)*np.exp(-P13*g**1.092)*P12/P14) + Fo = P1*P2*((P3*P4+1.844)*fn*P15)**1.5763 + odd = e_r - (e_r - odd0)/(1+Fo) + + return even,odd,even0,odd0 + +def mclZcf(W,h,s,e_r,f): + ''' + Calculate odd and even characteristic impedance of parallel + coupled microstrip lines. + M. Kirschning, R. H. Jansen, and N. H. L. Koster, + "Coupled microstrip parallel-gap model for improved filter and coupler design," + Electronics Letters, vol. 19, no. 10, pp. 377–379, May 1983, + doi: 10.1049/el:19830261. + + even, odd = mcl_eps(W,h,s,e_r,f): + W <- width of microstrip (mm) + h <- height of substrate (mm) + s <- spacing between lines (mm) + e_r <- substrate relative dielectric cosntatn + f <- frequency (GHz) + Ze -> even mode charachterstic impedance + Zo -> odd mode characteristic impedance + ''' + u = W/h + g = s/h + fn = f*h + + eps0 = eps_re(u,e_r) + epsf = eps_f(W,h,e_r,f) + even,odd,even0,odd0 = mcl_eps(W,h,s,e_r,f) + Z0 = getZc(u,e_r) + Z0f, Q0 = getZcf(W,h,e_r,f,R=True) + + Q1 = 0.8695*u**0.194 + Q2 = 1+0.7519*g+0.189*g**2.31 + Q3 = 0.1975+(16.6 + (8.4/g)**6)**-0.387 +np.log(g**10/(1+(g/3.4)**10))/241 + Q4 = 2*Q1/Q2/(np.exp(-g)*u**Q3+(2-np.exp(-g))*u**-Q3) + + Ze0 = np.sqrt(eps0/even0)*Z0/(1-Z0/377*np.sqrt(eps0)*Q4) + + Q5 = 1.794 + 1.14*np.log(1+0.638/(g+0.517*g**2.43)) + Q6 = 0.2305+np.log(g**10/(1+(g/5.8)**10))/281.3+np.log(1+0.598*g**1.154)/5.1 + Q7 = (10+190*g**2)/(1+82.3*g**3) + #print(-6.5-0.95*np.log(g)-(g/0.15)**5) + Q8 = np.exp(-6.5-0.95*np.log(g)-(g/0.15)**5) + Q9 = np.log(Q7)*(Q8+1/16.5) + Q10 = (Q2*Q4-Q5*np.exp(np.log(u)*Q6*u**-Q9))/Q2 + + Zo0 = np.sqrt(eps0/odd0)*Z0/(1-Z0/377*np.sqrt(eps0)*Q10) + + # dispersion accounted + Q11 = 0.893*(1-0.3/(1+0.7*(e_r-1))) + Q12 = 2.121*(fn/20)**4.91*np.exp(-2.87*g)*g**0.902/(1+Q11*(fn/20)**4.91) + Q13 = 1+0.038*(e_r/8)**5.1 + Q14 = 1+1.203*(e_r/15)**4/(1+(e_r/15)**4) + Q15 = 1.887*np.exp(-1.5*g**0.84)*g**Q14/(1+0.41*(fn/15)**3*u**(2/Q13)/(0.125+u**(1.625/Q13))) + Q16 = Q15 * (1+ 9/(1+0.403*(e_r-1)**2)) + Q17 = 0.394*(1-np.exp(-1.47*(u/7)**0.672))*(1-np.exp(-4.25*(fn/20)**1.87)) + Q18 = 0.61*(1-np.exp(-2.13*(u/8)**1.593))/(1+6.544*g**4.17) + Q19 = 0.21*g**4/(1+0.18*g**4.9)/(1+0.1*u**2)/(1+(fn/24)**3) + Q20 = Q19 * (0.09+1/(1+0.1*(e_r-1)**2.7)) + Q21 = np.abs(1-42.54*g**0.133*np.exp(-0.812*g)*u**2.5/(1+0.033*u**2.5)) + + re = (fn/28.843)**12 + qe = 0.016+(0.0514*e_r*Q21)**4.524 + pe = 4.766*np.exp(-3.228*u**0.641) + de = 5.086*qe*re*np.exp(-22.2*u**1.92)*(e_r-1)**6/(0.3838+0.386*qe)/(1+1.2992*re)/(1+10*(e_r-1)**6) + + Ce = 1+1.275*(1-np.exp(-0.004625*pe*e_r**1.674*(fn/18.365)**2.745))-Q12+Q16-Q17+Q18+Q20 + Ze = Ze0*( (0.9408*epsf**Ce-0.9603)/( (0.9408-de)*eps0**Ce-0.9603))**Q0 + + Q29 = 15.16/(1+0.196*(e_r-1)**2) + Q28 = 0.149*(e_r-1)**3/(94.5+0.038*(e_r-1)**3) + Q27 = 0.4*g**0.84*(1+(2.5*(e_r-1)**1.5)/(5+(e_r-1)**1.5)) + Q26 = 30 - ( 22.2*((e_r-1)/13)**13)/(1+3*((e_r-1)/13)**12) - Q29 + Q25 = (0.3*fn**2)/(10+fn**2)*(1+(2.333*(e_r-1)**2)/(5+(e_r-1)**2)) + Q24 = 2.506*Q28*u**0.894/(3.575+u**0.894)*((1+1.3*u)*fn/99.25)**4.29 + Q23 = 1+0.005*fn*Q27/(1+0.812*(fn/15)**1.9)/(1+0.025*u**2) + Q22 = 0.925*(fn/Q26)**1.536/(1+0.3*(fn/30)**1.536) + + Zo = Z0f+(Zo0*(odd/odd0)**Q22 - Z0f*Q23)/(1+Q24+(0.46*g)**2.2*Q25) + return Ze,Zo + +def get_mcl(Ze, Zo, h, e_r, f): + ''' + Find width W and gap s of parallel coupled microstrip lines + + [W, s] = get_mcl(Ze, Zo, h, e_r, f): + Ze <- even mode characteristic impedance (ohm) + Zo <- odd mode ch. impedance (ohm) + h <- height of substrate (mm) + e_r <- relative permitivity of substrate + f <- frequency (GHz) + W -> strip width (mm) + s -> gap (mm) + ''' + Z = np.array([Ze,Zo]) + u = opt.root(lambda X: Z - np.array(mclZcf(X[0],h,X[1],e_r,f)), [h/2,h/5],method='lm') + return u.x + +def open_end(W, h, e_r, f): + ''' + Calculate open end displacment dl of microstrip open end. + Kirschning, M., R. H. Jansen, and N. H. L. Koster. + "Accurate model for open end effect of microstrip lines." + Electronics Letters 17.3 (1981): 123-125. + + dl = open_end(W,h,e_r,f) + W <- width of microstrip line (mm) + h <- height of substrate (mm) + e_r <- relative dielectric constant of substrate + f <- frequency (GHz) + ''' + epsf = eps_f(W,h,e_r,f) + u = W/h + + x1 = 0.434907*(epsf**0.81+0.26)/(epsf**0.81-0.189)*(u**0.8544+0.236)/(u**0.8544+0.87) + x2 = 1 + u**0.371/(2.358*e_r+1) + x3 = 1 + 0.5274*np.arctan(0.084*u**(1.9413/x2))/epsf**0.9236 + x4 = 1 + 0.0377*np.arctan(0.067*u**1.456)*(6-5*np.exp(0.036*(1-e_r))) + x5 = 1 - 0.218*np.exp(-7.5*u) + + return x1*x3*x5/x4 *h