Added npt_threaded_rod()

This commit is contained in:
Garth Minette 2021-01-31 21:08:03 -08:00
parent 2a51cf271d
commit 0dc5b9c7f2
2 changed files with 158 additions and 53 deletions

View file

@ -48,7 +48,7 @@ module thread_helix(
d, pitch=2, thread_depth, thread_angle=15, twist=720, d, pitch=2, thread_depth, thread_angle=15, twist=720,
profile, left_handed=false, internal=false, profile, left_handed=false, internal=false,
d1, d2, higbee, higbee1, higbee2, d1, d2, higbee, higbee1, higbee2,
anchor=CENTER, spin=0, orient=UP anchor, spin, orient
) { ) {
h = pitch*twist/360; h = pitch*twist/360;
r1 = get_radius(d1=d1, d=d, dflt=10); r1 = get_radius(d1=d1, d=d, dflt=10);
@ -88,17 +88,24 @@ module thread_helix(
// For ACME threads, use thread_angle=14.5 and thread_depth=pitch/2. // For ACME threads, use thread_angle=14.5 and thread_depth=pitch/2.
// For square threads, use thread_angle=0 and thread_depth=pitch/2. // For square threads, use thread_angle=0 and thread_depth=pitch/2.
// For normal UTS or ISO screw threads, use the `threaded_rod()` module instead to get the correct thread profile. // For normal UTS or ISO screw threads, use the `threaded_rod()` module instead to get the correct thread profile.
// For NPT (National Pipe Threading) threads, use the `npt_threaded_rod() module instead.
// Arguments: // Arguments:
// d = Outer diameter of threaded rod. // d = Outer diameter of threaded rod.
// l = Length of threaded rod. // l = Length of threaded rod.
// pitch = Length between threads. // pitch = Length between threads.
// thread_depth = Depth of the threads. Default=pitch/2
// thread_angle = The pressure angle profile angle of the threads. Default = 14.5 degree ACME profile. // thread_angle = The pressure angle profile angle of the threads. Default = 14.5 degree ACME profile.
// ---
// thread_depth = Depth of the threads. Default=pitch/2
// left_handed = If true, create left-handed threads. Default = false // left_handed = If true, create left-handed threads. Default = false
// bevel = if true, bevel the thread ends. Default: true // bevel = if true, bevel the thread ends. Default: true
// starts = The number of lead starts. Default = 1 // starts = The number of lead starts. Default = 1
// internal = If true, make this a mask for making internal threads.
// profile = The shape of a thread, if not a symmetric trapezoidal form. Given as a 2D path, where X is between -1/2 and 1/2, representing the pitch distance, and Y is 0 for the peak, and `-depth/pitch` for the valleys. The segment between the end of one thread profile and the start of the next is automatic, so the start and end coordinates should not both be at the same Y at X = ±1/2. This path is scaled up by the pitch size in both dimensions when making the final threading. This overrides the `thread_angle` and `thread_depth` options. // profile = The shape of a thread, if not a symmetric trapezoidal form. Given as a 2D path, where X is between -1/2 and 1/2, representing the pitch distance, and Y is 0 for the peak, and `-depth/pitch` for the valleys. The segment between the end of one thread profile and the start of the next is automatic, so the start and end coordinates should not both be at the same Y at X = ±1/2. This path is scaled up by the pitch size in both dimensions when making the final threading. This overrides the `thread_angle` and `thread_depth` options.
// internal = If true, make this a mask for making internal threads.
// d1 = Bottom outside diameter of threads.
// d2 = Top outside diameter of threads.
// higbee = Length to taper thread ends over. Default: 0
// higbee1 = Length to taper bottom thread end over.
// higbee2 = Length to taper top thread end over.
// center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`. // center = If given, overrides `anchor`. A true value sets `anchor=CENTER`, false sets `anchor=UP`.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
@ -132,9 +139,7 @@ module thread_helix(
// ]; // ];
// stroke(profile, width=0.02); // stroke(profile, width=0.02);
module trapezoidal_threaded_rod( module trapezoidal_threaded_rod(
d=10, d, l=100, pitch=2,
l=100,
pitch=2,
thread_angle=15, thread_angle=15,
thread_depth=undef, thread_depth=undef,
left_handed=false, left_handed=false,
@ -142,18 +147,42 @@ module trapezoidal_threaded_rod(
starts=1, starts=1,
profile, profile,
internal=false, internal=false,
center, anchor, spin=0, orient=UP d1, d2,
higbee=0, higbee1, higbee2,
center, anchor, spin, orient
) { ) {
function _thread_pt(thread, threads, start, starts, astep, asteps, part, parts) = function _thread_pt(thread, threads, start, starts, astep, asteps, part, parts) =
astep + asteps * (thread + threads * (part + parts * start)); astep + asteps * (thread + threads * (part + parts * start));
d = internal? (d/cos(180/segs(d/2)) + $slop*3) : d; _r1 = get_radius(d1=d1, d=d, dflt=10);
astep = 360 / quantup(segs(d/2), starts); _r2 = get_radius(d1=d2, d=d, dflt=10);
sides = segs(max(_r1,_r2));
rsc = internal? (1/cos(180/sides) + $slop*3) : 1;
astep = 360 / quantup(sides, starts);
asteps = ceil(360/astep); asteps = ceil(360/astep);
threads = ceil(l/pitch/starts)+(starts<4?4-starts:1); threads = ceil(l/pitch/starts)+(starts<4?4-starts:1);
depth = min((thread_depth==undef? pitch/2 : thread_depth), pitch/2/tan(thread_angle)); depth = min((thread_depth==undef? pitch/2 : thread_depth), pitch/2/tan(thread_angle));
pa_delta = min(pitch/4-0.01,depth*tan(thread_angle)/2)/pitch; pa_delta = min(pitch/4-0.01,depth*tan(thread_angle)/2)/pitch;
dir = left_handed? -1 : 1; dir = left_handed? -1 : 1;
twist = 360 * l / pitch / starts;
higbee1 = first_defined([higbee1, higbee, 0]);
higbee2 = first_defined([higbee2, higbee, 0]);
higang1 = 360 * higbee1 / (2 * _r1 * PI);
higang2 = 360 * higbee2 / (2 * _r2 * PI);
higsteps1 = ceil(higang1/360*sides);
higsteps2 = ceil(higang2/360*sides);
assert(higang1 < twist/2);
assert(higang2 < twist/2);
higbee_table = [
[-twist, 0],
[-twist/2-0.001, 0],
[-twist/2+higang1, 1],
[ twist/2-higang2, 1],
[ twist/2+0.001, 0],
[ twist, 0]
];
r1 = -depth/pitch; r1 = -depth/pitch;
z1 = 1/4-pa_delta; z1 = 1/4-pa_delta;
z2 = 1/4+pa_delta; z2 = 1/4+pa_delta;
@ -172,13 +201,17 @@ module trapezoidal_threaded_rod(
thread = [0:1:threads-1], thread = [0:1:threads-1],
astep = [0:1:asteps-1] astep = [0:1:asteps-1]
) let ( ) let (
a = astep / asteps,
z = (thread + a - threads/2) * starts * pitch,
u = z / l,
higsc = higbee1==0 && higbee2==0? 1 :
let ( tot_ang = (thread+a-threads/2) * 360 )
lookup(tot_ang, higbee_table),
ppt = profile[part] * pitch, ppt = profile[part] * pitch,
dz = ppt.x, dz = ppt.x,
r = ppt.y + d/2, r = lerp(_r1, _r2, u) - depth + higsc*(ppt.y+depth),
a = astep / asteps,
c = cos(360 * (a * dir + start/starts)), c = cos(360 * (a * dir + start/starts)),
s = sin(360 * (a * dir + start/starts)), s = sin(360 * (a * dir + start/starts))
z = (thread + a - threads/2) * starts * pitch
) [r*c, r*s, z+dz] ) [r*c, r*s, z+dz]
], ],
[[0, 0, -threads*pitch*starts/2-pitch/4], [0, 0, threads*pitch*starts/2+pitch/4]] [[0, 0, -threads*pitch*starts/2-pitch/4], [0, 0, threads*pitch*starts/2+pitch/4]]
@ -280,11 +313,11 @@ module trapezoidal_threaded_rod(
] ]
); );
anchor = get_anchor(anchor, center, BOT, CENTER); anchor = get_anchor(anchor, center, BOT, CENTER);
attachable(anchor,spin,orient, d=d, l=l) { attachable(anchor,spin,orient, r1=_r1, r2=_r2, l=l) {
difference() { difference() {
polyhedron(points=poly_points, faces=poly_faces, convexity=threads*starts*2); polyhedron(points=poly_points, faces=poly_faces, convexity=threads*starts*2);
zcopies(l+4*pitch*starts) cube([d+1, d+1, 4*pitch*starts], center=true); zcopies(l+4*pitch*starts) cylinder(h=4*pitch*starts, r=2*max(_r1,_r2)+1, center=true);
if (bevel) cylinder_mask(d=d, l=l+0.01, chamfer=depth); if (bevel) cylinder_mask(r1=_r1, r2=_r2, l=l+0.01, chamfer=depth);
} }
children(); children();
} }
@ -330,9 +363,7 @@ module trapezoidal_threaded_nut(
left_handed=false, left_handed=false,
starts=1, starts=1,
bevel=true, bevel=true,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
depth = min((thread_depth==undef? pitch/2 : thread_depth), pitch/2/tan(thread_angle)); depth = min((thread_depth==undef? pitch/2 : thread_depth), pitch/2/tan(thread_angle));
attachable(anchor,spin,orient, size=[od/cos(30),od,h]) { attachable(anchor,spin,orient, size=[od/cos(30),od,h]) {
@ -375,6 +406,11 @@ module trapezoidal_threaded_nut(
// left_handed = if true, create left-handed threads. Default = false // left_handed = if true, create left-handed threads. Default = false
// bevel = if true, bevel the thread ends. Default: false // bevel = if true, bevel the thread ends. Default: false
// internal = If true, make this a mask for making internal threads. // internal = If true, make this a mask for making internal threads.
// d1 = Bottom outside diameter of threads.
// d2 = Top outside diameter of threads.
// higbee = Length to taper thread ends over. Default: 0
// higbee1 = Length to taper bottom thread end over.
// higbee2 = Length to taper top thread end over.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER` // anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0` // spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP` // orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
@ -386,14 +422,16 @@ module trapezoidal_threaded_nut(
// threaded_rod(d=10, l=20, pitch=1.25, left_handed=true, $fa=1, $fs=1); // threaded_rod(d=10, l=20, pitch=1.25, left_handed=true, $fa=1, $fs=1);
// threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1); // threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1);
module threaded_rod( module threaded_rod(
d=10, l=100, pitch=2, d, l=100, pitch=2,
left_handed=false, left_handed=false,
bevel=false, bevel=false,
internal=false, internal=false,
anchor=CENTER, d1, d2,
spin=0, higbee, higbee1, higbee2,
orient=UP anchor, spin, orient
) { ) {
_r1 = get_radius(d1=d1, d=d, dflt=10);
_r2 = get_radius(d1=d2, d=d, dflt=10);
depth = pitch * cos(30) * 5/8; depth = pitch * cos(30) * 5/8;
profile = internal? [ profile = internal? [
[-6/16, -depth/pitch], [-6/16, -depth/pitch],
@ -411,13 +449,17 @@ module threaded_rod(
[ 7/16, -depth/pitch*1.07] [ 7/16, -depth/pitch*1.07]
]; ];
trapezoidal_threaded_rod( trapezoidal_threaded_rod(
d=d, l=l, pitch=pitch, d=d, d1=d1, d2=d2, l=l,
pitch=pitch,
thread_depth=depth, thread_depth=depth,
thread_angle=30, thread_angle=30,
profile=profile, profile=profile,
left_handed=left_handed, left_handed=left_handed,
bevel=bevel, bevel=bevel,
internal=internal, internal=internal,
higbee=higbee,
higbee1=higbee1,
higbee2=higbee2,
anchor=anchor, anchor=anchor,
spin=spin, spin=spin,
orient=orient orient=orient
@ -446,7 +488,7 @@ module threaded_rod(
module threaded_nut( module threaded_nut(
od=16, id=10, h=10, od=16, id=10, h=10,
pitch=2, left_handed=false, bevel=false, pitch=2, left_handed=false, bevel=false,
anchor=CENTER, spin=0, orient=UP anchor, spin, orient
) { ) {
depth = pitch * cos(30) * 5/8; depth = pitch * cos(30) * 5/8;
profile = [ profile = [
@ -469,6 +511,87 @@ module threaded_nut(
} }
// Section: Pipe Threading
// Module: npt_threaded_rod()
// Description:
// Constructs a standard NPT pipe threading.
// Arguments:
// d = Outer diameter of threaded rod.
// left_handed = if true, create left-handed threads. Default = false
// bevel = if true, bevel the thread ends. Default: false
// internal = If true, make this a mask for making internal threads.
// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#anchor). Default: `CENTER`
// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#spin). Default: `0`
// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#orient). Default: `UP`
// $slop = The printer-specific slop value to make parts fit just right.
// Example(2D):
// projection(cut=true) npt_threaded_rod(size=1/4, orient=BACK);
// Examples(Med):
// npt_threaded_rod(size=3/8, $fn=72);
// npt_threaded_rod(size=1/2, $fn=72);
// npt_threaded_rod(size=1/2, left_handed=true, $fn=72);
module npt_threaded_rod(
size=1/2,
left_handed=false,
bevel=false,
internal=false,
anchor, spin, orient
) {
info_table = [
// Size OD len TPI
[ 1/16, [ 0.3896, 0.308, 27 ]],
[ 1/8, [ 0.3924, 0.401, 27 ]],
[ 1/4, [ 0.5946, 0.533, 18 ]],
[ 3/8, [ 0.6006, 0.668, 18 ]],
[ 1/2, [ 0.7815, 0.832, 14 ]],
[ 3/4, [ 0.7935, 1.043, 14 ]],
[ 1, [ 0.9845, 1.305, 11.5]],
[ 1+1/4, [ 1.0085, 1.649, 11.5]],
[ 1+1/2, [ 1.0252, 1.888, 11.5]],
[ 2, [ 1.0582, 2.362, 11.5]],
];
info = [for (data=info_table) if(approx(size,data[0])) data[1]][0];
dummy1 = assert(is_def(info), "Unsupported NPT size. Try one of 1/16, 1/8, 1/4, 3/8, 1/2, 3/4, 1, 1+1/4, 1+1/2, 2");
l = 25.4 * info[0];
d = 25.4 * info[1];
pitch = 25.4 / info[2];
r1 = get_radius(d=d, dflt=0.84 * 25.4 / 2);
r2 = r1 - l/32;
depth = pitch * cos(30) * 5/8;
profile = internal? [
[-6/16, -depth/pitch],
[-1/16, 0],
[-1/32, 0.02],
[ 1/32, 0.02],
[ 1/16, 0],
[ 6/16, -depth/pitch]
] : [
[-7/16, -depth/pitch*1.07],
[-6/16, -depth/pitch],
[-1/16, 0],
[ 1/16, 0],
[ 6/16, -depth/pitch],
[ 7/16, -depth/pitch*1.07]
];
trapezoidal_threaded_rod(
d1=2*r1, d2=2*r2, l=l,
pitch=pitch,
thread_depth=depth,
thread_angle=30,
profile=profile,
left_handed=left_handed,
bevel=bevel,
internal=internal,
higbee=r1*PI/2,
anchor=anchor,
spin=spin,
orient=orient
) children();
}
// Section: Buttress Threading // Section: Buttress Threading
// Module: buttress_threaded_rod() // Module: buttress_threaded_rod()
@ -497,9 +620,7 @@ module buttress_threaded_rod(
left_handed=false, left_handed=false,
bevel=false, bevel=false,
internal=false, internal=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
depth = pitch * 3/4; depth = pitch * 3/4;
profile = [ profile = [
@ -546,9 +667,7 @@ module buttress_threaded_nut(
od=16, id=10, h=10, od=16, id=10, h=10,
pitch=2, left_handed=false, pitch=2, left_handed=false,
bevel=false, bevel=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
depth = pitch * 3/4; depth = pitch * 3/4;
profile = [ profile = [
@ -600,9 +719,7 @@ module metric_trapezoidal_threaded_rod(
starts=1, starts=1,
bevel=false, bevel=false,
internal=false, internal=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
trapezoidal_threaded_rod( trapezoidal_threaded_rod(
d=d, l=l, d=d, l=l,
@ -644,9 +761,7 @@ module metric_trapezoidal_threaded_nut(
starts=1, starts=1,
left_handed=false, left_handed=false,
bevel=false, bevel=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
trapezoidal_threaded_nut( trapezoidal_threaded_nut(
od=od, id=id, h=h, od=od, id=id, h=h,
@ -695,9 +810,7 @@ module acme_threaded_rod(
left_handed=false, left_handed=false,
bevel=false, bevel=false,
internal=false, internal=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
trapezoidal_threaded_rod( trapezoidal_threaded_rod(
d=d, l=l, pitch=pitch, d=d, l=l, pitch=pitch,
@ -742,9 +855,7 @@ module acme_threaded_nut(
starts=1, starts=1,
left_handed=false, left_handed=false,
bevel=false, bevel=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
trapezoidal_threaded_nut( trapezoidal_threaded_nut(
od=od, id=id, h=h, pitch=pitch, od=od, id=id, h=h, pitch=pitch,
@ -789,9 +900,7 @@ module square_threaded_rod(
bevel=false, bevel=false,
starts=1, starts=1,
internal=false, internal=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
trapezoidal_threaded_rod( trapezoidal_threaded_rod(
d=d, l=l, pitch=pitch, d=d, l=l, pitch=pitch,
@ -832,9 +941,7 @@ module square_threaded_nut(
left_handed=false, left_handed=false,
bevel=false, bevel=false,
starts=1, starts=1,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
trapezoidal_threaded_nut( trapezoidal_threaded_nut(
od=od, id=id, h=h, pitch=pitch, od=od, id=id, h=h, pitch=pitch,
@ -884,9 +991,7 @@ module ball_screw_rod(
left_handed=false, left_handed=false,
internal=false, internal=false,
bevel=false, bevel=false,
anchor=CENTER, anchor, spin, orient
spin=0,
orient=UP
) { ) {
depth = ball_diam * (1-cos(ball_arc/2))/2; depth = ball_diam * (1-cos(ball_arc/2))/2;
profile = arc(N=11, d=ball_diam/pitch, cp=[0,ball_diam/2/pitch*cos(ball_arc/2)], start=270-ball_arc/2, angle=ball_arc); profile = arc(N=11, d=ball_diam/pitch, cp=[0,ball_diam/2/pitch*cos(ball_arc/2)], start=270-ball_arc/2, angle=ball_arc);

View file

@ -6,7 +6,7 @@
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
BOSL_VERSION = [2,0,553]; BOSL_VERSION = [2,0,554];
// Section: BOSL Library Version Functions // Section: BOSL Library Version Functions