# # hello4.cad # # Neil Gershenfeld # CBA MIT 10/30/06 # # # 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 # 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=14)) 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,w,*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(-.0325,.0325,-.034,.034,0,0) class R_1206(part): def __init__(self,value=''): self.value = value self.labels = [] self.pad = [point(0,0,0)] self.shape = translate(pad_1206,-.055,0,0) self.pad.append(point(-.055,0,0)) self.shape = add(self.shape,translate(pad_1206,.055,0,0)) self.pad.append(point(.055,0,0)) class C_1206(part): def __init__(self,value=''): self.value = value self.labels = [] self.pad = [point(0,0,0)] self.shape = translate(pad_1206,-.055,0,0) self.pad.append(point(-.055,0,0)) self.shape = add(self.shape,translate(pad_1206,.055,0,0)) self.pad.append(point(.055,0,0)) # # connectors # pad_Molex = cube(-.0155,.0155,-.0265,.0265,0,0) pad_Molex_solder = cube(-.055,.055,-.065,.065,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,-.16,-.065,0)) self.shape = add(self.shape,translate(pad_Molex_solder,.16,-.065,0)) pad_five_mm_horizontal = cube(-.025,.025,-.075,.075,0,0) class five_mm_horizontal(part): def __init__(self,value=''): self.value = value self.pad = [point(0,0,0)] self.labels = [] self.shape = translate(pad_five_mm_horizontal,-.05,0,0) self.pad.append(point(-.05,0,0)) self.shape = add(self.shape,(translate(pad_five_mm_horizontal,.05,0,0))) self.pad.append(point(.05,0,0)) # # 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 # width = 0.0156 x = 0.25 y = -.3 z = 0 pcb = "0" IC1 = ATtiny45_SOP('IC1\nt45') pcb = IC1.add(pcb,x,y,z) R1 = R_1206('R1\n10k') pcb = R1.add(pcb,IC1.x,IC1.y+.2) pcb = wire(pcb,width,\ IC1.pad[1],\ point(IC1.pad[1].x-.05,IC1.pad[1].y),\ point(IC1.pad[1].x-.05,R1.pad[1].y),\ R1.pad[1]) pcb = wire(pcb,width,\ IC1.pad[8],\ point(IC1.pad[8].x+.05,IC1.pad[8].y),\ point(IC1.pad[8].x+.05,R1.pad[2].y),\ R1.pad[2]) IC2 = regulator_SOT23('IC2\n5V') pcb = IC2.add(pcb,IC1.x-.33,IC1.y+.02,angle=90) C1 = C_1206('C1\n3.3uF') pcb = C1.add(pcb,IC2.x,IC2.y+.18) pcb = wire(pcb,width, C1.pad[1], IC2.pad[1]) pcb = wire(pcb,width, C1.pad[2], IC2.pad[3]) pcb = wire(pcb,width, C1.pad[1], point(C1.pad[1].x,C1.pad[1].y+.08), R1.pad[2]) J1 = Molex_serial() pcb = J1.add(pcb,IC1.x-.6,IC1.y,angle=90) pcb = wire(pcb,width, J1.pad[4], IC1.pad[4]) pcb = wire(pcb,width, J1.pad[4], IC2.pad[3]) pcb = wire(pcb,width, J1.pad[3], IC2.pad[2]) pcb = wire(pcb,width, J1.pad[1], point(J1.pad[1].x+.07,J1.pad[1].y), point(J1.pad[1].x+.07,C1.pad[1].y+.12), point(IC1.pad[6].x+.09,C1.pad[1].y+.12), point(IC1.pad[6].x+.09,IC1.pad[6].y), IC1.pad[6]) R2 = R_1206('R2\n4.99k') pcb = R2.add(pcb,IC1.x+.3,IC1.y,angle=-90) pcb = wire(pcb,width, IC1.pad[8], point(IC1.x+.04,IC1.pad[8].y), point(IC1.x+.04,IC1.y-.13), point(R2.pad[1].x,IC1.y-.13), R2.pad[1]) pcb = wire(pcb,width, IC1.pad[2], point(IC1.x-.04,IC1.pad[2].y), point(IC1.x-.04,IC1.y-.18), point(R2.x+.065,IC1.y-.18), point(R2.x+.065,R2.pad[2].y), R2.pad[2]) J2 = five_mm_horizontal('J2') pcb = J2.add(pcb,R2.x+.05,R1.y+.05) pcb = wire(pcb,width, J2.pad[1], R2.pad[2]) pcb = wire(pcb,width, IC2.pad[3], point(IC2.pad[3].x,IC1.y-.22), point(J2.pad[2].x,IC1.y-.22), point(J2.pad[2].x,J2.pad[2].y)) board = cube(-10,10,-10,10,0,0) board = subtract(board,cube(-.52,.72,-.58,.07,0,0)) pcb = add(pcb,board) # # define limits and parameters # d = 1.3 x0 = 0.1 y0 = 0. cad.xmin = x0-d/2 # min x to render cad.xmax = x0+d/2 # max x to render cad.ymin = y0-d/2 # min y to render cad.ymax = y0+d/2 # max y to render nxy = 500 cad.nx = nxy # x points to render cad.ny = nxy # y points to render # # assign part to cad.function # cad.function = pcb