Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

All published worksheets from http://sagenb.org

Views: 168698
Image: ubuntu2004
rho = lambda z: (z-1)/(z+1) # return the (complex) reflection coefficient zz = lambda r: (1 + r)/(1 - r) # return the normalized impedance from the reflection coefficient def cart(z): return (z.real(), z.imag()) def rhoxy(z): '''return the real and imaginary part of the reflection coefficient as a tuple''' r = rho(z) return (r.real(), r.imag()) def screal(x): '''generate smith chart coordinates of constant real part; these are complete circles''' r = rhoxy(x + 0j) radius = 0.5*(1 - r[0]) return circle((1 - radius, 0), radius) def scimag(y): '''generate smith chart coordinates of constant imaginary part; these are circular arcs''' rx = lambda t: rhoxy(t + 1j*y)[0] ry = lambda t: rhoxy(t + 1j*y)[1] return parametric_plot((rx,ry),(0,50)) def polar(z): '''return the polar form of a cartesian complex number, as a tuple''' return (abs(z), arg(z)) # draw an unlabeled smith chart smithchart = screal(0) + screal(1/3) + screal(1) + screal(3) + scimag(0) + scimag(1/3) + scimag(-1/3) + scimag(1) + scimag(-1) + scimag(3) + scimag(-3)
class SmithChart: '''a class for drawing and manipulating Smith Charts by John D Sahr [email protected]''' def __init__(self): '''initialize a smith chart''' self.chart = smithchart self.last_rho = None self.markradius = 0.015 self.mark_ind = 0 self.fontsize = 15 self.admittance_mode = True self.annotation = [] def clear(self): '''reset the smith chart''' self.chart = smithchart self.last_rho = None self.mark_ind = 0 self.admittance_mode = True self.annotation = [] def mark(self, label = True): '''make a small circular mark at the last location on the chart''' self.chart += circle(cart(self.last_rho), self.markradius, rgbcolor = (0,0,0)) center = (self.last_rho.real(), self.last_rho.imag()) polar = self.polar(self.last_rho) if label == False: # don't label at all. return elif label == True: # generate a generic label tag = chr(self.mark_ind + ord('A')) self.mark_ind += 1 elif type(label) == type('a string'): # use a custom label tag = label else: # error out raise 'improper label passed to mark' tagloc = (center[0]+3*self.markradius, center[1]+3*self.markradius) self.chart += text(tag, tagloc, fontsize=self.fontsize) msg = '%4s :: rho %5.3f at %6.1f deg; ' % (tag, polar[0], polar[1]) z = zz(self.last_rho) msg += '%6.3f + %6.3fj' % (z.real(),z.imag()) self.annotation.append(msg) def markz(self, z, label = True): '''mark a (normalized) impedance on the Smith Chart''' center = rho(z) self.last_rho = center.real() + 1j*center.imag() self.mark(label) def marky(self, z, label = True): '''mark a (normalized) impedance at its admittance position on the Smith Chart''' self.markz(1/z, label) def markr(self, r, dolabel = True): '''mark the smith chart given a (complex) reflection coefficient''' self.markz(zz(r),dolabel) def polar(self, r): '''convert a complex number in cartesian format to mag, phase(degrees) format as a tuple''' return( r.abs(), 180*r.arg()/math.pi) def togen(self, wavelengths, rgbcolor=(1,0,1), dolabel = True): '''start at the current point on the Smith Chart, and rotate <wavelengths> towards the generator''' if self.last_rho == None: raise "not anywhere yet!" radius = sqrt(self.last_rho[0]^2 + self.last_rho[1]^2) t1 = math.atan2(self.last_rho[1],self.last_rho[0]) t2 = t1 - 4*math.pi*wavelengths self.last_rho *= exp(1j*(t2-t1)) t = var('t') self.chart += parametric_plot((radius*cos(t), radius*sin(t)), (t,t1,t2), rgbcolor=rgbcolor) self.mark(dolabel) def singlestub(self, z, bottom = True): '''solve a single stub match using shorted stub. There are two solutions: inductive (bottom) or capacitive (top)''' self.markz(z, 'Zl') # mark the location of the load impedance self.marky(z, 'Yl') # mark the location of the load admittance magRhoL = self.last_rho.abs() argRhoL = self.last_rho.arg() self.chart += circle((0,0), magRhoL, rgbcolor = (1,0,0)) # the circle of const |refcoef| argMatch = acos(magRhoL) # the intersection of the circle with the 1 + jX circle if bottom != True: # ... get the capacitive stub instead argMatch = -argMatch ym1 = zz(magRhoL*exp(1j*argMatch)) # ... get the intersection point self.markz(ym1,'Ym1') # ... and mark it stb1 = 0 - 1j*ym1.imag() # ... the input admittance of the stub self.markz(stb1,'stb1') # ... and mark it stubloc = 180*(argRhoL - argMatch)/math.pi - 360 # compute the location of the stub while stubloc < 0.0: stubloc += 360 stublength = -180.0*rho(stb1).arg()/math.pi - 360 # compute the length of the stub while stublength < 0.0: stublength += 360 print 'stub location: %6.3f :: ' % (stubloc*0.5/360), print 'stub length: %6.3f' % (stublength*0.5/360) def show(self): '''draw the annotated smith chart''' self.chart.show(aspect_ratio = 1, axes = False) for x in self.annotation: print x
h = SmithChart() h.markz(0.5j) h.togen(-0.3238) h.show() 0.3238*0.06666
A :: rho 1.000 at 126.9 deg; -0.000 + 0.500j B :: rho 1.000 at 0.0 deg; -0.000 + 19430.051j 0.0215845080000000
h.clear() h.markz(1 + 1j,'Z1'); h.markz(3 - 1j,'Z2'); h.markz(0.333 - 0.333j,'Z3'); h.markz(0.0, 'Z4'); h.markz(10000.0, 'Z5'); h.show()
Z1 :: rho 0.447 at 63.4 deg; 1.000 + 1.000j Z2 :: rho 0.542 at -12.5 deg; 3.000 + -1.000j Z3 :: rho 0.543 at -139.4 deg; 0.333 + -0.333j Z4 :: rho 1.000 at 180.0 deg; 0.000 + 0.000j Z5 :: rho 1.000 at 0.0 deg; 10000.000 + 0.000j
h.chart.save('yaya.pdf',aspect_ratio = 1, axes = False)
h.clear(); h.markr(0.75*exp(1.1j)) h.marky(0.5-0.5j,'1/Z1') h.togen(0.339-0.25) h.togen(0.125) h.markz(1+1j) h.show() r = abs(h.last_rho) print('SWR is %5.2f' % ((1 + r)/(1-r),))
A :: rho 0.750 at 63.0 deg; 0.496 + 1.515j 1/Z1 :: rho 0.447 at 63.4 deg; 1.000 + 1.000j B :: rho 0.447 at -0.6 deg; 2.618 + -0.033j C :: rho 0.447 at -90.6 deg; 0.661 + -0.739j D :: rho 0.447 at 63.4 deg; 1.000 + 1.000j SWR is 2.62
h.clear() h.singlestub(1.25-1.25j, True) h.show()
help(SmithChart)