make triangle window for bearing and weight
[ozzloy@gmail.com/3d-printables] / spin-data.scad
1 /* GNU AGPLv3 (or later at your option)
2 see bottom for more license info */
3
4 /* spin thing that erin likes */
5 $fn = 75;
6
7 layer_height = 0.35;
8
9 weight = "penny";
10 // weight = "608zz";
11
12 bearing = "608zz";
13 // bearing = "625rs";
14
15 weight_lip_overhang = 0.3;
16 bearing_lip_overhang = weight_lip_overhang;
17 wall = 3;
18 penny_thickness = 1.52;
19 penny_radius = 19.05 / 2;
20
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;
25 _608zz_thickness = 7;
26
27 _625rs_radius = 16 / 2;
28 _625rs_inner_radius = 5 / 2;
29 _625rs_thickness = 5;
30 _625rs_cover_radius = _625rs_radius;
31 _625rs_cap_footprint_radius = _625rs_inner_radius + 1;
32
33 weight_radius = (weight == "penny") ? penny_radius : _608zz_radius;
34 weight_thickness = (weight == "penny") ?
35 penny_thickness * 5 : _608zz_thickness;
36
37 bearing_radius =
38 (bearing == "608zz") ? _608zz_radius
39 : (bearing == "625rs") ? _625rs_radius
40 : 1/0;
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
45 : 1/0;
46 bearing_cover_radius =
47 (bearing == "608zz") ? _608zz_cover_radius
48 : (bearing == "625rs") ? _625rs_cover_radius
49 : 1/0;
50 bearing_cap_footprint_radius =
51 (bearing == "608zz") ? _608zz_cap_footprint_radius
52 : (bearing == "625rs" ) ? _625rs_cap_footprint_radius
53 : 1/0;
54 bearing_thickness =
55 (bearing == "608zz") ? _608zz_thickness
56 : (bearing == "625rs") ? _625rs_thickness
57 : 1/0;
58
59 spinner_height = penny_thickness * 5 + 2;
60 arms = 3;
61
62 module cap(bearing_inner_radius,
63 bearing_cap_footprint_radius,
64 bearing_cover_radius,
65 bearing_thickness,
66 bearing_window_radius) {
67 footprint_height = 4.5;
68 footprint_radius_safety = 0.2;
69 cap_height = 3;
70 bearing_thickness_safety = 0.6;
71 finger_spot_height = cap_height * 2 / 3;
72 stripes = 3;
73
74 difference() {
75 union() {
76 cylinder(r1 = bearing_cover_radius - tan(30) * cap_height,
77 r2 = bearing_cover_radius,
78 h = cap_height);
79 linear_extrude(height = cap_height
80 + footprint_height
81 - 1.05) {
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
86 + footprint_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) {
97 polygon([[0, 0],
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]]); } } } } } }
103
104 module donut(height, footprint_radius) {
105 bread_radius = height / 2;
106 rotate_extrude() {
107 translate([footprint_radius, 0]) {
108 circle(bread_radius); } } }
109
110 module donut_hole(height, footprint_radius) {
111 difference() {
112 cylinder(r = footprint_radius, h = height, center = true);
113 donut(height, footprint_radius); } }
114
115 module jelly_filled(height, footprint_radius) {
116 cylinder(r = footprint_radius, h = height, center = true);
117 donut(height, footprint_radius); }
118
119 module fillet(r) {
120 offset(r = -r) { offset(delta = r) { children(); } } }
121
122 module mirrored(axis) {
123 children();
124 mirror(axis) children(); }
125
126 module spin_slice(weight_radius,
127 bearing_radius,
128 round_extra,
129 wall,
130 arms) {
131 joiner_radius = (bearing_radius + weight_radius) / 2;
132
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;
139
140 cos_C = (pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2 * a * b);
141 sin_C = sqrt(1 - pow(cos_C, 2));
142
143 bearing_xy = [0, 0];
144 weight_xy = [a, 0];
145 joiner_xy = [cos_C, sin_C] * b;
146
147 for(arm = [0 : arms - 1]) {
148 rotate(arm * (360 / arms)) {
149 difference() {
150 union() {
151 translate(bearing_xy) {
152 circle(bearing_radius + round_extra); }
153 translate(weight_xy) {
154 circle(weight_radius + round_extra); }
155 mirrored([0, 1]) {
156 polygon([bearing_xy, weight_xy, joiner_xy]); } }
157 mirrored([0, 1]) {
158 translate(joiner_xy) {
159 circle(joiner_radius); } } } } } }
160
161 module spin_cosine_slice(weight_radius,
162 bearing_radius,
163 round_extra,
164 wall,
165 arms) {
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.
169
170 the joiner circle's radius and position are calculated using
171 geometry. the center of the bearing, weight and joiner circle
172 create a triangle.
173
174 a = side between bearing and weight centers
175 b = side between bearing and joiner centers
176 c = side between joiner and weight centers
177
178 A = angle opposite a, inside joiner
179 B = angle opposite b, inside weight
180 C = angle opposite c, inside bearing
181 */
182
183 r0 = bearing_radius;
184 r1 = weight_radius;
185 // slightly cheated. calculated using 3 arms, C = 60.
186 r2 = ((pow(r0, 2)
187 + r0 * wall
188 + r0 * r1
189 + pow(wall, 2)
190 + 2 * r1 * wall
191 + r0 * round_extra
192 - wall * round_extra
193 - 3 * r1 * round_extra)
194 / (3 * r1 + wall - r0));
195
196 joiner_radius = r2;
197
198 // a = side along x axis
199 a = r0 + wall + r1;
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;
204
205 bearing_xy = [0, 0];
206 weight_xy = [a, 0];
207 joiner_xy = [cos(60), sin(60)] * b;
208
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); }
215 mirrored([0, 1]) {
216 difference() {
217 polygon([bearing_xy, weight_xy, joiner_xy]);
218 translate(joiner_xy) {
219 circle(joiner_radius); } } } } } }
220
221 module spin_slices(weight_radius,
222 weight_thickness,
223 bearing_radius,
224 bearing_thickness,
225 weight_lip_overhang = 0.3,
226 bearing_lip_overhang = 0.3,
227 wall = 3,
228 arms = 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;
236
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.
240
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 */
243 old_start = 0;
244 old_end = (layers / 2) - 1;
245
246 /* add one to have some thickness all around weight holes
247 for first layer */
248 new_start = old_end / 16 + 1;
249 new_end = old_end;
250
251 old_range = old_end - old_start;
252 new_range = new_end - new_start;
253
254 factor = new_range / old_range;
255
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);
261
262 difference() {
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,
272 bearing_radius,
273 round_extra,
274 wall,
275 arms); } } } }
276 cylinder(h = actual_height + 0.1,
277 r = bearing_radius - bearing_lip_overhang,
278 center = true);
279 cylinder(h = bearing_thickness + 0.05,
280 r = bearing_radius + 0.15,
281 center = true);
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,
287 center = true);
288 cylinder(h = weight_thickness + 0.05,
289 r = weight_radius + 0.15,
290 center = true); } } } } }
291
292 module spin_cosine(weight_radius,
293 weight_thickness,
294 bearing_radius,
295 bearing_thickness,
296 weight_lip_overhang = 0.3,
297 bearing_lip_overhang = 0.3,
298 wall = 3,
299 arms = 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;
307
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.
311
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 */
314 old_start = 0;
315 old_end = (layers / 2) - 1;
316
317 /* add one to have some thickness all around weight holes
318 for first layer */
319 new_start = old_end / 16 + 1;
320 new_end = old_end;
321
322 old_range = old_end - old_start;
323 new_range = new_end - new_start;
324
325 factor = new_range / old_range;
326
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);
332
333 difference() {
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,
343 bearing_radius,
344 round_extra,
345 wall,
346 arms); } } } }
347 // bearing window hole
348 /*cylinder(h = actual_height + 0.1,
349 r = bearing_radius - bearing_lip_overhang,
350 center = true);*/
351 linear_extrude(height = actual_height + 0.1, center = true) {
352 intersection() {
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); } }
359 // bearing cavity
360 cylinder(h = bearing_thickness + 0.05,
361 r = bearing_radius + 0.15,
362 center = true);
363 // arm holes
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) {
371 intersection(){
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); } } } }
379 // weight cavity
380 cylinder(h = weight_thickness + 0.05,
381 r = weight_radius + 0.20,
382 center = true); } } } } }
383
384 module spin_donut(weight_radius,
385 weight_thickness,
386 bearing_radius,
387 bearing_thickness,
388 weight_lip_overhang,
389 bearing_lip_overhang,
390 wall,
391 arms) {
392 thicker_thickness = (bearing_thickness > weight_thickness)
393 ? bearing_thickness : weight_thickness;
394 height = thicker_thickness + wall * 2;
395
396 center_to_arm_center = bearing_radius + wall + weight_radius;
397
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); } } } }
403
404 /*
405 This file is part of 3d-printables.
406
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.
411
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.
416
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/>.
419 */