update puzzle to latest version to match solution instructions
[ozzloy@gmail.com/3d-printables] / spin-data.scad
CommitLineData
818dd661 1/* GNU AGPLv3 (or later at your option)
2 see bottom for more license info */
3
4/* spin thing that erin likes */
0c7b5029 5$fn = 75;
cc410ed6 6
5f8325d2 7layer_height = 0.35;
818dd661 8
9weight = "penny";
10// weight = "608zz";
0c7b5029 11
a8c6c94f 12//bearing = "608zz";
13bearing = "sr188";
0c7b5029 14// bearing = "625rs";
15
cc410ed6 16weight_lip_overhang = 0.3;
17bearing_lip_overhang = weight_lip_overhang;
cc410ed6 18wall = 3;
2645ef26 19penny_thickness = 1.52;
818dd661 20penny_radius = 19.05 / 2;
7f1519fb 21
a8c6c94f 22sr188_radius = 12.74 / 2; // 0.5 / 2
23sr188_inner_radius = 6.3 / 2; // 0.2470 / 2
24sr188_thickness = 4.8; // 0.1895 inch
25sr188_cover_radius = sr188_radius;
26sr188_cap_footprint_radius = 12 / 2;
27
7f1519fb 28_608zz_radius = 22 / 2;
29_608zz_inner_radius = 8.1 / 2;
8d55712b 30_608zz_cover_radius = _608zz_radius;
7f1519fb 31_608zz_cap_footprint_radius = 12 / 2;
32_608zz_thickness = 7;
33
0c7b5029 34_625rs_radius = 16 / 2;
35_625rs_inner_radius = 5 / 2;
36_625rs_thickness = 5;
37_625rs_cover_radius = _625rs_radius;
38_625rs_cap_footprint_radius = _625rs_inner_radius + 1;
39
818dd661 40weight_radius = (weight == "penny") ? penny_radius : _608zz_radius;
2645ef26 41weight_thickness = (weight == "penny") ?
42 penny_thickness * 5 : _608zz_thickness;
7f1519fb 43
0c7b5029 44bearing_radius =
45 (bearing == "608zz") ? _608zz_radius
46 : (bearing == "625rs") ? _625rs_radius
a8c6c94f 47 : (bearing == "sr188") ? sr188_radius
0c7b5029 48 : 1/0;
3381230e 49bearing_window_radius = bearing_radius - bearing_lip_overhang - 1;
0c7b5029 50bearing_inner_radius =
51 (bearing == "608zz") ? _608zz_inner_radius
04db4766 52 : (bearing == "625rs") ? _625rs_inner_radius
a8c6c94f 53 : (bearing == "sr188") ? sr188_inner_radius
0c7b5029 54 : 1/0;
55bearing_cover_radius =
56 (bearing == "608zz") ? _608zz_cover_radius
57 : (bearing == "625rs") ? _625rs_cover_radius
a8c6c94f 58 : (bearing == "sr188") ? sr188_cover_radius
0c7b5029 59 : 1/0;
7f1519fb 60bearing_cap_footprint_radius =
0c7b5029 61 (bearing == "608zz") ? _608zz_cap_footprint_radius
62 : (bearing == "625rs" ) ? _625rs_cap_footprint_radius
a8c6c94f 63 : (bearing == "sr188" ) ? sr188_cap_footprint_radius
0c7b5029 64 : 1/0;
65bearing_thickness =
66 (bearing == "608zz") ? _608zz_thickness
67 : (bearing == "625rs") ? _625rs_thickness
a8c6c94f 68 : (bearing == "sr188") ? sr188_thickness
0c7b5029 69 : 1/0;
7f1519fb 70
71spinner_height = penny_thickness * 5 + 2;
818dd661 72arms = 3;
73
7f1519fb 74module cap(bearing_inner_radius,
75 bearing_cap_footprint_radius,
76 bearing_cover_radius,
3381230e 77 bearing_thickness,
78 bearing_window_radius) {
79 footprint_height = 4.5;
80 footprint_radius_safety = 0.2;
7f1519fb 81 cap_height = 3;
3381230e 82 bearing_thickness_safety = 0.6;
23616d65 83 finger_spot_height = cap_height * 2 / 3;
84 stripes = 3;
7f1519fb 85
86 difference() {
87 union() {
88 cylinder(r1 = bearing_cover_radius - tan(30) * cap_height,
89 r2 = bearing_cover_radius,
90 h = cap_height);
3381230e 91 linear_extrude(height = cap_height
92 + footprint_height
93 - 1.05) {
94 circle(bearing_window_radius - 1); }
7f1519fb 95 linear_extrude(height = cap_height + footprint_height) {
96 circle(bearing_cap_footprint_radius - footprint_radius_safety); }
97 linear_extrude(height = cap_height
98 + footprint_height
99 + bearing_thickness / 2
100 - bearing_thickness_safety) {
23616d65 101 circle(bearing_inner_radius + 0.1); } }
7f1519fb 102 translate([0, 0, -0.01]) {
3381230e 103 cylinder(r1 = bearing_inner_radius,
104 r2 = bearing_inner_radius - tan(30) * finger_spot_height,
23616d65 105 h = finger_spot_height);
106 for(stripe = [0 : stripes - 1]) {
107 rotate((stripe / stripes) * 360) {
108 linear_extrude(height = finger_spot_height) {
109 polygon([[0, 0],
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]]); } } } } } }
7f1519fb 115
d4c56d9d 116module donut(height, footprint_radius) {
117 bread_radius = height / 2;
118 rotate_extrude() {
119 translate([footprint_radius, 0]) {
120 circle(bread_radius); } } }
121
122module donut_hole(height, footprint_radius) {
123 difference() {
124 cylinder(r = footprint_radius, h = height, center = true);
125 donut(height, footprint_radius); } }
126
127module jelly_filled(height, footprint_radius) {
128 cylinder(r = footprint_radius, h = height, center = true);
129 donut(height, footprint_radius); }
130
cc410ed6 131module fillet(r) {
132 offset(r = -r) { offset(delta = r) { children(); } } }
133
cc410ed6 134module mirrored(axis) {
135 children();
136 mirror(axis) children(); }
2645ef26 137
5f8325d2 138module spin_slice(weight_radius,
139 bearing_radius,
140 round_extra,
141 wall,
142 arms) {
143 joiner_radius = (bearing_radius + weight_radius) / 2;
144
5f8325d2 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;
151
5f8325d2 152 cos_C = (pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2 * a * b);
153 sin_C = sqrt(1 - pow(cos_C, 2));
154
85cda07f 155 bearing_xy = [0, 0];
156 weight_xy = [a, 0];
5f8325d2 157 joiner_xy = [cos_C, sin_C] * b;
158
159 for(arm = [0 : arms - 1]) {
160 rotate(arm * (360 / arms)) {
161 difference() {
162 union() {
163 translate(bearing_xy) {
164 circle(bearing_radius + round_extra); }
165 translate(weight_xy) {
166 circle(weight_radius + round_extra); }
167 mirrored([0, 1]) {
168 polygon([bearing_xy, weight_xy, joiner_xy]); } }
169 mirrored([0, 1]) {
170 translate(joiner_xy) {
171 circle(joiner_radius); } } } } } }
172
85cda07f 173module spin_cosine_slice(weight_radius,
174 bearing_radius,
175 round_extra,
176 wall,
177 arms) {
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.
181
182 the joiner circle's radius and position are calculated using
183 geometry. the center of the bearing, weight and joiner circle
184 create a triangle.
185
186 a = side between bearing and weight centers
187 b = side between bearing and joiner centers
188 c = side between joiner and weight centers
189
190 A = angle opposite a, inside joiner
191 B = angle opposite b, inside weight
192 C = angle opposite c, inside bearing
193 */
194
195 r0 = bearing_radius;
196 r1 = weight_radius;
197 // slightly cheated. calculated using 3 arms, C = 60.
198 r2 = ((pow(r0, 2)
199 + r0 * wall
200 + r0 * r1
201 + pow(wall, 2)
202 + 2 * r1 * wall
203 + r0 * round_extra
204 - wall * round_extra
205 - 3 * r1 * round_extra)
206 / (3 * r1 + wall - r0));
207
208 joiner_radius = r2;
209
210 // a = side along x axis
211 a = r0 + wall + r1;
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;
216
217 bearing_xy = [0, 0];
218 weight_xy = [a, 0];
219 joiner_xy = [cos(60), sin(60)] * b;
220
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); }
227 mirrored([0, 1]) {
228 difference() {
229 polygon([bearing_xy, weight_xy, joiner_xy]);
230 translate(joiner_xy) {
231 circle(joiner_radius); } } } } } }
232
5f8325d2 233module spin_slices(weight_radius,
234 weight_thickness,
235 bearing_radius,
236 bearing_thickness,
237 weight_lip_overhang = 0.3,
238 bearing_lip_overhang = 0.3,
239 wall = 3,
240 arms = 3,
241 layer_height = 0.15) {
cc410ed6 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;
248
5f8325d2 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.
252
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 */
e1a02727 255 old_start = 0;
256 old_end = (layers / 2) - 1;
257
5f8325d2 258 /* add one to have some thickness all around weight holes
259 for first layer */
5fdbde1b 260 new_start = old_end / 16 + 1;
e1a02727 261 new_end = old_end;
262
263 old_range = old_end - old_start;
264 new_range = new_end - new_start;
265
266 factor = new_range / old_range;
267
5f8325d2 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);
e1a02727 271 initial_angle = acos(initial_adjacent / round_radius);
272 initial_round_extra = initial_adjacent * tan(initial_angle);
5f8325d2 273
274 difference() {
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,
284 bearing_radius,
285 round_extra,
286 wall,
287 arms); } } } }
85cda07f 288 cylinder(h = actual_height + 0.1,
289 r = bearing_radius - bearing_lip_overhang,
290 center = true);
291 cylinder(h = bearing_thickness + 0.05,
292 r = bearing_radius + 0.15,
293 center = true);
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,
299 center = true);
300 cylinder(h = weight_thickness + 0.05,
301 r = weight_radius + 0.15,
302 center = true); } } } } }
303
a8c6c94f 304module equilateral_triangle(radius){
305 polygon([[cos(0) * radius, sin(0) * radius],
306 [cos(120) * radius,
307 sin(120) * radius],
308 [cos(240) * radius,
309 sin(240) * radius]]); }
310
85cda07f 311module spin_cosine(weight_radius,
312 weight_thickness,
313 bearing_radius,
314 bearing_thickness,
315 weight_lip_overhang = 0.3,
316 bearing_lip_overhang = 0.3,
317 wall = 3,
318 arms = 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;
326
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.
330
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 */
333 old_start = 0;
334 old_end = (layers / 2) - 1;
335
336 /* add one to have some thickness all around weight holes
337 for first layer */
338 new_start = old_end / 16 + 1;
339 new_end = old_end;
340
341 old_range = old_end - old_start;
342 new_range = new_end - new_start;
343
344 factor = new_range / old_range;
345
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);
351
352 difference() {
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,
362 bearing_radius,
363 round_extra,
364 wall,
365 arms); } } } }
baad6cfa 366 // bearing window hole
367 /*cylinder(h = actual_height + 0.1,
5f8325d2 368 r = bearing_radius - bearing_lip_overhang,
baad6cfa 369 center = true);*/
370 linear_extrude(height = actual_height + 0.1, center = true) {
371 intersection() {
a8c6c94f 372 equilateral_triangle(1.8 * bearing_radius);
baad6cfa 373 circle(bearing_radius + 0.1); } }
374 // bearing cavity
5fdbde1b 375 cylinder(h = bearing_thickness + 0.05,
376 r = bearing_radius + 0.15,
5f8325d2 377 center = true);
baad6cfa 378 // arm holes
5f8325d2 379 for(arm = [0 : arms - 1]) {
380 rotate(arm * (360 / arms)) {
381 translate([bearing_radius + wall + weight_radius, 0]) {
baad6cfa 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) {
386 intersection(){
a8c6c94f 387 equilateral_triangle(1.8 * weight_radius);
baad6cfa 388 circle(weight_radius + 0.2); } } } }
389 // weight cavity
5fdbde1b 390 cylinder(h = weight_thickness + 0.05,
baad6cfa 391 r = weight_radius + 0.20,
5f8325d2 392 center = true); } } } } }
818dd661 393
1dc634e1 394module spin_donut(weight_radius,
395 weight_thickness,
396 bearing_radius,
397 bearing_thickness,
398 weight_lip_overhang,
399 bearing_lip_overhang,
400 wall,
401 arms) {
402 thicker_thickness = (bearing_thickness > weight_thickness)
403 ? bearing_thickness : weight_thickness;
404 height = thicker_thickness + wall * 2;
405
406 center_to_arm_center = bearing_radius + wall + weight_radius;
407
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); } } } }
413
818dd661 414/*
415 This file is part of 3d-printables.
416
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.
421
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.
426
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/>.
429*/