use correct bearing size for 625rs
[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 / 10;
72
73 difference() {
74 union() {
75 cylinder(r1 = bearing_cover_radius - tan(30) * cap_height,
76 r2 = bearing_cover_radius,
77 h = cap_height);
78 linear_extrude(height = cap_height
79 + footprint_height
80 - 1.05) {
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
85 + footprint_height
86 + bearing_thickness / 2
87 - bearing_thickness_safety) {
88 circle(bearing_inner_radius); }
89 }
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
95 module donut(height, footprint_radius) {
96 bread_radius = height / 2;
97 rotate_extrude() {
98 translate([footprint_radius, 0]) {
99 circle(bread_radius); } } }
100
101 module donut_hole(height, footprint_radius) {
102 difference() {
103 cylinder(r = footprint_radius, h = height, center = true);
104 donut(height, footprint_radius); } }
105
106 module jelly_filled(height, footprint_radius) {
107 cylinder(r = footprint_radius, h = height, center = true);
108 donut(height, footprint_radius); }
109
110 module fillet(r) {
111 offset(r = -r) { offset(delta = r) { children(); } } }
112
113 module mirrored(axis) {
114 children();
115 mirror(axis) children(); }
116
117 module spin_slice(weight_radius,
118 bearing_radius,
119 round_extra,
120 wall,
121 arms) {
122 joiner_radius = (bearing_radius + weight_radius) / 2;
123
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;
130
131 cos_C = (pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2 * a * b);
132 sin_C = sqrt(1 - pow(cos_C, 2));
133
134 bearing_xy = [0, 0];
135 weight_xy = [a, 0];
136 joiner_xy = [cos_C, sin_C] * b;
137
138 for(arm = [0 : arms - 1]) {
139 rotate(arm * (360 / arms)) {
140 difference() {
141 union() {
142 translate(bearing_xy) {
143 circle(bearing_radius + round_extra); }
144 translate(weight_xy) {
145 circle(weight_radius + round_extra); }
146 mirrored([0, 1]) {
147 polygon([bearing_xy, weight_xy, joiner_xy]); } }
148 mirrored([0, 1]) {
149 translate(joiner_xy) {
150 circle(joiner_radius); } } } } } }
151
152 module spin_cosine_slice(weight_radius,
153 bearing_radius,
154 round_extra,
155 wall,
156 arms) {
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.
160
161 the joiner circle's radius and position are calculated using
162 geometry. the center of the bearing, weight and joiner circle
163 create a triangle.
164
165 a = side between bearing and weight centers
166 b = side between bearing and joiner centers
167 c = side between joiner and weight centers
168
169 A = angle opposite a, inside joiner
170 B = angle opposite b, inside weight
171 C = angle opposite c, inside bearing
172 */
173
174 r0 = bearing_radius;
175 r1 = weight_radius;
176 // slightly cheated. calculated using 3 arms, C = 60.
177 r2 = ((pow(r0, 2)
178 + r0 * wall
179 + r0 * r1
180 + pow(wall, 2)
181 + 2 * r1 * wall
182 + r0 * round_extra
183 - wall * round_extra
184 - 3 * r1 * round_extra)
185 / (3 * r1 + wall - r0));
186
187 joiner_radius = r2;
188
189 // a = side along x axis
190 a = r0 + wall + r1;
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;
195
196 bearing_xy = [0, 0];
197 weight_xy = [a, 0];
198 joiner_xy = [cos(60), sin(60)] * b;
199
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); }
206 mirrored([0, 1]) {
207 difference() {
208 polygon([bearing_xy, weight_xy, joiner_xy]);
209 translate(joiner_xy) {
210 circle(joiner_radius); } } } } } }
211
212 module spin_slices(weight_radius,
213 weight_thickness,
214 bearing_radius,
215 bearing_thickness,
216 weight_lip_overhang = 0.3,
217 bearing_lip_overhang = 0.3,
218 wall = 3,
219 arms = 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;
227
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.
231
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 */
234 old_start = 0;
235 old_end = (layers / 2) - 1;
236
237 /* add one to have some thickness all around weight holes
238 for first layer */
239 new_start = old_end / 16 + 1;
240 new_end = old_end;
241
242 old_range = old_end - old_start;
243 new_range = new_end - new_start;
244
245 factor = new_range / old_range;
246
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);
252
253 difference() {
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,
263 bearing_radius,
264 round_extra,
265 wall,
266 arms); } } } }
267 cylinder(h = actual_height + 0.1,
268 r = bearing_radius - bearing_lip_overhang,
269 center = true);
270 cylinder(h = bearing_thickness + 0.05,
271 r = bearing_radius + 0.15,
272 center = true);
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,
278 center = true);
279 cylinder(h = weight_thickness + 0.05,
280 r = weight_radius + 0.15,
281 center = true); } } } } }
282
283 module spin_cosine(weight_radius,
284 weight_thickness,
285 bearing_radius,
286 bearing_thickness,
287 weight_lip_overhang = 0.3,
288 bearing_lip_overhang = 0.3,
289 wall = 3,
290 arms = 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;
298
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.
302
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 */
305 old_start = 0;
306 old_end = (layers / 2) - 1;
307
308 /* add one to have some thickness all around weight holes
309 for first layer */
310 new_start = old_end / 16 + 1;
311 new_end = old_end;
312
313 old_range = old_end - old_start;
314 new_range = new_end - new_start;
315
316 factor = new_range / old_range;
317
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);
323
324 difference() {
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,
334 bearing_radius,
335 round_extra,
336 wall,
337 arms); } } } }
338 cylinder(h = actual_height + 0.1,
339 r = bearing_radius - bearing_lip_overhang,
340 center = true);
341 cylinder(h = bearing_thickness + 0.05,
342 r = bearing_radius + 0.15,
343 center = true);
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,
349 center = true);
350 cylinder(h = weight_thickness + 0.05,
351 r = weight_radius + 0.15,
352 center = true); } } } } }
353
354 module spin_donut(weight_radius,
355 weight_thickness,
356 bearing_radius,
357 bearing_thickness,
358 weight_lip_overhang,
359 bearing_lip_overhang,
360 wall,
361 arms) {
362 thicker_thickness = (bearing_thickness > weight_thickness)
363 ? bearing_thickness : weight_thickness;
364 height = thicker_thickness + wall * 2;
365
366 center_to_arm_center = bearing_radius + wall + weight_radius;
367
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); } } } }
373
374 /*
375 This file is part of 3d-printables.
376
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.
381
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.
386
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/>.
389 */