@@ -3,38 +3,41 @@ use <tubemesh.scad>;
33use < certamenbutton.scad> ;
44
55// TODO:
6- // speaker rails
76// cut up
8- // screw wells for screen
97// screw wells for joining halves
108
11- includeBoards = false ;
9+ includeBoards = true ;
1210megaWidth = 53.34 ;
1311megaLength = 101.6 ;
14- megaPCBThickness = 1.66 ;
15- megaHoles = [ // [ 50.8, 13.97 ],
16- [ 50.8 , 96.52 ]];
12+ megaHoles = [
13+ [ 2.54 , 15.24 ],
14+ [ 50.8 , 13.97 ],
15+ [ 2.54 , 90.17 ],
16+ [ 50.8 , 96.52 ]
17+ ]; // from Kelly Egan's Arduino library
1718/* [[x,z,width,height],...] */
19+ megaPCBThickness = 1.66 ;
1820megaFrontCutouts = [ [7 , megaPCBThickness, 12.23 , 10.82 ],
1921 [ megaWidth- 9.04 - 6.7 , megaPCBThickness, 9.04 , 11.08 ] ];
2022cbWidth = 54.9 ;
2123cbLength = 99.06 ; // between edges of RJ-45 breakout board
2224cbPCBThickness = 1.7 ;
2325cbFrontCutouts = [[5.88 ,5.45 ,15.15 ,11.56 ],[cbWidth- 5.58 - 15.15 ,5.45 ,15.15 ,11.56 ]];
2426cbBackCutouts = [[cbWidth- 5.58 - 15.15 ,5.45 ,15.15 ,11.56 ]];
25- cbHoles = [[4.04 ,cbLength- 7.5 ]];
26- maxPCBThickness = max (megaPCBThickness, cbPCBThickness);
27+ cbHoles = [[4.04 ,7.5 ],[cbWidth- 4.04 ,7.5 ],[4.04 ,cbLength- 7.5 ],[cbWidth- 4.04 ,cbLength- 7.5 ]];
28+
29+ pcbThickness = max (cbPCBThickness,megaPCBThickness);
30+
2731mountExtra = 2 ;
2832
29- boardDivider = 3 ;
30- slideBackbone = 3 ;
3133underPCBs = 5 ;
3234
35+ cutLine = underPCBs + 0.5 * ( cbFrontCutouts[0 ][1 ] + megaPCBThickness + max ([for (c= megaFrontCutouts) c[3 ]]) );
36+
3337fitTolerance = 0.4 ;
3438cutoutTolerance = 1 ;
35- bottomSlideWidth = 1.82 ;
36- topSlideWidth = 1.75 ;
3739
40+ boardDivider = 2 ;
3841sideWallThickness = 1.25 ;
3942bottomThickness = 1.5 ;
4043topThickness = 3.2 ; // match Certamen button
@@ -43,7 +46,7 @@ screenScrewHorizontalSpacing = 74.8;
4346screenScrewVerticalSpacing = 31.2 ;
4447screenWidth = 71.21 ;
4548screenHeight = 24.04 ;
46- // make sure screendepth fits well
49+ screenDepth = 7 ;
4750
4851screenScrewWellDepth = 7.97 ;
4952speakerDiameter = 39.2 ;
@@ -53,9 +56,12 @@ speakerMountThickness = 1.5;
5356grilleSolidWidth = 2 ;
5457grilleHoleWidth = 2.5 ;
5558
56- corner = 9 ;
59+ corner = 9 ; // corner-boardDivider must allow room for the speaker
5760
58- boxHeight = speakerDiameter+ underPCBs+ 2 + maxPCBThickness+ topThickness+ bottomThickness;
61+ pcbHolderThickness = 2 ;
62+ pcbHolderHeight = underPCBs+ pcbThickness+ 2 ;
63+
64+ boxHeight = speakerDiameter+ underPCBs+ 2 + pcbThickness+ topThickness+ bottomThickness;
5965
6066nudge = 0.001 ;
6167insideWidth = boardDivider+ 4 * fitTolerance+ megaWidth+ cbWidth;
@@ -72,13 +78,27 @@ modeX = 0.75*insideWidth;
7278modeY = 0.75 * insideLength;
7379
7480cbX = fitTolerance;
81+ cbY = fitTolerance;
7582megaX = 3 * fitTolerance+ cbWidth+ boardDivider;
83+ megaY = fitTolerance;
7684topZ = boxHeight- topThickness- bottomThickness;
7785speakerDiameter1 = speakerDiameter + 2 * fitTolerance;
7886
87+ screwTolerance = 0.125 ;
88+ screwHoleSize = 2.6 ;
89+ screwHoleSize1 = screwHoleSize + 2 * screwTolerance;
90+ screwPillarSize = 12 ;
91+
7992speakerY = 0.5 * insideLength;
8093speakerX = boxWidth- corner- 2 * sideWallThickness;
81- speakerZ = (topZ + maxPCBThickness+ underPCBs)/2 ;
94+ speakerZ = speakerDiameter1/2 ;
95+
96+ ventHeight= 18 ;
97+ ventWidth= insideWidth* 0.75 ;
98+ ventSpacing= 2 ;
99+
100+ ventX= insideWidth/2 ;
101+ ventZ= topZ- 10 ;
82102
83103module cutouts(cutouts, length, extra) {
84104 for (c= cutouts) {
@@ -105,13 +125,13 @@ module contents(visualize=true) {
105125 extraCutout = visualize?0 :cutoutTolerance;
106126 color ("blue" ) {
107127 translate ( [megaX,fitTolerance,underPCBs] ) cube ([megaWidth, megaLength, megaPCBThickness]);
108- translate ([megaX,fitTolerance+ nudge - cutoutLength,underPCBs- nudge ]) cutouts(megaFrontCutouts, cutoutLength,extraCutout);
128+ translate ([megaX,fitTolerance- cutoutLength,underPCBs]) cutouts(megaFrontCutouts, cutoutLength,extraCutout);
109129 }
110130 color ("red" ) {
111131 translate ( [cbX,fitTolerance,underPCBs])
112132 cube ([cbWidth, cbLength, cbPCBThickness]);
113- translate ([cbX,fitTolerance+ nudge - cutoutLength,underPCBs- nudge ]) cutouts(cbFrontCutouts, cutoutLength,extraCutout);
114- translate ([cbX,fitTolerance+ cbLength- nudge ,underPCBs- nudge ]) cutouts(cbBackCutouts, cutoutLength,extraCutout);
133+ translate ([cbX,fitTolerance- cutoutLength,underPCBs]) cutouts(cbFrontCutouts, cutoutLength,extraCutout);
134+ translate ([cbX,fitTolerance+ cbLength,underPCBs]) cutouts(cbBackCutouts, cutoutLength,extraCutout);
115135 }
116136 color ([0 ,.4 ,0 ]) {
117137 translate ([screenX- screenHeight/2 - extraCutout,screenY- screenWidth/2 - extraCutout,topZ- 1 ]) cube ([screenHeight+ 2 * extraCutout,screenWidth+ 2 * extraCutout,cutoutLength]);
@@ -125,67 +145,106 @@ module contents(visualize=true) {
125145 }
126146}
127147
128- mountHeight = underPCBs+ maxPCBThickness+ topSlideWidth+ mountExtra;
129-
130148module boardMounts() {
131- module diagonalSlideLeft() {
132- section1 = [ [0 ,0 ,0 ], [topSlideWidth,0 ,topSlideWidth], [topSlideWidth,0 ,topSlideWidth+ mountExtra],[0 ,0 ,topSlideWidth+ mountExtra] ];
133- section2 = [for (v= section1) v+ [0 ,insideLength,0 ]];
134-
135- leftPointsAndFaces =
136- pointsAndFaces([ section1, section2]);
137- polyhedron (points= leftPointsAndFaces[0 ], faces= leftPointsAndFaces[1 ]);
138- }
139-
140- module diagonalSlideRight() {
141- mirror ([1 ,0 ,0 ]) diagonalSlideLeft();
142- }
143-
144- render (convexity= 2 )
149+ render (convexity= 2 ) {
145150 intersection () {
146151 union () {
147- translate ([nudge- slideBackbone,0 ,0 ])
148- cube ([slideBackbone,insideLength,mountHeight]);
149- translate ([insideWidth- nudge,0 ,0 ])
150- cube ([slideBackbone,insideLength,mountHeight]);
151-
152- cube ([bottomSlideWidth, insideLength, underPCBs]);
153- translate ([2 * fitTolerance+ cbWidth- bottomSlideWidth,0 ,0 ])
154- cube ([bottomSlideWidth* 2 + boardDivider, insideLength, underPCBs]);
155- translate ([insideWidth- bottomSlideWidth, 0 ,0 ])
156- cube ([bottomSlideWidth+ nudge, insideLength, underPCBs]);
157- translate ([2 * fitTolerance+ cbWidth- nudge,0 ,0 ])
158- cube ([boardDivider+ 2 * nudge,insideLength,mountHeight]);
159- translate ([0 ,0 ,underPCBs+ cbPCBThickness]) diagonalSlideLeft();
160- translate ([2 * fitTolerance+ cbWidth,0 ,underPCBs+ cbPCBThickness]) diagonalSlideRight();
161- translate ([megaX- fitTolerance,0 ,underPCBs+ megaPCBThickness]) diagonalSlideLeft();
162- translate ([megaX+ fitTolerance+ megaWidth,0 ,underPCBs+ megaPCBThickness]) diagonalSlideRight();
163- translate ([0 ,insideLength- (megaLength- cbLength),0 ]) cube ([2 * fitTolerance+ cbWidth, megaLength- cbLength, underPCBs+ cbPCBThickness+ topSlideWidth]);
164- }
165- box(inset= sideWallThickness+ fitTolerance);
152+ translate ([cbX- fitTolerance- pcbHolderThickness,0 ,0 ]) cube ([pcbHolderThickness,insideLength,pcbHolderHeight]);
153+ translate ([cbX+ cbWidth+ fitTolerance,0 ,0 ]) cube ([pcbHolderThickness,insideLength,pcbHolderHeight]);
154+ translate ([megaX+ megaWidth+ fitTolerance,0 ,0 ]) cube ([pcbHolderThickness,insideLength,pcbHolderHeight]);
155+ translate ([0 ,insideLength- (megaLength- cbLength),0 ]) cube ([2 * fitTolerance+ cbWidth, megaLength- cbLength, pcbHolderHeight]);
156+ }
157+ box();
158+ }
159+ pcbScrews(megaX,megaY,megaHoles);
160+ pcbScrews(cbX,cbY,cbHoles);
161+ }
162+ }
163+
164+ module screwPillar(height, taper=true) {
165+ difference () {
166+ cylinder (d1= screwPillarSize, d2= taper ? screwHoleSize1+ 4 : screwPillarSize, h= height, $ fn= 16 );
167+ cylinder (d= screwHoleSize1, h= height+ nudge, $ fn= 16 );
168+ }
169+ }
170+
171+ module pcbScrews(x,y,positions) {
172+ for (pos= positions) {
173+ translate ([x+ pos[0 ],y+ pos[1 ],0 ]) screwPillar(underPCBs, taper= true );
166174 }
167175}
168176
169177module box(height=boxHeight,inset=0) {
170178 linear_extrude(height= height) translate ([- corner- sideWallThickness+ inset,- sideWallThickness+ inset]) roundedSquare([boxWidth- 2 * inset, boxLength- 2 * inset], radius= corner- inset);
171179}
172180
181+ module screenScrew(holeOnly=false) {
182+ pillarSize = screwHoleSize1+ 4 ;
183+ render (convexity= 2 )
184+ translate ([0 ,0 ,topZ- (screenDepth- topThickness)- nudge])
185+ difference () {
186+ if (! holeOnly) cylinder (d= pillarSize, h= screenDepth, $ fn= 16 );
187+ translate ([0 ,0 ,- nudge]) cylinder (d= screwHoleSize1, h= screenDepth- 1 , $ fn= 16 );
188+ }
189+ }
190+
191+ module screenScrews(holeOnly=false) {
192+ dx = screenScrewVerticalSpacing / 2 ;
193+ dy = screenScrewHorizontalSpacing / 2 ;
194+
195+ translate ([screenX- dx,screenY- dy]) screenScrew(holeOnly= holeOnly);
196+ translate ([screenX+ dx,screenY- dy]) screenScrew(holeOnly= holeOnly);
197+ translate ([screenX- dx,screenY+ dy]) screenScrew(holeOnly= holeOnly);
198+ translate ([screenX+ dx,screenY+ dy]) screenScrew(holeOnly= holeOnly);
199+ }
200+
173201module shell() {
174202 render (convexity= 6 )
175203 difference () {
176- translate ([0 ,0 ,- bottomThickness]) box();
204+ translate ([0 ,0 ,- bottomThickness+ nudge ]) box();
177205 box(height= boxHeight- bottomThickness- topThickness,inset= sideWallThickness);
178206 contents(visualize= false );
207+ screenScrews(holeOnly= true );
208+ translate ([0 ,- sideWallThickness- nudge,0 ]) vent();
209+ translate ([0 ,insideLength- nudge,0 ]) vent();
179210 }
180211}
181212
182- module bottom() {
213+ module speakerMount() {
214+ height = nudge+ topZ- speakerZ+ 10 ;
215+ module strip() {
216+ cube ([speakerMountXStickout+ speakerMountThickness,speakerMountThickness,height]);
217+ translate ([speakerMountXStickout,0 ,0 ])
218+ cube ([speakerMountThickness,speakerMountYStickout+ speakerMountThickness,height]);
219+ }
220+ translate ([speakerX+ nudge,speakerY,0 ])
221+ rotate ([0 ,0 ,180 ]) {
222+ translate ([0 ,0 ,topZ- height]) {
223+ translate ([0 ,- speakerDiameter1/2 - speakerMountThickness,0 ]) strip();
224+ translate ([0 ,speakerDiameter1/2 + speakerMountThickness,0 ]) mirror (v= [0 ,1 ,0 ]) strip();
225+ }
226+ topHolderHeight = (topZ- speakerZ)- speakerDiameter1/2 ;
227+ translate ([0 ,- 5 , topZ- topHolderHeight])
228+ cube ([speakerMountXStickout, 10 , topHolderHeight+ nudge]);
229+ }
230+ }
231+
232+ module vent() {
233+ translate ([ventX- ventWidth/2 ,- nudge,ventZ- ventHeight/2 ])
234+ for (x= [0 :2 * ventSpacing:ventWidth]) {
235+ translate ([x,0 ,0 ])
236+ cube ([ventSpacing,2 * nudge+ sideWallThickness,ventHeight]);
237+ }
238+ }
239+
240+
241+ module inside() {
183242 boardMounts();
243+ screenScrews();
184244 % shell();
185245 if (includeBoards) contents(visualize= true );
186246}
187247
188248% shell();
189- bottom();
190-
191- // todo: screws; front empty, back full
249+ inside();
250+ speakerMount();
0 commit comments