From 907a41fd61912b151f4b7cadba6f12080d3330ff Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 19 Nov 2018 15:24:44 -0800 Subject: [PATCH] Added metric_bolt(). Improved metric_nut() detail. --- metric_screws.scad | 518 +++++++++++++++++++++++++++++++++++++++++--- phillips_drive.scad | 93 ++++++++ 2 files changed, 580 insertions(+), 31 deletions(-) create mode 100644 phillips_drive.scad diff --git a/metric_screws.scad b/metric_screws.scad index fd1e926..2fe8e3d 100644 --- a/metric_screws.scad +++ b/metric_screws.scad @@ -31,18 +31,280 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +use +use +use +use +use + + function get_metric_bolt_head_size(size) = lookup(size, [ + [ 3.0, 5.5], [ 4.0, 7.0], [ 5.0, 8.0], [ 6.0, 10.0], [ 7.0, 11.0], [ 8.0, 13.0], + [10.0, 17.0], + [12.0, 19.0], + [14.0, 22.0], + [16.0, 24.0], + [18.0, 27.0], + [20.0, 30.0], + [24.0, 36.0], + [30.0, 46.0], + [36.0, 55.0], + [42.0, 65.0], + [48.0, 75.0], + [56.0, 85.0], + [64.0, 95.0] + ]); + + +function get_metric_bolt_head_height(size) = lookup(size, [ + [ 1.6, 1.23], + [ 2.0, 1.53], + [ 2.5, 1.83], + [ 3.0, 2.13], + [ 4.0, 2.93], + [ 5.0, 3.65], + [ 6.0, 4.15], + [ 8.0, 5.45], + [10.0, 6.58], + [12.0, 7.68], + [14.0, 8.98], + [16.0, 10.18], + [20.0, 12.72], + [24.0, 15.35], + [30.0, 19.12], + [36.0, 22.92], + [42.0, 26.42], + [48.0, 30.42], + [56.0, 35.50], + [64.0, 40.50] + ]); + + +function get_metric_socket_cap_diam(size) = lookup(size, [ + [ 1.6, 3.0], + [ 2.0, 3.8], + [ 2.5, 4.5], + [ 3.0, 5.5], + [ 4.0, 7.0], + [ 5.0, 8.5], + [ 6.0, 10.0], + [ 8.0, 13.0], [10.0, 16.0], [12.0, 18.0], [14.0, 21.0], [16.0, 24.0], [18.0, 27.0], - [20.0, 30.0] + [20.0, 30.0], + [22.0, 33.0], + [24.0, 36.0], + [27.0, 40.0], + [30.0, 45.0], + [33.0, 50.0], + [36.0, 54.0], + [42.0, 63.0], + [48.0, 72.0], + [56.0, 84.0], + [64.0, 96.0] + ]); + + +function get_metric_socket_cap_height(size) = lookup(size, [ + [ 1.6, 1.7], + [ 2.0, 2.0], + [ 2.5, 2.5], + [ 3.0, 3.0], + [ 4.0, 4.0], + [ 5.0, 5.0], + [ 6.0, 6.0], + [ 8.0, 8.0], + [10.0, 10.0], + [12.0, 12.0], + [14.0, 14.0], + [16.0, 16.0], + [18.0, 18.0], + [20.0, 20.0], + [22.0, 22.0], + [24.0, 24.0], + [27.0, 27.0], + [30.0, 30.0], + [33.0, 33.0], + [36.0, 36.0], + [42.0, 42.0], + [48.0, 48.0], + [56.0, 56.0], + [64.0, 64.0] + ]); + + +function get_metric_socket_cap_socket_size(size) = lookup(size, [ + [ 1.6, 1.5], + [ 2.0, 1.5], + [ 2.5, 2.0], + [ 3.0, 2.5], + [ 4.0, 3.0], + [ 5.0, 4.0], + [ 6.0, 5.0], + [ 8.0, 6.0], + [10.0, 8.0], + [12.0, 10.0], + [14.0, 12.0], + [16.0, 14.0], + [18.0, 14.0], + [20.0, 17.0], + [22.0, 17.0], + [24.0, 19.0], + [27.0, 19.0], + [30.0, 22.0], + [33.0, 24.0], + [36.0, 27.0], + [42.0, 32.0], + [48.0, 36.0], + [56.0, 41.0], + [64.0, 46.0] + ]); + + +function get_metric_socket_cap_socket_depth(size) = lookup(size, [ + [ 1.6, 0.7], + [ 2.0, 1.0], + [ 2.5, 1.1], + [ 3.0, 1.3], + [ 4.0, 2.0], + [ 5.0, 2.5], + [ 6.0, 3.0], + [ 8.0, 4.0], + [10.0, 5.0], + [12.0, 6.0], + [14.0, 7.0], + [16.0, 8.0], + [18.0, 9.0], + [20.0, 10.0], + [22.0, 11.0], + [24.0, 12.0], + [27.0, 13.5], + [30.0, 15.5], + [33.0, 18.0], + [36.0, 19.0], + [42.0, 24.0], + [48.0, 28.0], + [56.0, 34.0], + [64.0, 38.0] + ]); + + +function get_metric_iso_coarse_thread_pitch(size) = lookup(size, [ + [ 1.6, 0.35], + [ 2.0, 0.40], + [ 2.5, 0.45], + [ 3.0, 0.50], + [ 4.0, 0.70], + [ 5.0, 0.80], + [ 6.0, 1.00], + [ 7.0, 1.00], + [ 8.0, 1.25], + [10.0, 1.50], + [12.0, 1.75], + [14.0, 2.00], + [16.0, 2.00], + [18.0, 2.50], + [20.0, 2.50], + [22.0, 2.50], + [24.0, 3.00], + [27.0, 3.00], + [30.0, 3.50], + [33.0, 3.50], + [36.0, 4.00], + [39.0, 4.00], + [42.0, 4.50], + [45.0, 4.50], + [48.0, 5.00], + [56.0, 5.50], + [64.0, 6.00] + ]); + + +function get_metric_iso_fine_thread_pitch(size) = lookup(size, [ + [ 1.6, 0.35], + [ 2.0, 0.40], + [ 2.5, 0.45], + [ 3.0, 0.50], + [ 4.0, 0.70], + [ 5.0, 0.80], + [ 6.0, 1.00], + [ 7.0, 1.00], + [ 8.0, 1.00], + [10.0, 1.25], + [12.0, 1.50], + [14.0, 1.50], + [16.0, 2.00], + [18.0, 2.50], + [20.0, 2.50], + [22.0, 2.50], + [24.0, 3.00], + [27.0, 3.00], + [30.0, 3.50], + [33.0, 3.50], + [36.0, 4.00], + [39.0, 4.00], + [42.0, 4.50], + [45.0, 4.50], + [48.0, 5.00], + [56.0, 5.50], + [64.0, 6.00] + ]); + + +function get_metric_iso_superfine_thread_pitch(size) = lookup(size, [ + [ 1.6, 0.35], + [ 2.0, 0.40], + [ 2.5, 0.45], + [ 3.0, 0.50], + [ 4.0, 0.70], + [ 5.0, 0.80], + [ 6.0, 1.00], + [ 7.0, 1.00], + [ 8.0, 1.00], + [10.0, 1.00], + [12.0, 1.25], + [14.0, 1.50], + [16.0, 2.00], + [18.0, 2.50], + [20.0, 2.50], + [22.0, 2.50], + [24.0, 3.00], + [27.0, 3.00], + [30.0, 3.50], + [33.0, 3.50], + [36.0, 4.00], + [39.0, 4.00], + [42.0, 4.50], + [45.0, 4.50], + [48.0, 5.00], + [56.0, 5.50], + [64.0, 6.00] + ]); + + +function get_metric_jis_thread_pitch(size) = lookup(size, [ + [ 2.0, 0.40], + [ 2.5, 0.45], + [ 3.0, 0.50], + [ 4.0, 0.70], + [ 5.0, 0.80], + [ 6.0, 1.00], + [ 7.0, 1.00], + [ 8.0, 1.25], + [10.0, 1.25], + [12.0, 1.25], + [14.0, 1.50], + [16.0, 1.50], + [18.0, 1.50], + [20.0, 1.50] ]); @@ -60,11 +322,12 @@ function get_metric_nut_size(size) = lookup(size, [ [14.0, 22.0], [16.0, 24.0], [18.0, 27.0], - [20.0, 30.0], + [20.0, 30.0] ]); function get_metric_nut_thickness(size) = lookup(size, [ + [ 1.6, 1.3], [ 2.0, 1.6], [ 2.5, 2.0], [ 3.0, 2.4], @@ -78,46 +341,239 @@ function get_metric_nut_thickness(size) = lookup(size, [ [14.0, 11.0], [16.0, 13.0], [18.0, 15.0], - [20.0, 16.0] + [20.0, 16.0], + [24.0, 21.5], + [30.0, 25.6], + [36.0, 31.0], + [42.0, 34.0], + [48.0, 38.0], + [56.0, 45.0], + [64.0, 51.0] ]); -// Makes a simple threadless screw, useful for making screwholes. +// Makes a very simple screw model, useful for making screwholes. // screwsize = diameter of threaded part of screw. // screwlen = length of threaded part of screw. // headsize = diameter of the screw head. // headlen = length of the screw head. +// countersunk = If true, center from cap's top instead of it's bottom. // Example: -// screw(screwsize=3,screwlen=10,headsize=6,headlen=3); -module screw(screwsize=3,screwlen=10,headsize=6,headlen=3,$fn=undef) -{ - $fn = ($fn==undef)?max(8,floor(180/asin(2/screwsize)/2)*2):$fn; - translate([0,0,-(screwlen)/2]) - cylinder(r=screwsize/2, h=screwlen+0.05, center=true, $fn=$fn); - translate([0,0,(headlen)/2]) - cylinder(r=headsize/2, h=headlen, center=true, $fn=$fn*2); -} - - -// Makes an unthreaded model of a standard nut for a standard metric screw. -// size = standard metric screw size in mm. (Default: 3) -// hole = include an unthreaded hole in the nut. (Default: true) -// Example: -// metric_nut(size=8, hole=true); -// metric_nut(size=3, hole=false); -module metric_nut(size=3, hole=true, $fn=undef, center=false) -{ - $fn = ($fn==undef)?max(8,floor(180/asin(2/size)/2)*2):$fn; - radius = get_metric_nut_size(size)/2/cos(30); - thick = get_metric_nut_thickness(size); - offset = (center == true)? 0 : thick/2; - translate([0,0,offset]) difference() { - cylinder(r=radius, h=thick, center=true, $fn=6); - if (hole == true) - cylinder(r=size/2, h=thick+0.5, center=true, $fn=$fn); +// screw(screwsize=3,screwlen=10,headsize=6,headlen=3,countersunk=true); +module screw( + screwsize=3, + screwlen=10, + headsize=6, + headlen=3, + pitch=undef, + countersunk=false +) { + sides = max(12, segs(screwsize/2)); + down(countersunk? headlen-0.01 : 0) { + down(screwlen/2) { + if (pitch == undef) { + cylinder(r=screwsize/2, h=screwlen+0.05, center=true, $fn=sides); + } else { + threaded_rod(d=screwsize, l=screwlen+0.05, pitch=pitch, $fn=sides); + } + } + up(headlen/2) cylinder(r=headsize/2, h=headlen, center=true, $fn=sides*2); } } +// Makes a standard metric screw model. +// size = diameter of threaded part of screw. +// headtype = One of "hex", "pan", "button", "round", "countersunk", "oval", "socket". Default: "socket" +// l = length of screw, except for the head. +// shank = Length of unthreaded portion of the shaft. +// pitch = If given, render threads of the given pitch. Overrides coarse argument. +// details = If true model should be rendered with extra details. (Default: false) +// coarse = If true, make coarse threads instead of fine threads. Default = true +// flange = radius of flange beyond the head. Default = 0 (no flange) +// phillips = If given, the size of the phillips drive hole to add. (ie: "#1", "#2", or "#3") +// Examples: +// metric_bolt(headtype="pan", size=10, l=15, details=true, phillips="#2"); +// metric_bolt(headtype="countersunk", size=10, l=15, details=true, phillips="#2"); +// metric_bolt(headtype="socket", size=10, l=15, flange=4, coarse=false, shank=5, details=true); +// metric_bolt(headtype="hex", size=10, l=15, flange=4, coarse=false, shank=5, details=true, phillips="#2"); +module metric_bolt( + headtype="socket", + size=3, + l=12, + shank=0, + pitch=undef, + details=false, + coarse=true, + phillips=undef, + flange=0 +) { + D = headtype != "hex"? + get_metric_socket_cap_diam(size) : + get_metric_bolt_head_size(size); + H = headtype == "socket"? + get_metric_socket_cap_height(size) : + get_metric_bolt_head_height(size); + P = coarse? + (pitch==undef? get_metric_iso_coarse_thread_pitch(size) : pitch) : + (pitch==undef? get_metric_iso_fine_thread_pitch(size) : pitch); + tlen = l - min(l, shank); + sides = max(12, segs(size/2)); + tcirc = D/cos(30); + bevtop = (tcirc-D)/2; + bevbot = P/2; + + color("silver") + down(headtype == "countersunk" || headtype == "oval"? (D-size)/2 : 0) { + difference() { + union() { + // Head + if (headtype == "hex") { + difference() { + cylinder(d=tcirc, h=H, center=false, $fn=6); + + // Bevel hex nut top + if (details) { + up(H-bevtop) { + difference() { + upcube([tcirc+1, tcirc+1, bevtop+0.5]); + down(0.01) cylinder(d1=tcirc, d2=tcirc-bevtop*2, h=bevtop+0.02, center=false); + } + } + } + } + } else if (headtype == "socket") { + sockw = get_metric_socket_cap_socket_size(size); + sockd = get_metric_socket_cap_socket_depth(size); + difference() { + cylinder(d=D, h=H, center=false); + up(H-sockd) cylinder(h=sockd+0.1, d=sockw/cos(30), center=false, $fn=6); + if (details) { + kcnt = 36; + zring(n=kcnt, r=D/2) up(H/3) upcube([PI*D/kcnt/2, PI*D/kcnt/2, H]); + } + } + } else if (headtype == "pan") { + top_half() rcylinder(h=H*0.75*2, d=D, fillet=H/2, center=true); + } else if (headtype == "round") { + top_half() zscale(H*0.75/D*2) sphere(d=D); + } else if (headtype == "button") { + up(H*0.75/3) top_half() zscale(H*0.75*2/3/D*2) sphere(d=D); + cylinder(d=D, h=H*0.75/3+0.01, center=false); + } else if (headtype == "countersunk") { + cylinder(h=(D-size)/2, d1=size, d2=D, center=false); + } else if (headtype == "oval") { + up((D-size)/2) top_half() zscale(0.333) sphere(d=D); + cylinder(h=(D-size)/2, d1=size, d2=D, center=false); + } + + // Flange + if (flange>0) { + up(headtype == "countersunk" || headtype == "oval"? (D-size)/2 : 0) { + cylinder(d=D+flange, h=H/8, center=false); + up(H/8) cylinder(d1=D+flange, d2=D, h=H/8, center=false); + } + } + + // Unthreaded Shank + if (tlen < l) { + down(l-tlen) cylinder(d=size, h=l-tlen+0.05, center=false, $fn=sides); + } + + // Threads + down(l) { + difference() { + up(tlen/2+0.05) threaded_rod(d=size, l=tlen+0.05, pitch=P, $fn=sides); + + // Bevel bottom end of threads + if (details) { + difference() { + down(0.5) upcube([size+1, size+1, bevbot+0.5]); + cylinder(d1=size-bevbot*2, d2=size, h=bevbot+0.01, center=false); + } + } + } + } + } + + // Phillips drive hole + if (headtype != "socket" && phillips != undef) { + down(headtype != "hex"? H/6 : 0) { + phillips_drive(size=phillips, shaft=D); + } + } + } + } +} + + +// Makes a model of a standard nut for a standard metric screw. +// size = standard metric screw size in mm. (Default: 3) +// hole = include the hole in the nut. (Default: true) +// pitch = pitch of threads in the hole. No threads if not given. +// flange = radius of flange beyond the head. Default = 0 (no flange) +// details = true if model should be rendered with extra details. (Default: false) +// center = If true, center the nut at the origin, otherwise on top of the XY plane. Default = false. +// Example: +// metric_nut(size=6, hole=false); +// metric_nut(size=8, hole=true); +// metric_nut(size=6, hole=true, pitch=1, details=true, center=true); +// metric_nut(size=8, hole=true, pitch=1, details=true, flange=3, center=true); +module metric_nut( + size=3, + hole=true, + pitch=undef, + details=false, + flange=0, + center=false +) { + H = get_metric_nut_thickness(size); + D = get_metric_nut_size(size); + boltfn = max(12, segs(size/2)); + nutfn = max(12, segs(D/2)); + dcirc = D/cos(30); + bevtop = (dcirc - D)/2; + offset = (center == true)? 0 : H/2; + color("silver") + up(offset) { + difference() { + union() { + difference() { + cylinder(d=dcirc, h=H, center=true, $fn=6); + if (details) { + up(H/2-bevtop) { + difference() { + upcube([dcirc+1, dcirc+1, bevtop+0.5]); + down(0.01) cylinder(d1=dcirc, d2=dcirc-bevtop*2, h=bevtop+0.02, center=false, $fn=nutfn); + } + } + if (flange == 0) { + down(H/2) { + difference() { + down(0.5) upcube([dcirc+1, dcirc+1, bevtop+0.5]); + down(0.01) cylinder(d1=dcirc-bevtop*2, d2=dcirc, h=bevtop+0.02, center=false, $fn=nutfn); + } + } + } + } + } + if (flange>0) { + down(H/2) { + cylinder(d=D+flange, h=H/8, center=false); + up(H/8) cylinder(d1=D+flange, d2=D, h=H/8, center=false); + } + } + } + if (hole == true) { + if (pitch == undef) { + cylinder(r=size/2, h=H+0.5, center=true, $fn=boltfn); + } else { + threaded_rod(d=size, l=H+0.5, pitch=pitch, $fn=boltfn); + } + } + } + } +} + // vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap diff --git a/phillips_drive.scad b/phillips_drive.scad new file mode 100644 index 0000000..57ebbc9 --- /dev/null +++ b/phillips_drive.scad @@ -0,0 +1,93 @@ +////////////////////////////////////////////////////////////////////// +// Phillips driver bits +////////////////////////////////////////////////////////////////////// + +/* +BSD 2-Clause License + +Copyright (c) 2017, Revar Desmera +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +use +use + + +// Creates a model of a phillips driver bit of a given named size. +// size = The size of the bit. "#00", "#0", "#1", "#2", or "#3" +// shaft = The diameter of the drive bit's shaft. +// l = The length of the drive bit. +// Example: +// xdistribute(10) { +// phillips_drive(size="#1", shaft=4, l=30); +// phillips_drive(size="#2", shaft=6, l=30); +// phillips_drive(size="#3", shaft=6, l=30); +// } +module phillips_drive(size="#2", shaft=6, l=20) { + // These are my best guess reverse-engineered measurements of + // the tip diameters of various phillips screwdriver sizes. + ang = 11; + rads = [["#1", 1.25], ["#2", 1.77], ["#3", 2.65]]; + radidx = search([size], rads)[0]; + r = radidx == []? 0 : rads[radidx][1]; + h = (r/2)/tan(ang); + cr = r/2; + difference() { + intersection() { + union() { + clip = (shaft-1.2*r)/2/tan(26.5); + zrot(360/8/2) cylinder(h=clip, d1=1.2*r/cos(360/8/2), d2=shaft/cos(360/8/2), center=false, $fn=8); + up(clip-0.01) cylinder(h=l-clip, d=shaft, center=false, $fn=24); + } + cylinder(d=shaft, h=l, center=false, $fn=24); + } + zrot(45) + zring(n=4) { + yrot(ang) { + zrot(-45) { + off = (r/2-cr*(sqrt(2)-1))/sqrt(2); + translate([off, off, 0]) { + linear_extrude(height=l*2, convexity=4) { + difference() { + union() { + square([shaft, shaft], center=false); + back(cr) zrot(1.125) square([shaft, shaft], center=false); + right(cr) zrot(-1.125) square([shaft, shaft], center=false); + } + difference() { + square([cr*2, cr*2], center=true); + translate([cr,cr,0]) circle(r=cr, $fn=8); + } + } + } + } + } + } + } + } +} + + +// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap