BOSL2/metric_screws.scad

717 lines
19 KiB
OpenSCAD

//////////////////////////////////////////////////////////////////////
// LibFile: metric_screws.scad
// Screws, Bolts, and Nuts.
// To use, include the following lines at the top of your file:
// ```
// include <BOSL2/std.scad>
// include <BOSL2/threading.scad>
// include <BOSL2/phillips_drive.scad>
// include <BOSL2/torx_drive.scad>
// include <BOSL2/metric_screws.scad>
// ```
//////////////////////////////////////////////////////////////////////
/*
BSD 2-Clause License
Copyright (c) 2017-2019, 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.
*/
// Section: Functions
// Function: get_metric_bolt_head_size()
// Description: Returns the diameter of a typical metric bolt's head, based on the bolt `size`.
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()
// Description: Returns the height of a typical metric bolt's head, based on the bolt `size`.
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()
// Description: Returns the diameter of a typical metric socket cap bolt's head, based on the bolt `size`.
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],
[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()
// Description: Returns the height of a typical metric socket cap bolt's head, based on the bolt `size`.
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()
// Description: Returns the diameter of a typical metric socket cap bolt's hex drive socket, based on the bolt `size`.
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()
// Description: Returns the depth of a typical metric socket cap bolt's hex drive socket, based on the bolt `size`.
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()
// Description: Returns the ISO metric standard coarse threading pitch for a given bolt `size`.
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()
// Description: Returns the ISO metric standard fine threading pitch for a given bolt `size`.
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()
// Description: Returns the ISO metric standard superfine threading pitch for a given bolt `size`.
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()
// Description: Returns the JIS metric standard threading pitch for a given bolt `size`.
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]
]);
// Function: get_metric_nut_size()
// Description: Returns the typical metric nut flat-to-flat diameter for a given bolt `size`.
function get_metric_nut_size(size) = lookup(size, [
[ 2.0, 4.0],
[ 2.5, 5.0],
[ 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]
]);
// Function: get_metric_nut_thickness()
// Description: Returns the typical metric nut thickness for a given bolt `size`.
function get_metric_nut_thickness(size) = lookup(size, [
[ 1.6, 1.3],
[ 2.0, 1.6],
[ 2.5, 2.0],
[ 3.0, 2.4],
[ 4.0, 3.2],
[ 5.0, 4.0],
[ 6.0, 5.0],
[ 7.0, 5.5],
[ 8.0, 6.5],
[10.0, 8.0],
[12.0, 10.0],
[14.0, 11.0],
[16.0, 13.0],
[18.0, 15.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]
]);
// Section: Modules
// Module: screw()
// Description:
// Makes a very simple screw model, useful for making screwholes.
// Usage:
// screw(screwsize, screwlen, headsize, headlen, [countersunk], [orient], [align])
// Arguments:
// 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.
// orient = Orientation of the screw. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Z`.
// align = Alignment of the screw. Use the constants from `constants.scad` or `"sunken"`, or `"base"`. Default: `"base"`.
// Examples:
// screw(screwsize=3,screwlen=10,headsize=6,headlen=3,countersunk=true);
// screw(screwsize=3,screwlen=10,headsize=6,headlen=3, align="base");
module screw(
screwsize=3,
screwlen=10,
headsize=6,
headlen=3,
pitch=undef,
countersunk=false,
orient=ORIENT_Z,
align="base"
) {
sides = max(12, segs(screwsize/2));
algn = countersunk? DOWN : align;
alignments = [
["base", [0,0,-headlen/2+screwlen/2]],
["sunken", [0,0,(headlen+screwlen)/2-0.01]]
];
orient_and_align([headsize, headsize, headlen+screwlen], orient, algn, alignments=alignments, chain=true) {
down(headlen/2-screwlen/2) {
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);
}
children();
}
}
// Module: metric_bolt()
// Description:
// Makes a standard metric screw model.
// Arguments:
// 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. If 0, then no threads. 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")
// torx = If given, the size of the torx drive hole to add. (ie: 10, 20, 30, etc.)
// orient = Orientation of the bolt. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Z`.
// align = Alignment of the bolt. Use the constants from `constants.scad` or `"sunken"`, `"base"`, or `"shank"`. Default: `"base"`.
// Example: Bolt Head Types
// ydistribute(40) {
// xdistribute(30) {
// // Front Row, Left to Right
// metric_bolt(headtype="pan", size=10, l=15, details=true, phillips="#2");
// metric_bolt(headtype="button", size=10, l=15, details=true, phillips="#2");
// metric_bolt(headtype="round", size=10, l=15, details=true, phillips="#2");
// }
// xdistribute(30) {
// // Back Row, Left to Right
// metric_bolt(headtype="socket", size=10, l=15, details=true);
// metric_bolt(headtype="hex", size=10, l=15, details=true, phillips="#2");
// metric_bolt(headtype="countersunk", size=10, l=15, details=true, phillips="#2");
// metric_bolt(headtype="oval", size=10, l=15, details=true, phillips="#2");
// }
// }
// Example: Details
// metric_bolt(size=10, l=15, details=true, $fn=32);
// Example: No Details Except Threads
// metric_bolt(size=10, l=15);
// Example: No Details, No Threads
// metric_bolt(size=10, l=15, pitch=0);
// Example: Fine Threads
// metric_bolt(size=10, l=15, coarse=false);
// Example: Flange
// metric_bolt(size=10, l=15, flange=5);
// Example: Shank
// metric_bolt(size=10, l=25, shank=10);
// Example: Hex Head with Phillips
// metric_bolt(headtype="hex", size=10, l=15, phillips="#2");
// Example: Hex Head with Torx
// metric_bolt(headtype="hex", size=10, l=15, torx=50);
module metric_bolt(
headtype="socket",
size=3,
l=12,
shank=0,
pitch=undef,
details=false,
coarse=true,
phillips=undef,
torx=undef,
flange=0,
orient=ORIENT_Z,
align="base"
) {
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;
//algn = (headtype == "countersunk" || headtype == "oval")? (D-size)/2 : 0;
headlen = (
(headtype == "pan" || headtype == "round" || headtype == "button")? H*0.75 :
(headtype == "countersunk")? (D-size)/2 :
(headtype == "oval")? ((D-size)/2 + D/2/3) :
H
);
base = l/2 - headlen/2;
sunklen = (
(headtype == "oval")? (D-size)/2 :
headlen-0.001
);
alignments = [
["sunken", [0,0,base+sunklen]],
["base", [0,0,base]],
["shank", [0,0,base-shank]]
];
color("silver")
orient_and_align([D+flange, D+flange, headlen+l], orient, align, alignments=alignments, chain=true) {
up(base) {
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") {
cyl(l=H*0.75, d=D, fillet2=H*0.75/2, align=UP);
} 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) {
if (tlen > 0) {
if (P > 0) {
threaded_rod(d=size, l=tlen+0.05, pitch=P, $fn=sides);
} else {
cylinder(d=size, h=tlen+0.05, $fn=sides, center=true);
}
}
}
// 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);
}
}
// Torx drive hole
if (headtype != "socket" && torx != undef) {
up(1) torx_drive(size=torx, l=H+0.1, center=false);
}
}
}
children();
}
}
// Module: metric_nut()
// Description:
// Makes a model of a standard nut for a standard metric screw.
// Arguments:
// 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)
// orient = Orientation of the nut. Use the `ORIENT_` constants from `constants.scad`. Default: `ORIENT_Z`.
// align = Alignment of the nut. Use the constants from `constants.scad`. Default: `UP`.
// center = If true, centers the nut at the origin. If false, sits on top of XY plane. Overrides `align` if given.
// Example: No details, No Hole. Useful for a mask.
// metric_nut(size=10, hole=false);
// Example: Hole, with No Threads
// metric_nut(size=10, hole=true);
// Example: Threads
// metric_nut(size=10, hole=true, pitch=1.5);
// Example: Details
// metric_nut(size=10, hole=true, pitch=1.5, details=true);
// Example: Centered
// metric_nut(size=10, hole=true, pitch=1.5, details=true, center=true);
// Example: Flange
// metric_nut(size=10, hole=true, pitch=1.5, flange=3, details=true);
module metric_nut(
size=3,
hole=true,
pitch=undef,
details=false,
flange=0,
center=undef,
orient=ORIENT_Z,
align=UP
) {
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;
color("silver")
orient_and_align([dcirc+flange, dcirc+flange, H], orient, align, center, chain=true) {
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);
}
}
}
children();
}
}
// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap