1 /* GNU AGPLv3 (or later at your option)
2 see bottom for more license info */
4 /* spin thing that erin likes */
15 weight_lip_overhang
= 0.3;
16 bearing_lip_overhang
= weight_lip_overhang
;
18 penny_thickness
= 1.52;
19 penny_radius
= 19.05 / 2;
21 _608zz_radius
= 22 / 2;
22 _608zz_inner_radius
= 8.1 / 2;
23 _608zz_cover_radius
= _608zz_radius
;
24 _608zz_cap_footprint_radius
= 12 / 2;
27 _625rs_radius
= 16 / 2;
28 _625rs_inner_radius
= 5 / 2;
30 _625rs_cover_radius
= _625rs_radius
;
31 _625rs_cap_footprint_radius
= _625rs_inner_radius
+ 1;
33 weight_radius
= (weight
== "penny") ? penny_radius
: _608zz_radius
;
34 weight_thickness
= (weight
== "penny") ?
35 penny_thickness
* 5 : _608zz_thickness
;
38 (bearing
== "608zz") ? _608zz_radius
39 : (bearing
== "625rs") ? _625rs_radius
41 bearing_window_radius
= bearing_radius
- bearing_lip_overhang
- 1;
42 bearing_inner_radius
=
43 (bearing
== "608zz") ? _608zz_inner_radius
44 : (bearing
== "625rs") ? _625rs_inner_radius
46 bearing_cover_radius
=
47 (bearing
== "608zz") ? _608zz_cover_radius
48 : (bearing
== "625rs") ? _625rs_cover_radius
50 bearing_cap_footprint_radius
=
51 (bearing
== "608zz") ? _608zz_cap_footprint_radius
52 : (bearing
== "625rs" ) ? _625rs_cap_footprint_radius
55 (bearing
== "608zz") ? _608zz_thickness
56 : (bearing
== "625rs") ? _625rs_thickness
59 spinner_height
= penny_thickness
* 5 + 2;
62 module
cap(bearing_inner_radius
,
63 bearing_cap_footprint_radius
,
66 bearing_window_radius
) {
67 footprint_height
= 4.5;
68 footprint_radius_safety
= 0.2;
70 bearing_thickness_safety
= 0.6;
71 finger_spot_height
= cap_height
* 2 / 3;
76 cylinder(r1
= bearing_cover_radius
- tan(30) * cap_height
,
77 r2
= bearing_cover_radius
,
79 linear_extrude(height
= cap_height
82 circle(bearing_window_radius
- 1); }
83 linear_extrude(height
= cap_height
+ footprint_height
) {
84 circle(bearing_cap_footprint_radius
- footprint_radius_safety
); }
85 linear_extrude(height
= cap_height
87 + bearing_thickness
/ 2
88 - bearing_thickness_safety
) {
89 circle(bearing_inner_radius
+ 0.1); } }
90 translate([0, 0, -0.01]) {
91 cylinder(r1
= bearing_inner_radius
,
92 r2
= bearing_inner_radius
- tan(30) * finger_spot_height
,
93 h
= finger_spot_height
);
94 for(stripe
= [0 : stripes
- 1]) {
95 rotate((stripe
/ stripes
) * 360) {
96 linear_extrude(height
= finger_spot_height
) {
98 [bearing_cover_radius
* 2, 0],
99 [cos(3 + 360 / (stripes
* 2))
100 * bearing_cover_radius
* 2,
101 sin(3 + 360 / (stripes
* 2))
102 * bearing_cover_radius
* 2]]); } } } } } }
104 module
donut(height
, footprint_radius
) {
105 bread_radius
= height
/ 2;
107 translate([footprint_radius
, 0]) {
108 circle(bread_radius
); } } }
110 module
donut_hole(height
, footprint_radius
) {
112 cylinder(r
= footprint_radius
, h
= height
, center
= true);
113 donut(height
, footprint_radius
); } }
115 module
jelly_filled(height
, footprint_radius
) {
116 cylinder(r
= footprint_radius
, h
= height
, center
= true);
117 donut(height
, footprint_radius
); }
120 offset(r
= -r
) { offset(delta
= r
) { children(); } } }
122 module
mirrored(axis
) {
124 mirror(axis
) children(); }
126 module
spin_slice(weight_radius
,
131 joiner_radius
= (bearing_radius
+ weight_radius
) / 2;
133 // a = side along x axis
134 a
= bearing_radius
+ weight_radius
+ wall
;
135 // b = side from center to joiner
136 b
= bearing_radius
+ joiner_radius
+ round_extra
;
137 // c = side between joiner and arm center
138 c
= joiner_radius
+ weight_radius
+ round_extra
;
140 cos_C
= (pow(a
, 2) + pow(b
, 2) - pow(c
, 2)) / (2 * a
* b
);
141 sin_C
= sqrt(1 - pow(cos_C
, 2));
145 joiner_xy
= [cos_C
, sin_C
] * b
;
147 for(arm
= [0 : arms
- 1]) {
148 rotate(arm
* (360 / arms
)) {
151 translate(bearing_xy
) {
152 circle(bearing_radius
+ round_extra
); }
153 translate(weight_xy
) {
154 circle(weight_radius
+ round_extra
); }
156 polygon([bearing_xy
, weight_xy
, joiner_xy
]); } }
158 translate(joiner_xy
) {
159 circle(joiner_radius
); } } } } } }
161 module
spin_cosine_slice(weight_radius
,
166 /* in order to make a smooth transition from one arm to the next,
167 follow the path of a circle just barely touching both arms and
168 the center circle. this is referred to as the joiner circle.
170 the joiner circle's radius and position are calculated using
171 geometry. the center of the bearing, weight and joiner circle
174 a = side between bearing and weight centers
175 b = side between bearing and joiner centers
176 c = side between joiner and weight centers
178 A = angle opposite a, inside joiner
179 B = angle opposite b, inside weight
180 C = angle opposite c, inside bearing
185 // slightly cheated. calculated using 3 arms, C = 60.
193 - 3 * r1
* round_extra
)
194 / (3 * r1
+ wall
- r0
));
198 // a = side along x axis
200 // b = side from center to joiner
201 b
= r0
+ round_extra
+ r2
;
202 // c = side between joiner and arm center
203 c
= r1
+ round_extra
+ r2
;
207 joiner_xy
= [cos(60), sin(60)] * b
;
209 translate(bearing_xy
) {
210 circle(bearing_radius
+ round_extra
); }
211 for(arm
= [0 : arms
- 1]) {
212 rotate(arm
* (360 / arms
)) {
213 translate(weight_xy
) {
214 circle(weight_radius
+ round_extra
); }
217 polygon([bearing_xy
, weight_xy
, joiner_xy
]);
218 translate(joiner_xy
) {
219 circle(joiner_radius
); } } } } } }
221 module
spin_slices(weight_radius
,
225 weight_lip_overhang
= 0.3,
226 bearing_lip_overhang
= 0.3,
229 layer_height
= 0.15) {
230 thicker_thickness
= (bearing_thickness
> weight_thickness
) ?
231 bearing_thickness
: weight_thickness
;
232 calculated_height
= thicker_thickness
+ 2 * wall
;
233 layers
= 2 * ceil(ceil(calculated_height
/ layer_height
) / 2);
234 actual_height
= layers
* layer_height
;
235 round_radius
= actual_height
/ 2;
237 /* rounding the outside edge of the spinner with a semi-circle leads
238 to a shape that an overhang on the second layer several times the
239 thickness of a printed extrusion width.
241 rather than using a full semi-circle, this code aims to use just the
242 portion in the middle, where the overhang is less severe */
244 old_end
= (layers
/ 2) - 1;
246 /* add one to have some thickness all around weight holes
248 new_start
= old_end
/ 16 + 1;
251 old_range
= old_end
- old_start
;
252 new_range
= new_end
- new_start
;
254 factor
= new_range
/ old_range
;
256 /* initial adjacent is adjusted to (new start - 1) to allow some
257 thickness all around weight holes on first layer */
258 initial_adjacent
= round_radius
- ((new_start
- 1) * layer_height
);
259 initial_angle
= acos(initial_adjacent
/ round_radius
);
260 initial_round_extra
= initial_adjacent
* tan(initial_angle
);
263 mirrored([0, 0, 1]) {
264 for(layer
= [0 : (layers
/ 2) - 1]) {
265 translate([0, 0, layer
* layer_height
- actual_height
/ 2]) {
266 linear_extrude(height
= layer_height
) {
267 new_layer
= (layer
- old_start
) * factor
+ new_start
;
268 adjacent
= round_radius
- (new_layer
* layer_height
);
269 angle
= acos(adjacent
/ round_radius
);
270 round_extra
= adjacent
* tan(angle
) - initial_round_extra
;
271 spin_slice(weight_radius
,
276 cylinder(h
= actual_height
+ 0.1,
277 r
= bearing_radius
- bearing_lip_overhang
,
279 cylinder(h
= bearing_thickness
+ 0.05,
280 r
= bearing_radius
+ 0.15,
282 for(arm
= [0 : arms
- 1]) {
283 rotate(arm
* (360 / arms
)) {
284 translate([bearing_radius
+ wall
+ weight_radius
, 0]) {
285 cylinder(h
= actual_height
+ 0.1,
286 r
= weight_radius
- weight_lip_overhang
,
288 cylinder(h
= weight_thickness
+ 0.05,
289 r
= weight_radius
+ 0.15,
290 center
= true); } } } } }
292 module
spin_cosine(weight_radius
,
296 weight_lip_overhang
= 0.3,
297 bearing_lip_overhang
= 0.3,
300 layer_height
= 0.15) {
301 thicker_thickness
= (bearing_thickness
> weight_thickness
) ?
302 bearing_thickness
: weight_thickness
;
303 calculated_height
= thicker_thickness
+ 2 * wall
;
304 layers
= 2 * ceil(ceil(calculated_height
/ layer_height
) / 2);
305 actual_height
= layers
* layer_height
;
306 round_radius
= actual_height
/ 2;
308 /* rounding the outside edge of the spinner with a semi-circle leads
309 to a shape that an overhang on the second layer several times the
310 thickness of a printed extrusion width.
312 rather than using a full semi-circle, this code aims to use just the
313 portion in the middle, where the overhang is less severe */
315 old_end
= (layers
/ 2) - 1;
317 /* add one to have some thickness all around weight holes
319 new_start
= old_end
/ 16 + 1;
322 old_range
= old_end
- old_start
;
323 new_range
= new_end
- new_start
;
325 factor
= new_range
/ old_range
;
327 /* initial adjacent is adjusted to (new start - 1) to allow some
328 thickness all around weight holes on first layer */
329 initial_adjacent
= round_radius
- ((new_start
- 1) * layer_height
);
330 initial_angle
= acos(initial_adjacent
/ round_radius
);
331 initial_round_extra
= initial_adjacent
* tan(initial_angle
);
334 mirrored([0, 0, 1]) {
335 for(layer
= [0 : (layers
/ 2) - 1]) {
336 translate([0, 0, layer
* layer_height
- actual_height
/ 2]) {
337 linear_extrude(height
= layer_height
) {
338 new_layer
= (layer
- old_start
) * factor
+ new_start
;
339 adjacent
= round_radius
- (new_layer
* layer_height
);
340 angle
= acos(adjacent
/ round_radius
);
341 round_extra
= adjacent
* tan(angle
) - initial_round_extra
;
342 spin_cosine_slice(weight_radius
,
347 // bearing window hole
348 /*cylinder(h = actual_height + 0.1,
349 r = bearing_radius - bearing_lip_overhang,
351 linear_extrude(height
= actual_height
+ 0.1, center
= true) {
353 polygon([[bearing_radius
+ 3 * wall
, 0],
354 [cos(120) * (bearing_radius
+ 3 * wall
),
355 sin(120) * (bearing_radius
+ 3 * wall
)],
356 [cos(240) * (bearing_radius
+ 3 * wall
),
357 sin(240) * (bearing_radius
+ 3 * wall
)]]);
358 circle(bearing_radius
+ 0.1); } }
360 cylinder(h
= bearing_thickness
+ 0.05,
361 r
= bearing_radius
+ 0.15,
364 for(arm
= [0 : arms
- 1]) {
365 rotate(arm
* (360 / arms
)) {
366 translate([bearing_radius
+ wall
+ weight_radius
, 0]) {
367 // weight window hole
368 mirrored([0, 0, 1]) {
369 translate([0, 0, (weight_thickness
+ 0.05) / 2]) {
370 linear_extrude(height
= wall
+ 0.1) {
372 polygon([[cos(0) * (weight_radius
+ 2.5 * wall
),
373 sin(0) * (weight_radius
+ 2.5 * wall
)],
374 [cos(120) * (weight_radius
+ 2.5 * wall
),
375 sin(120) * (weight_radius
+ 2.5 * wall
)],
376 [cos(240) * (weight_radius
+ 2.5 * wall
),
377 sin(240) * (weight_radius
+ 2.5 * wall
)]]);
378 circle(weight_radius
+ 0.2); } } } }
380 cylinder(h
= weight_thickness
+ 0.05,
381 r
= weight_radius
+ 0.20,
382 center
= true); } } } } }
384 module
spin_donut(weight_radius
,
389 bearing_lip_overhang
,
392 thicker_thickness
= (bearing_thickness
> weight_thickness
)
393 ? bearing_thickness
: weight_thickness
;
394 height
= thicker_thickness
+ wall
* 2;
396 center_to_arm_center
= bearing_radius
+ wall
+ weight_radius
;
398 jelly_filled(height
, bearing_radius
);
399 for(arm
= [0 : arms
]) {
400 rotate(arm
* (360 / arms
)) {
401 translate([center_to_arm_center
, 0, 0]) {
402 jelly_filled(height
, weight_radius
); } } } }
405 This file is part of 3d-printables.
407 3d-printables is free software: you can redistribute it and/or modify
408 it under the terms of the GNU Affero General Public License as published by
409 the Free Software Foundation, either version 3 of the License, or
410 (at your option) any later version.
412 3d-printables is distributed in the hope that it will be useful,
413 but WITHOUT ANY WARRANTY; without even the implied warranty of
414 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
415 GNU Affero General Public License for more details.
417 You should have received a copy of the GNU Affero General Public License
418 along with challenge-bot. If not, see <http://www.gnu.org/licenses/>.