def smp_connector(em, x, y, z, zmax, coax_port_length=0.2e-3, pin_diameter=0.85e-3): copper_shield = openems.Metal(em, 'smp_shield') copper = openems.Metal(em, 'smp_pin') lcp = openems.Dielectric(em, 'lcp', eps_r=3.2) # shield outside = np.array([[-2.5, 1.0], [-2.5, 2.5], [2.5, 2.5], [2.5, -2.5], [-2.5, -2.5], [-2.5, -1.0]]) * 1e-3 angle = np.arcsin(1.0 / 2.25) inside = openems.arc(0, 0, 4.5e-3 / 2.0, -np.pi + angle, np.pi - angle) openems.Polygon(copper_shield, priority=9, pcb_layer=None, points=[x, y] + np.concatenate((inside, outside)), elevation=[z, z + 0.9e-3], normal_direction='z') outside = np.array([[0, 2.5], [2.5, 2.5], [2.5, -2.5], [0, -2.5]]) * 1e-3 inside = openems.arc(0, 0, 1.95e-3 / 2.0, -np.pi * 0.5, np.pi * 0.5) openems.Polygon(copper_shield, priority=9, pcb_layer=None, points=[x, y] + np.concatenate((inside, outside)), elevation=[z + 0.9e-3, zmax], normal_direction='z').duplicate().mirror('x') # pin start = np.array([x, y, zmax - coax_port_length]) stop = np.array([x, y, z + 0.9e-3]) copper.AddCylinder(start, stop, 0.5 * pin_diameter, priority=9) # smaller part of pin stop[2] = z copper.AddCylinder(start, stop, 0.5 * 0.8e-3, priority=9) # insulator start = np.array([x, y, z]) stop = np.array([x, y, z + 0.9e-3]) lcp.AddCylinder(start, stop, 4.5e-3 * 0.5, priority=1) if coax_port_length != 0: # port (coax) start = [ x + 0.5 * coax_port_length, y + 0.5 * coax_port_length, zmax - coax_port_length ] stop = [x - 0.5 * coax_port_length, y - 0.5 * coax_port_length, zmax] openems.Port(em, start, stop, direction='z', z=50) em.mesh.AddLine('z', start[2])
def generate( em, sub, z, # [bottom of substrate, top of substrate, top of metal] port_length, ms_width, section, # pairs of x and y size of a segment box_width): box_length = 2.0*(port_length) + np.sum(section[:,0]) pec = openems.Metal(em, 'pec') # substrate start = np.array([ 0.5*box_length, 0.5*box_width, z[0]]) stop = np.array([-0.5*box_length, -0.5*box_width, z[1]]) openems.Box(sub, 1, start, stop) # pads x0 = -0.5*box_length x1 = x0 + port_length x2 = x1 + ms_width start = np.array([x1, 0.5*ms_width, z[1]]) stop = np.array([x2, -0.5*ms_width, z[2]]) l1 = openems.Box(pec, 9, start, stop, padname = '1') l2 = l1.duplicate("line_p2").mirror('x') l2.padname = '2' x = x1 points = np.zeros((2*len(section),2)) i = 0 for s in section: points[i,0] = x x += s[0] points[i+1,0] = x points[i,1] = 0.5*s[1] points[i+1,1] = 0.5*s[1] i += 2 print(points) points = np.concatenate((points, points[::-1]*[1,-1.0])) print(points) pec.AddPolygon( points = points, priority = 9, elevation = z[1:], normal_direction = 'z', pcb_layer = 'F.Cu', pcb_width = 1e-5) # main line ports start = [x0, -0.5*ms_width, z[1]] stop = [x1, 0.5*ms_width, z[2]] em.AddPort(start, stop, direction='x', z=50).duplicate().mirror('x')
#!/usr/bin/env python3 import sys import openems import numpy as np mm = 1e-3 # default unit is the meter em = openems.OpenEMS(sys.argv[1], EndCriteria = 1e-6, fmin = 0e6, fmax = 60e9) em.fsteps = 801 copper = openems.Metal(em, 'copper') sub = openems.Dielectric(em, 'substrate', eps_r=3.2) mask = openems.Dielectric(em, 'mask', eps_r=3.3) air = openems.Dielectric(em, 'air', eps_r=1.0006) foil_thickness = 0.035*mm port_length = 0.05*mm box_length = 5*mm box_width = 1.5*mm ms_width = 0.190*mm box_top = 1.5*mm # dimensions Z substrate_top = 0.102*mm foil_top = substrate_top + foil_thickness em.resolution = 50e-6 em.mesh.AddLine('z', foil_top + box_top) em.mesh.AddLine('z', -0.5*mm) # substrate start = np.array([-0.5*box_length, 0.5*box_width, 0]) stop = np.array([0.5*box_length, -0.5*box_width, substrate_top])
def generate( em, substrate, z, # [bottom of substrate, top of substrate, top of metal] y1=5.5 * mm, y2=0.9 * mm, r=0.5 * mm, rv=[200, 200, 200, 200], w=[0.127 * mm, 0.152 * mm, 0.19 * mm, 0.23 * mm], port_length=0.2 * mm, ms_width=0.36 * mm, endspace=0.5 * mm, resistor_size='0402'): alumina = openems.Dielectric(em, 'alumina', eps_r=9.8) metal = openems.Metal(em, 'pec_wilkinson') n = len(rv) # substrate start = np.array([(n * 4 - 1) * r + endspace, y1 + r + endspace, z[0]]) stop = np.array([-1.0 * endspace, -1.0 * start[1], z[1]]) substrate.AddBox(start, stop, 1) # common port line (pad 1) start = np.array([-1.0 * endspace + port_length, 0.5 * ms_width, z[1]]) stop = np.array([0, -0.5 * ms_width, z[2]]) metal.AddBox(start, stop, priority=9, padname='1') lo = arc(r, -y1, r + 0.5 * w[0], pi, 2 * pi, 16) li = arc(r, -y1, r - 0.5 * w[0], pi, 2 * pi, 16) lo = cat((lo, arc(3 * r, -y2, r - 0.5 * w[0], pi, 0.55 * pi, 16))) li = cat((li, arc(3 * r, -y2, r + 0.5 * w[0], pi, 0.55 * pi, 16))) for i in range(n - 1): x = (4 * i + 3) * r w2 = w[1 + i] em.mesh.AddLine('x', x + r - 0.5 * w2) em.mesh.AddLine('x', x + r + 0.5 * w2) em.mesh.AddLine('x', x + 3 * r - 0.5 * w2) em.mesh.AddLine('x', x + 3 * r + 0.5 * w2) lo = cat((lo, arc(x, -y2, r - 0.5 * w2, 0.45 * pi, 0, 16))) li = cat((li, arc(x, -y2, r + 0.5 * w2, 0.45 * pi, 0, 16))) lo = cat((lo, arc(2 * r + x, -y1, r + 0.5 * w2, pi, 2 * pi, 16))) li = cat((li, arc(2 * r + x, -y1, r - 0.5 * w2, pi, 2 * pi, 16))) lo = cat((lo, arc(4 * r + x, -y2, r - 0.5 * w2, pi, 0.55 * pi, 16))) li = cat((li, arc(4 * r + x, -y2, r + 0.5 * w2, pi, 0.55 * pi, 16))) l = cat((lo, li[::-1])) l = cat((l[::-1] * [1, -1], l)) openems.Polygon(metal, priority=9, points=l, elevation=z[1:], normal_direction='z', pcb_layer='F.Cu', pcb_width=0.001) # x at 2 port side x0 = (n * 4 - 1) * r + endspace x1 = x0 - port_length # output lines for (ym, padname) in [(1, 2), (-1, 3)]: start = np.array([x1, ym * 0.2 * mm, z[1]]) stop = np.array([(n * 4 - 1) * r - 0.1 * mm, ym * (0.2 * mm + ms_width), z[2]]) lp2 = metal.AddBox(start, stop, priority=9, padname=padname) # main line port start = [-1.0 * endspace, -0.5 * ms_width, z[1]] stop = [-1.0 * endspace + port_length, 0.5 * ms_width, z[2]] openems.Port(em, start, stop, direction='x', z=50) # coupled line ports for ym in [-1, 1]: start = [x0 - port_length, ym * 0.2 * mm, z[1]] stop = [x0, ym * (0.2 * mm + ms_width), z[2]] openems.Port(em, start, stop, direction='x', z=50) for i in range(n): if not rv[i]: continue em.add_resistor('r{}'.format(i), origin=np.array([4 * r * i + 3 * r, 0, z[2]]), direction='y', value=rv[i], invert=False, priority=9, dielectric=alumina, metal=metal, element_down=False, size=resistor_size)
#!/usr/bin/env python3 # Common SMA edge launch to OSHPark 4 layer import sys from scipy.constants import mil import openems import numpy as np em = openems.OpenEMS('sma_el', EndCriteria=1e-6, fmin=0, fmax=20e9, fsteps=1001) em.resolution = 8e-5 copper = openems.Metal(em, 'copper') copper_shield = openems.Metal(em, 'copper_shield') sub = openems.Dielectric(em, 'ro4350b', eps_r=3.66, tand=0.0035, fc=em.fmax) teflon = openems.Dielectric(em, 'teflon', eps_r=2.1, tand=0.0002, fc=em.fmax) foil_thickness = 35e-6 substrate_thickness = 62 * mil - 7 * mil port_length = 300e-6 box_length = 10e-3 box_width = 6e-3 box_height = 6e-3 ms_width = 1.0e-3 board_gap = 0.0 # coax coax_scale = 2.0 pin_diameter = 0.5e-3 * coax_scale dielectric_diameter = 1.67e-3 * coax_scale
#!/usr/bin/env python3 import sys from scipy.constants import pi, c, epsilon_0, mu_0, mil, inch mm = 0.001 import openems import openems.miter import numpy as np em = openems.OpenEMS('miter_6.6') em.end_criteria = 1e-6 em.fmin = 0 em.fmax = 40e9 em.fsteps = 1601 fc = 40e9 pec = openems.Metal(em, 'pec') sub = openems.Dielectric(em, 'ro4350b', eps_r=3.66, tand=0.0035, fc=fc) foil_thickness = 0.033*mm substrate_thickness = 6.6*mil ms_air_above = 1.0*mm z = [0.0, substrate_thickness, substrate_thickness + foil_thickness] em.mesh.AddLine('z', z[2] + ms_air_above) em.resolution = 50e-6 openems.miter.generate( em, pec, sub, miter = 0.35 * mm, z = z,
#!/usr/bin/env python import sys from scipy.constants import pi, c, epsilon_0, mu_0, mil, inch mm = 0.001 import openems import openems.idbpf import numpy as np em = openems.OpenEMS('idbpf_b3', fmin=1e6, fmax=16e9) em.end_criteria = 1e-10 em.fsteps = 1601 fc = 7.12e9 eps_r = 3.66 #em.add_lossy_metal('copper', frequency=fc, conductivity=56e6/3, ur=1.0) openems.Metal(em, 'copper') openems.Metal(em, 'pec') #em.via_offset_x = 5*mil #em.via_offset_y = 5*mil openems.Dielectric(em, 'sub', eps_r=eps_r).set_tanD(0.0035, freq=fc) foil_thickness = 0.035 * mm substrate_thickness = 22 * mil ms_air_above = 2.0 * mm via = 0.3 * mm via_pad = 0.6 * mm # dimensions Z substrate_bottom = 0.0 substrate_top = substrate_bottom + substrate_thickness foil_top = substrate_top + foil_thickness
def generate(self): pec = openems.Metal(self.em, 'pec_filter') ring_ix = 0.5 * (np.max(self.rl) + self.end_gap) ring_ox = ring_ix + 2.0 * self.via_padradius via_z = [[self.z[0], self.z[1] + self.lidz], [self.z[1], self.z[2]]] # fingers y = -0.5 * self.space[-1:][0] mirror = False mirrorstring = ['', 'x'] for i in range(len(self.space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - self.rl[i] y += self.space[i] start = [x1, y, self.z[1]] y += self.rw[i] stop = [x2, y, self.z[2]] box = openems.Box(pec, 9, start, stop, padname='poly', pcb_layer=self.pcb_layer) box.mirror(mirrorstring[mirror]) mirror = not mirror box2 = box.duplicate() box2.mirror('xy') v = openems.Via(pec, priority=2, x=ring_ix + self.via_padradius, y=y - 0.5 * self.rw[i], z=via_z, drillradius=self.via_radius, padradius=self.via_padradius, padname='2') if not mirror: v.mirror('x') v.duplicate().mirror('xy') if self.endmetal: v.duplicate().mirror('y') v.duplicate().mirror('x') mirror = not mirror # ports y1 = y y -= 0.5 * self.rw[0] # center of line y2 = y + 0.5 * self.feedwidth + self.ring_y_width # y outside px = ring_ix - self.tapoffset py = y2 - self.portlength start = [px + 0.5 * self.feedwidth, y2, self.z[1]] stop = [px - 0.5 * self.feedwidth, py, self.z[2]] p = openems.Port(self.em, start, stop, direction='y', z=50) p.mirror(mirrorstring[mirror]) p2 = p.duplicate().mirror('xy') # feed lines start = [px + 0.5 * self.feedwidth, py, self.z[1]] stop = [px - 0.5 * self.feedwidth, y - 0.5 * self.rw[0], self.z[2]] box = openems.Box(pec, 9, start, stop, padname='1', pcb_layer=self.pcb_layer) box.mirror(mirrorstring[mirror]) box2 = box.duplicate() box2.mirror('xy') box2.padname = '3' # substrate start = np.array([ring_ox, y2, self.z[0]]) stop = openems.mirror(start, 'xy') stop[2] = self.z[1] + self.lidz sub = openems.Box(self.sub, 1, start, stop) # mask if self.mask_thickness > 0.0: start = np.array([ring_ox, y2, self.z[1]]) stop = openems.mirror(start, 'xy') stop[2] += self.mask_thickness openems.Box(mask, 1, start, stop) # grounded end metal if self.endmetal: em1 = openems.Box( pec, 9, start=[ring_ix, y2, self.z[1]], stop=[ring_ix + 2.0 * self.via_padradius, -y2, self.z[2]], padname='2', pcb_layer=self.pcb_layer) em1.duplicate().mirror('x')
def idbpf( em, # openems instance sub, # substrate, define with openems.Dielectric() z=[], # z position, z[0] = sub bottom, z[1] = sub top, z[2] = foil top lidz=0, # upper substrate thickness rl=[], # length of resonator fingers rw=[], # width of resonator fingers space=[], # space between resonator fingers endmetal=True, # add metal to filter ends portlength=0.2 * mm, # length of the openems port feedwidth=0.85 * mm, # width of the trace leaving the filter and port end_gap=0.3 * mm, # space between the end of a resonator and ground via_radius=0.15 * mm, # radius of the via drills via_padradius=0.3 * mm, # radius of the via pads pcb_layer='F.Cu', # Kicad layer mask=None, # mask, define with openems.Dielectric() mask_thickness=0, # set to non-zero to enable solder mask over filter ): edge_space = 0.5 * mm pec = openems.Metal(em, 'pec_filter') ring_ix = 0.5 * (np.max(rl) + end_gap) ring_ox = ring_ix + 2.0 * via_padradius via_z = [[z[0], z[1] + lidz], [z[1], z[2]]] # fingers y = -0.5 * space[-1:][0] mirror = False mirrorstring = ['', 'x'] for i in range(len(space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - rl[i] y += space[i] start = [x1, y, z[1]] y += rw[i] stop = [x2, y, z[2]] box = openems.Box(pec, 9, start, stop, padname='poly', pcb_layer=pcb_layer) box.mirror(mirrorstring[mirror]) mirror = not mirror box2 = box.duplicate() box2.mirror('xy') if i == 0: continue v = openems.Via(pec, priority=2, x=ring_ix + via_padradius, y=y - 0.5 * rw[i], z=via_z, drillradius=via_radius, padradius=via_padradius, padname='2') if not mirror: v.mirror('x') v.duplicate().mirror('xy') mirror = not mirror # ports y1 = y + feedwidth - rw[0] # outer edge of feed y2 = y - rw[0] # inner edge px = ring_ox start = [px, y2, z[1]] stop = [px - portlength, y1, z[2]] p = openems.Port(em, start, stop, direction='x', z=50) p.mirror(mirrorstring[mirror]) p2 = p.duplicate().mirror('xy') # feed lines start = [-ring_ix + rl[0], y1, z[1]] stop = [px - portlength, y2, z[2]] box = openems.Box(pec, 9, start, stop, padname='1', pcb_layer=pcb_layer) box.mirror(mirrorstring[mirror]) box2 = box.duplicate() box2.mirror('xy') box2.padname = '3' # substrate start = np.array([ring_ox, y1 + edge_space, z[0]]) stop = openems.mirror(start, 'xy') stop[2] = z[1] + lidz sub = openems.Box(sub, 1, start, stop) # mask if mask_thickness > 0.0: start = np.array([ring_ox, y2, z[1]]) stop = openems.mirror(start, 'xy') stop[2] += mask_thickness openems.Box(mask, 1, start, stop) # grounded end metal if endmetal: em1 = openems.Box( pec, 9, start=[ring_ix, -y2 + space[0], z[1]], stop=[ring_ix + 2.0 * via_padradius, y1 + edge_space, z[2]], padname='2', pcb_layer=pcb_layer) em1.duplicate().mirror('xy')
def idbpf(em, # openems instance sub, # substrate, define with openems.Dielectric() lidz = 0.0, z = [], # z position, z[0] = sub bottom, z[1] = sub top, z[2] = foil top space = [], # space between resonator fingers rl = [], # length of resonator fingers rw = [], # width of resonator fingers portlength = 0.2*mm, # length of the openems port feedwidth = 0.85*mm, # width of the trace leaving the filter and port tapoffset = 1.0*mm, # offset of tap from end of resonator end_gap = 0.3*mm, # space between the end of a resonator and ground via_radius = 0.15*mm, # radius of the via drills via_padradius = 0.3*mm, # radius of the via pads pcb_layer = 'F.Cu', # Kicad layer mask_thickness = 0, # set to non-zero to enable solder mask over filter mask = None, # mask, define with openems.Dielectric() endmetal = True, # add metal to filter ends ): pec = openems.Metal(em, 'pec_filter') ring_y_width = via_padradius * 2.0 ring_ix = 0.5 * (np.max(rl) + end_gap) ring_ox = ring_ix + 2.0 * via_padradius via_z = [[z[0], z[1]+lidz], [z[1], z[2]]] # fingers y = -0.5*space[-1:][0] mirror = np.array([1,1,1]) if len(space) % 2 == 0: mirror[0] *= -1 for i in range(len(space))[::-1]: # reverse order x1 = 0.5 * (ring_ox + ring_ix) x2 = ring_ix - rl[i] y += space[i] start = [x1, y, z[1]]; y += rw[i] stop = [x2, y, z[2]]; for m in [np.array([1,1,1]),np.array([-1,-1,1])]: m *= mirror openems.Box(pec, 9, start*m, stop*m, padname = 'poly', pcb_layer=pcb_layer) openems.Via(pec, priority=2, x=m[0]*(ring_ix+via_padradius), y=m[1]*(y-0.5*rw[i]), z=via_z, drillradius=via_radius, padradius=via_padradius, padname='2') mirror[0] *= -1 if endmetal: v.duplicate().mirror('y') v.duplicate().mirror('x') mirror *= [-1,1,1] # ports y1 = y y -= 0.5*rw[0] # center of line y2 = y + 0.5*feedwidth + ring_y_width # y outside px = ring_ix - tapoffset py = y2 - portlength for m in [-1,1]: start = [m*(px + 0.5*feedwidth), m*y2, z[1]] stop = [m*(px - 0.5*feedwidth), m*py, z[2]] openems.Port(em, start, stop, direction='y', z=50) # feed lines start = [m*(px + 0.5*feedwidth), m*py, z[1]] stop = [m*(px - 0.5*feedwidth), m*(y-0.5*rw[0]), z[2]] openems.Box(pec, 9, start, stop, padname = '1' if m==1 else '3', pcb_layer=pcb_layer) # substrate start = np.array([ring_ox, y2, z[0]]) stop = openems.mirror(start, 'xy') stop[2] = z[1]+lidz sub = openems.Box(sub, 1, start, stop) # mask if mask_thickness > 0.0: start = np.array([ring_ox, y2, z[1]]) stop = openems.mirror(start, 'xy') stop[2] += mask_thickness openems.Box(mask, 1, start, stop) # grounded end metal if endmetal: for xm in [-1,1]: em1 = openems.Box(pec, 9, start = [xm*ring_ix, y2, z[1]], stop = [xm*(ring_ix + 2.0*via_padradius), -y2, z[2]], padname = '2', pcb_layer=pcb_layer)
def generate( em, sub, mask, min_width, # minimum copper width, typically design rule minimum cutout_width, # width of ground plane cutouts inductors, capacitors, z, # bottom of [air below, bottom metal, substrate, top metal, air above, lid] port_length, ms_width, box_width, half_fan_angle=0.25*np.pi): em.mesh.AddLine('z', z[0]) # air above, below em.mesh.AddLine('z', z[5]) em.mesh.AddLine('z', 0.5*(z[2]+z[3])) em.mesh.AddLine('z', 0.25*(3*z[2]+z[3])) em.mesh.AddLine('z', 0.25*(z[2]+3*z[3])) em.mesh.AddLine('y', -0.5*min_width) em.mesh.AddLine('y', 0.5*min_width) box_length = 2.0*(np.sum(inductors) + capacitors[0] + 0.5e-3) x0 = -0.5*box_length x1 = x0 + port_length x2 = x1 + ms_width yb = 0.5*cutout_width yo = -0.1e-3 # overlap pec = openems.Metal(em, 'pec') # substrate start = np.array([ 0.5*box_length, 0.5*box_width, z[2]]) stop = np.array([-0.5*box_length, -0.5*box_width, z[3]]) openems.Box(sub, 1, start, stop) # solder mask if mask != None: start[2] = z[3] + 25e-6 openems.Box(mask, 1, start, stop) # top copper polygon points = np.zeros((6+10*len(inductors),2)) points[0] = [x1, 0.5*ms_width] x = -np.sum(inductors) points[1] = [x - 0.5*ms_width, 0.5*ms_width] points[2:10] = arc(x, 0, capacitors[0], 0.5*np.pi+half_fan_angle, 0.5*np.pi-half_fan_angle, npoints = 8) points[10] = [x + 0.5*min_width, 0.5*min_width] i = 11 x += inductors[0] for j in range(1, len(inductors)): points[i+0] = [x-0.5*min_width, 0.5*min_width] points[i+1:i+9] = arc(x, 0, capacitors[j], 0.5*np.pi+half_fan_angle, 0.5*np.pi-half_fan_angle, npoints = 8) points[i+9] = [x+0.5*min_width, 0.5*min_width] i += 10 x += inductors[j] # center cap points[i+0] = [-0.5*min_width, 0.5*min_width] points[i+1:i+5] = arc(0, 0, capacitors[-1], 0.5*np.pi+half_fan_angle, 0.5*np.pi + 0.001, npoints = 4) print(points) points = np.concatenate((points, points[::-1]*[-1,1])) points = np.concatenate((points, points[::-1]*[1,-1])) pec.AddPolygon( points = points, priority = 9, elevation = z[3:5], pcb_layer = 'F.Cu') # ground plane gpec = openems.Metal(em, 'ground_plane') points = np.zeros((2+6*len(inductors),2)) points[0] = [x0, 0.5*box_width] points[1] = [x0, yo] i = 2 x = -np.sum(inductors) for l in inductors: hmw = 0.5*min_width xl = x + hmw points[i+0] = [xl,yo] points[i+1] = [xl,hmw] xl = x + yb points[i+2] = [xl,yb] xl = x + l - yb points[i+3] = [xl,yb] xl = x + l - hmw points[i+4] = [xl,hmw] points[i+5] = [xl,yo] i += 6 x += l print("ground plane",points) for ym in [1,-1]: gpec.AddPolygon( points = [1,ym] * np.concatenate((points, points[::-1]*[-1,1])), priority = 9, elevation = z[1:3], pcb_layer = 'B.Cu', is_custom_pad = True, x=0, y=ym*(yb+0.1e-3), pad_name='3', ) for (xm,padname) in [(-1,2),(1,1)]: # main line ports start = [x0*xm, -0.5*ms_width, z[3]] stop = [x1*xm, 0.5*ms_width, z[4]] em.AddPort(start, stop, direction='x', z=50) # pads start[0] = x2*xm l1 = openems.Box(pec, 9, start, stop, padname=padname)