summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--delta.jscad453
1 files changed, 453 insertions, 0 deletions
diff --git a/delta.jscad b/delta.jscad
new file mode 100644
index 0000000..63eea6c
--- a/dev/null
+++ b/delta.jscad
@@ -0,0 +1,453 @@
1var PRINT = {
2 layer_height: 0.2,
3 extrusion_width: 0.4,
4
5 fit_tolerance: 0.4,
6 slide_tolerance: 0.2
7};
8
9var CONFIG = {
10 hotend: {
11 h: 62.4, // full assembly height
12 groove: { d:12, h:6 }, // grove diameter and height
13 ungroove: { d:16, above:3.7, below: 3+4 }
14 },
15 effector: {
16 h: 6,
17 o: 20,// offset to the rod mounts line
18 rods_apart: 40,
19 cone: { shell: 1, angle: Math.PI/6 },
20 rodend: {
21 joint_w: 7,// thickness of the joint
22 screw_l: 20-1, // 20 with the head
23 screw_d: 3
24 },
25 hotend: { margin: 2 },
26 hinge: {
27 d: 3, w: 5, margin: 2.5,
28 h: 1+(6+3.7)/2, // elevation + grove + top
29 e: 1 // elevation
30 },
31 clamp: {
32 shell: 4.6,
33 d: 3,
34 margin: 2.5,
35 split: 0.6
36 },
37 mswitch: {
38 size: [ 19.8, 6, 10 ],
39 screw: {
40 d: 2, h: 10/2-2,
41 s: 1.3, // screw shell
42 o: [-9.5/2,9.5/2].map(function(x) {
43 return -19.8/2+x;
44 })
45 },
46 switch_x: 2.5
47 },
48 guide: {
49 width: 3, height: 5+1, length: 6
50 },
51 fanholder: {
52 r: 30,
53 screw: { d: 3, m: 2.5/*margin*/ },
54 w: 3
55 }
56 },
57 nut: { h: 2.3, w: 5.5 }
58};
59
60var U = {
61 hypotenuse: function(a,b) {
62 return Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
63 },
64 peek: function(x,m) {
65 console.log(x,m);
66 return x;
67 }
68};
69
70/* {h:,w:} */
71function nut(o) {
72 var rv = CSG.cylinder({
73 start:[0,0,0],end:[0,0,o.h],
74 radius: o.w/2/Math.cos(Math.PI/6),
75 resolution: 6
76 });
77 rv.properties.axis_connector = new CSG.Connector([0,0,0],[0,0,1],[0,1,0]);
78 return rv;
79}
80
81var E3DV6 = {
82 dimensions: {
83 big_d: 22.3,
84
85 },
86 heatsink: function() {
87 var fn = 16;
88 var z=0;
89 var unite = [ {d:16,h:3.7},{d:12,h:6},{d:16,h:3} ].map(function(x) {
90 return CSG.cylinder({
91 start: [0,0,z], end: [0,0,z-=x.h],
92 radius: x.d/2, resolution: fn
93 });
94 });
95 unite.push(CSG.cylinder({
96 start:[0,0,z-=1.5], end:[0,0,z-=1],
97 radius: 16/2, resolution: fn
98 }));
99 for(var i=0;i<11;++i) unite.push(CSG.cylinder({
100 start:[0,0,z-=1.5], end:[0,0,z-=1],
101 radius: this.dimensions.big_d/2, resolution: fn
102 }));
103 unite.push(CSG.cylinder({
104 start:[0,0,z], end: [0,0,-12.7],
105 radiusStart: 10/2, radiusEnd: 8.5/2, /* pretty arbitrary */
106 resolution: fn
107 }));
108 var rv = union(unite);
109 rv = rv.subtract([CSG.cylinder({
110 start:[0,0,1], end: [0,0,z-1],
111 radius: 4.2/2, resolution: fn
112 }),CSG.cylinder({
113 start:[0,0,1], end: [0,0,-6.7/*somewhat arbitrary*/],
114 radius: 8/2, resolution: fn
115 }),CSG.cylinder({
116 start:[0,0,z-1], end: [0,0,z+14.8],
117 radius: 6/2 /*M7*/, resolution: fn
118 })]);
119 rv.properties.pushfit_connector = new CSG.Connector([0,0,0],[0,0,-1],[1,0,0]);
120 rv.properties.heatbreak_connector = new CSG.Connector([0,0,z+14.8],[0,0,-1],[1,0,0]);
121 rv.properties.grove_connector = new CSG.Connector([0,0,-3.7-3],[0,0,1],[1,0,0]);
122 return rv.setColor([0.8,0.8,0.8,0.9]);
123 }
124};
125
126var EFFECTOR = {
127 /* {sd: screw diameter, l: cone length, s: screw shell, a: angle from axis} */
128 cone: function effector_cone(o) {
129 var re = o.sd/2+o.s, rs = re+o.l*Math.tan(o.a||(Math.PI/4));
130 var rv = CSG.cylinder({
131 start: [0,0,0], end: [0,0,o.l],
132 radiusStart: rs, radiusEnd: re,
133 resolution: Math.floor(rs*2*2)
134 }).subtract(CSG.cylinder({
135 start:[0,0,-1], end:[0,0,o.l+1], radius: o.sd,
136 //resolution: Math.floor(o.sd*2*2)
137 }));
138 rv.properties.top_connector = new CSG.Connector([0,0,o.l],[0,0,-1],[1,0,0]);
139 rv.properties.bottom_connector = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]);
140 var nuthole = nut(CONFIG.nut);
141 rv = rv.subtract(nuthole.connectTo(
142 nuthole.properties.axis_connector, rv.properties.bottom_connector,
143 false, 0
144 ));
145 return rv.intersect(CSG.cylinder({start:[0,0,0],end:[0,0,o.l],radius:6/*TODO:calculate*/}));
146 },
147 platform_bb: function platform_bb() {
148 var e = CONFIG.effector;
149 var r = U.hypotenuse(e.rods_apart/2,e.o+e.rodend.screw_d/2+e.cone.shell);
150 var rv = CSG.sphere({
151 center: [0,0,e.h/2], radius: r,
152 resolution: r*2*2
153 }).intersect(CSG.cube({
154 corner1: [-r,-r,0], corner2: [r,r,e.h]
155 }));
156 rv.properties.base_connector = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]);
157 return rv;
158 },
159 effector: function effector_effector() {
160 var e = CONFIG.effector;
161 var conel = e.rodend.screw_l-e.rodend.joint_w;
162 var nutr = CONFIG.nut.w/2/Math.cos(Math.PI/6);
163 var cone = this.cone({sd:e.rodend.screw_d/2,l:conel,s:e.cone.shell,a:e.cone.angle});
164 var rcorner = U.hypotenuse(e.o-e.rodend.screw_d/2-e.cone.shell,e.rods_apart/2)-3.85; //XXX:config/calc
165 var ropen = E3DV6.dimensions.big_d/2+e.hotend.margin;
166 var rmount = this.rmount = (rcorner+ropen)/2;
167 var rv = [];
168 for(var a=0;a<360;a+=120) {
169 rv.push(union([-1,1].map(function(s) {
170 return cone.connectTo(cone.properties.top_connector,
171 new CSG.Connector([s*e.rods_apart/2,e.o,e.h/2],[-s,0,0],[0,0,1]),
172 false, 0);
173 })).union(CSG.cube({
174 corner1:[e.rods_apart/2-conel+.1,e.o-nutr,0],
175 corner2:[-e.rods_apart/2+conel-.1,
176 -rcorner,
177 e.h]
178 })).rotateZ(a));
179 }
180 rv.push(CSG.cylinder({
181 start:[0,0,0], end:[0,0,e.h],
182 radius: U.hypotenuse(e.o-nutr,e.rods_apart/2-conel)
183 }));
184 rv = union(rv).intersect(this.platform_bb()).subtract(CSG.cylinder({
185 start:[0,0,-1], end:[0,0,e.h+1],
186 radius: ropen, resolution: ropen*4
187 })).subtract([/*0, probe here*/120,240].map(function(x) { /* nut pockets */
188 return CSG.cube({
189 corner1:[-CONFIG.nut.w/2,0,(e.h-CONFIG.nut.h)/2],
190 corner2:[CONFIG.nut.w/2,-rcorner-1,(e.h+CONFIG.nut.h)/2]
191 }).union(CSG.cylinder({
192 start:[0,-rmount,-1], end:[0,-rmount,e.h+1],
193 radius: 3/2 // XXX:
194 })).subtract(CSG.cylinder({
195 start:[0,-rmount,(e.h+CONFIG.nut.h)/2],
196 end:[0,-rmount,(e.h+CONFIG.nut.h)/2+PRINT.layer_height*3/2],
197 radius: 3/2+.1
198 })).rotateZ(x);
199 })).subtract( CSG.cylinder({ // pulldown screw
200 start: [0,-rcorner+e.mswitch.size[1]+PRINT.extrusion_width+3/2/*XXX:conf*/,-1],
201 end: [0,-rcorner+e.mswitch.size[1]+PRINT.extrusion_width+3/2/*XXX:conf*/,e.h+1],
202 radius: 3/2+1 /*XXX: config */
203 })).subtract( CSG.cylinder({ /* switch-screw */
204 start: [e.mswitch.switch_x,-rcorner+e.mswitch.size[1]/2,-1],
205 end: [e.mswitch.switch_x,-rcorner+e.mswitch.size[1]/2,e.h+1],
206 radius: e.mswitch.screw.d/2
207 }));
208 // add hinges
209 rv.properties.hinge_connector=new CSG.Properties();
210 var hinges_apart=e.rods_apart/2-conel;
211 rv = rv.union([-1,1].map(function hinge(s) {
212 rv.properties.hinge_connector[s]=new CSG.Connector([s*hinges_apart,e.o,e.h+e.hinge.h],[s,0,0],[0,0,1]);
213 return CSG.cube({
214 corner1: [s*hinges_apart,e.o-e.hinge.margin-e.hinge.d/2,e.h],
215 corner2: [s*(hinges_apart+e.hinge.w),e.o+e.hinge.margin+e.hinge.d/2,e.h+e.hinge.h]
216 }).union(CSG.cylinder({
217 start: [s*hinges_apart,e.o,e.h+e.hinge.h],
218 end: [s*(hinges_apart+e.hinge.w),e.o,e.h+e.hinge.h],
219 radius: e.hinge.d/2+e.hinge.margin
220 })).subtract(CSG.cylinder({
221 start: [s*(hinges_apart-1),e.o,e.h+e.hinge.h],
222 end: [s*(hinges_apart+e.hinge.w+1),e.o,e.h+e.hinge.h],
223 radius: e.hinge.d/2
224 }));
225 }));
226 // add clamp guides
227 var cgrr = e.guide.width/3;
228 rv = rv.union([-1,1].map(function guide(s) {
229 return CSG.roundedCube({
230 center: [s*(e.mswitch.size[0]+PRINT.slide_tolerance+e.guide.width)/2,-rcorner+e.guide.length/2,e.h+e.guide.height/2-cgrr],
231 radius: [e.guide.width/2,e.guide.length/2,e.guide.height/2+cgrr],
232 roundradius: cgrr
233 }).intersect(CSG.cube({
234 center: [s*(e.mswitch.size[0]+PRINT.slide_tolerance+e.guide.width)/2,-rcorner+e.guide.length/2,e.h+e.guide.height/2],
235 radius: [e.guide.width/2,e.guide.length/2,e.guide.height/2+.1],
236 roundradius: cgrr
237 }));
238 }));
239 rv.properties.grove_connector = new CSG.Connector([0,0,e.h+e.hinge.e+6/2],[0,0,1],[1,0,0]);
240 rv.properties.rcorner = rcorner;
241 return rv.setColor([0.4,0.8,0.4,0.9]);
242 },
243 hinged: function effector_hinged(o) {
244 var e = CONFIG.effector;
245 var conel = e.rodend.screw_l-e.rodend.joint_w;
246 var hinges_apart = e.rods_apart/2-conel;
247 var hhr = e.o-e.hinge.d/2-e.hinge.margin; // hotend holder radius
248 var hhh = CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above;
249 var rv = CSG.cylinder({ /* hinge */
250 start: [-hinges_apart+PRINT.slide_tolerance,e.o,e.h+e.hinge.h],
251 end: [hinges_apart-PRINT.slide_tolerance,e.o,e.h+e.hinge.h],
252 radius: e.hinge.d/2+e.hinge.margin
253 }).union( /* lower hotend holder */
254 CSG.cylinder({
255 start: [0,0,e.h+e.hinge.e], end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h],
256 radius: hhr
257 }).subtract(CSG.cylinder({
258 start: [0,0,e.h+e.hinge.e-1], end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+1],
259 radius: CONFIG.hotend.groove.d/2 +PRINT.fit_tolerance
260 }))
261 ).union( /* upper hotend holder */
262 CSG.cylinder({
263 start: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h],
264 end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above],
265 radius: hhr
266 }).subtract(CSG.cylinder({
267 start: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h-1],
268 end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above+1],
269 radius: CONFIG.hotend.ungroove.d/2 +PRINT.fit_tolerance
270 }))
271 ).union( /* connect mount with hinge */
272 CSG.cube({
273 corner1: [-hinges_apart+PRINT.slide_tolerance,CONFIG.hotend.ungroove.d/2+PRINT.fit_tolerance,e.h+e.hinge.e],
274 corner2: [hinges_apart-PRINT.slide_tolerance,e.o,e.h+e.hinge.h+e.hinge.d/2+e.hinge.margin]
275 })
276 ).subtract( /* hinge screwhole */
277 CSG.cylinder({
278 start: [-hinges_apart-1,e.o,e.h+e.hinge.h],
279 end: [hinges_apart+1,e.o,e.h+e.hinge.h],
280 radius: e.hinge.d/2
281 })
282 ).union( /* hold clamp together */
283 [-1,1].map(function(s) {
284 return CSG.roundedCube({
285 corner1: [s*(-hhr-e.clamp.margin*2-e.clamp.d),-e.clamp.shell,e.h+e.hinge.e],
286 corner2: [s*(-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance),+e.clamp.shell,e.h+e.hinge.e+hhh],
287 roundradius: 1.5
288 });
289 })
290 ).subtract( /* screws for holding clamp */
291 [-1,1].map(function(s) {
292 var nuthole = nut(CONFIG.nut);
293 var x = s*(-hhr-e.clamp.margin-e.clamp.d/2);
294 return CSG.cylinder({
295 start: [x,-e.clamp.shell-1,e.h+e.hinge.e+hhh/2],
296 end: [x,e.clamp.shell+1,e.h+e.hinge.e+hhh/2],
297 radius: e.clamp.d/2
298 }).union(nuthole.connectTo(
299 nuthole.properties.axis_connector,
300 new CSG.Connector([x,e.clamp.shell,e.h+e.hinge.e+hhh/2],[0,-1,0],[0,0,1]),
301 false, 0
302 )).union(CSG.cylinder({
303 start: [x,-e.clamp.shell-1,e.h+e.hinge.e+hhh/2],
304 end: [x,0,e.h+e.hinge.e+hhh/2],
305 radius: e.clamp.d/2+PRINT.slide_tolerance
306 }));
307 })
308 );
309 var ms = o.microswitch;
310 var msedge = o.effector.properties.rcorner;
311 var msh = 9.5; // microswitch holes apart
312 var mshh = Math.abs(ms.properties.switch_connector.point.z-ms.properties.screw_connector[0].point.z); // microswitch holes height
313 rv = rv.union(CSG.cube({ // connect clamp with microswitch
314 corner1: [-ms.properties.microswitch.size.x/2,-msedge+.1,e.h+e.hinge.e],
315 corner2: [+ms.properties.microswitch.size.x/2,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance,e.h+e.hinge.e+hhh]
316 })).union([-msh/2,msh/2].map(function(x) { // shell for microswitch screws
317 return CSG.roundedCylinder({
318 start: [x,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance-(e.mswitch.screw.d/2+e.mswitch.screw.s),e.h+e.hinge.e+mshh],
319 end: [x,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e+mshh],
320 radius: e.mswitch.screw.d/2+e.mswitch.screw.s
321 });
322 })).subtract(CSG.cube({ // cut off excess if any
323 corner1:[-hhr,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e-1],
324 corner2:[hhr,-msedge-1,e.h+e.hinge.e+hhh+e.mswitch.screw.d+e.mswitch.screw.s+1]
325 })).subtract([-msh/2,msh/2].map(function(x) { return CSG.roundedCylinder({ // screwholes
326 start: [x,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance-(e.mswitch.screw.d/2+e.mswitch.screw.s),e.h+e.hinge.e+mshh],
327 end: [x,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e+mshh],
328 radius: e.mswitch.screw.d/2
329 })})).subtract(CSG.cylinder({ // pulldown screw
330 start:[0,-msedge+ms.properties.microswitch.size.y+3/2/*XXX:config*/+PRINT.extrusion_width,e.h+e.hinge.e-1],
331 end:[0,-msedge+ms.properties.microswitch.size.y+3/2/*XXX:config*/+PRINT.extrusion_width,e.h+e.hinge.e+hhh+1],
332 radius: 3/2/*XXX:config*/
333 }));
334 rv.properties.microswitch_screw_connector = new CSG.Properties();
335 [-msh/2,msh/2].forEach(function(x,i) {
336 rv.properties.microswitch_screw_connector[i] = new CSG.Connector(
337 [x,-msedge,e.h+e.hinge.e+mshh],
338 [0,1,0], [0,0,-1]
339 );
340 });
341 return rv.setColor([0.3,0.8,0.3,0.9]);
342 },
343 split_hinged: function effector_split_hinged(hinged) {
344 var e = CONFIG.effector;
345 var b = hinged.getBounds();
346 var ymax = Math.max(Math.abs(b[0].y),Math.abs(b[1].y));
347 var zmax = Math.max(b[0].z,b[1].z);
348 return [-1,1].map(function(s) {
349 return hinged.intersect(CSG.cube({
350 corner1: [Math.min(b[0].x,b[1].x)-1,s*e.clamp.split/2,-zmax-1],
351 corner2: [Math.max(b[0].x,b[1].x)+1,s*(ymax+1),zmax+1]
352 }));
353 });
354 },
355 fanholder: function effector_fanholder() {
356 var fh = CONFIG.effector.fanholder;
357 var od = fh.screw.d+2*fh.screw.m;
358 return linear_extrude({height:fh.w},hull(
359 CAG.circle({center:[0,-this.rmount],radius:od/2}),
360 CAG.circle({center:[0,-fh.r+od/2+fh.w/2],radius:fh.w/2})
361 )).translate([0,0,-fh.w]).union(
362 linear_extrude({height:fh.w},hull(
363 CAG.circle({center:[fh.w/2,-this.rmount-od/2-fh.w/2],radius:fh.w/2}),
364 CAG.circle({center:[od/2,-fh.r],radius:od/2})
365 )).rotateY(90).translate([-fh.w/2,0,0])
366 ).subtract( CSG.cylinder({
367 start: [-fh.w,-fh.r,-od/2],
368 end: [fh.w,-fh.r,-od/2],
369 radius: fh.screw.d/2
370 })).subtract( CSG.cylinder({
371 start: [0,-this.rmount,1],
372 end: [0,-this.rmount,-fh.w-1],
373 radius: fh.screw.d/2
374 })).setColor([0.3,0.8,0.3,0.9]).rotateZ(-120);
375 }
376};
377
378function columns() {
379 var rv = [0,1,2].map(function(x) {
380 return union(vector_char(0,0,String.fromCharCode('A'.charCodeAt(0)+x)).segments.map(function(x) {
381 return rectangular_extrude(x,{w:2,h:1});
382 })).center().rotateX(90).translate([0,50,0]).rotateZ(x*120+120);
383 });
384 return union(rv);
385}
386
387function microswitch() {
388 var screw_connector = new CSG.Properties();
389 var rv = CSG.cube({ center:[0,0,2.5],radius: [19.8/2,6/2,10/2] }).union(
390 CSG.cube({ center: [2.5,0.5,6], radius: [2/2,3.5/2,5/2] })
391 ).union(
392 [-8,-1,8].map(function(x) {
393 return CSG.cube({ center:[x,0,0], radius: [0.6/2,3.2/2,13/2] })
394 })
395 ).subtract(
396 [-9.5/2,9.5/2].map(function(x,i) {
397 screw_connector[i] = new CSG.Connector([x,6/2,0],[0,-1,0],[0,0,1]);
398 return CSG.cylinder({
399 start: [x,-4,0], end: [x,4,0],
400 radius: 2/2
401 })
402 })
403 );
404 rv.properties.switch_connector = new CSG.Connector([2.5,0.5,6+5/2],[0,0,1],[0,-1,0]);
405 rv.properties.screw_connector = screw_connector;
406 rv.properties.microswitch = new CSG.Properties();
407 rv.properties.microswitch.size = new CSG.Vector3D(
408 19.8,6,10
409 );
410 return rv;
411}
412
413function getParameterDefinitions() {
414 return [{
415 name: 'part',
416 type: 'choice',
417 values: ['platform', 'hinged', 'clamp', 'fanholder', 'alltogethernow'],
418 captions: ['Effector platform','Hinged part', 'Clamp', 'Fan holder', 'All together now!'],
419 caption: 'Part',
420 initial: 'alltogethernow'
421 }];
422}
423
424function main(params) {
425 var e = EFFECTOR.effector();
426 var hs = E3DV6.heatsink();
427 hs = hs.connectTo(hs.properties.grove_connector,e.properties.grove_connector,false,0);
428 var ms = microswitch();
429 var hd = EFFECTOR.hinged({
430 microswitch:ms,effector:e
431 });
432 ms = ms.connectTo(
433 ms.properties.screw_connector[0],
434 hd.properties.microswitch_screw_connector[0],
435 false, 0);
436 var hdhd = EFFECTOR.split_hinged(hd);
437 var fh = EFFECTOR.fanholder();
438 return union({
439 platform: e,
440 hinged: hdhd[1],
441 clamp: hdhd[0],
442 fanholder: fh,
443 alltogethernow: [e,hdhd[0],hdhd[1], columns(),hs,ms,fh]
444 }[params.part||'alltogethernow'])
445 var rv = union(
446 e,
447 hs,
448 columns(),
449 ///hd,
450 hdhd[0], hdhd[1],
451 ms);
452 return rv;
453}