chiark / gitweb /
air-hockey-puck: wip
[reprap-play.git] / powerbank-bike-clamp.scad
1 // -*- C -*-
2
3 // Print one of each:
4 //    Main
5 //    TubeClampRight
6
7 include <utils.scad>
8
9 tube_dia = 22.4;
10
11 hinge_around = 2.5;
12 hinge_pin = 1.8 + 0.75;
13 main_th = 3;
14 minor_wall_min = 1;
15
16 screw = 5.0 + 0.75;
17 screw_head = 8.7 + 1.2;
18 screw_head_space_above = 10;
19 screw_nut_across = 7.9 + 0.75;
20 screw_nut_th = 3.9 + 0.75;
21
22 knob_behind_across = 12.2 + 0.75;
23 behind_knob_th = 5;
24 knob_standout_h = 2;
25
26 clamp_min_width = 20;
27
28 clamp_gap = 2;
29
30 corner_rounding_r = 10;
31
32 lower_th = 1;
33
34 overlap_l = 0.1;
35
36 bridge_slop = 1.2;
37
38 hinge_lobe_per = 10;
39 hinge_gap_z = 0.75;
40 hinge_gap_xy = 0.75;
41
42 $fs = 0.1;
43 $fa = 5;
44
45 bank_eps_bbox_x = [149, 598];
46 bank_eps_bbox_y = [274, 1452];
47
48 bank_y_sz = 102.25 + 0.50 + 3.2;
49 bank_x_sz = (26.0 + 0.5);
50 bank_recess_y = 5;
51
52 strap_th = 3;
53 strap_w = 5;
54 strap_above = 2.5;
55
56 strap_around_over = 1.0;
57 strap_around_attach = 2.0;
58
59 retainer_walls = [18, 30];
60
61 bank_profile_scale_bodge = 1.0;
62
63 bank_output_ctr = [ 12.5, 11.5 ]; // from nearest corner
64 bank_output_sz  = [ 11.0, 10.5 ];
65
66 mounted_pos_y_offset_lim = -100;
67
68 liner_th = 0.8;
69
70 brace_r = 5;
71 brace_len = 50;
72
73 straps_y_adj = [ 3.5,
74                  0,
75                  0 ];
76
77 // calculated
78
79 straps_y = [ -bank_y_sz * 0.25, // these entries are special and used
80              +bank_y_sz * 0.25, //  for the brace struts
81              0 ];
82
83 screw_head_behind = main_th;
84 endwall_th = main_th;
85
86 bank_recess_dx = minor_wall_min;
87
88 pspt_to_mm = 25.4 / 72;
89
90 main_r = tube_dia/2 + main_th;
91
92 screw_max_y_lhs = -main_r -screw_nut_across/2;
93 screw_max_y_rhs = -main_r -knob_behind_across/2;
94
95 screw_y = min(screw_max_y_lhs,
96               screw_max_y_rhs);
97
98 bot_y = screw_y -max( screw_nut_across/2, knob_behind_across/2 )
99   -minor_wall_min;
100
101 holder_x_sz = bank_x_sz + bank_recess_dx*2;
102 bank_bot_y = strap_above + strap_th;
103 strap_r = strap_th;
104
105 brace_total_len = brace_len + main_th;
106 brace_ctrs_y_nom = [ straps_y[0] - (brace_r + strap_w/2),
107                      straps_y[1] + (brace_r + strap_w/2) ];
108
109 brace_ctrs_y = [ (straps_y + straps_y_adj)[0] + (brace_r + strap_w/2),
110                  (straps_y + straps_y_adj)[1] + (brace_r + strap_w/2) ];
111
112 clamp_width_actual = max(clamp_min_width, holder_x_sz);
113
114 hinge_lobes = floor(clamp_width_actual / hinge_lobe_per);
115 hinge_stride = (clamp_width_actual + hinge_gap_z) / hinge_lobes;
116
117 hinge_outer_r = hinge_around + hinge_pin/2;
118 hinge_y = tube_dia/2 + hinge_outer_r;
119
120 top_cnr_r = min(endwall_th, main_th);
121
122 mounted_pos_y_offset = max(mounted_pos_y_offset_lim,
123                            bot_y - (-(bank_y_sz/2 + endwall_th)));
124
125
126 module TubePlan(){ circle(r = tube_dia/2); }
127 module HingePinPlan(){ translate([0, hinge_y]) circle(r= hinge_pin/2); }
128 module HingeBodyPlan(){ translate([0, hinge_y]) circle(r= hinge_outer_r); }
129
130 module TubeClampLeftPlan(){
131   difference(){
132     union(){
133       polygon([[ 0,                      hinge_y + hinge_outer_r ],
134                [ -(main_r + overlap_l),  hinge_y + hinge_outer_r ],
135                [ -(main_r + overlap_l),  bot_y                   ],
136                [ -clamp_gap/2,           bot_y                   ],
137                [ -clamp_gap/2,           0,                      ],
138                [ 0,                      0,                      ],
139                ]);
140       HingeBodyPlan();
141     }
142     TubePlan();
143     HingePinPlan();
144   }
145 }
146
147 module TubeClampLeft() { ////toplevel
148   linextr(-clamp_width_actual/2, clamp_width_actual/2)
149     TubeClampLeftPlan();
150 }
151
152 module TubeClampRightPlan(){ ////toplevel
153   difference(){
154     // It broke at the inside corner, round these a bit
155     offset(r=-corner_rounding_r)
156     offset(r=+corner_rounding_r)
157     difference(){
158       union(){
159         rectfromto([ clamp_gap/2,                   bot_y ],
160                    [ clamp_gap/2 + behind_knob_th,  0     ]);
161         intersection(){
162           circle(r= main_r); // maybe split off from main_r and increase?
163           union(){
164             rectfromto([0,0],
165                        main_r *  [5,5]);
166             rectfromto([ clamp_gap/2, main_r*5 ],
167                        main_r * [2,-5]);
168           }
169         }
170         HingeBodyPlan();
171       }
172       TubePlan();
173     }
174     HingePinPlan();
175   }
176 }
177
178 module Screws(){
179   linextr_x_yz(-main_r*5, main_r*5)
180     translate([screw_y, 0])
181     circle(r= screw/2);
182
183   translate([0, screw_y, 0]) {
184     linextr_x_yz(-(clamp_gap/2 + screw_nut_th), 0)
185       square([screw_nut_across,
186               screw_nut_across / cos(30) + bridge_slop*2],
187              center=true);
188
189     linextr_x_yz(-(main_r + bank_recess_y + screw_head_space_above),
190                  -(clamp_gap/2 + screw_nut_th + screw_head_behind))
191       square([screw_head, screw_head + bridge_slop*2],
192              center=true);
193   }
194 }
195
196 module SomeClamp(hinge_alt=false){
197   difference(){
198     linextr(-clamp_width_actual/2, clamp_width_actual/2)
199       children(0);
200
201     Screws();
202
203     for (i=[0 : hinge_lobes-1]) {
204       translate([0,
205                  hinge_y,
206                  -clamp_width_actual/2 + i * hinge_stride
207                  + (hinge_alt ? hinge_stride/2 : 0)
208                  ])
209         linextr(-hinge_gap_z, hinge_stride/2)
210         square(hinge_outer_r*2 + hinge_gap_xy, center=true);
211     }
212   }
213 }
214
215 module PowerBankItselfSidePlan(){
216   translate([0, bank_bot_y]){
217     minkowski(){
218       circle($fn=8, r=liner_th);
219       scale( bank_profile_scale_bodge *
220              bank_x_sz / ( (
221                             bank_eps_bbox_x[1] -
222                             bank_eps_bbox_x[0]
223                             ) * pspt_to_mm ))
224         translate(pspt_to_mm *
225                   [-0.5 * (bank_eps_bbox_x[0] +
226                            bank_eps_bbox_x[1]),
227                    -bank_eps_bbox_y[0]])
228         import("powerbank-anker-10000.dxf", convexity=5);
229     }
230   }
231 }
232
233 module PowerBankItself(){ ////toplevel
234   rotate([0,90,0])
235     linextr_y_xz(-bank_y_sz/2,
236                  +bank_y_sz/2)
237     PowerBankItselfSidePlan();
238 }
239
240 module PowerBankSidePlan(){ ////toplevel
241   render() difference(){
242     rectfromto([ -holder_x_sz/2,  0 ],
243                [ +holder_x_sz/2,  bank_recess_y + bank_bot_y ]);
244
245     PowerBankItselfSidePlan();
246   }
247 }
248
249 module PowerBankStrapCut(){ ////toplevel
250   difference(){
251     rectfromto([ -holder_x_sz, -0.05 ],
252                [ +holder_x_sz, strap_th + strap_r ]);
253     hull(){
254       for (sx=[-1,+1]) {
255         translate([sx * (holder_x_sz/2 - strap_r + 0.1),
256                    strap_th + strap_r])
257           circle(strap_r);
258       }
259     }
260   }
261 }
262
263 module PowerBankHolderTest(){ ////toplevel
264   difference(){
265     linextr(-1,5) PowerBankSidePlan();
266     linextr(0, strap_w) PowerBankStrapCut();
267   }
268 }
269
270 module EndRetainer(depth){ ////toplevel
271   translate([0, -bank_y_sz/2, 0]) {
272     linextr_y_xz(-endwall_th, 0)
273     rectfromto([ 0,         -holder_x_sz/2 ],
274                [ -depth,    +holder_x_sz/2 ]);
275     
276     for (m=[0,1]) {
277       mirror([0,0,m]) {
278         linextr(-holder_x_sz/2, -bank_x_sz/2){
279           hull(){
280             rectfromto([ 0, -endwall_th ],
281                        [ depth, 0 ]);
282             rectfromto([ 0, 0 ],
283                        [ 0.1, depth-0.1 ]);
284           }
285         }
286       }
287     }
288   }
289 }
290
291 module BraceTubePlan(){
292   intersection(){
293     circle(r= brace_r);
294     rectfromto(brace_r * [-2,  0],
295                brace_r * [+2, +2]);
296   }
297 }
298
299 module PowerBankHolder(){ ////toplevel
300   difference(){
301     union(){
302       rotate([0,90,0])
303         linextr_y_xz(-(bank_y_sz/2 + 0.1),
304                      +(bank_y_sz/2 + 0.1))
305         PowerBankSidePlan();
306
307       EndRetainer(retainer_walls[0]);
308       mirror([0,1,0]) EndRetainer(retainer_walls[1]);
309
310       translate([0,0, bank_x_sz/2]){
311         for (y = brace_ctrs_y) {
312           translate([0,y,0]) {
313             linextr_x_yz(0, brace_total_len)
314               BraceTubePlan();
315           }
316         }
317         translate([brace_total_len, 0,0])
318           linextr_y_xz(brace_ctrs_y_nom[0] - brace_r,
319                        brace_ctrs_y_nom[1] + brace_r)
320           BraceTubePlan();
321       }
322
323       for (strap_y = straps_y + straps_y_adj) {
324         translate([0, strap_y, 0]) {
325           linextr(-holder_x_sz/2,
326                   +holder_x_sz/2){
327             hull(){
328               for (dy = [-1,+1] *
329                      (strap_w/2 + strap_around_attach - strap_around_over)) {
330                 translate([0, dy, 0])
331                   circle(r=strap_around_over);
332               }
333             }
334           }
335         }
336       }
337     }
338
339     for (strap_y = straps_y + straps_y_adj)
340       translate([0, strap_y, 0])
341         rotate([0,0,-90])
342         rotate([0,90,0])
343         linextr(-strap_w/2,
344                 +strap_w/2)
345         PowerBankStrapCut();
346
347     translate([ bank_bot_y, -bank_y_sz/2, -bank_x_sz/2 ])
348       linextr_y_xz(-50,50)
349        rotate([0,0,90])
350        translate(bank_output_ctr)
351        square(center=true, bank_output_sz);
352
353     translate([0, -(bank_y_sz/2 + endwall_th), 0] + 0.01 * [-1,-1]) {
354       linextr(-200,200){
355         difference(){
356           square(center=true, top_cnr_r*2);
357           translate(top_cnr_r * [1,1])
358             circle(r= top_cnr_r);
359         }
360       }
361     }
362   }
363 }
364
365 module TubeClampLeft() { ////toplevel
366   // We want this to print with the recess overhand to the right
367   // where the workpiece cooling fan is
368   rotate([0,0,180]){
369     difference(){
370       SomeClamp(true)
371         TubeClampLeftPlan();
372
373       Screws();
374     }
375   }
376 }
377
378 module PlacePowerBank(){
379   translate([main_r, -mounted_pos_y_offset, 0])
380     children(0);
381 }
382
383 module Main(){ ////toplevel
384   TubeClampLeft();
385   difference(){
386     PlacePowerBank()
387       PowerBankHolder();
388     rotate([0,0,180])
389       Screws();
390   }
391 }
392
393 module TubeClampRight() { ////toplevel
394   rotate([0,0,180]) {
395     rotate([180,0,0]) {
396       difference(){
397         union(){
398           SomeClamp()
399             TubeClampRightPlan();
400
401           translate([clamp_gap/2 + behind_knob_th, screw_y, 0]) {
402             hull(){
403               linextr_x_yz(-0.1, 0)
404                 square(center=true,
405                        [knob_behind_across,
406                         knob_behind_across + knob_standout_h*2]);
407               linextr_x_yz(0, knob_standout_h)
408                 square(center=true,
409                        knob_behind_across);
410             }
411           }
412         }
413         Screws();
414       }
415     }
416   }
417 }
418
419 module TubeClampDemo() { ////toplevel
420   TubeClampLeft();
421   rotate([180,0,0])
422     TubeClampRight();
423 }
424
425 module Demo() { ////toplevel
426   Main();
427   rotate([180,0,0])
428     TubeClampRight();
429   PlacePowerBank()
430     %PowerBankItself();
431 }