chiark / gitweb /
c0d1c0f6bce1e238651a86904346e90c3123033a
[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_nut_across = 7.9 + 0.75;
19 screw_nut_th = 3.9 + 0.75;
20
21 knob_behind_across = 12.2 + 0.75;
22 behind_knob_th = 5;
23
24 clamp_min_width = 20;
25
26 clamp_gap = 2;
27
28 lower_th = 1;
29
30 overlap_l = 0.1;
31
32 bridge_slop = 1.2;
33
34 hinge_lobe_per = 10;
35 hinge_gap_z = 0.75;
36 hinge_gap_xy = 0.75;
37
38 $fs = 0.1;
39 $fa = 5;
40
41 bank_eps_bbox_x = [149, 598];
42 bank_eps_bbox_y = [274, 1452];
43
44 bank_y_sz = 102.25 + 0.50 + 3.2;
45 bank_x_sz = (26.0 + 0.5);
46 bank_recess_y = 5;
47
48 strap_th = 3;
49 strap_above = 2.5;
50
51 retainer_walls = [18, 30];
52
53 bank_profile_scale_bodge = 1.0;
54
55 bank_input_ctr = [ 12.5, 11.5 ]; // from nearest corner
56 bank_input_sz  = [ 8.5, 10.5 ];
57
58 mounted_pos_y_offset = 20;
59
60 liner_th = 0.8;
61
62 brace_r = 5;
63 brace_len = 50;
64
65 // calculated
66
67 straps_y = [ -bank_y_sz * 0.25,
68              +bank_y_sz * 0.25 ];
69
70 screw_head_behind = main_th;
71 endwall_th = main_th;
72
73 bank_recess_dx = minor_wall_min;
74
75 pspt_to_mm = 25.4 / 72;
76
77 main_r = tube_dia/2 + main_th;
78
79 screw_max_y_lhs = -main_r -screw_nut_across/2;
80 screw_max_y_rhs = -main_r -knob_behind_across/2;
81
82 screw_y = min(screw_max_y_lhs,
83               screw_max_y_rhs);
84
85 bot_y = screw_y -max( screw_nut_across, knob_behind_across/2 )
86   -minor_wall_min;
87
88 holder_x_sz = bank_x_sz + bank_recess_dx*2;
89 bank_bot_y = strap_above + strap_th;
90 strap_r = strap_th;
91
92 brace_total_len = brace_len + main_th;
93 brace_ctrs_y = [ straps_y[0] - (brace_r + strap_r/2),
94                  straps_y[1] + (brace_r + strap_r/2) ];
95
96 clamp_width_actual = max(clamp_min_width, holder_x_sz);
97
98 hinge_lobes = floor(clamp_width_actual / hinge_lobe_per);
99 hinge_stride = (clamp_width_actual + hinge_gap_z) / hinge_lobes;
100
101 hinge_outer_r = hinge_around + hinge_pin/2;
102 hinge_y = tube_dia/2 + hinge_outer_r;
103
104 echo(bot_y);
105
106 module TubePlan(){ circle(r = tube_dia/2); }
107 module HingePinPlan(){ translate([0, hinge_y]) circle(r= hinge_pin/2); }
108 module HingeBodyPlan(){ translate([0, hinge_y]) circle(r= hinge_outer_r); }
109
110 module TubeClampLeftPlan(){
111   difference(){
112     union(){
113       polygon([[ 0,                      hinge_y + hinge_outer_r ],
114                [ -(main_r + overlap_l),  hinge_y + hinge_outer_r ],
115                [ -(main_r + overlap_l),  bot_y                   ],
116                [ -clamp_gap/2,           bot_y                   ],
117                [ -clamp_gap/2,           0,                      ],
118                [ 0,                      0,                      ],
119                ]);
120       HingeBodyPlan();
121     }
122     TubePlan();
123     HingePinPlan();
124   }
125 }
126
127 module TubeClampLeft() { ////toplevel
128   linextr(-clamp_width_actual/2, clamp_width_actual/2)
129     TubeClampLeftPlan();
130 }
131
132 module TubeClampRightPlan(){
133   difference(){
134     union(){
135       rectfromto([ clamp_gap/2,                   bot_y ],
136                  [ clamp_gap/2 + behind_knob_th,  0     ]);
137       intersection(){
138         circle(r= main_r);
139         union(){
140           rectfromto([0,0],
141                       main_r *  [5,5]);
142           rectfromto([ clamp_gap/2, main_r*5 ],
143                       main_r * [2,-5]);
144         }
145       }
146       HingeBodyPlan();
147     }
148     TubePlan();
149     HingePinPlan();
150   }
151 }
152
153 module Screws(){
154   linextr_x_yz(-main_r*5, main_r*5)
155     translate([screw_y, 0])
156     circle(r= screw/2);
157
158   translate([0, screw_y, 0]) {
159     linextr_x_yz(-(clamp_gap/2 + screw_nut_th), 0)
160       square([screw_nut_across,
161               screw_nut_across / cos(30) + bridge_slop*2],
162              center=true);
163
164     linextr_x_yz(-200,
165                  -(clamp_gap/2 + screw_nut_th + screw_head_behind))
166       square([screw_head, screw_head + bridge_slop*2],
167              center=true);
168   }
169 }
170
171 module SomeClamp(hinge_alt=false){
172   difference(){
173     linextr(-clamp_width_actual/2, clamp_width_actual/2)
174       children(0);
175
176     Screws();
177
178     for (i=[0 : hinge_lobes-1]) {
179       translate([0,
180                  hinge_y,
181                  -clamp_width_actual/2 + i * hinge_stride
182                  + (hinge_alt ? hinge_stride/2 : 0)
183                  ])
184         linextr(-hinge_gap_z, hinge_stride/2)
185         square(hinge_outer_r*2 + hinge_gap_xy, center=true);
186     }
187   }
188 }
189
190 module PowerBankItselfSidePlan(){
191   translate([0, bank_bot_y]){
192     minkowski(){
193       circle($fn=8, r=liner_th);
194       scale( bank_profile_scale_bodge *
195              bank_x_sz / ( (
196                             bank_eps_bbox_x[1] -
197                             bank_eps_bbox_x[0]
198                             ) * pspt_to_mm ))
199         translate(pspt_to_mm *
200                   [-0.5 * (bank_eps_bbox_x[0] +
201                            bank_eps_bbox_x[1]),
202                    -bank_eps_bbox_y[0]])
203         import("powerbank-anker-10000.dxf", convexity=5);
204     }
205   }
206 }
207
208 module PowerBankItself(){ ////toplevel
209   rotate([0,90,0])
210     linextr_y_xz(-bank_y_sz/2,
211                  +bank_y_sz/2)
212     PowerBankItselfSidePlan();
213 }
214
215 module PowerBankSidePlan(){ ////toplevel
216   render() difference(){
217     rectfromto([ -holder_x_sz/2,  0 ],
218                [ +holder_x_sz/2,  bank_recess_y + bank_bot_y ]);
219
220     PowerBankItselfSidePlan();
221   }
222 }
223
224 module PowerBankStrapCut(){ ////toplevel
225   difference(){
226     rectfromto([ -holder_x_sz, -0.05 ],
227                [ +holder_x_sz, strap_th + strap_r ]);
228     hull(){
229       for (sx=[-1,+1]) {
230         translate([sx * (holder_x_sz/2 - strap_r + 0.1),
231                    strap_th + strap_r])
232           circle(strap_r);
233       }
234     }
235   }
236 }
237
238 module PowerBankHolderTest(){ ////toplevel
239   difference(){
240     linextr(-1,5) PowerBankSidePlan();
241     linextr(0, strap_th) PowerBankStrapCut();
242   }
243 }
244
245 module EndRetainer(depth){ ////toplevel
246   translate([0, -bank_y_sz/2, 0]) {
247     linextr_y_xz(-endwall_th, 0)
248     rectfromto([ 0,         -holder_x_sz/2 ],
249                [ -depth,    +holder_x_sz/2 ]);
250     
251     for (m=[0,1]) {
252       mirror([0,0,m]) {
253         linextr(-holder_x_sz/2, -bank_x_sz/2){
254           hull(){
255             rectfromto([ 0, -endwall_th ],
256                        [ depth, 0 ]);
257             rectfromto([ 0, 0 ],
258                        [ 0.1, depth-0.1 ]);
259           }
260         }
261       }
262     }
263   }
264 }
265
266 module BraceTubePlan(){
267   intersection(){
268     circle(r= brace_r);
269     rectfromto(brace_r * [-2,  0],
270                brace_r * [+2, +2]);
271   }
272 }
273
274 module PowerBankHolder(){ ////toplevel
275   difference(){
276     union(){
277       rotate([0,90,0])
278         linextr_y_xz(-(bank_y_sz/2 + 0.1),
279                      +(bank_y_sz/2 + 0.1))
280         PowerBankSidePlan();
281
282       EndRetainer(retainer_walls[0]);
283       mirror([0,1,0]) EndRetainer(retainer_walls[1]);
284     }
285
286     for (strap_y = straps_y)
287       translate([0, strap_y, 0])
288         rotate([0,0,-90])
289         rotate([0,90,0])
290         linextr(-strap_th/2,
291                 +strap_th/2)
292         PowerBankStrapCut();
293
294     translate([ bank_bot_y, -bank_y_sz/2, -bank_x_sz/2 ])
295       linextr_y_xz(-50,50)
296        rotate([0,0,90])
297        translate(bank_input_ctr)
298        square(center=true, bank_input_sz);
299   }
300
301   translate([0,0, bank_x_sz/2]){
302     for (y = brace_ctrs_y) {
303       translate([0,y,0]) {
304         linextr_x_yz(0, brace_total_len)
305           BraceTubePlan();
306       }
307     }
308     translate([brace_total_len, 0,0])
309       linextr_y_xz(brace_ctrs_y[0] - brace_r,
310                    brace_ctrs_y[1] + brace_r)
311       BraceTubePlan();
312   }
313 }
314
315 module TubeClampLeft() { ////toplevel
316   // We want this to print with the recess overhand to the right
317   // where the workpiece cooling fan is
318   rotate([0,0,180]){
319     difference(){
320       SomeClamp(true)
321         TubeClampLeftPlan();
322
323       Screws();
324     }
325   }
326 }
327
328 module PlacePowerBank(){
329   translate([main_r, -mounted_pos_y_offset, 0])
330     children(0);
331 }
332
333 module Main(){ ////toplevel
334   TubeClampLeft();
335   difference(){
336     PlacePowerBank()
337       PowerBankHolder();
338     rotate([0,0,180])
339       Screws();
340   }
341 }
342
343 module TubeClampRight() { ////toplevel
344   rotate([0,0,180])
345     rotate([180,0,0])
346     SomeClamp()
347     TubeClampRightPlan();
348 }
349
350 module TubeClampDemo() { ////toplevel
351   TubeClampLeft();
352   rotate([180,0,0])
353     TubeClampRight();
354 }
355
356 module Demo() { ////toplevel
357   Main();
358   rotate([180,0,0])
359     TubeClampRight();
360   PlacePowerBank()
361     %PowerBankItself();
362 }