# # 10.15.2.cad # # Neil Gershenfeld # 11/10/06 # # (c) Massachusetts Institute of Technology 2006 # Permission granted for experimental and personal use; # license for commercial sale available from MIT. # # # define shapes and transformation # # circle(x0, y0, r) # cylinder(x0, y0, z0, z1, r) # cone(x0, y0, z0, h, r0) # sphere(x0, y0, z0, r) # torus(x0, y0, z0, r0, r1) # rectangle(x0, x1, y0, y1) # cube(x0, x1, y0, y1, z0, z1) # pyramid(x0, y0, z0, h, r) # add(part1, part2) # subtract(part1, part2) # intersect(part1, part2) # move(part,dx,dy) # translate(part,dx,dy,dz) # rotate(part, angle) # rotate_90(part) # rotate_180(part) # rotate_270(part) # rotate_x(part, angle) # rotate_y(part, angle) # rotate_z(part, angle) # reflect_x(part) # reflect_y(part) # reflect_z(part) # reflect_xy(part) # reflect_xz(part) # reflect_yz(part) # scale_x(part, sx) # scale_y(part, sy) # scale_z(part, sz) # (many more to come) def circle(x0, y0, r): part = "(((X-x0)**2 + (Y-y0)**2) <= r**2)" part = replace(part,'x0',str(x0)) part = replace(part,'y0',str(y0)) part = replace(part,'r',str(r)) return part def cylinder(x0, y0, z0, z1, r): part = "(((X-x0)**2 + (Y-y0)**2 <= r**2) & (Z >= z0) & (Z <= z1))" part = replace(part,'x0',str(x0)) part = replace(part,'y0',str(y0)) part = replace(part,'z0',str(z0)) part = replace(part,'z1',str(z1)) part = replace(part,'r',str(r)) return part def cone(x0, y0, z0, h, r0): part = "((sqrt((X-x0)**2 + (Y-y0)**2) <= (r0 - (Z-z0)*r0/h)) & (Z >= z0) & (Z <= (z0+h)))" part = replace(part,'x0',str(x0)) part = replace(part,'y0',str(y0)) part = replace(part,'z0',str(z0)) part = replace(part,'r0',str(r0)) part = replace(part,'h',str(h)) return part def sphere(x0, y0, z0, r): part = "(((X-x0)**2 + (Y-y0)**2 + (Z-z0)**2) <= r**2)" part = replace(part,'x0',str(x0)) part = replace(part,'y0',str(y0)) part = replace(part,'z0',str(z0)) part = replace(part,'r',str(r)) return part def torus(x0, y0, z0, r0, r1): part = "(((r0 - sqrt((X-x0)**2 + (Y-y0)**2))**2 + (Z-z0)**2) <= r1**2)" part = replace(part,'x0',str(x0)) part = replace(part,'y0',str(y0)) part = replace(part,'z0',str(z0)) part = replace(part,'r0',str(r0)) part = replace(part,'r1',str(r1)) return part def rectangle(x0, x1, y0, y1): part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1))" part = replace(part,'x0',str(x0)) part = replace(part,'x1',str(x1)) part = replace(part,'y0',str(y0)) part = replace(part,'y1',str(y1)) return part def cube(x0, x1, y0, y1, z0, z1): part = "((X >= x0) & (X <= x1) & (Y >= y0) & (Y <= y1) & (Z >= z0) & (Z <= z1))" part = replace(part,'x0',str(x0)) part = replace(part,'x1',str(x1)) part = replace(part,'y0',str(y0)) part = replace(part,'y1',str(y1)) part = replace(part,'z0',str(z0)) part = replace(part,'z1',str(z1)) return part def pyramid(x0, y0, z0, h, r): part = "((X >= (x0-r*(1-(Z-z0)/h))) & (X <= (x0+r*(1-(Z-z0)/h))) & (Y >= (y0-r*(1-(Z-z0)/h))) & (Y <= (y0+r*(1-(Z-z0)/h))) & (Z >= z0) & (Z <= (z0+h)))" part = replace(part,'x0',str(x0)) part = replace(part,'y0',str(y0)) part = replace(part,'z0',str(z0)) part = replace(part,'r',str(r)) part = replace(part,'h',str(h)) return part def add(part1, part2): part = "part1 | part2" #part = "(part1) | (part2)" part = replace(part,'part1',part1) part = replace(part,'part2',part2) return part def subtract(part1, part2): part = "(part1) & ~(part2)" part = replace(part,'part1',part1) part = replace(part,'part2',part2) return part def intersect(part1, part2): part = "(part1) & (part2)" part = replace(part,'part1',part1) part = replace(part,'part2',part2) return part def move(part,dx,dy): part = replace(part,'X','(X-'+str(dx)+')') part = replace(part,'Y','(Y-'+str(dy)+')') return part def translate(part,dx,dy,dz): part = replace(part,'X','(X-'+str(dx)+')') part = replace(part,'Y','(Y-'+str(dy)+')') part = replace(part,'Z','(Z-'+str(dz)+')') return part def rotate(part, angle): angle = angle*pi/180 part = replace(part,'X','(cos(angle)*X+sin(angle)*y)') part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)') part = replace(part,'y','Y') part = replace(part,'angle',str(angle)) return part def rotate_90(part): part = reflect_xy(part) part = reflect_y(part) return part def rotate_180(part): part = reflect_xy(part) part = reflect_y(part) part = reflect_xy(part) part = reflect_y(part) return part def rotate_270(part): part = reflect_xy(part) part = reflect_y(part) part = reflect_xy(part) part = reflect_y(part) part = reflect_xy(part) part = reflect_y(part) return part def rotate_x(part, angle): angle = angle*pi/180 part = replace(part,'Y','(cos(angle)*Y+sin(angle)*z)') part = replace(part,'Z','(-sin(angle)*Y+cos(angle)*z)') part = replace(part,'z','Z') part = replace(part,'angle',str(angle)) return part def rotate_y(part, angle): angle = angle*pi/180 part = replace(part,'X','(cos(angle)*X+sin(angle)*z)') part = replace(part,'Z','(-sin(angle)*X+cos(angle)*z)') part = replace(part,'z','Z') part = replace(part,'angle',str(angle)) return part def rotate_z(part, angle): angle = angle*pi/180 part = replace(part,'X','(cos(angle)*X+sin(angle)*y)') part = replace(part,'Y','(-sin(angle)*X+cos(angle)*y)') part = replace(part,'y','Y') part = replace(part,'angle',str(angle)) return part def reflect_x(part): part = replace(part,'X','-X') return part def reflect_y(part): part = replace(part,'Y','-Y') return part def reflect_z(part): part = replace(part,'Z','-Z') return part def reflect_xy(part): part = replace(part,'X','temp') part = replace(part,'Y','X') part = replace(part,'temp','Y') return part def reflect_xz(part): part = replace(part,'X','temp') part = replace(part,'Z','X') part = replace(part,'temp','Z') return part def reflect_yz(part): part = replace(part,'Y','temp') part = replace(part,'Z','Y') part = replace(part,'temp','Z') return part def scale_x(part, sx): part = replace(part,'X','(X/sx)') part = replace(part,'sx',str(sx)) return part def scale_y(part, sy): part = replace(part,'Y','(Y/sy)') part = replace(part,'sy',str(sy)) return part def scale_z(part, sz): part = replace(part,'Z','(Z/sz)') part = replace(part,'sz',str(sz)) return part # # PCB classes and definitions # cad.labels = [] class part: def add(self,pcb,x,y,z=0,angle=0): self.x = x self.y = y self.z = z self.angle = angle if (angle == 90): self.shape = rotate_90(self.shape) elif (angle == 180): self.shape = rotate_180(self.shape) elif ((angle == 270) | (angle == -90)): self.shape = rotate_270(self.shape) angle = pi*angle/180 self.shape = translate(self.shape,x,y,z) for i in range(len(self.pad)): xnew = cos(angle)*self.pad[i].x + sin(angle)*self.pad[i].y ynew = -sin(angle)*self.pad[i].x + cos(angle)*self.pad[i].y self.pad[i].x = x + xnew self.pad[i].y = y + ynew self.pad[i].z += z cad.labels.append(cad_text(x,y,z,self.value,size=12)) for i in range(len(self.labels)): xnew = cos(angle)*self.labels[i].x + sin(angle)*self.labels[i].y ynew = -sin(angle)*self.labels[i].x + cos(angle)*self.labels[i].y self.labels[i].x = x + xnew self.labels[i].y = y + ynew self.labels[i].z += z cad.labels.append(self.labels[i]) return add(pcb,self.shape) def wire(pcb,width,*points): for i in range(1,len(points)): x0 = points[i-1].x y0 = points[i-1].y z0 = points[i-1].z x1 = points[i].x y1 = points[i].y z1 = points[i].z if (x0 < x1): pcb = add(pcb,cube(x0-width/2,x1+width/2,y0-width/2,y0+width/2,z0,z0)) elif (x1 < x0): pcb = add(pcb,cube(x1-width/2,x0+width/2,y0-width/2,y0+width/2,z0,z0)) if (y0 < y1): pcb = add(pcb,cube(x1-width/2,x1+width/2,y0-width/2,y1+width/2,z0,z0)) elif (y1 < y0): pcb = add(pcb,cube(x1-width/2,x1+width/2,y1-width/2,y0+width/2,z0,z0)) return pcb # # PCB library # # # discretes # pad_0402 = cube(-.0175,.0175,-.014,.014,0,0) class R_0402(part): def __init__(self,value=''): self.value = value self.labels = [] self.pad = [point(0,0,0)] self.shape = translate(pad_0402,-.0265,0,0) self.pad.append(point(-.0265,0,0)) self.shape = add(self.shape,translate(pad_0402,.0265,0,0)) self.pad.append(point(.0265,0,0)) pad_1206 = cube(-.032,.032,-.034,.034,0,0) class R_1206(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] self.shape = translate(pad_1206,-.06,0,0) self.pad.append(point(-.055,0,0)) self.shape = add(self.shape,translate(pad_1206,.06,0,0)) self.pad.append(point(.055,0,0)) class C_1206(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] self.shape = translate(pad_1206,-.06,0,0) self.pad.append(point(-.055,0,0)) self.shape = add(self.shape,translate(pad_1206,.06,0,0)) self.pad.append(point(.055,0,0)) class D_1206(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] # # anode # self.shape = translate(pad_1206,-.06,0,0) self.pad.append(point(-.055,0,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A',8)) # # cathode # self.shape = add(self.shape,translate(pad_1206,.06,0,0)) self.pad.append(point(.055,0,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',8)) pad_SOD_123 = cube(-.02,.02,-.024,.024,0,0) class D_SOD_123(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] # # anode # self.shape = translate(pad_SOD_123,-.07,0,0) self.pad.append(point(-.07,0,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'A',8)) # # cathode # self.shape = add(self.shape,translate(pad_SOD_123,.07,0,0)) self.pad.append(point(.07,0,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'C',8)) # # connectors # pad_Molex = cube(-.0155,.0155,-.0265,.045,0,0) pad_Molex_solder = cube(-.04,.04,-.035,.095,0,0) class Molex_serial(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] # # pin 1: Rx # self.shape = translate(pad_Molex,-.075,.064,0) self.pad.append(point(-.075,.064,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Rx',8)) # # pin 2: Tx # self.shape = add(self.shape,translate(pad_Molex,-.025,.064,0)) self.pad.append(point(-.025,.064,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'Tx',8)) # # pin 3: DTR # self.shape = add(self.shape,translate(pad_Molex,.025,.064,0)) self.pad.append(point(.025,.064,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'DTR',8)) # # pin 4: GND # self.shape = add(self.shape,translate(pad_Molex,.075,.064,0)) self.pad.append(point(.075,.064,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',8)) # # solder pads # self.shape = add(self.shape,translate(pad_Molex_solder,-.19,-.08,0)) self.shape = add(self.shape,translate(pad_Molex_solder,.19,-.08,0)) pad_stereo_2_5mm = cube(-.03,.03,-.05,.05,0,0) class stereo_2_5mm(part): # # CUI SJ1-2533-SMT # def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] # # pin 1: base # self.shape = translate(pad_stereo_2_5mm,-.130,-.16,0) self.pad.append(point(-.130,-.149,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'base',8)) # # pin 2: tip # self.shape = add(self.shape,translate(pad_stereo_2_5mm,.197,.15,0)) self.pad.append(point(.197,.141,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'tip',8)) # # pin 3: middle # self.shape = add(self.shape,translate(pad_stereo_2_5mm,-.012,-.16,0)) self.pad.append(point(-.012,-.149,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'middle',8)) # # switches # pad_button_6mm = cube(-.04,.04,-.03,.03,0,0) class button_6mm(part): # # Omron 6mm pushbutton # B3SN-3112P # def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] # # L1 # self.shape = translate(pad_button_6mm,-.125,.08,0) self.pad.append(point(-.125,.08,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L1',8)) # # R1 # self.shape = add(self.shape,translate(pad_button_6mm,-.125,-.08,0)) self.pad.append(point(-.125,-.08,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R1',8)) # # R2 # self.shape = add(self.shape,translate(pad_button_6mm,.125,-.08,0)) self.pad.append(point(.125,-.08,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'R2',8)) # # L2 # self.shape = add(self.shape,translate(pad_button_6mm,.125,.08,0)) self.pad.append(point(.125,.08,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'L2',8)) # # ICs # pad_SOT23 = cube(-.02,.02,-.02,.02,0,0) class regulator_SOT23(part): def __init__(self,value=''): self.value = value self.x = 0 self.y = 0 self.z = 0 self.pad = [point(0,0,0)] self.labels = [] # # pin 1: output # self.shape = translate(pad_SOT23,-.0375,-.045,0) self.pad.append(point(-.0375,-.045,0)) # # pin 2: input # self.shape = add(self.shape,translate(pad_SOT23,.0375,-.045,0)) self.pad.append(point(.0375,-.045,0)) # # pin 3: ground # self.shape = add(self.shape,translate(pad_SOT23,0,.045,0)) self.pad.append(point(0,.045,0)) pad_SOP = cube(-.043,.043,-.010,.010,0,0) class ATtiny45_SOP(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] # # pin 1: PB5/dW/ADC0/-RESET/PCINT5 # self.shape = translate(pad_SOP,-.14,.075,0) self.pad.append(point(-.14,.075,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'1',8)) # # pin 2: PB3/ADC3/-OC1B/CLKI/XTAL1/PCINT3 # self.shape = add(self.shape,translate(pad_SOP,-.14,.025,0)) self.pad.append(point(-.14,.025,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB3',8)) # # pin 3: PB4/ADC2/OC1B/CLKO/XTAL2/PCINT4 # self.shape = add(self.shape,translate(pad_SOP,-.14,-.025,0)) self.pad.append(point(-.14,-.025,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB4',8)) # # pin 4: GND # self.shape = add(self.shape,translate(pad_SOP,-.14,-.075,0)) self.pad.append(point(-.14,-.075,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'GND',8)) # # pin 5: PB0/MOSI/DI/SDA/AIN0/OC0A/-OC1A/AREF/PCINT0 # self.shape = add(self.shape,translate(pad_SOP,.14,-.075,0)) self.pad.append(point(.14,-.075,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB0',8)) # # pin 6: PB1/MISO/DO/AIN1/OC0B/OC1A/PCINT1 # self.shape = add(self.shape,translate(pad_SOP,.14,-.025,0)) self.pad.append(point(.14,-.025,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB1',8)) # # pin 7: PB2/SCK/USCK/SCL/ADC1/T0/INT0/PCINT2 # self.shape = add(self.shape,translate(pad_SOP,.14,.025,0)) self.pad.append(point(.14,.025,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'PB2',8)) # # pin 8: VCC # self.shape = add(self.shape,translate(pad_SOP,.14,.075,0)) self.pad.append(point(.14,.075,0)) self.labels.append(cad_text(self.pad[-1].x,self.pad[-1].y,self.pad[-1].z,'VCC',8)) # # define board # w = .016 width = 1.56 height = .67 x = 1 y = 1 z = -.005 pcb = cube(-10,10,-10,10,z,z) pcb = subtract(pcb,cube(x,x+width,y,y+height,-10,10)) IC1 = ATtiny45_SOP('IC1\nt45') pcb = IC1.add(pcb,x+.85,y+.285,z) R1 = R_1206('R1\n10k') pcb = R1.add(pcb,IC1.x,IC1.y+.16,z) pcb = wire(pcb,w, IC1.pad[1], R1.pad[1]) pcb = wire(pcb,w, IC1.pad[8], R1.pad[2]) R2 = R_1206('R2\n10k') pcb = R2.add(pcb,IC1.x,IC1.y-.16,z) pcb = wire(pcb,w, IC1.pad[3], R2.pad[1]) pcb = wire(pcb,w, R2.pad[2], R1.pad[2]) IC2 = regulator_SOT23('IC2\n5V') pcb = IC2.add(pcb,IC1.x-.31,IC1.y+.08,z,angle=90) pcb = wire(pcb,w, IC1.pad[4], IC2.pad[3]) C1 = C_1206('C1\n3.3uF') pcb = C1.add(pcb,IC2.x,IC2.y+.15,z) pcb = wire(pcb,w, C1.pad[1], IC2.pad[1]) pcb = wire(pcb,w, C1.pad[2], IC2.pad[3]) pcb = wire(pcb,w, C1.pad[1], point(C1.pad[1].x,C1.y+.07,z), R1.pad[2]) J1 = stereo_2_5mm('J1') pcb = J1.add(pcb,IC1.x-.6,IC1.y+.17,z,angle=90) pcb = wire(pcb,w, J1.pad[1], point(J1.x,J1.pad[2].y-.08,z), IC2.pad[3]) pcb = wire(pcb,w, J1.pad[2], IC2.pad[2]) pcb = wire(pcb,w, R2.pad[1], J1.pad[3]) J2 = Molex_serial('J2') pcb = J2.add(pcb,IC1.x+.555,IC1.y+.05,z,angle=-90) pcb = wire(pcb,w, J2.pad[4], point(J2.pad[4].x+.09,J2.pad[4].y,z), point(J2.pad[4].x+.09,J2.pad[1].y-.045,z), point(J2.pad[4].x-.06,J2.pad[1].y-.045,z), point(J2.pad[4].x-.1,R2.y-.07,z), point(IC1.x,C1.y,z), C1.pad[2]) pcb = wire(pcb,w, J2.pad[1], IC1.pad[6]) D1 = D_SOD_123('D1\n4.7V') pcb = D1.add(pcb,IC1.x+.39,IC1.y+.225,z,angle=-90) pcb = wire(pcb,w, J2.pad[4], D1.pad[1]) R3 = R_1206('R2\n10k') pcb = R3.add(pcb,IC1.x+.29,IC1.y+.225,z,angle=90) pcb = wire(pcb,w, D1.pad[2], R3.pad[1]) pcb = wire(pcb,w, J2.pad[2], R3.pad[2]) pcb = wire(pcb,w, IC1.pad[7], point(IC1.pad[7].x+.09,IC1.pad[7].y,z), point(IC1.pad[7].x+.09,R3.pad[1].y,z), R3.pad[1]) # # define limits and parameters # cad.xmin = x-.1 # min x to render cad.xmax = x+width+.1 # max x to render cad.ymin = y-.1 # min y to render cad.ymax = y+width+.1 # max y to render cad.zmin = z cad.zmax = .050 nxy = 200 cad.nx = nxy # x points to render cad.ny = nxy # y points to render cad.nz = 1 # # assign board to cad.function # cad.function = pcb