1 /* GNU AGPLv3 (or later at your option)
2 see bottom for more license info */
4 /* spin thing that erin likes */
16 weight_lip_overhang
= 0.3;
17 bearing_lip_overhang
= weight_lip_overhang
;
19 penny_thickness
= 1.52;
20 penny_radius
= 19.05 / 2;
22 sr188_radius
= 12.74 / 2; // 0.5 / 2
23 sr188_inner_radius
= 6.3 / 2; // 0.2470 / 2
24 sr188_thickness
= 4.8; // 0.1895 inch
25 sr188_cover_radius
= sr188_radius
;
26 sr188_cap_footprint_radius
= 12 / 2;
28 _608zz_radius
= 22 / 2;
29 _608zz_inner_radius
= 8.1 / 2;
30 _608zz_cover_radius
= _608zz_radius
;
31 _608zz_cap_footprint_radius
= 12 / 2;
34 _625rs_radius
= 16 / 2;
35 _625rs_inner_radius
= 5 / 2;
37 _625rs_cover_radius
= _625rs_radius
;
38 _625rs_cap_footprint_radius
= _625rs_inner_radius
+ 1;
40 weight_radius
= (weight
== "penny") ? penny_radius
: _608zz_radius
;
41 weight_thickness
= (weight
== "penny") ?
42 penny_thickness
* 5 : _608zz_thickness
;
45 (bearing
== "608zz") ? _608zz_radius
46 : (bearing
== "625rs") ? _625rs_radius
47 : (bearing
== "sr188") ? sr188_radius
49 bearing_window_radius
= bearing_radius
- bearing_lip_overhang
- 1;
50 bearing_inner_radius
=
51 (bearing
== "608zz") ? _608zz_inner_radius
52 : (bearing
== "625rs") ? _625rs_inner_radius
53 : (bearing
== "sr188") ? sr188_inner_radius
55 bearing_cover_radius
=
56 (bearing
== "608zz") ? _608zz_cover_radius
57 : (bearing
== "625rs") ? _625rs_cover_radius
58 : (bearing
== "sr188") ? sr188_cover_radius
60 bearing_cap_footprint_radius
=
61 (bearing
== "608zz") ? _608zz_cap_footprint_radius
62 : (bearing
== "625rs" ) ? _625rs_cap_footprint_radius
63 : (bearing
== "sr188" ) ? sr188_cap_footprint_radius
66 (bearing
== "608zz") ? _608zz_thickness
67 : (bearing
== "625rs") ? _625rs_thickness
68 : (bearing
== "sr188") ? sr188_thickness
71 spinner_height
= penny_thickness
* 5 + 2;
74 module
cap(bearing_inner_radius
,
75 bearing_cap_footprint_radius
,
78 bearing_window_radius
) {
79 footprint_height
= 4.5;
80 footprint_radius_safety
= 0.2;
82 bearing_thickness_safety
= 0.6;
83 finger_spot_height
= cap_height
* 2 / 3;
88 cylinder(r1
= bearing_cover_radius
- tan(30) * cap_height
,
89 r2
= bearing_cover_radius
,
91 linear_extrude(height
= cap_height
94 circle(bearing_window_radius
- 1); }
95 linear_extrude(height
= cap_height
+ footprint_height
) {
96 circle(bearing_cap_footprint_radius
- footprint_radius_safety
); }
97 linear_extrude(height
= cap_height
99 + bearing_thickness
/ 2
100 - bearing_thickness_safety
) {
101 circle(bearing_inner_radius
+ 0.1); } }
102 translate([0, 0, -0.01]) {
103 cylinder(r1
= bearing_inner_radius
,
104 r2
= bearing_inner_radius
- tan(30) * finger_spot_height
,
105 h
= finger_spot_height
);
106 for(stripe
= [0 : stripes
- 1]) {
107 rotate((stripe
/ stripes
) * 360) {
108 linear_extrude(height
= finger_spot_height
) {
110 [bearing_cover_radius
* 2, 0],
111 [cos(3 + 360 / (stripes
* 2))
112 * bearing_cover_radius
* 2,
113 sin(3 + 360 / (stripes
* 2))
114 * bearing_cover_radius
* 2]]); } } } } } }
116 module
donut(height
, footprint_radius
) {
117 bread_radius
= height
/ 2;
119 translate([footprint_radius
, 0]) {
120 circle(bread_radius
); } } }
122 module
donut_hole(height
, footprint_radius
) {
124 cylinder(r
= footprint_radius
, h
= height
, center
= true);
125 donut(height
, footprint_radius
); } }
127 module
jelly_filled(height
, footprint_radius
) {
128 cylinder(r
= footprint_radius
, h
= height
, center
= true);
129 donut(height
, footprint_radius
); }
132 offset(r
= -r
) { offset(delta
= r
) { children(); } } }
134 module
mirrored(axis
) {
136 mirror(axis
) children(); }
138 module
spin_slice(weight_radius
,
143 joiner_radius
= (bearing_radius
+ weight_radius
) / 2;
145 // a = side along x axis
146 a
= bearing_radius
+ weight_radius
+ wall
;
147 // b = side from center to joiner
148 b
= bearing_radius
+ joiner_radius
+ round_extra
;
149 // c = side between joiner and arm center
150 c
= joiner_radius
+ weight_radius
+ round_extra
;
152 cos_C
= (pow(a
, 2) + pow(b
, 2) - pow(c
, 2)) / (2 * a
* b
);
153 sin_C
= sqrt(1 - pow(cos_C
, 2));
157 joiner_xy
= [cos_C
, sin_C
] * b
;
159 for(arm
= [0 : arms
- 1]) {
160 rotate(arm
* (360 / arms
)) {
163 translate(bearing_xy
) {
164 circle(bearing_radius
+ round_extra
); }
165 translate(weight_xy
) {
166 circle(weight_radius
+ round_extra
); }
168 polygon([bearing_xy
, weight_xy
, joiner_xy
]); } }
170 translate(joiner_xy
) {
171 circle(joiner_radius
); } } } } } }
173 module
spin_cosine_slice(weight_radius
,
178 /* in order to make a smooth transition from one arm to the next,
179 follow the path of a circle just barely touching both arms and
180 the center circle. this is referred to as the joiner circle.
182 the joiner circle's radius and position are calculated using
183 geometry. the center of the bearing, weight and joiner circle
186 a = side between bearing and weight centers
187 b = side between bearing and joiner centers
188 c = side between joiner and weight centers
190 A = angle opposite a, inside joiner
191 B = angle opposite b, inside weight
192 C = angle opposite c, inside bearing
197 // slightly cheated. calculated using 3 arms, C = 60.
205 - 3 * r1
* round_extra
)
206 / (3 * r1
+ wall
- r0
));
210 // a = side along x axis
212 // b = side from center to joiner
213 b
= r0
+ round_extra
+ r2
;
214 // c = side between joiner and arm center
215 c
= r1
+ round_extra
+ r2
;
219 joiner_xy
= [cos(60), sin(60)] * b
;
221 translate(bearing_xy
) {
222 circle(bearing_radius
+ round_extra
); }
223 for(arm
= [0 : arms
- 1]) {
224 rotate(arm
* (360 / arms
)) {
225 translate(weight_xy
) {
226 circle(weight_radius
+ round_extra
); }
229 polygon([bearing_xy
, weight_xy
, joiner_xy
]);
230 translate(joiner_xy
) {
231 circle(joiner_radius
); } } } } } }
233 module
spin_slices(weight_radius
,
237 weight_lip_overhang
= 0.3,
238 bearing_lip_overhang
= 0.3,
241 layer_height
= 0.15) {
242 thicker_thickness
= (bearing_thickness
> weight_thickness
) ?
243 bearing_thickness
: weight_thickness
;
244 calculated_height
= thicker_thickness
+ 2 * wall
;
245 layers
= 2 * ceil(ceil(calculated_height
/ layer_height
) / 2);
246 actual_height
= layers
* layer_height
;
247 round_radius
= actual_height
/ 2;
249 /* rounding the outside edge of the spinner with a semi-circle leads
250 to a shape that an overhang on the second layer several times the
251 thickness of a printed extrusion width.
253 rather than using a full semi-circle, this code aims to use just the
254 portion in the middle, where the overhang is less severe */
256 old_end
= (layers
/ 2) - 1;
258 /* add one to have some thickness all around weight holes
260 new_start
= old_end
/ 16 + 1;
263 old_range
= old_end
- old_start
;
264 new_range
= new_end
- new_start
;
266 factor
= new_range
/ old_range
;
268 /* initial adjacent is adjusted to (new start - 1) to allow some
269 thickness all around weight holes on first layer */
270 initial_adjacent
= round_radius
- ((new_start
- 1) * layer_height
);
271 initial_angle
= acos(initial_adjacent
/ round_radius
);
272 initial_round_extra
= initial_adjacent
* tan(initial_angle
);
275 mirrored([0, 0, 1]) {
276 for(layer
= [0 : (layers
/ 2) - 1]) {
277 translate([0, 0, layer
* layer_height
- actual_height
/ 2]) {
278 linear_extrude(height
= layer_height
) {
279 new_layer
= (layer
- old_start
) * factor
+ new_start
;
280 adjacent
= round_radius
- (new_layer
* layer_height
);
281 angle
= acos(adjacent
/ round_radius
);
282 round_extra
= adjacent
* tan(angle
) - initial_round_extra
;
283 spin_slice(weight_radius
,
288 cylinder(h
= actual_height
+ 0.1,
289 r
= bearing_radius
- bearing_lip_overhang
,
291 cylinder(h
= bearing_thickness
+ 0.05,
292 r
= bearing_radius
+ 0.15,
294 for(arm
= [0 : arms
- 1]) {
295 rotate(arm
* (360 / arms
)) {
296 translate([bearing_radius
+ wall
+ weight_radius
, 0]) {
297 cylinder(h
= actual_height
+ 0.1,
298 r
= weight_radius
- weight_lip_overhang
,
300 cylinder(h
= weight_thickness
+ 0.05,
301 r
= weight_radius
+ 0.15,
302 center
= true); } } } } }
304 module
equilateral_triangle(radius
){
305 polygon([[cos(0) * radius
, sin(0) * radius
],
309 sin(240) * radius
]]); }
311 module
spin_cosine(weight_radius
,
315 weight_lip_overhang
= 0.3,
316 bearing_lip_overhang
= 0.3,
319 layer_height
= 0.15) {
320 thicker_thickness
= (bearing_thickness
> weight_thickness
) ?
321 bearing_thickness
: weight_thickness
;
322 calculated_height
= thicker_thickness
+ 2 * wall
;
323 layers
= 2 * ceil(ceil(calculated_height
/ layer_height
) / 2);
324 actual_height
= layers
* layer_height
;
325 round_radius
= actual_height
/ 2;
327 /* rounding the outside edge of the spinner with a semi-circle leads
328 to a shape that an overhang on the second layer several times the
329 thickness of a printed extrusion width.
331 rather than using a full semi-circle, this code aims to use just the
332 portion in the middle, where the overhang is less severe */
334 old_end
= (layers
/ 2) - 1;
336 /* add one to have some thickness all around weight holes
338 new_start
= old_end
/ 16 + 1;
341 old_range
= old_end
- old_start
;
342 new_range
= new_end
- new_start
;
344 factor
= new_range
/ old_range
;
346 /* initial adjacent is adjusted to (new start - 1) to allow some
347 thickness all around weight holes on first layer */
348 initial_adjacent
= round_radius
- ((new_start
- 1) * layer_height
);
349 initial_angle
= acos(initial_adjacent
/ round_radius
);
350 initial_round_extra
= initial_adjacent
* tan(initial_angle
);
353 mirrored([0, 0, 1]) {
354 for(layer
= [0 : (layers
/ 2) - 1]) {
355 translate([0, 0, layer
* layer_height
- actual_height
/ 2]) {
356 linear_extrude(height
= layer_height
) {
357 new_layer
= (layer
- old_start
) * factor
+ new_start
;
358 adjacent
= round_radius
- (new_layer
* layer_height
);
359 angle
= acos(adjacent
/ round_radius
);
360 round_extra
= adjacent
* tan(angle
) - initial_round_extra
;
361 spin_cosine_slice(weight_radius
,
366 // bearing window hole
367 /*cylinder(h = actual_height + 0.1,
368 r = bearing_radius - bearing_lip_overhang,
370 linear_extrude(height
= actual_height
+ 0.1, center
= true) {
372 equilateral_triangle(1.8 * bearing_radius
);
373 circle(bearing_radius
+ 0.1); } }
375 cylinder(h
= bearing_thickness
+ 0.05,
376 r
= bearing_radius
+ 0.15,
379 for(arm
= [0 : arms
- 1]) {
380 rotate(arm
* (360 / arms
)) {
381 translate([bearing_radius
+ wall
+ weight_radius
, 0]) {
382 // weight window hole
383 mirrored([0, 0, 1]) {
384 translate([0, 0, (weight_thickness
+ 0.05) / 2]) {
385 linear_extrude(height
= wall
+ 0.1) {
387 equilateral_triangle(1.8 * weight_radius
);
388 circle(weight_radius
+ 0.2); } } } }
390 cylinder(h
= weight_thickness
+ 0.05,
391 r
= weight_radius
+ 0.20,
392 center
= true); } } } } }
394 module
spin_donut(weight_radius
,
399 bearing_lip_overhang
,
402 thicker_thickness
= (bearing_thickness
> weight_thickness
)
403 ? bearing_thickness
: weight_thickness
;
404 height
= thicker_thickness
+ wall
* 2;
406 center_to_arm_center
= bearing_radius
+ wall
+ weight_radius
;
408 jelly_filled(height
, bearing_radius
);
409 for(arm
= [0 : arms
]) {
410 rotate(arm
* (360 / arms
)) {
411 translate([center_to_arm_center
, 0, 0]) {
412 jelly_filled(height
, weight_radius
); } } } }
415 This file is part of 3d-printables.
417 3d-printables is free software: you can redistribute it and/or modify
418 it under the terms of the GNU Affero General Public License as published by
419 the Free Software Foundation, either version 3 of the License, or
420 (at your option) any later version.
422 3d-printables is distributed in the hope that it will be useful,
423 but WITHOUT ANY WARRANTY; without even the implied warranty of
424 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
425 GNU Affero General Public License for more details.
427 You should have received a copy of the GNU Affero General Public License
428 along with challenge-bot. If not, see <http://www.gnu.org/licenses/>.