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
/ 10;
75 cylinder(r1
= bearing_cover_radius
- tan(30) * cap_height
,
76 r2
= bearing_cover_radius
,
78 linear_extrude(height
= cap_height
81 circle(bearing_window_radius
- 1); }
82 linear_extrude(height
= cap_height
+ footprint_height
) {
83 circle(bearing_cap_footprint_radius
- footprint_radius_safety
); }
84 linear_extrude(height
= cap_height
86 + bearing_thickness
/ 2
87 - bearing_thickness_safety
) {
88 circle(bearing_inner_radius
); }
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
); } } }
95 module
donut(height
, footprint_radius
) {
96 bread_radius
= height
/ 2;
98 translate([footprint_radius
, 0]) {
99 circle(bread_radius
); } } }
101 module
donut_hole(height
, footprint_radius
) {
103 cylinder(r
= footprint_radius
, h
= height
, center
= true);
104 donut(height
, footprint_radius
); } }
106 module
jelly_filled(height
, footprint_radius
) {
107 cylinder(r
= footprint_radius
, h
= height
, center
= true);
108 donut(height
, footprint_radius
); }
111 offset(r
= -r
) { offset(delta
= r
) { children(); } } }
113 module
mirrored(axis
) {
115 mirror(axis
) children(); }
117 module
spin_slice(weight_radius
,
122 joiner_radius
= (bearing_radius
+ weight_radius
) / 2;
124 // a = side along x axis
125 a
= bearing_radius
+ weight_radius
+ wall
;
126 // b = side from center to joiner
127 b
= bearing_radius
+ joiner_radius
+ round_extra
;
128 // c = side between joiner and arm center
129 c
= joiner_radius
+ weight_radius
+ round_extra
;
131 cos_C
= (pow(a
, 2) + pow(b
, 2) - pow(c
, 2)) / (2 * a
* b
);
132 sin_C
= sqrt(1 - pow(cos_C
, 2));
136 joiner_xy
= [cos_C
, sin_C
] * b
;
138 for(arm
= [0 : arms
- 1]) {
139 rotate(arm
* (360 / arms
)) {
142 translate(bearing_xy
) {
143 circle(bearing_radius
+ round_extra
); }
144 translate(weight_xy
) {
145 circle(weight_radius
+ round_extra
); }
147 polygon([bearing_xy
, weight_xy
, joiner_xy
]); } }
149 translate(joiner_xy
) {
150 circle(joiner_radius
); } } } } } }
152 module
spin_cosine_slice(weight_radius
,
157 /* in order to make a smooth transition from one arm to the next,
158 follow the path of a circle just barely touching both arms and
159 the center circle. this is referred to as the joiner circle.
161 the joiner circle's radius and position are calculated using
162 geometry. the center of the bearing, weight and joiner circle
165 a = side between bearing and weight centers
166 b = side between bearing and joiner centers
167 c = side between joiner and weight centers
169 A = angle opposite a, inside joiner
170 B = angle opposite b, inside weight
171 C = angle opposite c, inside bearing
176 // slightly cheated. calculated using 3 arms, C = 60.
184 - 3 * r1
* round_extra
)
185 / (3 * r1
+ wall
- r0
));
189 // a = side along x axis
191 // b = side from center to joiner
192 b
= r0
+ round_extra
+ r2
;
193 // c = side between joiner and arm center
194 c
= r1
+ round_extra
+ r2
;
198 joiner_xy
= [cos(60), sin(60)] * b
;
200 translate(bearing_xy
) {
201 circle(bearing_radius
+ round_extra
); }
202 for(arm
= [0 : arms
- 1]) {
203 rotate(arm
* (360 / arms
)) {
204 translate(weight_xy
) {
205 circle(weight_radius
+ round_extra
); }
208 polygon([bearing_xy
, weight_xy
, joiner_xy
]);
209 translate(joiner_xy
) {
210 circle(joiner_radius
); } } } } } }
212 module
spin_slices(weight_radius
,
216 weight_lip_overhang
= 0.3,
217 bearing_lip_overhang
= 0.3,
220 layer_height
= 0.15) {
221 thicker_thickness
= (bearing_thickness
> weight_thickness
) ?
222 bearing_thickness
: weight_thickness
;
223 calculated_height
= thicker_thickness
+ 2 * wall
;
224 layers
= 2 * ceil(ceil(calculated_height
/ layer_height
) / 2);
225 actual_height
= layers
* layer_height
;
226 round_radius
= actual_height
/ 2;
228 /* rounding the outside edge of the spinner with a semi-circle leads
229 to a shape that an overhang on the second layer several times the
230 thickness of a printed extrusion width.
232 rather than using a full semi-circle, this code aims to use just the
233 portion in the middle, where the overhang is less severe */
235 old_end
= (layers
/ 2) - 1;
237 /* add one to have some thickness all around weight holes
239 new_start
= old_end
/ 16 + 1;
242 old_range
= old_end
- old_start
;
243 new_range
= new_end
- new_start
;
245 factor
= new_range
/ old_range
;
247 /* initial adjacent is adjusted to (new start - 1) to allow some
248 thickness all around weight holes on first layer */
249 initial_adjacent
= round_radius
- ((new_start
- 1) * layer_height
);
250 initial_angle
= acos(initial_adjacent
/ round_radius
);
251 initial_round_extra
= initial_adjacent
* tan(initial_angle
);
254 mirrored([0, 0, 1]) {
255 for(layer
= [0 : (layers
/ 2) - 1]) {
256 translate([0, 0, layer
* layer_height
- actual_height
/ 2]) {
257 linear_extrude(height
= layer_height
) {
258 new_layer
= (layer
- old_start
) * factor
+ new_start
;
259 adjacent
= round_radius
- (new_layer
* layer_height
);
260 angle
= acos(adjacent
/ round_radius
);
261 round_extra
= adjacent
* tan(angle
) - initial_round_extra
;
262 spin_slice(weight_radius
,
267 cylinder(h
= actual_height
+ 0.1,
268 r
= bearing_radius
- bearing_lip_overhang
,
270 cylinder(h
= bearing_thickness
+ 0.05,
271 r
= bearing_radius
+ 0.15,
273 for(arm
= [0 : arms
- 1]) {
274 rotate(arm
* (360 / arms
)) {
275 translate([bearing_radius
+ wall
+ weight_radius
, 0]) {
276 cylinder(h
= actual_height
+ 0.1,
277 r
= weight_radius
- weight_lip_overhang
,
279 cylinder(h
= weight_thickness
+ 0.05,
280 r
= weight_radius
+ 0.15,
281 center
= true); } } } } }
283 module
spin_cosine(weight_radius
,
287 weight_lip_overhang
= 0.3,
288 bearing_lip_overhang
= 0.3,
291 layer_height
= 0.15) {
292 thicker_thickness
= (bearing_thickness
> weight_thickness
) ?
293 bearing_thickness
: weight_thickness
;
294 calculated_height
= thicker_thickness
+ 2 * wall
;
295 layers
= 2 * ceil(ceil(calculated_height
/ layer_height
) / 2);
296 actual_height
= layers
* layer_height
;
297 round_radius
= actual_height
/ 2;
299 /* rounding the outside edge of the spinner with a semi-circle leads
300 to a shape that an overhang on the second layer several times the
301 thickness of a printed extrusion width.
303 rather than using a full semi-circle, this code aims to use just the
304 portion in the middle, where the overhang is less severe */
306 old_end
= (layers
/ 2) - 1;
308 /* add one to have some thickness all around weight holes
310 new_start
= old_end
/ 16 + 1;
313 old_range
= old_end
- old_start
;
314 new_range
= new_end
- new_start
;
316 factor
= new_range
/ old_range
;
318 /* initial adjacent is adjusted to (new start - 1) to allow some
319 thickness all around weight holes on first layer */
320 initial_adjacent
= round_radius
- ((new_start
- 1) * layer_height
);
321 initial_angle
= acos(initial_adjacent
/ round_radius
);
322 initial_round_extra
= initial_adjacent
* tan(initial_angle
);
325 mirrored([0, 0, 1]) {
326 for(layer
= [0 : (layers
/ 2) - 1]) {
327 translate([0, 0, layer
* layer_height
- actual_height
/ 2]) {
328 linear_extrude(height
= layer_height
) {
329 new_layer
= (layer
- old_start
) * factor
+ new_start
;
330 adjacent
= round_radius
- (new_layer
* layer_height
);
331 angle
= acos(adjacent
/ round_radius
);
332 round_extra
= adjacent
* tan(angle
) - initial_round_extra
;
333 spin_cosine_slice(weight_radius
,
338 cylinder(h
= actual_height
+ 0.1,
339 r
= bearing_radius
- bearing_lip_overhang
,
341 cylinder(h
= bearing_thickness
+ 0.05,
342 r
= bearing_radius
+ 0.15,
344 for(arm
= [0 : arms
- 1]) {
345 rotate(arm
* (360 / arms
)) {
346 translate([bearing_radius
+ wall
+ weight_radius
, 0]) {
347 cylinder(h
= actual_height
+ 0.1,
348 r
= weight_radius
- weight_lip_overhang
,
350 cylinder(h
= weight_thickness
+ 0.05,
351 r
= weight_radius
+ 0.15,
352 center
= true); } } } } }
354 module
spin_donut(weight_radius
,
359 bearing_lip_overhang
,
362 thicker_thickness
= (bearing_thickness
> weight_thickness
)
363 ? bearing_thickness
: weight_thickness
;
364 height
= thicker_thickness
+ wall
* 2;
366 center_to_arm_center
= bearing_radius
+ wall
+ weight_radius
;
368 jelly_filled(height
, bearing_radius
);
369 for(arm
= [0 : arms
]) {
370 rotate(arm
* (360 / arms
)) {
371 translate([center_to_arm_center
, 0, 0]) {
372 jelly_filled(height
, weight_radius
); } } } }
375 This file is part of 3d-printables.
377 3d-printables is free software: you can redistribute it and/or modify
378 it under the terms of the GNU Affero General Public License as published by
379 the Free Software Foundation, either version 3 of the License, or
380 (at your option) any later version.
382 3d-printables is distributed in the hope that it will be useful,
383 but WITHOUT ANY WARRANTY; without even the implied warranty of
384 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
385 GNU Affero General Public License for more details.
387 You should have received a copy of the GNU Affero General Public License
388 along with challenge-bot. If not, see <http://www.gnu.org/licenses/>.