X-Git-Url: http://challenge-bot.com/repos/?a=blobdiff_plain;f=spin-data.scad;h=e5df4e2aa718930ecff0a5909ca9d037a351f7f2;hb=HEAD;hp=9a889dac4882f0771a48bf05b476c872becd2bd4;hpb=cc410ed626d352fa34138860c80d76d369a7013d;p=ozzloy%40gmail.com%2F3d-printables diff --git a/spin-data.scad b/spin-data.scad index 9a889da..e5df4e2 100644 --- a/spin-data.scad +++ b/spin-data.scad @@ -2,39 +2,71 @@ see bottom for more license info */ /* spin thing that erin likes */ -$fn = 50; +$fn = 75; -layer_height = 0.15; +layer_height = 0.35; weight = "penny"; // weight = "608zz"; -bearing = "608zz"; + +//bearing = "608zz"; +bearing = "sr188"; +// bearing = "625rs"; + weight_lip_overhang = 0.3; bearing_lip_overhang = weight_lip_overhang; -// TODO: switch wall_thickness -> wall -wall_thickness = 3; wall = 3; penny_thickness = 1.52; penny_radius = 19.05 / 2; +sr188_radius = 12.74 / 2; // 0.5 / 2 +sr188_inner_radius = 6.3 / 2; // 0.2470 / 2 +sr188_thickness = 4.8; // 0.1895 inch +sr188_cover_radius = sr188_radius; +sr188_cap_footprint_radius = 12 / 2; + _608zz_radius = 22 / 2; _608zz_inner_radius = 8.1 / 2; -_608zz_cover_radius = 19.4 / 2; +_608zz_cover_radius = _608zz_radius; _608zz_cap_footprint_radius = 12 / 2; _608zz_thickness = 7; +_625rs_radius = 16 / 2; +_625rs_inner_radius = 5 / 2; +_625rs_thickness = 5; +_625rs_cover_radius = _625rs_radius; +_625rs_cap_footprint_radius = _625rs_inner_radius + 1; + weight_radius = (weight == "penny") ? penny_radius : _608zz_radius; weight_thickness = (weight == "penny") ? penny_thickness * 5 : _608zz_thickness; -bearing_radius = (bearing == "608zz") ? _608zz_radius : 1/0; -bearing_inner_radius = (bearing == "608zz") ? _608zz_inner_radius : 1/0; -bearing_cover_radius = (bearing == "608zz") - ? _608zz_cover_radius + wall - : 1/0; +bearing_radius = + (bearing == "608zz") ? _608zz_radius + : (bearing == "625rs") ? _625rs_radius + : (bearing == "sr188") ? sr188_radius + : 1/0; +bearing_window_radius = bearing_radius - bearing_lip_overhang - 1; +bearing_inner_radius = + (bearing == "608zz") ? _608zz_inner_radius + : (bearing == "625rs") ? _625rs_inner_radius + : (bearing == "sr188") ? sr188_inner_radius + : 1/0; +bearing_cover_radius = + (bearing == "608zz") ? _608zz_cover_radius + : (bearing == "625rs") ? _625rs_cover_radius + : (bearing == "sr188") ? sr188_cover_radius + : 1/0; bearing_cap_footprint_radius = - (bearing == "608zz") ? _608zz_cap_footprint_radius : 1/0; -bearing_thickness = (bearing == "608zz") ? _608zz_thickness : 1/0; + (bearing == "608zz") ? _608zz_cap_footprint_radius + : (bearing == "625rs" ) ? _625rs_cap_footprint_radius + : (bearing == "sr188" ) ? sr188_cap_footprint_radius + : 1/0; +bearing_thickness = + (bearing == "608zz") ? _608zz_thickness + : (bearing == "625rs") ? _625rs_thickness + : (bearing == "sr188") ? sr188_thickness + : 1/0; spinner_height = penny_thickness * 5 + 2; arms = 3; @@ -42,66 +74,171 @@ arms = 3; module cap(bearing_inner_radius, bearing_cap_footprint_radius, bearing_cover_radius, - bearing_thickness) { - footprint_height = 1.6; - footprint_radius_safety = 0.25; + bearing_thickness, + bearing_window_radius) { + footprint_height = 4.5; + footprint_radius_safety = 0.2; cap_height = 3; - bearing_cover_radius_safety = 0.75; - bearing_thickness_safety = 0.2; + bearing_thickness_safety = 0.6; + finger_spot_height = cap_height * 2 / 3; + stripes = 3; difference() { union() { cylinder(r1 = bearing_cover_radius - tan(30) * cap_height, r2 = bearing_cover_radius, h = cap_height); + linear_extrude(height = cap_height + + footprint_height + - 1.05) { + circle(bearing_window_radius - 1); } linear_extrude(height = cap_height + footprint_height) { circle(bearing_cap_footprint_radius - footprint_radius_safety); } linear_extrude(height = cap_height + footprint_height + bearing_thickness / 2 - bearing_thickness_safety) { - circle(bearing_inner_radius); } } + circle(bearing_inner_radius + 0.1); } } translate([0, 0, -0.01]) { - cylinder(r1 = bearing_inner_radius + tan(30) * (cap_height - 1), - r2 = bearing_inner_radius, - h = cap_height - 1); } } } + cylinder(r1 = bearing_inner_radius, + r2 = bearing_inner_radius - tan(30) * finger_spot_height, + h = finger_spot_height); + for(stripe = [0 : stripes - 1]) { + rotate((stripe / stripes) * 360) { + linear_extrude(height = finger_spot_height) { + polygon([[0, 0], + [bearing_cover_radius * 2, 0], + [cos(3 + 360 / (stripes * 2)) + * bearing_cover_radius * 2, + sin(3 + 360 / (stripes * 2)) + * bearing_cover_radius * 2]]); } } } } } } -module ring(outer_radius, inner_radius) { +module donut(height, footprint_radius) { + bread_radius = height / 2; + rotate_extrude() { + translate([footprint_radius, 0]) { + circle(bread_radius); } } } + +module donut_hole(height, footprint_radius) { difference() { - circle(outer_radius); - circle(inner_radius); } } + cylinder(r = footprint_radius, h = height, center = true); + donut(height, footprint_radius); } } + +module jelly_filled(height, footprint_radius) { + cylinder(r = footprint_radius, h = height, center = true); + donut(height, footprint_radius); } module fillet(r) { offset(r = -r) { offset(delta = r) { children(); } } } -module spin_footprint(weight_radius, - bearing_radius, - round_extra, - wall, - arms) { - thinner_radius = (bearing_radius < weight_radius)? - bearing_radius : weight_radius; - fillet(thinner_radius) { - for(arm = [0 : arms - 1]) { - hull() { - circle(bearing_radius + round_extra); - rotate( (arm / arms) * 360 ) { - translate([bearing_radius + wall + weight_radius, 0]) { - circle(weight_radius + round_extra); } } } } } } - module mirrored(axis) { children(); mirror(axis) children(); } -module spin(weight_radius, - weight_thickness, - bearing_radius, - bearing_thickness, - weight_lip_overhang = 0.3, - bearing_lip_overhang = 0.3, - wall = 3, - arms = 3) { - layer_height = 0.15; +module spin_slice(weight_radius, + bearing_radius, + round_extra, + wall, + arms) { + joiner_radius = (bearing_radius + weight_radius) / 2; + + // a = side along x axis + a = bearing_radius + weight_radius + wall; + // b = side from center to joiner + b = bearing_radius + joiner_radius + round_extra; + // c = side between joiner and arm center + c = joiner_radius + weight_radius + round_extra; + + cos_C = (pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2 * a * b); + sin_C = sqrt(1 - pow(cos_C, 2)); + + bearing_xy = [0, 0]; + weight_xy = [a, 0]; + joiner_xy = [cos_C, sin_C] * b; + + for(arm = [0 : arms - 1]) { + rotate(arm * (360 / arms)) { + difference() { + union() { + translate(bearing_xy) { + circle(bearing_radius + round_extra); } + translate(weight_xy) { + circle(weight_radius + round_extra); } + mirrored([0, 1]) { + polygon([bearing_xy, weight_xy, joiner_xy]); } } + mirrored([0, 1]) { + translate(joiner_xy) { + circle(joiner_radius); } } } } } } + +module spin_cosine_slice(weight_radius, + bearing_radius, + round_extra, + wall, + arms) { + /* in order to make a smooth transition from one arm to the next, + follow the path of a circle just barely touching both arms and + the center circle. this is referred to as the joiner circle. + + the joiner circle's radius and position are calculated using + geometry. the center of the bearing, weight and joiner circle + create a triangle. + + a = side between bearing and weight centers + b = side between bearing and joiner centers + c = side between joiner and weight centers + + A = angle opposite a, inside joiner + B = angle opposite b, inside weight + C = angle opposite c, inside bearing + */ + + r0 = bearing_radius; + r1 = weight_radius; + // slightly cheated. calculated using 3 arms, C = 60. + r2 = ((pow(r0, 2) + + r0 * wall + + r0 * r1 + + pow(wall, 2) + + 2 * r1 * wall + + r0 * round_extra + - wall * round_extra + - 3 * r1 * round_extra) + / (3 * r1 + wall - r0)); + + joiner_radius = r2; + + // a = side along x axis + a = r0 + wall + r1; + // b = side from center to joiner + b = r0 + round_extra + r2; + // c = side between joiner and arm center + c = r1 + round_extra + r2; + + bearing_xy = [0, 0]; + weight_xy = [a, 0]; + joiner_xy = [cos(60), sin(60)] * b; + + translate(bearing_xy) { + circle(bearing_radius + round_extra); } + for(arm = [0 : arms - 1]) { + rotate(arm * (360 / arms)) { + translate(weight_xy) { + circle(weight_radius + round_extra); } + mirrored([0, 1]) { + difference() { + polygon([bearing_xy, weight_xy, joiner_xy]); + translate(joiner_xy) { + circle(joiner_radius); } } } } } } + +module spin_slices(weight_radius, + weight_thickness, + bearing_radius, + bearing_thickness, + weight_lip_overhang = 0.3, + bearing_lip_overhang = 0.3, + wall = 3, + arms = 3, + layer_height = 0.15) { thicker_thickness = (bearing_thickness > weight_thickness) ? bearing_thickness : weight_thickness; calculated_height = thicker_thickness + 2 * wall; @@ -109,18 +246,170 @@ module spin(weight_radius, actual_height = layers * layer_height; round_radius = actual_height / 2; - mirrored([0, 0, 1]) { - for(layer = [0 : (layers / 2) - 1]) { - translate([0, 0, layer * layer_height - actual_height / 2]) { - linear_extrude(height = layer_height) { - adjacent = round_radius - (layer * layer_height); - angle = acos(adjacent / round_radius); - round_extra = adjacent * tan(angle); - spin_footprint(weight_radius, - bearing_radius, - round_extra, - wall, - arms); } } } } } + /* rounding the outside edge of the spinner with a semi-circle leads + to a shape that an overhang on the second layer several times the + thickness of a printed extrusion width. + + rather than using a full semi-circle, this code aims to use just the + portion in the middle, where the overhang is less severe */ + old_start = 0; + old_end = (layers / 2) - 1; + + /* add one to have some thickness all around weight holes + for first layer */ + new_start = old_end / 16 + 1; + new_end = old_end; + + old_range = old_end - old_start; + new_range = new_end - new_start; + + factor = new_range / old_range; + + /* initial adjacent is adjusted to (new start - 1) to allow some + thickness all around weight holes on first layer */ + initial_adjacent = round_radius - ((new_start - 1) * layer_height); + initial_angle = acos(initial_adjacent / round_radius); + initial_round_extra = initial_adjacent * tan(initial_angle); + + difference() { + mirrored([0, 0, 1]) { + for(layer = [0 : (layers / 2) - 1]) { + translate([0, 0, layer * layer_height - actual_height / 2]) { + linear_extrude(height = layer_height) { + new_layer = (layer - old_start) * factor + new_start; + adjacent = round_radius - (new_layer * layer_height); + angle = acos(adjacent / round_radius); + round_extra = adjacent * tan(angle) - initial_round_extra; + spin_slice(weight_radius, + bearing_radius, + round_extra, + wall, + arms); } } } } + cylinder(h = actual_height + 0.1, + r = bearing_radius - bearing_lip_overhang, + center = true); + cylinder(h = bearing_thickness + 0.05, + r = bearing_radius + 0.15, + center = true); + for(arm = [0 : arms - 1]) { + rotate(arm * (360 / arms)) { + translate([bearing_radius + wall + weight_radius, 0]) { + cylinder(h = actual_height + 0.1, + r = weight_radius - weight_lip_overhang, + center = true); + cylinder(h = weight_thickness + 0.05, + r = weight_radius + 0.15, + center = true); } } } } } + +module equilateral_triangle(radius){ + polygon([[cos(0) * radius, sin(0) * radius], + [cos(120) * radius, + sin(120) * radius], + [cos(240) * radius, + sin(240) * radius]]); } + +module spin_cosine(weight_radius, + weight_thickness, + bearing_radius, + bearing_thickness, + weight_lip_overhang = 0.3, + bearing_lip_overhang = 0.3, + wall = 3, + arms = 3, + layer_height = 0.15) { + thicker_thickness = (bearing_thickness > weight_thickness) ? + bearing_thickness : weight_thickness; + calculated_height = thicker_thickness + 2 * wall; + layers = 2 * ceil(ceil(calculated_height / layer_height) / 2); + actual_height = layers * layer_height; + round_radius = actual_height / 2; + + /* rounding the outside edge of the spinner with a semi-circle leads + to a shape that an overhang on the second layer several times the + thickness of a printed extrusion width. + + rather than using a full semi-circle, this code aims to use just the + portion in the middle, where the overhang is less severe */ + old_start = 0; + old_end = (layers / 2) - 1; + + /* add one to have some thickness all around weight holes + for first layer */ + new_start = old_end / 16 + 1; + new_end = old_end; + + old_range = old_end - old_start; + new_range = new_end - new_start; + + factor = new_range / old_range; + + /* initial adjacent is adjusted to (new start - 1) to allow some + thickness all around weight holes on first layer */ + initial_adjacent = round_radius - ((new_start - 1) * layer_height); + initial_angle = acos(initial_adjacent / round_radius); + initial_round_extra = initial_adjacent * tan(initial_angle); + + difference() { + mirrored([0, 0, 1]) { + for(layer = [0 : (layers / 2) - 1]) { + translate([0, 0, layer * layer_height - actual_height / 2]) { + linear_extrude(height = layer_height) { + new_layer = (layer - old_start) * factor + new_start; + adjacent = round_radius - (new_layer * layer_height); + angle = acos(adjacent / round_radius); + round_extra = adjacent * tan(angle) - initial_round_extra; + spin_cosine_slice(weight_radius, + bearing_radius, + round_extra, + wall, + arms); } } } } + // bearing window hole + /*cylinder(h = actual_height + 0.1, + r = bearing_radius - bearing_lip_overhang, + center = true);*/ + linear_extrude(height = actual_height + 0.1, center = true) { + intersection() { + equilateral_triangle(1.8 * bearing_radius); + circle(bearing_radius + 0.1); } } + // bearing cavity + cylinder(h = bearing_thickness + 0.05, + r = bearing_radius + 0.15, + center = true); + // arm holes + for(arm = [0 : arms - 1]) { + rotate(arm * (360 / arms)) { + translate([bearing_radius + wall + weight_radius, 0]) { + // weight window hole + mirrored([0, 0, 1]) { + translate([0, 0, (weight_thickness + 0.05) / 2]) { + linear_extrude(height = wall + 0.1) { + intersection(){ + equilateral_triangle(1.8 * weight_radius); + circle(weight_radius + 0.2); } } } } + // weight cavity + cylinder(h = weight_thickness + 0.05, + r = weight_radius + 0.20, + center = true); } } } } } + +module spin_donut(weight_radius, + weight_thickness, + bearing_radius, + bearing_thickness, + weight_lip_overhang, + bearing_lip_overhang, + wall, + arms) { + thicker_thickness = (bearing_thickness > weight_thickness) + ? bearing_thickness : weight_thickness; + height = thicker_thickness + wall * 2; + + center_to_arm_center = bearing_radius + wall + weight_radius; + + jelly_filled(height, bearing_radius); + for(arm = [0 : arms]) { + rotate(arm * (360 / arms)) { + translate([center_to_arm_center, 0, 0]) { + jelly_filled(height, weight_radius); } } } } /* This file is part of 3d-printables.