From ce0b4e9d323dea11be48f6845dfa1b1afa7e5df7 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 22 Aug 2021 21:53:08 -0400 Subject: [PATCH] internal: can set bevel to true and get non-garbage result bevel is always set by thread depth acme takes tpi square threads are at angle 0 added generic_threaded_{rod,nut} eliminated metric_trapezoidal_* cleaned up matrices some in generic_threaded_rod threaded_rod can produce spec-true ISO/UTS profile with a triplet input for the diameter. Added bevel1 and bevel2 to all modules. Made default uniformly false for every case instead of sometimes true, sometimes false Profiles that go over zero are not clipped, and bevels are based on actual profile top, not nominal When bevel is given to nuts it bevels the outside of the nut by thread depth higbee looks best with quincunx, but it's more expensive. Select quincunx when higbee is used, min_edge otherwise Current code uses difference to remove excess length in the rod. This gives faster renders at the cost of more complex code and green top/bottom surfaces. Changed slop to 4 * $slop. I got good results printing with $slop=0.05 with this setting. Don't generate excess threads when starts>1, and don't force threads to be even --- paths.scad | 19 +- screws.scad | 50 +-- threading.scad | 1162 +++++++++++++++++++++++++++++------------------- vnf.scad | 2 +- 4 files changed, 734 insertions(+), 499 deletions(-) diff --git a/paths.scad b/paths.scad index 31f963e..8522a7a 100644 --- a/paths.scad +++ b/paths.scad @@ -1040,6 +1040,9 @@ module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) { // --- // d = Diameter of the spiral to extrude along. // higbee = Length to taper thread ends over. +// higbee1 = Taper length at start +// higbee2 = Taper length at end +// internal = direction to taper the threads with higbee. Default: false // 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` @@ -1047,7 +1050,11 @@ module extrude_from_to(pt1, pt2, convexity, twist, scale, slices) { // Example: // poly = [[-10,0], [-3,-5], [3,-5], [10,0], [0,-30]]; // spiral_sweep(poly, h=200, r=50, twist=1080, $fn=36); -module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, anchor, spin=0, orient=UP) { +module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, higbee1, higbee2, internal=false, anchor, spin=0, orient=UP) { + bounds = pointlist_bounds(poly); + yctr = (bounds[0].y+bounds[1].y)/2; + xmin = bounds[0].x; + xmax = bounds[1].x; poly = path3d(poly); anchor = get_anchor(anchor,center,BOT,BOT); r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=50); @@ -1062,7 +1069,6 @@ module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, hi higsteps2 = ceil(higang2/360*sides); assert(higang1 < twist/2); assert(higang2 < twist/2); - function higsize(a) = lookup(a,[ [-0.001, 0], for (x=[0.125:0.125:1]) [ x*higang1, pow(x,1/2)], @@ -1071,9 +1077,11 @@ module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, hi ]); us = [ - for (i=[0:higsteps1/10:higsteps1]) i, + 0, + for (i=[higsteps1/10:higsteps1/10:higsteps1]) i, for (i=[higsteps1+1:1:steps-higsteps2-1]) i, - for (i=[steps-higsteps2:higsteps2/10:steps]) i, + for (i=[steps-higsteps2:higsteps2/10:steps-higsteps2/10]) i, + steps ]; zang = atan2(r2-r1,h); points = [ @@ -1086,7 +1094,8 @@ module spiral_sweep(poly, h, r, twist=360, higbee, center, r1, r2, d, d1, d2, hi affine3d_translate([r, 0, h * (u-0.5)]) * affine3d_xrot(90) * affine3d_skew_xz(xa=zang) * - affine3d_scale([hsc,lerp(hsc,1,0.25),1]), + //affine3d_scale([hsc,lerp(hsc,1,0.25),1]), + scale([hsc,lerp(hsc,1,0.25),1], cp=[internal ? xmax : xmin, yctr, 0]), pts = apply(mat, poly) ) pts ]; diff --git a/screws.scad b/screws.scad index b66674d..2da1ee3 100644 --- a/screws.scad +++ b/screws.scad @@ -1243,38 +1243,30 @@ function thread_specification(screw_spec, internal=false, tolerance=undef) = function _thread_profile(thread) = let( pitch = struct_val(thread,"pitch"), - basicrad = struct_val(thread,"basic")/2, meanpitchrad = mean(struct_val(thread,"d_pitch"))/2, meanminorrad = mean(struct_val(thread,"d_minor"))/2, meanmajorrad = mean(struct_val(thread,"d_major"))/2, - depth = (meanmajorrad-meanminorrad)/pitch, - crestwidth = (pitch/2 - 2*(meanmajorrad-meanpitchrad)/sqrt(3))/pitch - + depth = meanmajorrad-meanminorrad, + crestwidth = pitch/2 - 2*(meanmajorrad-meanpitchrad)/sqrt(3) ) + [ + [-depth/sqrt(3)-crestwidth/2, -depth], + [ -crestwidth/2, 0], + [ crestwidth/2, 0], + [ depth/sqrt(3)+crestwidth/2, -depth] + ]/pitch; + + +/* Old non-centered profile + [ [-1/2,-depth], [depth/sqrt(3)-1/2,0], [depth/sqrt(3)+crestwidth-1/2, 0], [crestwidth + 2*depth/sqrt(3)-1/2,-depth] - ]; - -function _thread_profile_e(thread) = - let( - pitch = struct_val(thread,"pitch"), - basicrad = struct_val(thread,"basic")/2, - meanpitchrad = mean(struct_val(thread,"d_pitch"))/2, - meanminorrad = mean(struct_val(thread,"d_minor"))/2, - meanmajorrad = mean(struct_val(thread,"d_major"))/2, - depth = (meanmajorrad-meanminorrad)/pitch, - crestwidth = (pitch/2 - 2*(meanmajorrad-meanpitchrad)/sqrt(3))/pitch - - ) - [ - [-1/2,-1], // -1 instead of -depth? - [depth/sqrt(3)-1/2,0], - [depth/sqrt(3)+crestwidth-1/2, 0], - [crestwidth + 2*depth/sqrt(3)-1/2,-1] - ]; + ] + ; +*/ module _rod(spec, length, tolerance, orient=UP, spin=0, anchor=CENTER) @@ -1283,11 +1275,19 @@ module _rod(spec, length, tolerance, orient=UP, spin=0, anchor=CENTER) echo(d_major_mean = mean(struct_val(threadspec, "d_major"))); echo(bolt_profile=_thread_profile(threadspec)); - trapezoidal_threaded_rod( d=mean(struct_val(threadspec, "d_major")), + threaded_rod([mean(struct_val(threadspec, "d_minor")), + mean(struct_val(threadspec, "d_pitch")), + mean(struct_val(threadspec, "d_major"))], + pitch = struct_val(threadspec, "pitch"), + l=length, left_handed=false, + bevel=false, orient=orient, anchor=anchor, spin=spin); + /* + generic_threaded_rod( d=mean(struct_val(threadspec, "d_major")), l=length, pitch = struct_val(threadspec, "pitch"), profile = _thread_profile(threadspec),left_handed=false, bevel=false, orient=orient, anchor=anchor, spin=spin); + */ } @@ -1352,7 +1352,7 @@ module nut(name, diameter, thickness, thread="coarse", oversize=0, spec, toleran threadspec = thread_specification(spec, internal=true, tolerance=tolerance); echo(threadspec=threadspec,"for nut threads"); echo(nut_minor_diam = mean(struct_val(threadspec,"d_minor"))); - trapezoidal_threaded_nut( + generic_threaded_nut( od=diameter, id=mean(struct_val(threadspec, "d_major")), h=thickness, pitch=struct_val(threadspec, "pitch"), profile=_thread_profile(threadspec), diff --git a/threading.scad b/threading.scad index bccf180..4f9fee9 100644 --- a/threading.scad +++ b/threading.scad @@ -9,6 +9,283 @@ // Section: Generic Threading +// Module: generic_threaded_rod() +// Description: +// Constructs a generic threaded rod using an arbitrary thread profile that you supply. The rod can be tapered (e.g. for pipe threads). +// For specific thread types use other modules that supply the appropriate profile. +// . +// You give the profile as a 2D path that will be scaled by the pitch to produce the final thread shape. The profile X values +// must be between -1/2 and 1/2. The Y value is 0 at the peak and, due to scaling by the pitch, `-depth/pitch` in the valleys. The segment between the end +// of one thread and the start of the next is added automatically, so you should not have the path start and end at equivalent points (X = ±1/2 with the same Y value). +// Generally you should center the profile horizontally in the interval [-1/2, 1/2]. +// . +// If internal is true then produce a thread mask to difference from an object. +// When internal is true the rod diameter is enlarged to correct for the polygonal nature of circles to ensure that the internal diameter is the specified size. +// The diameter is also increased by `4 * $slop` to create clearance for threading by allowing a `2 * $slop` gap on each side. +// If bevel is set to true and internal is false then the ends of the rod will be beveled. When bevel is true and internal is true the ends of the rod will +// be filled in so that the rod mask will create a bevel when subtracted from an object. The bevel is at 45 deg and is the depth of the threads. +// . +// Higbee specifies tapering of the thread ends to make screws easier to start. Specify the number of degrees for the taper. Higbee +// only works for external threads. It is ignored if internal is true. +// Arguments: +// d = Outer diameter of threaded rod. +// l = Length of threaded rod. +// pitch = Thread spacing. +// profile = A 2D path giving the shape of a thread +// --- +// left_handed = If true, create left-handed threads. Default: false +// bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. +// starts = The number of lead starts. Default: 1 +// internal = If true, make this a mask for making internal threads. Default: false +// d1 = Bottom outside diameter of threads. +// d2 = Top outside diameter of threads. +// higbee = Angle to taper thread ends over. Default: 0 (No higbee thread tapering) +// higbee1 = Angle to taper bottom thread end over. +// higbee2 = Angle to taper top thread end over. +// 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` +// 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, which adds clearance (`4*$slop`) to internal threads. +// Example(2DMed): Example Tooth Profile +// pitch = 2; +// depth = pitch * cos(30) * 5/8; +// profile = [ +// [-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] +// ]; +// stroke(profile, width=0.02); +// Example: +// pitch = 2; +// depth = pitch * cos(30) * 5/8; +// profile = [ +// [-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] +// ]; +// generic_threaded_rod(d=10, l=40, pitch=2, profile=profile); +module generic_threaded_rod( + d, l, pitch, profile, + left_handed=false, + bevel, + bevel1, bevel2, + starts=1, + internal=false, + d1, d2, + higbee, higbee1, higbee2, + center, anchor, spin, orient +) { + dummy0 = + assert(all_positive(pitch)) + assert(all_positive(l)) + assert(is_path(profile)) + assert(is_bool(left_handed)); + bevel1 = first_defined([bevel1,bevel,false]); + bevel2 = first_defined([bevel2,bevel,false]); + r1 = get_radius(d1=d1, d=d); + r2 = get_radius(d1=d2, d=d); + sides = quantup(segs(max(r1,r2)), starts); + rsc = internal? (1/cos(180/sides)) : 1; + islop = internal? 2*$slop : 0; + _r1 = r1 * rsc + islop; + _r2 = r2 * rsc + islop; + threads = quantup(l/pitch+2,1); // Was quantup(1/pitch+2,2*starts); + echo(threads=threads); + dir = left_handed? -1 : 1; + twist = 360 * l / pitch / starts; + higang1 = first_defined([higbee1, higbee, 0]); + higang2 = first_defined([higbee2, higbee, 0]); + assert(higang1 < twist/2); + assert(higang2 < twist/2); + prof3d = path3d(profile); + pdepth = -min(subindex(profile,1)); + pmax = pitch * max(subindex(profile,1)); + rmax = max(_r1,_r2)+pmax; + depth = pdepth * pitch; + dummy1 = assert(_r1>depth && _r2>depth, "Screw profile deeper than rod radius"); + skew_mat = affine3d_skew(sxz=(_r2-_r1)/l); + map3d_and_scale = affine3d_frame_map(x=[0,0,1], y=[1,0,0]) // Map profile to 3d, parallel to z axis + * scale(pitch); // scale profile by pitch + hig_table = [ + [-twist, 0], + [-twist/2-0.00001, 0], + [-twist/2+higang1, 1], + [+twist/2-higang2, 1], + [+twist/2+0.00001, 0], + [+twist, 0], + ]; + start_steps = floor(sides / starts); + thread_verts = [ + // Outer loop constructs a vertical column of the screw at each angle + for (step = [0:1:start_steps]) let( + ang = 360 * step/sides, + dz = step / start_steps, // z offset for threads at this angle + rot_prof = zrot(ang*dir) // Rotate profile to correct angular location + * right((_r1 + _r2) / 2) // Shift profile out to thread radius + * skew_mat // Skew correction for tapered threads + * map3d_and_scale, // Map profile into 3d + full_profile = [ // profile for the entire rod + for (thread = [-threads/2:1:threads/2-1]) let( + tang = (thread/starts) * 360 + ang, + hsc = internal? 1 + : (higang1==0 && tang<=0)? 1 + : (higang2==0 && tang>=0)? 1 + : lookup(tang, hig_table), + higscale = yscale(hsc,cp = -pdepth) // Scale for higbee + //,eff=echo(tang=tang, twist=twist) + ) + // The right movement finds the position of the thread along + // what will be the z axis after the profile is mapped to 3d + each apply(right(dz + thread) * higscale, prof3d) + ] + ) [ + [0, 0, -l/2-pitch], + each apply(rot_prof , full_profile), + [0, 0, +l/2+pitch] + ] + ]; + + style = higang1>0 || higang2>0 ? "quincunx" : "min_edge"; + + thread_vnfs = vnf_merge([ + for (i=[0:1:starts-1]) + zrot(i*360/starts, p=vnf_vertex_array(thread_verts, reverse=left_handed, style=style)), + for (i=[0:1:starts-1]) let( + rmat = zrot(i*360/starts), + pts = deduplicate(list_head(thread_verts[0], len(prof3d)+1)), + faces = [for (i=idx(pts,e=-2)) [0, i+1, i]], + rfaces = left_handed? [for (x=faces) reverse(x)] : faces + ) [apply(rmat,pts), rfaces], + for (i=[0:1:starts-1]) let( + rmat = zrot(i*360/starts), + pts = deduplicate(list_tail(last(thread_verts), -len(prof3d)-2)), + faces = [for (i=idx(pts,e=-2)) [len(pts)-1, i, i+1]], + rfaces = left_handed? [for (x=faces) reverse(x)] : faces + ) [apply(rmat,pts), rfaces] + ]); + + slope = (_r1-_r2)/l; + maxlen = 2*pitch; + + anchor = get_anchor(anchor, center, BOT, CENTER); + attachable(anchor,spin,orient, r1=_r1, r2=_r2, l=l) { + union(){ + + // This method is faster but more complex code and it produces green tops + difference() { + //vnf_validate(vnf_quantize(thread_vnfs), size=0.1); + vnf_polyhedron(vnf_quantize(thread_vnfs), convexity=10); + + if (!internal){ + if (bevel1 || bevel2) + rotate_extrude(){ + if (bevel2) polygon([[0,l/2], [_r2+pmax-depth, l/2], [_r2+pmax+slope*depth,l/2-depth], [rmax+1, l/2-depth], [rmax+1,l/2+maxlen], [0,l/2+maxlen]]); + if (bevel1) polygon([[0,-l/2], [_r1+pmax-depth, -l/2], [_r1+pmax-slope*depth,-l/2+depth], [rmax+1, -l/2+depth], [rmax+1,-l/2-maxlen], [0,-l/2-maxlen]]); + } + if (!bevel1) + down(l/2) cuboid([2*rmax+1,2*rmax+1, maxlen], anchor=TOP); + if (!bevel2) + up(l/2) cuboid([2*rmax+1,2*rmax+1, maxlen], anchor=BOTTOM); + + } + } + + +/* intersection(){ + //vnf_validate(vnf_quantize(thread_vnfs), size=0.1); + vnf_polyhedron(vnf_quantize(thread_vnfs), convexity=10); + cyl(l=l, r1=_r1+pmax, r2=_r2+pmax, chamfer1=bevel1?depth:undef, chamfer2=bevel2?depth:undef); + }*/ + + // Add bevel for internal threads + if (internal) { + if (bevel1) + down(l/2)cyl(l=depth, r1=_r1+pmax, r2=_r1+pmax-slope*depth-depth,anchor=BOTTOM); + if (bevel2) + up(l/2)cyl(l=depth, r2=_r2+pmax, r1=_r2+pmax+slope*depth-depth,anchor=TOP); + } + } + children(); + } +} + + + +// Module: generic_threaded_nut() +// Description: +// Constructs a hexagonal nut for an generic threaded rod using a user-supplied thread profile. +// See generic_threaded_rod for details on the profile specification. +// Arguments: +// od = diameter of the nut. +// id = diameter of threaded rod to screw onto. +// h = height/thickness of nut. +// pitch = Thread spacing. +// profile = Thread profile. +// --- +// left_handed = if true, create left-handed threads. Default = false +// starts = The number of lead starts. Default = 1 +// bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. +// id1 = inner diameter at the bottom +// id2 = inner diameter at the top +// 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, which adds clearance (`4*$slop`) to internal threads. +module generic_threaded_nut( + od, + id, + h, + pitch, + profile, + left_handed=false, + starts=1, + bevel,bevel1,bevel2, + id1,id2, + anchor, spin, orient +) { + extra = 0.01; + id1 = first_defined([id1,id]); + id2 = first_defined([id2,id]); + assert(is_def(id1) && is_def(id2), "Must specify inner diameter of nut"); + slope = (id2-id1)/h; + full_id1 = id1-slope*extra/2; + full_id2 = id2+slope*extra/2; + echo(id1=full_id1,id2=full_id2); + bevel1 = first_defined([bevel1,bevel,false]); + bevel2 = first_defined([bevel2,bevel,false]); + dummy1 = assert(is_num(pitch) && pitch>0); + depth = -pitch*min(subindex(profile,1)); + attachable(anchor,spin,orient, size=[od/cos(30),od,h]) { + difference() { + cyl(d=od/cos(30), h=h, center=true, $fn=6,chamfer1=bevel1?depth:undef,chamfer2=bevel2?depth:undef); + generic_threaded_rod( + d1=full_id1,d2=full_id2, + l=h+extra, + pitch=pitch, + profile=profile, + left_handed=left_handed, + starts=starts, + internal=true, + bevel1=bevel1,bevel2=bevel2 + ); + } + children(); + } +} + + + // Module: thread_helix() // Usage: // thread_helix(d, pitch, thread_depth, [thread_angle], [twist], [profile=], [left_handed=], [higbee=], [internal=]); @@ -75,35 +352,60 @@ module thread_helix( idir = internal? -1 : 1; attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) { zrot_copies(n=starts) { - spiral_sweep(pline, h=h, r1=r1, r2=r2, twist=twist*dir, higbee=higbee, higbee1=higbee1, higbee2=higbee2, anchor=CENTER); + spiral_sweep(pline, h=h, r1=r1, r2=r2, twist=twist*dir, higbee=higbee, higbee1=higbee1, higbee2=higbee2, internal=internal, anchor=CENTER); } children(); } } - // Module: trapezoidal_threaded_rod() // Description: -// Constructs a generic trapezoidal threaded screw rod. This method makes -// much smoother threads than the naive linear_extrude method. -// For metric trapezoidal threads, use thread_angle=15 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 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. +// Constructs a threaded rod with a symmetric trapezoidal thread. Trapezoidal threads are used for lead screws because +// they are one of the strongest symmetric profiles. This tooth shape is stronger than a similarly +// sized square thread becuase of its wider base. However, it does place a radial load on the nut, unlike the square thread. +// For loads in only one direction the asymmetric buttress thread profile can bear greater loads. +// . +// By default produces the nominal dimensions +// for metric trapezoidal threads: a thread angle of 30 degrees and a depth set to half the pitch. +// You can also specify your own trapezoid parameters. For ACME threads see acme_threaded_rod(). +// Figure(2D,Med): +// pa_delta = tan(15)/4; +// rr1 = -1/2; +// z1 = 1/4-pa_delta; +// z2 = 1/4+pa_delta; +// profile = [ +// [-z2, rr1], +// [-z1, 0], +// [ z1, 0], +// [ z2, rr1], +// ]; +// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile))); +// stroke(fullprofile,width=1); +// dir = fullprofile[2]-fullprofile[3]; +// dir2 = fullprofile[5]-fullprofile[4]; +// curve = arc(32,angle=[75,105],r=67.5); +// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]); +// color("red"){ +// stroke([fullprofile[2]+.1*dir, fullprofile[2]+.4*dir], width=1); +// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1); +// stroke(move(-curve[0]+avgpt,p=curve), width=1,endcaps="arrow2"); +// back(10)text("thread",size=4,halign="center"); +// back(3)text("angle",size=4,halign="center"); +// } // Arguments: // d = Outer diameter of threaded rod. // l = Length of threaded rod. -// pitch = Length between threads. -// thread_angle = The pressure angle profile angle of the threads. Default = 14.5 degree ACME profile. +// pitch = Thread spacing. +// thread_angle = Angle between two thread faces. Default: 30 +// thread_depth = Depth of threads. Default: pitch/2 // --- -// thread_depth = Depth of the threads. Default=pitch/2 -// left_handed = If true, create left-handed threads. Default = false -// bevel = if true, bevel the thread ends. Default: true -// starts = The number of lead starts. Default = 1 -// 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. +// left_handed = If true, create left-handed threads. Default: false +// bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. +// starts = The number of lead starts. Default: 1 +// internal = If true, make this a mask for making internal threads. Default: false // d1 = Bottom outside diameter of threads. // d2 = Top outside diameter of threads. // higbee = Length to taper thread ends over. Default: 0 (No higbee thread tapering) @@ -113,233 +415,243 @@ module thread_helix( // 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. -// Examples(Med): -// trapezoidal_threaded_rod(d=10, l=40, pitch=2, thread_angle=15, $fn=32); -// trapezoidal_threaded_rod(d=3/8*25.4, l=20, pitch=1/8*25.4, thread_angle=29, $fn=32); -// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=45, left_handed=true, $fa=2, $fs=2); -// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=45, left_handed=true, starts=4, $fa=2, $fs=2); -// trapezoidal_threaded_rod(d=16, l=40, pitch=2, thread_angle=30); -// trapezoidal_threaded_rod(d=10, l=40, pitch=3, thread_angle=15, left_handed=true, starts=3, $fn=36); -// trapezoidal_threaded_rod(d=25, l=40, pitch=10, thread_depth=8/3, thread_angle=50, starts=4, center=false, $fa=2, $fs=2); -// trapezoidal_threaded_rod(d=50, l=35, pitch=8, thread_angle=30, starts=3, bevel=true); -// trapezoidal_threaded_rod(l=25, d=10, pitch=2, thread_angle=15, starts=3, $fa=1, $fs=1, orient=RIGHT, anchor=BOTTOM); +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. +// Example(2D): +// projection(cut=true) +// trapezoidal_threaded_rod(d=10, l=15, pitch=2, orient=BACK); +// Examples(Med): +// trapezoidal_threaded_rod(d=10, l=40, pitch=2, $fn=32); // Standard metric threading +// trapezoidal_threaded_rod(d=10, l=17, pitch=2, higbee=25, $fn=32); // Standard metric threading +// trapezoidal_threaded_rod(d=10, l=17, pitch=2, bevel=true, $fn=32); // Standard metric threading +// trapezoidal_threaded_rod(d=10, l=30, pitch=2, left_handed=true, $fa=1, $fs=1); // Standard metric threading +// trapezoidal_threaded_rod(d=10, l=40, pitch=3, left_handed=true, starts=3, $fn=36); +// trapezoidal_threaded_rod(l=25, d=10, pitch=2, starts=3, $fa=1, $fs=1, orient=RIGHT, anchor=BOTTOM); +// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, left_handed=true, $fa=2, $fs=2); +// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, left_handed=true, starts=4, $fa=2, $fs=2); +// trapezoidal_threaded_rod(d=16, l=40, pitch=2, thread_angle=60); +// trapezoidal_threaded_rod(d=25, l=40, pitch=10, thread_depth=8/3, thread_angle=100, starts=4, center=false, $fa=2, $fs=2); +// trapezoidal_threaded_rod(d=50, l=35, pitch=8, thread_angle=60, starts=11, higbee=10,$fn=120); // Example(Med): Using as a Mask to Make Internal Threads // bottom_half() difference() { // cube(50, center=true); // trapezoidal_threaded_rod(d=40, l=51, pitch=5, thread_angle=30, internal=true, orient=RIGHT, $fn=36); // } -// Example(2DMed): Typical Tooth Profile -// pitch = 2; -// depth = pitch * cos(30) * 5/8; -// profile = [ -// [-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] -// ]; -// stroke(profile, width=0.02); module trapezoidal_threaded_rod( - d, l=100, pitch=2, - thread_angle=15, + d, l, pitch, + thread_angle=30, thread_depth=undef, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, starts=1, - profile, internal=false, - d1, d2, - higbee, higbee1, higbee2, + higbee, higbee1, higbee2,d1,d2, center, anchor, spin, orient ) { - r1 = get_radius(d1=d1, d=d, dflt=10); - r2 = get_radius(d1=d2, d=d, dflt=10); - sides = quantup(segs(max(r1,r2)), starts); - rsc = internal? (1/cos(180/sides)) : 1; - islop = internal? $slop*3 : 0; - _r1 = r1 * rsc + islop; - _r2 = r2 * rsc + islop; - threads = quantup(l/pitch+2, 2*starts); - 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; - dir = left_handed? -1 : 1; - twist = 360 * l / pitch / starts; - higang1 = first_defined([higbee1, higbee, 0]); - higang2 = first_defined([higbee2, higbee, 0]); - assert(higang1 < twist/2); - assert(higang2 < twist/2); - + dummy0 = assert(all_positive(pitch)); + dummy1 = assert(thread_angle>=0 && thread_angle<180); + depth = first_defined([thread_depth, pitch/2]); + pa_delta = 0.5*depth*tan(thread_angle/2) / pitch; + dummy2 = assert(pa_delta<1/4, "Specified thread geometry is impossible"); rr1 = -depth/pitch; z1 = 1/4-pa_delta; z2 = 1/4+pa_delta; - profile = ( - profile!=undef? profile : [ - [-z2, rr1], - [-z1, 0], - [ z1, 0], - [ z2, rr1], - ] - ); - prof3d = path3d(profile); - higthr1 = ceil(higang1 / 360); - higthr2 = ceil(higang2 / 360); - pdepth = -min(subindex(profile,1)); - dummy1 = assert(_r1>pdepth) assert(_r2>pdepth); - skew_mat = affine3d_skew(sxz=(_r2-_r1)/l); - side_mat = affine3d_xrot(90) * - affine3d_mirror([-1,1,0]) * - affine3d_scale([1,1,1] * pitch); - hig_table = [ - [-twist, 0], - [-twist/2-0.00001, 0], - [-twist/2+higang1, 1], - [+twist/2-higang2, 1], - [+twist/2+0.00001, 0], - [+twist, 0], - ]; - start_steps = floor(sides / starts); - thread_verts = [ - for (step = [0:1:start_steps]) let( - ang = 360 * step/sides, - dz = pitch * step / start_steps, - mat1 = affine3d_zrot(ang*dir), - mat2 = affine3d_translate([(_r1 + _r2) / 2 - pdepth*pitch, 0, 0]) * - skew_mat * - affine3d_translate([0, 0, dz]), - prof = apply(side_mat, [ - for (thread = [-threads/2:1:threads/2-1]) let( - tang = (thread/starts) * 360 + ang, - hsc = internal? 1 : - (higang1==0 && tang<=0)? 1 : - (higang2==0 && tang>=0)? 1 : - lookup(tang, hig_table), - mat3 = affine3d_translate([thread, 0, 0]) * - affine3d_scale([1, hsc, 1]) * - affine3d_translate([0,pdepth,0]) - ) each apply(mat3, prof3d) - ]) - ) [ - [0, 0, -l/2-pitch], - each apply(mat1*mat2, prof), - [0, 0, +l/2+pitch] - ] - ]; - thread_vnfs = vnf_merge([ - for (i=[0:1:starts-1]) - zrot(i*360/starts, p=vnf_vertex_array(thread_verts, reverse=left_handed, style="min_edge")), - for (i=[0:1:starts-1]) let( - rmat = zrot(i*360/starts), - pts = deduplicate(list_head(thread_verts[0], len(prof3d)+1)), - faces = [for (i=idx(pts,e=-2)) [0, i+1, i]], - rfaces = left_handed? [for (x=faces) reverse(x)] : faces - ) [apply(rmat,pts), rfaces], - for (i=[0:1:starts-1]) let( - rmat = zrot(i*360/starts), - pts = deduplicate(list_tail(last(thread_verts), -len(prof3d)-2)), - faces = [for (i=idx(pts,e=-2)) [len(pts)-1, i, i+1]], - rfaces = left_handed? [for (x=faces) reverse(x)] : faces - ) [apply(rmat,pts), rfaces] - ]); - - anchor = get_anchor(anchor, center, BOT, CENTER); - attachable(anchor,spin,orient, r1=_r1, r2=_r2, l=l) { - intersection() { - //vnf_validate(vnf_quantize(thread_vnfs), size=0.1); - vnf_polyhedron(vnf_quantize(thread_vnfs), convexity=10); - if (bevel) { - cyl(l=l, r1=_r1, r2=_r2, chamfer=depth); - } else { - cyl(l=l, r1=_r1, r2=_r2); - } - } - children(); - } + profile = [ + [-z2, rr1], + [-z1, 0], + [ z1, 0], + [ z2, rr1], + ]; + generic_threaded_rod(d=d,l=l,pitch=pitch,profile=profile, + left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts,internal=internal,d1=d1,d2=d2, + higbee=higbee,higbee1=higbee1,higbee2=higbee2,center=center,anchor=anchor,spin=spin,orient=orient) + children(); } // Module: trapezoidal_threaded_nut() // Description: -// Constructs a hex nut for a threaded screw rod. This method makes -// much smoother threads than the naive linear_extrude method. -// For metric screw threads, use thread_angle=30 and leave out thread_depth argument. -// For SAE screw threads, use thread_angle=30 and leave out thread_depth argument. -// For metric trapezoidal threads, use thread_angle=15 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. +// Constructs a hex nut for a symmetric trapzoidal threaded rod. +// By default produces the nominal dimensions +// for metric trapezoidal threads: a thread angle of 30 degrees and a depth set to half the pitch. +// You can also specify your own trapezoid parameters. For ACME threads see acme_threaded_nut(). // Arguments: // od = diameter of the nut. // id = diameter of threaded rod to screw onto. // h = height/thickness of nut. -// 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. +// pitch = Thread spacing. +// thread_angle = Angle between two thread faces. Default: 30 +// thread_depth = Depth of the threads. Default: pitch/2 +// --- // left_handed = if true, create left-handed threads. Default = false // starts = The number of lead starts. Default = 1 -// bevel = if true, bevel the thread ends. Default: true -// 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. +// bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Examples(Med): -// trapezoidal_threaded_nut(od=16, id=8, h=8, pitch=2, $slop=0.2, anchor=UP); -// trapezoidal_threaded_nut(od=17.4, id=10, h=10, pitch=2, $slop=0.2, left_handed=true); -// trapezoidal_threaded_nut(od=17.4, id=10, h=10, pitch=2, thread_angle=15, starts=3, $fa=1, $fs=1); +// trapezoidal_threaded_nut(od=16, id=8, h=8, pitch=2, $slop=0.1, anchor=UP); +// trapezoidal_threaded_nut(od=16, id=8, h=8, pitch=2, bevel=true, $slop=0.05, anchor=UP); +// trapezoidal_threaded_nut(od=17.4, id=10, h=10, pitch=2, $slop=0.1, left_handed=true); +// trapezoidal_threaded_nut(od=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15); module trapezoidal_threaded_nut( - od=17.4, - id=10, - h=10, - pitch=2, - thread_depth=undef, - thread_angle=15, - profile=undef, + od, + id, + h, + pitch, + thread_angle=30, + thread_depth, left_handed=false, starts=1, - bevel=true, + bevel,bevel1,bevel2, + id1,id2, anchor, spin, orient ) { - depth = min((thread_depth==undef? pitch/2 : thread_depth), pitch/2/tan(thread_angle)); - attachable(anchor,spin,orient, size=[od/cos(30),od,h]) { - difference() { - cylinder(d=od/cos(30), h=h, center=true, $fn=6); - trapezoidal_threaded_rod( - d=id, - l=h+1, - pitch=pitch, - thread_depth=depth, - thread_angle=thread_angle, - profile=profile, - left_handed=left_handed, - starts=starts, - internal=true - ); - if (bevel) { - zflip_copy() { - down(h/2+0.01) { - cylinder(r1=id/2+$slop, r2=id/2+$slop-depth, h=depth, center=false); - } - } - } - } - children(); - } + dummy1 = assert(pitch>0 && thread_angle>=0 && thread_angle<180); + depth = first_defined([thread_depth, pitch/2]); + pa_delta = 0.5*depth*tan(thread_angle/2) / pitch; + dummy2 = assert(pa_delta<1/4, "Specified thread geometry is impossible"); + rr1 = -depth/pitch; + z1 = 1/4-pa_delta; + z2 = 1/4+pa_delta; + profile = [ + [-z2, rr1], + [-z1, 0], + [ z1, 0], + [ z2, rr1], + ]; + generic_threaded_nut(od=od,id=id,h=h,pitch=pitch,profile=profile,id1=id1,id2=id2, + left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts, + anchor=anchor,spin=spin,orient=orient) + children(); } -// Section: Triangular Threading + + +// Section: ACME Trapezoidal Threading + +// Module: acme_threaded_rod() +// Description: +// Constructs an ACME trapezoidal threaded screw rod. This form has a 29 degree thread angle with a +// symmetric trapezoidal thread. +// Arguments: +// d = Outer diameter of threaded rod. +// l = length of threaded rod. +// tpi = threads per inch. +// --- +// pitch = thread spacing (alternative to tpi) +// starts = The number of lead starts. Default = 1 +// left_handed = if true, create left-handed threads. Default = false +// bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. +// internal = If true, this is a mask for making internal threads. +// higbee = Length to taper thread ends over. Default: 0 (No higbee thread tapering) +// 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` +// 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, which adds clearance (`4*$slop`) to internal threads. +// Example(2D): +// projection(cut=true) +// acme_threaded_rod(d=10, l=15, pitch=2, orient=BACK); +// Examples(Med): +// acme_threaded_rod(d=3/8*INCH, l=20, pitch=1/8*INCH, $fn=32); +// acme_threaded_rod(d=10, l=30, pitch=2, starts=3, $fa=1, $fs=1); +module acme_threaded_rod( + d, l, tpi, pitch, + starts=1, + left_handed=false, + bevel,bevel1,bevel2, + internal=false, + higbee, higbee1, higbee2, + anchor, spin, orient +) { + dummy = assert(num_defined([pitch,tpi])==1,"Must give exactly one of pitch and tpi"); + pitch = is_undef(pitch) ? INCH/tpi : pitch; + trapezoidal_threaded_rod( + d=d, l=l, pitch=pitch, + thread_angle=29, + thread_depth=pitch/2, + starts=starts, + left_handed=left_handed, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, + internal=internal, + anchor=anchor, + spin=spin, + orient=orient + ) children(); +} + + + +// Module: acme_threaded_nut() +// Description: +// Constructs a hex nut for an ACME threaded screw rod. +// Arguments: +// od = diameter of the nut. +// id = diameter of threaded rod to screw onto. +// h = height/thickness of nut. +// tpi = threads per inch +// --- +// pitch = Thread spacing (alternative to tpi) +// left_handed = if true, create left-handed threads. Default = false +// bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. +// 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, which adds clearance (`4*$slop`) to internal threads. +// Examples(Med): +// acme_threaded_nut(od=16, id=3/8*INCH, h=8, tpi=8, $slop=0.05); +// acme_threaded_nut(od=16, id=1/2*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1); +module acme_threaded_nut( + od, id, h, tpi, pitch, + starts=1, + left_handed=false, + bevel,bevel1,bevel2, + anchor, spin, orient +) { + dummy = assert(num_defined([pitch,tpi])==1,"Must give exactly one of pitch and tpi"); + pitch = is_undef(pitch) ? INCH/tpi : pitch; + dummy2=assert(is_num(pitch) && pitch>0); + trapezoidal_threaded_nut( + od=od, id=id, h=h, pitch=pitch, + thread_depth = pitch/2, + thread_angle=29, + left_handed=left_handed, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, + starts=starts, + anchor=anchor, + spin=spin, + orient=orient + ) children(); +} + + + +// Section: Standard (UTS/ISO) Threading // Module: threaded_rod() // Description: -// Constructs a standard metric or UTS threaded screw rod. This method -// makes much smoother threads than the naive linear_extrude method. +// Constructs a standard ISO (metric) or UTS (English) threaded rod. These threads are close to triangular, +// with a 60 degree thread angle. You can give the outer diameter and get the "basic form" or you can +// set d to a triplet [d_min, d_pitch, d_major] where are parameters determined by the ISO and UTS specifications +// that define clearance sizing for the threading. See screws.scad for how to make screws +// using the specification parameters. // Arguments: -// d = Outer diameter of threaded rod. +// d = Outer diameter of threaded rod, or a triplet of [d_min, d_pitch, d_major]. // l = length of threaded rod. // pitch = Length between threads. // left_handed = if true, create left-handed threads. Default = false // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // internal = If true, make this a mask for making internal threads. // d1 = Bottom outside diameter of threads. // d2 = Top outside diameter of threads. @@ -349,48 +661,58 @@ module trapezoidal_threaded_nut( // 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Example(2D): // projection(cut=true) -// threaded_rod(d=10, l=15, pitch=2, orient=BACK); +// threaded_rod(d=10, l=15, pitch=1.5, orient=BACK); // Examples(Med): // 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); module threaded_rod( - d, l=100, pitch=2, + d, l, pitch, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, internal=false, d1, d2, higbee, higbee1, higbee2, 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; - profile = internal? [ - [-6/16, -depth/pitch], + dummy1= + assert(all_positive(pitch)) + assert(all_positive(d)) + assert(all_positive(l)); + basic = is_num(d) || is_undef(d) || is_def(d1) || is_def(d2); + dummy2 = assert(basic || is_vector(d,3)); + depth = basic ? cos(30) * 5/8 + : (d[2] - d[0])/2/pitch; + crestwidth = basic ? 1/8 : 1/2 - (d[2]-d[1])/sqrt(3)/pitch; + profile = [ + [-depth/sqrt(3)-crestwidth/2, -depth], + [ -crestwidth/2, 0], + [ crestwidth/2, 0], + [ depth/sqrt(3)+crestwidth/2, -depth] + ]; + oprofile = internal? [ + [-6/16, -depth], [-1/16, 0], [-1/32, 0.02], [ 1/32, 0.02], [ 1/16, 0], - [ 6/16, -depth/pitch] + [ 6/16, -depth] ] : [ - [-7/16, -depth/pitch*1.07], - [-6/16, -depth/pitch], + [-7/16, -depth*1.07], + [-6/16, -depth], [-1/16, 0], [ 1/16, 0], - [ 6/16, -depth/pitch], - [ 7/16, -depth/pitch*1.07] + [ 6/16, -depth], + [ 7/16, -depth*1.07] ]; - trapezoidal_threaded_rod( - d=d, d1=d1, d2=d2, l=l, + generic_threaded_rod( + d=basic ? d : d[2], d1=d1, d2=d2, l=l, pitch=pitch, - thread_depth=depth, - thread_angle=30, profile=profile, left_handed=left_handed, - bevel=bevel, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, internal=internal, higbee=higbee, higbee1=higbee1, @@ -405,24 +727,27 @@ module threaded_rod( // Module: threaded_nut() // Description: -// Constructs a hex nut for a metric or UTS threaded screw rod. This method -// makes much smoother threads than the naive linear_extrude method. +// Constructs a hex nut for an ISO (metric) or UTS (English) threaded rod. // Arguments: // od = diameter of the nut. // id = diameter of threaded rod to screw onto. // h = height/thickness of nut. // pitch = Length between threads. +// --- // left_handed = if true, create left-handed threads. Default = false // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Examples(Med): -// threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.2, $fa=1, $fs=1); +// threaded_nut(od=16, id=8, h=8, pitch=1.25, $slop=0.05, $fa=1, $fs=1); +// threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, bevel=true, $slop=0.1, $fa=1, $fs=1); module threaded_nut( - od=16, id=10, h=10, - pitch=2, left_handed=false, bevel=false, + od, id, h, + pitch, left_handed=false, bevel, bevel1, bevel2, anchor, spin, orient ) { depth = pitch * cos(30) * 5/8; @@ -434,12 +759,12 @@ module threaded_nut( [ 1/16, 0], [ 6/16, -depth/pitch] ]; - trapezoidal_threaded_nut( + generic_threaded_nut( od=od, id=id, h=h, - pitch=pitch, thread_angle=30, + pitch=pitch, profile=profile, left_handed=left_handed, - bevel=bevel, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, anchor=anchor, spin=spin, orient=orient ) children(); @@ -456,36 +781,50 @@ module threaded_nut( // hollowed out into a pipe with the apropriate internal diameter. // Arguments: // size = NPT standard pipe size in inches. 1/16", 1/8", 1/4", 3/8", 1/2", 3/4", 1", 1+1/4", 1+1/2", or 2". Default: 1/2" +// --- // 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 +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // hollow = If true, create a pipe with the correct internal diameter. // 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): +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.p +// Example(2D): The straight gray rectangle reveals the tapered threads. // projection(cut=true) npt_threaded_rod(size=1/4, orient=BACK); +// right(.533*INCH/2) color("gray") rect([2,0.5946*INCH],anchor=LEFT); // Examples(Med): // npt_threaded_rod(size=3/8, $fn=72); -// npt_threaded_rod(size=1/2, $fn=72); +// npt_threaded_rod(size=1/2, $fn=72, bevel=true); // npt_threaded_rod(size=1/2, left_handed=true, $fn=72); +// npt_threaded_rod(size=3/4, hollow=true, $fn=96); +// Example: +// diff("remove"){ +// cuboid([40,40,40]) +// tags("remove"){ +// up(.01)position(TOP) +// npt_threaded_rod(size=3/4, $fn=96, internal=true, $slop=0.1, anchor=TOP); +// cyl(d=3/4*INCH, l=42, $fn=32); +// } +// } module npt_threaded_rod( size=1/2, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, hollow=false, internal=false, anchor, spin, orient ) { assert(is_finite(size)); assert(is_bool(left_handed)); - assert(is_bool(bevel)); + assert(is_undef(bevel) || is_bool(bevel)); assert(is_bool(hollow)); assert(is_bool(internal)); assert(!(internal&&hollow), "Cannot created a hollow internal threads mask."); info_table = [ - // Size OD len TPI + // Size len OD TPI [ 1/16, [ 0.3896, 0.308, 27 ]], [ 1/8, [ 0.3924, 0.401, 27 ]], [ 1/4, [ 0.5946, 0.533, 18 ]], @@ -499,10 +838,10 @@ module npt_threaded_rod( ]; 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]; - rr = get_radius(d=d, dflt=0.84 * 25.4 / 2); + l = INCH * info[0]; + d = INCH * info[1]; + pitch = INCH / info[2]; + rr = d/2; rr2 = rr - l/32; r1 = internal? rr2 : rr; r2 = internal? rr : rr2; @@ -524,20 +863,17 @@ module npt_threaded_rod( ]; attachable(anchor,spin,orient, l=l, r1=r1, r2=r2) { difference() { - trapezoidal_threaded_rod( + generic_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, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, internal=internal, higbee=r1*PI/2 ); - if (hollow) { - cylinder(l=l+1, d=size*INCH, center=true); - } else nil(); + if (hollow) cylinder(l=l+1, d=size*INCH, center=true); + else nil(); } children(); } @@ -549,19 +885,28 @@ module npt_threaded_rod( // Module: buttress_threaded_rod() // Description: -// Constructs a simple buttress threaded screw rod. This method -// makes much smoother threads than the naive linear_extrude method. +// Constructs a simple buttress threaded rod with a 45 degree angle. The buttress thread or sawtooth thread has low friction and high loading +// in one direction at the cost of higher friction and inferior loading in the other direction. Buttress threads are sometimes used on +// vises, which are loaded only in one direction. // Arguments: // d = Outer diameter of threaded rod. // l = length of threaded rod. -// pitch = Length between threads. +// pitch = Thread spacing. +// --- // left_handed = if true, create left-handed threads. Default = false // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // internal = If true, this is a mask for making internal 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. +// d1 = Bottom outside diameter of threads. +// d2 = Top outside diameter of 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Example(2D): // projection(cut=true) // buttress_threaded_rod(d=10, l=15, pitch=2, orient=BACK); @@ -571,8 +916,12 @@ module npt_threaded_rod( module buttress_threaded_rod( d=10, l=100, pitch=2, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, internal=false, + higbee=0, + higbee1, + higbee2, + d1,d2, anchor, spin, orient ) { depth = pitch * 3/4; @@ -583,14 +932,16 @@ module buttress_threaded_rod( [ 7/16, -0.75], [ 1/ 2, -0.77], ]; - trapezoidal_threaded_rod( + generic_threaded_rod( d=d, l=l, pitch=pitch, - thread_depth=depth, - thread_angle=30, - profile=profile, + profile=profile, left_handed=left_handed, - bevel=bevel, + bevel=bevel,beve1=bevel1,bevel2=bevel2, internal=internal, + higbee=higbee, + higbee1=higbee1, + higbee2=higbee2, + d1=d1,d2=d2, anchor=anchor, spin=spin, orient=orient @@ -601,25 +952,27 @@ module buttress_threaded_rod( // Module: buttress_threaded_nut() // Description: -// Constructs a hex nut for a simple buttress threaded screw rod. This method -// makes much smoother threads than the naive linear_extrude method. +// Constructs a hex nut for a simple buttress threaded screw rod. // Arguments: // od = diameter of the nut. // id = diameter of threaded rod to screw onto. // h = height/thickness of nut. -// pitch = Length between threads. +// pitch = Thread spacing. +// --- // left_handed = if true, create left-handed threads. Default = false // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Examples(Med): -// buttress_threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.2, $fa=1, $fs=1); +// buttress_threaded_nut(od=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.05, $fa=1, $fs=1); module buttress_threaded_nut( od=16, id=10, h=10, pitch=2, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, anchor, spin, orient ) { depth = pitch * 3/4; @@ -630,238 +983,72 @@ module buttress_threaded_nut( [ 7/16, -0.75], [ 1/ 2, -0.77], ]; - trapezoidal_threaded_nut( + generic_threaded_nut( od=od, id=id, h=h, - pitch=pitch, thread_angle=30, + pitch=pitch, profile=profile, - thread_depth=pitch*3*sqrt(3)/8, left_handed=left_handed, - bevel=bevel, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, anchor=anchor, spin=spin, orient=orient ) children(); } -// Section: Metric Trapezoidal Threading - -// Module: metric_trapezoidal_threaded_rod() -// Description: -// Constructs a metric trapezoidal threaded screw rod. This method makes much -// smoother threads than the naive linear_extrude method. -// Arguments: -// d = Outer diameter of threaded rod. -// l = length of threaded rod. -// pitch = Length between threads. -// left_handed = if true, create left-handed threads. Default = false -// bevel = if true, bevel the thread ends. Default: false -// starts = The number of lead starts. Default = 1 -// internal = If true, this is 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) -// metric_trapezoidal_threaded_rod(d=10, l=15, pitch=2, orient=BACK); -// Examples(Med): -// metric_trapezoidal_threaded_rod(d=10, l=30, pitch=2, left_handed=true, $fa=1, $fs=1); -module metric_trapezoidal_threaded_rod( - d=10, l=100, pitch=2, - left_handed=false, - starts=1, - bevel=false, - internal=false, - anchor, spin, orient -) { - trapezoidal_threaded_rod( - d=d, l=l, - pitch=pitch, - thread_angle=15, - left_handed=left_handed, - starts=starts, - bevel=bevel, - internal=internal, - anchor=anchor, - spin=spin, - orient=orient - ) children(); -} - - - -// Module: metric_trapezoidal_threaded_nut() -// Description: -// Constructs a hex nut for a metric trapezoidal threaded screw rod. This method -// makes much smoother threads than the naive linear_extrude method. -// Arguments: -// od = diameter of the nut. -// id = diameter of threaded rod to screw onto. -// h = height/thickness of nut. -// pitch = Length between threads. -// left_handed = if true, create left-handed threads. Default = false -// bevel = if true, bevel the thread ends. Default: false -// starts = The number of lead starts. Default = 1 -// 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. -// Examples(Med): -// metric_trapezoidal_threaded_nut(od=16, id=10, h=10, pitch=2, left_handed=true, bevel=true, $fa=1, $fs=1); -module metric_trapezoidal_threaded_nut( - od=17.4, id=10.5, h=10, - pitch=3.175, - starts=1, - left_handed=false, - bevel=false, - anchor, spin, orient -) { - trapezoidal_threaded_nut( - od=od, id=id, h=h, - pitch=pitch, thread_angle=15, - left_handed=left_handed, - starts=starts, - bevel=bevel, - anchor=anchor, - spin=spin, - orient=orient - ) children(); -} - - -// Section: ACME Trapezoidal Threading - -// Module: acme_threaded_rod() -// Description: -// Constructs an ACME trapezoidal threaded screw rod. This method makes -// much smoother threads than the naive linear_extrude method. -// Arguments: -// d = Outer diameter of threaded rod. -// l = length of threaded rod. -// 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 degrees -// starts = The number of lead starts. Default = 1 -// left_handed = if true, create left-handed threads. Default = false -// bevel = if true, bevel the thread ends. Default: false -// internal = If true, this is 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) -// acme_threaded_rod(d=10, l=15, pitch=2, orient=BACK); -// Examples(Med): -// acme_threaded_rod(d=3/8*25.4, l=20, pitch=1/8*25.4, $fn=32); -// acme_threaded_rod(d=10, l=30, pitch=2, starts=3, $fa=1, $fs=1); -module acme_threaded_rod( - d=10, l=100, pitch=2, - thread_angle=14.5, - thread_depth=undef, - starts=1, - left_handed=false, - bevel=false, - internal=false, - anchor, spin, orient -) { - trapezoidal_threaded_rod( - d=d, l=l, pitch=pitch, - thread_angle=thread_angle, - thread_depth=thread_depth, - starts=starts, - left_handed=left_handed, - bevel=bevel, - internal=internal, - anchor=anchor, - spin=spin, - orient=orient - ) children(); -} - - - -// Module: acme_threaded_nut() -// Description: -// Constructs a hex nut for an ACME threaded screw rod. This method makes -// much smoother threads than the naive linear_extrude method. -// Arguments: -// od = diameter of the nut. -// id = diameter of threaded rod to screw onto. -// h = height/thickness of nut. -// 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. -// left_handed = if true, create left-handed threads. Default = false -// bevel = if true, bevel the thread ends. Default: false -// 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. -// Examples(Med): -// acme_threaded_nut(od=16, id=3/8*25.4, h=8, pitch=1/8*25.4, $slop=0.2); -// acme_threaded_nut(od=16, id=10, h=10, pitch=2, starts=3, $slop=0.2, $fa=1, $fs=1); -module acme_threaded_nut( - od, id, h, pitch, - thread_angle=14.5, - thread_depth=undef, - starts=1, - left_handed=false, - bevel=false, - anchor, spin, orient -) { - trapezoidal_threaded_nut( - od=od, id=id, h=h, pitch=pitch, - thread_depth=thread_depth, - thread_angle=thread_angle, - left_handed=left_handed, - bevel=bevel, - starts=starts, - anchor=anchor, - spin=spin, - orient=orient - ) children(); -} - // Section: Square Threading // Module: square_threaded_rod() // Description: -// Constructs a square profile threaded screw rod. This method makes -// much smoother threads than the naive linear_extrude method. +// Constructs a square profile threaded screw rod. The greatest advantage of square threads is that they have the least friction and a much higher intrinsic efficiency than trapezoidal threads. +// They produce no radial load on the nut. However, square threads cannot carry as much load as trapezoidal threads. // Arguments: // d = Outer diameter of threaded rod. // l = length of threaded rod. -// pitch = Length between threads. +// pitch = Thread spacing. +// --- // left_handed = if true, create left-handed threads. Default = false // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // starts = The number of lead starts. Default = 1 // internal = If true, this is a mask for making internal 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. +// d1 = Bottom outside diameter of threads. +// d2 = Top outside diameter of 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Example(2D): // projection(cut=true) // square_threaded_rod(d=10, l=15, pitch=2, orient=BACK); // Examples(Med): // square_threaded_rod(d=10, l=20, pitch=2, starts=2, $fn=32); module square_threaded_rod( - d=10, l=100, pitch=2, + d, l, pitch, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, starts=1, internal=false, + higbee=0, higbee1, higbee2, + d1,d2, anchor, spin, orient ) { trapezoidal_threaded_rod( d=d, l=l, pitch=pitch, thread_angle=0.1, left_handed=left_handed, - bevel=bevel, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, starts=starts, internal=internal, + higbee=higbee, + higbee1=higbee1, + higbee2=higbee2, + d1=d1, + d2=d2, anchor=anchor, spin=spin, orient=orient @@ -872,35 +1059,38 @@ module square_threaded_rod( // Module: square_threaded_nut() // Description: -// Constructs a hex nut for a square profile threaded screw rod. This method -// makes much smoother threads than the naive linear_extrude method. +// Constructs a hex nut for a square profile threaded screw rod. // Arguments: // od = diameter of the nut. // id = diameter of threaded rod to screw onto. // h = height/thickness of nut. // pitch = Length between threads. +// --- // left_handed = if true, create left-handed threads. Default = false // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // starts = The number of lead starts. Default = 1 // 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Examples(Med): -// square_threaded_nut(od=16, id=10, h=10, pitch=2, starts=2, $slop=0.15, $fn=32); +// square_threaded_nut(od=16, id=10, h=10, pitch=2, starts=2, $slop=0.1, $fn=32); module square_threaded_nut( - od=17.4, id=10.5, h=10, - pitch=3.175, + od, id, h, + pitch, left_handed=false, - bevel=false, + bevel,bevel1,bevel2, starts=1, anchor, spin, orient ) { + assert(is_num(pitch) && pitch>0) trapezoidal_threaded_nut( od=od, id=id, h=h, pitch=pitch, thread_angle=0, left_handed=left_handed, - bevel=bevel, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, starts=starts, anchor=anchor, spin=spin, @@ -913,21 +1103,24 @@ module square_threaded_nut( // Module: ball_screw_rod() // Description: -// Constructs a ball screw rod. This method makes much smoother threads than the naive linear_extrude method. +// Constructs a ball screw rod. This type of rod is used with ball bearings. // Arguments: // d = Outer diameter of threaded rod. // l = length of threaded rod. -// pitch = Length between threads. Also, the diameter of the ball bearings used. +// pitch = Thread spacing. Also, the diameter of the ball bearings used. // ball_diam = The diameter of the ball bearings to use with this ball screw. // ball_arc = The arc portion that should touch the ball bearings. Default: 120 degrees. +// --- // left_handed = if true, create left-handed threads. Default = false // starts = The number of lead starts. Default = 1 // bevel = if true, bevel the thread ends. Default: false +// bevel1 = if true bevel the bottom end. +// bevel2 = if true bevel the top end. // 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. +// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads. // Example(2D): Thread Profile, ball_diam=4, ball_arc=100 // projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=4, ball_arc=100, orient=BACK); // Example(2D): Thread Profile, ball_diam=4, ball_arc=120 @@ -939,11 +1132,12 @@ module square_threaded_nut( // ball_screw_rod(d=15, l=20, pitch=5, ball_diam=4, ball_arc=120, $fa=1, $fs=1); // ball_screw_rod(d=15, l=20, pitch=5, ball_diam=4, ball_arc=120, left_handed=true, $fa=1, $fs=1); module ball_screw_rod( - d=10, l=100, pitch=2, starts=1, + d, l, pitch, ball_diam=5, ball_arc=100, + starts=1, left_handed=false, internal=false, - bevel=false, + bevel,bevel1,bevel2, anchor, spin, orient ) { n = ceil(segs(ball_diam/2)*ball_arc/2/360); @@ -953,14 +1147,12 @@ module ball_screw_rod( each arc(N=n, d=ball_diam/pitch, cp=[-0.5,cpy], start=270, angle=ball_arc/2), each arc(N=n, d=ball_diam/pitch, cp=[+0.5,cpy], start=270-ball_arc/2, angle=ball_arc/2) ]; - trapezoidal_threaded_rod( + generic_threaded_rod( d=d, l=l, pitch=pitch, - thread_depth=depth, - thread_angle=90-ball_arc/2, profile=profile, left_handed=left_handed, starts=starts, - bevel=bevel, + bevel=bevel,bevel1=bevel1,bevel2=bevel2, internal=internal, higbee=0, anchor=anchor, @@ -972,3 +1164,37 @@ module ball_screw_rod( // vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap + +// Changes +// internal: can set bevel to true and get non-garbage result +// bevel is always set by thread depth +// acme takes tpi +// square threads are at angle 0 +// added generic_threaded_{rod,nut} +// eliminated metric_trapezoidal_* +// cleaned up matrices some in generic_threaded_rod +// threaded_rod can produce spec-true ISO/UTS profile with a triplet input for the diameter. +// Added bevel1 and bevel2 to all modules. Made default uniformly false for every case instead of +// sometimes true, sometimes false +// Profiles that go over zero are not clipped, and bevels are based on actual profile top, not nominal +// +// Fixed higbee in spiral_sweep for properly centered scaling and for staying on the internal/external base of threads +// Fixed bug in spiral_sweep where two segments were missing if higbee is zero +// When bevel is given to nuts it bevels the outside of the nut by thread depth +// higbee looks best with quincunx, but it's more expensive. Select quincunx when higbee is used, min_edge otherwise +// Current code uses difference to remove excess length in the rod. This gives faster renders at the cost +// of more complex code and green top/bottom surfaces. +// Changed slop to 4 * $slop. I got good results printing with $slop=0.05 with this setting. + + +// Questions: +// Existing code intersection with cylinder, so any profile over 0 gets removed. Also---exact match intersection? Better +// to intersect with a cube that is larger than the screw? Cheaper.... +// higbee can look bad due to edge issues in the VNF. Possibly "convex" style is better. "quincunx" may be best, but costly. +// buttress_threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1,higbee=15, $fn=32); +// Use quincunx when higbee is requested but min_edge otherwise? +// Should nut modules take d1/d2 for tapered nuts? + +// Run time checks. No difference for preview, but switching intersection to cube reduced render in the test from 11s to 8s. +// Switching to doing the intersection with vnf_halfspace made preview slower, 3.8s instead of 1.6s but render faster (4s instead of 8s) +// Using custom masks for beveling reduces render to 8s. diff --git a/vnf.scad b/vnf.scad index 85cd4d4..77e08e7 100644 --- a/vnf.scad +++ b/vnf.scad @@ -216,7 +216,7 @@ function vnf_triangulate(vnf) = // Function: vnf_vertex_array() // Usage: -// vnf = vnf_vertex_array(points, [caps], [cap1], [cap2], [reverse], [col_wrap], [row_wrap], [vnf]); +// vnf = vnf_vertex_array(points, [caps], [cap1], [cap2], [style], [reverse], [col_wrap], [row_wrap], [vnf]); // Description: // Creates a VNF structure from a vertex list, by dividing the vertices into columns and rows, // adding faces to tile the surface. You can optionally have faces added to wrap the last column