| 1 | // Threads for acorn model |
| 2 | // Copyright (c) 2017 Clinton Ebadi <clinton@unknownlamer.org> |
| 3 | |
| 4 | use <screw_threads.scad> // http://www.thingiverse.com/thing:1686322 |
| 5 | |
| 6 | AUTO_CALCULATE = -1; |
| 7 | |
| 8 | acorn_parts = [ "body", "cap", "gasket" ]; |
| 9 | |
| 10 | internal_thread_tolerance = 0.3; |
| 11 | external_thread_tolerance = 0.2; |
| 12 | thread_angle = 50; |
| 13 | |
| 14 | |
| 15 | function contains (x, lst) = len([ for (i = lst) if (x == i) i]) > 0; |
| 16 | |
| 17 | // dome module from https://github.com/Sembiance/common/blob/master/openscad/dome.scad, Public Domain |
| 18 | module dome(d=5, h=2, hollow=false, wallWidth=0.5) { |
| 19 | sphereRadius = (pow(h, 2) + pow((d/2), 2) ) / (2*h); |
| 20 | translate([0, 0, (sphereRadius-h)*-1]) { |
| 21 | difference() { |
| 22 | sphere(sphereRadius); |
| 23 | translate([0, 0, -h]) cube([2*sphereRadius, 2*sphereRadius, 2*sphereRadius], center=true); |
| 24 | if(hollow) sphere(sphereRadius-wallWidth); |
| 25 | } |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | module acorn (thread_pitch = 3.0, |
| 30 | thread_size = 2.5, |
| 31 | thread_height = 3.5, |
| 32 | thread_tooth_height = AUTO_CALCULATE, |
| 33 | |
| 34 | inner_d = 24.5, |
| 35 | base_height = AUTO_CALCULATE, |
| 36 | wall_thickness = AUTO_CALCULATE, |
| 37 | outer_d = AUTO_CALCULATE, |
| 38 | dome_h = AUTO_CALCULATE, |
| 39 | |
| 40 | keychain = true) { |
| 41 | |
| 42 | // derived settings |
| 43 | wall_thickness = (wall_thickness == AUTO_CALCULATE) ? thread_size : wall_thickness; |
| 44 | outer_d = (outer_d == AUTO_CALCULATE) ? inner_d + wall_thickness*2 : outer_d; |
| 45 | thread_tooth_height = (thread_tooth_height == AUTO_CALCULATE) ? ((thread_pitch - 0.4 > 0) ? thread_pitch - 0.4 : thread_pitch) : thread_tooth_height; |
| 46 | base_height = (base_height == AUTO_CALCULATE) ? inner_d : base_height; |
| 47 | |
| 48 | echo ("outer_d = ", outer_d); |
| 49 | |
| 50 | |
| 51 | module acorn_thread (outer_d = outer_d, internal = false, ring = true) { |
| 52 | if (internal) { |
| 53 | outer_ring_d = outer_d+max(thread_size, wall_thickness)+1; |
| 54 | echo ("outer ring = ", outer_ring_d); |
| 55 | ScrewHole (outer_diam=outer_d, height = thread_height, pitch = thread_pitch, tooth_height = thread_tooth_height, tooth_angle = thread_angle, tolerance=internal_thread_tolerance) { |
| 56 | if (ring) cylinder (d = outer_ring_d, h = thread_height); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | if (!internal) { |
| 61 | difference () { |
| 62 | ScrewThread (outer_diam=outer_d, height = thread_height, pitch = thread_pitch, tooth_height = thread_tooth_height, tooth_angle = thread_angle, tolerance=external_thread_tolerance); |
| 63 | cylinder (d = outer_d-wall_thickness-thread_size-0.01, h = thread_height * 4, center=true); |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | module nut_body (h = base_height, d = outer_d, nub = false) { |
| 69 | translate ([0 ,0, h]) { |
| 70 | intersection () { |
| 71 | union () { |
| 72 | resize ([d, d, h*2]) sphere (d=h*2); |
| 73 | if (nub) { |
| 74 | translate ([0, d/2-wall_thickness/2, -thread_height]) sphere (d=wall_thickness*2, $fs = 0.1); |
| 75 | } |
| 76 | } |
| 77 | translate ([0 ,0, -h/2]) cube ([d*2, d*2, h], center=true); |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | module nut () { |
| 83 | difference () { |
| 84 | nut_body (); |
| 85 | translate ([0, 0, wall_thickness + 0.01]) nut_body (d=outer_d-wall_thickness*2, nub=false); |
| 86 | } |
| 87 | |
| 88 | translate ([0, 0, base_height-0.1]) acorn_thread (outer_d = outer_d); |
| 89 | } |
| 90 | |
| 91 | |
| 92 | module cap_keychain_holes (hole_d=3, spacing=12) { |
| 93 | h=100; |
| 94 | translate ([-spacing/2, 0, 0]) cylinder (d=hole_d, h=h, $fs=0.1); |
| 95 | translate ([spacing/2, 0, 0]) cylinder (d=hole_d, h=h, $fs=0.1); |
| 96 | } |
| 97 | |
| 98 | module cap (model="3D/RaleighAcorn_Filled_simple.stl", native_d = 168) { |
| 99 | scale_f = outer_d / native_d; //168; |
| 100 | echo ("scale_f = ", scale_f); |
| 101 | difference () { |
| 102 | scale ([scale_f, scale_f, scale_f]) { |
| 103 | difference () { |
| 104 | union () { |
| 105 | translate ([0, 0, -1]) import (model); |
| 106 | echo ("h = ", thread_height/scale_f); |
| 107 | } |
| 108 | // todo: only makes sense for RaleighAcorn, fix in original model... |
| 109 | translate ([0, 0, -0.51]) cube ([200, 200, 1], center=true); |
| 110 | } |
| 111 | } |
| 112 | if (keychain) cap_keychain_holes (); |
| 113 | |
| 114 | // hollow the cap out (make parametric later, this is pretty ugly now, but calc seems to be ok for RaleighAcorn) |
| 115 | diam_to_height_ratio = 3.2; |
| 116 | dome_h = (dome_h == AUTO_CALCULATE) ? outer_d / diam_to_height_ratio - thread_height : dome_h; |
| 117 | echo ("dome_h = ", dome_h); |
| 118 | difference () { |
| 119 | translate ([0, 0, thread_height-0.01]) dome (d=outer_d, h=dome_h); |
| 120 | } |
| 121 | |
| 122 | |
| 123 | translate ([0, 0, -0.01]) acorn_thread (internal = true, ring = false); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | module gasket (gasket_height=0.9) { |
| 128 | cylinder (d = outer_d, h = gasket_height, center=true); |
| 129 | } |
| 130 | |
| 131 | module nuts () { |
| 132 | if (contains ("body", acorn_parts)) |
| 133 | translate ([outer_d+10, 0, 0,]) nut (); |
| 134 | if (contains ("cap", acorn_parts)) |
| 135 | cap (native_d=167);//model="3D/RaleighAcorn_ExaggeratedCap_Decimated.stl", native_d = 178); |
| 136 | if (contains ("gasket", acorn_parts)) |
| 137 | translate ([-(outer_d+10), 0, 0,]) gasket (); |
| 138 | } |
| 139 | |
| 140 | nuts (); |
| 141 | } |
| 142 | |
| 143 | //$fs = 1; |
| 144 | //$fa = 1; |
| 145 | |
| 146 | acorn_parts = [ "cap"]; |
| 147 | |
| 148 | //acorn (); |
| 149 | huge_acorn (); |
| 150 | |
| 151 | module huge_acorn () { |
| 152 | acorn (inner_d=100, base_height=80, |
| 153 | thread_size=4, thread_pitch=4, thread_height=8, |
| 154 | keychain=false); |
| 155 | } |