From 74fca586d7f23c1d7fa72bac309cd3907f29f9e9 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 18 Jun 2023 09:22:41 -0400 Subject: [PATCH 1/3] doc fixes --- beziers.scad | 8 ++++---- gears.scad | 54 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/beziers.scad b/beziers.scad index d5d5833..e66800c 100644 --- a/beziers.scad +++ b/beziers.scad @@ -179,7 +179,7 @@ function _bezier_matrix(N) = // Function: bezier_curve() -// Synopsis: Computes a number of uniformly distributed points along a bezier curve. +// Synopsis: Computes a specified number of points on a bezier curve. // SynTags: Path // Topics: Bezier Curves // See Also: bezier_curve(), bezier_curvature(), bezier_tangent(), bezier_derivative(), bezier_points() @@ -261,7 +261,7 @@ function bezier_tangent(bezier, u) = // Function: bezier_curvature() -// Synopsis: Returns the curvature values at one or more given positions along a bezier curve. +// Synopsis: Returns the curvature at one or more given positions along a bezier curve. // Topics: Bezier Curves // See Also: bezier_tangent(), bezier_derivative(), bezier_points() // Usage: @@ -437,7 +437,7 @@ function bezpath_points(bezpath, curveind, u, N=3) = // Function: bezpath_curve() -// Synopsis: Takes a bezier path and converts it into a path of points. +// Synopsis: Converts bezier path into a path of points. // SynTags: Path // Topics: Bezier Paths // See Also: bezier_points(), bezier_curve(), bezpath_points() @@ -474,7 +474,7 @@ function bezpath_curve(bezpath, splinesteps=16, N=3, endpoint=true) = // Function: bezpath_closest_point() -// Synopsis: Finds the closest part of a bezier path to a give point. +// Synopsis: Finds the closest point on a bezier path to a given point. // Topics: Bezier Paths // See Also: bezpath_points(), bezpath_curve(), bezier_points(), bezier_curve(), bezier_closest_point() // Usage: diff --git a/gears.scad b/gears.scad index ab8f687..1d8dc2a 100644 --- a/gears.scad +++ b/gears.scad @@ -26,7 +26,7 @@ // Section: Gears // Function&Module: spur_gear() -// Synopsis: Creates a spur gear shape. +// Synopsis: Creates a spur gear, helical gear, or internal ring gear. // SynTags: Geom, VNF // Topics: Gears, Parts // See Also: rack(), spur_gear(), spur_gear2d(), bevel_gear() @@ -37,9 +37,17 @@ // vnf = spur_gear(pitch, teeth, thickness, [shaft_diam=], ...); // vnf = spur_gear(mod=, teeth=, thickness=, [shaft_diam=], ...); // Description: -// Creates a (potentially helical) involute spur gear. The module `spur_gear()` gives an involute +// Creates a involute spur gear, helical gear, or internal ring gear. The module `spur_gear()` gives an involute // spur gear, with reasonable defaults for all the parameters. Normally, you should just choose the -// first 4 parameters, and let the rest be default values. The module `spur_gear()` gives a gear in +// first 4 parameters, and let the rest be default values. Spur gears have straight teeth and +// mesh together on parallel shafts without creating any axial thrust. The teeth engage suddenly across their +// entire width, creating stress and noise. Helical gears have angled teeth and engage more gradually, so they +// run more smoothly and quietly, however they do produce thrust along the gear axis. This can be +// circumvented using herringbone or double helical gears, which have no axial thrust and also self-align. +// Helical gears can mesh along shafts that are not parallel, where the angle between the shafts is +// the sum of the helical angles of the two gears. +// . +// The module `spur_gear()` gives a gear in // the XY plane, centered on the origin, with one tooth centered on the positive Y axis. The most // important is `pitch_radius()`, which tells how far apart to space gears that are meshing, and // `outer_radius()`, which gives the size of the region filled by the gear. A gear has a "pitch @@ -109,6 +117,24 @@ // color("#fc7") left(r1+r4) zrot(a4) spur_gear(pitch,n4,thickness,hole,hide=n4-3); // color("#ccc") fwd(r1) right(pitch*$t) // rack(pitch=pitch,teeth=n5,thickness=thickness,height=rack_base,anchor=CENTER,orient=BACK); +// Example: Helical gears meshing with non-parallel shafts +// ang1 = 30; +// ang2 = 10; +// pitch = 5; +// n = 20; +// r = pitch_radius(pitch,n); +// left(r) spur_gear( +// pitch=pitch, teeth=n, thickness=10, +// shaft_diam=5, helical=ang1, slices=12, +// $fa=1, $fs=1 +// ); +// right(r) +// xrot(ang1+ang2) +// zrot(360/n/2-5) spur_gear( +// pitch=pitch, teeth=n, thickness=10, +// shaft_diam=5, helical=ang2, slices=12, +// $fa=1, $fs=1 +// ); function spur_gear( pitch = 3, teeth = 11, @@ -193,7 +219,7 @@ module spur_gear( // Function&Module: spur_gear2d() -// Synopsis: Creates a 2D spur gear shape. +// Synopsis: Creates a 2D spur gear or internal ring gear. // SynTags: Geom, Path // Topics: Gears, Parts // See Also: rack(), spur_gear(), spur_gear2d(), bevel_gear() @@ -295,7 +321,7 @@ module spur_gear2d( // Function&Module: rack() -// Synopsis: Creates a gear rack shape. +// Synopsis: Creates a straight or helical gear rack. // SynTags: Geom, VNF // Topics: Gears, Parts // See Also: rack2d(), spur_gear(), spur_gear2d(), bevel_gear() @@ -445,7 +471,7 @@ function rack( // Function&Module: rack2d() -// Synopsis: Creates a 2D gear rack shape. +// Synopsis: Creates a 2D gear rack. // SynTags: Geom, Path // Topics: Gears, Parts // See Also: rack(), spur_gear(), spur_gear2d(), bevel_gear() @@ -569,7 +595,7 @@ module rack2d( // Function&Module: bevel_gear() -// Synopsis: Creates a possibly spiral beveled gear shape. +// Synopsis: Creates a straight or spiral bevel gear. // SynTags: Geom, VNF // Topics: Gears, Parts // See Also: rack(), rack2d(), spur_gear(), spur_gear2d(), bevel_pitch_angle(), bevel_gear() @@ -582,7 +608,13 @@ module rack2d( // Description: // Creates a (potentially spiral) bevel gear. The module `bevel_gear()` gives a bevel gear, with // reasonable defaults for all the parameters. Normally, you should just choose the first 4 -// parameters, and let the rest be default values. The module `bevel_gear()` gives a gear in the XY +// parameters, and let the rest be default values. In straight bevel gear sets, when each tooth +// engages it inpacts the corresponding tooth. The abrupt tooth engagement causes impact stress +// which makes them more prone to breakage. Spiral bevel gears have teeth formed along spirals so +// they engage more gradually, resulting in a less abrupt transfer of force, so they are quieter +// in operation and less likely to break. +// . +// The module `bevel_gear()` gives a gear in the XY // plane, centered on the origin, with one tooth centered on the positive Y axis. The various // functions below it take the same parameters, and return various measurements for the gear. The // most important is `pitch_radius()`, which tells how far apart to space gears that are meshing, @@ -830,7 +862,7 @@ module bevel_gear( // Function&Module: worm() -// Synopsis: Creates a worm shape that will mate with a worm gear. +// Synopsis: Creates a worm that will mate with a worm gear. // SynTags: Geom, VNF // Topics: Gears, Parts // See Also: worm(), worm_gear(), rack(), rack2d(), spur_gear(), spur_gear2d(), bevel_pitch_angle(), bevel_gear() @@ -951,7 +983,7 @@ module worm( // Function&Module: worm_gear() -// Synopsis: Creates a worm gear shape that will mate with a worm. +// Synopsis: Creates a worm gear that will mate with a worm. // SynTags: Geom, VNF // Topics: Gears, Parts // See Also: worm(), worm_gear(), rack(), rack2d(), spur_gear(), spur_gear2d(), bevel_pitch_angle(), bevel_gear() @@ -969,7 +1001,7 @@ module worm( // worm_diam = The pitch diameter of the worm gear to match to. Default: 30 // worm_starts = The number of lead starts on the worm gear to match to. Default: 1 // worm_arc = The arc of the worm to mate with, in degrees. Default: 60 degrees -// crowning = The amount to oversize the virtual hobbing cutter used to make the teeth, to add a slight crowning to the teeth to make them fir the work easier. Default: 1 +// crowning = The amount to oversize the virtual hobbing cutter used to make the teeth, to add a slight crowning to the teeth to make them fit the work easier. Default: 1 // left_handed = If true, the gear returned will have a left-handed spiral. Default: false // pressure_angle = Controls how straight or bulged the tooth sides are. In degrees. Default: 20 // backlash = Gap between two meshing teeth, in the direction along the circumference of the pitch circle. Default: 0 From 391a7078b63ccdae82fac35593b6d4a0d8648086 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Sun, 18 Jun 2023 20:20:01 -0400 Subject: [PATCH 2/3] attachability for torx, roberson, screw_head --- screw_drive.scad | 68 ++++++++++++++++----------- screws.scad | 117 ++++++++++++++++++++++++----------------------- 2 files changed, 102 insertions(+), 83 deletions(-) diff --git a/screw_drive.scad b/screw_drive.scad index 642df16..67b6213 100644 --- a/screw_drive.scad +++ b/screw_drive.scad @@ -168,7 +168,7 @@ function hex_drive_mask(size,length,l,h,height,anchor,spin,orient) = no_function // See Also: phillips_mask(), hex_drive_mask(), torx_mask(), phillips_depth(), phillips_diam(), robertson_mask() // Usage: // torx_mask(size, l, [center]) [ATTACHMENTS]; -// Description: Creates a torx bit tip. +// Description: Creates a torx bit tip. The anchors are located on the circumscribing cylinder. See {{torx_info()}} for allowed sizes. // Arguments: // size = Torx size. // l = Length of bit. @@ -191,7 +191,6 @@ module torx_mask(size, l=5, center, anchor, spin=0, orient=UP) { } - // Module: torx_mask2d() // Synopsis: Creates the 2D cross section for a torx drive recess. // SynTags: Geom @@ -199,13 +198,12 @@ module torx_mask(size, l=5, center, anchor, spin=0, orient=UP) { // See Also: phillips_mask(), hex_drive_mask(), torx_mask(), phillips_depth(), phillips_diam(), torx_info(), robertson_mask() // Usage: // torx_mask2d(size); -// Description: Creates a torx bit 2D profile. +// Description: Creates a torx bit 2D profile. The anchors are located on the circumscribing circle. See {{torx_info()}} for allowed sizes. // Arguments: // size = Torx size. // Example(2D): // torx_mask2d(size=30, $fa=1, $fs=1); -module torx_mask2d(size) { - no_children($children); +module torx_mask2d(size,anchor=CENTER,spin) { info = torx_info(size); od = info[0]; id = info[1]; @@ -213,26 +211,29 @@ module torx_mask2d(size) { rounding = info[4]; base = od - 2*tip; $fn = quantup(segs(od/2),12); - difference() { - union() { - circle(d=base); - zrot_copies(n=2) { - hull() { - zrot_copies(n=3) { - translate([base/2,0,0]) { - circle(r=tip, $fn=$fn/2); + attachable(anchor,spin,two_d=true,d=od){ + difference() { + union() { + circle(d=base); + zrot_copies(n=2) { + hull() { + zrot_copies(n=3) { + translate([base/2,0,0]) { + circle(r=tip, $fn=$fn/2); + } } } } } - } - zrot_copies(n=6) { - zrot(180/6) { - translate([id/2+rounding,0,0]) { - circle(r=rounding); + zrot_copies(n=6) { + zrot(180/6) { + translate([id/2+rounding,0,0]) { + circle(r=rounding); + } } } } + children(); } } @@ -251,6 +252,10 @@ module torx_mask2d(size) { // - Drive Hole Depth // - External Tip Rounding Radius // - Inner Rounding Radius +// . +// The allowed torx sizes are: +// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 27, 30, 40, 45, 50, 55, +// 60, 70, 80, 90, 100. // Arguments: // size = Torx size. function torx_info(size) = @@ -333,6 +338,11 @@ function torx_depth(size) = torx_info(size)[2]; // ang = taper angle of each face. Default: 2.5 // --- // $slop = enlarge recess by this twice amount. Default: 0 +// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: TOP +// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0` +// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP` +// Side Effects: +// Sets tag to "remove" if no tag is set. // Example: // robertson_mask(size=2); // Example: @@ -340,7 +350,7 @@ function torx_depth(size) = torx_info(size)[2]; // cyl(d1=2, d2=8, h=4, anchor=TOP); // robertson_mask(size=2); // } -module robertson_mask(size, extra=1, ang=2.5) { +module robertson_mask(size, extra=1, ang=2.5,anchor=TOP,spin,orient) { dummy=assert(is_int(size) && size>=0 && size<=4); Mmin = [0.0696, 0.0900, 0.1110, 0.1315, 0.1895][size]; Mmax = [0.0710, 0.0910, 0.1126, 0.1330, 0.1910][size]; @@ -353,14 +363,18 @@ module robertson_mask(size, extra=1, ang=2.5) { F = (Fmin + Fmax) / 2 * INCH; h = T + extra; Mslop=M+2*get_slop(); - down(T) { - intersection(){ - Mtop = Mslop + 2*adj_ang_to_opp(F+extra,ang); - Mbot = Mslop - 2*adj_ang_to_opp(T-F,ang); - prismoid([Mbot,Mbot],[Mtop,Mtop],h=h,anchor=BOT); - cyl(d1=0, d2=Mslop/(T-F)*sqrt(2)*h, h=h, anchor=BOT); - } - } + Mtop = Mslop + 2*adj_ang_to_opp(F+extra,ang); + Mbot = Mslop - 2*adj_ang_to_opp(T-F,ang); + anchors = [named_anchor("standard",[0,0,T-h/2], UP, 0)]; + default_tag("remove") + attachable(anchor,spin,orient,size=[Mbot,Mbot,T],size2=[Mtop,Mtop],anchors=anchors){ + down(T/2) + intersection(){ + prismoid([Mbot,Mbot],[Mtop,Mtop],h=h,anchor=BOT); + cyl(d1=0, d2=Mslop/(T-F)*sqrt(2)*h, h=h, anchor=BOT); + } + children(); + } } diff --git a/screws.scad b/screws.scad index 7a564ba..089eec5 100644 --- a/screws.scad +++ b/screws.scad @@ -1442,63 +1442,68 @@ module screw_head(screw_info,details=false, counterbore=0,flat_height,teardrop=f counterbore = counterbore_temp==0 && head!="flat" ? counterbore_temp : counterbore_temp + 0.01; adj_diam = struct_val(screw_info, "diameter") + head_oversize; // Used for determining chamfers and ribbing - if (head!="flat" && counterbore>0){ - d = head=="hex"? 2*head_size/sqrt(3) : head_size; - if (teardrop) - teardrop(d=d, l=counterbore, orient=BACK, anchor=BACK); - else - cyl(d=d, l=counterbore, anchor=BOTTOM); - } - if (head=="flat") { // For flat head, counterbore is integrated - angle = struct_val(screw_info, "head_angle")/2; - sharpsize = struct_val(screw_info, "head_size_sharp")+head_oversize; - sidewall_height = (sharpsize - head_size)/2 / tan(angle); - cylheight = counterbore + sidewall_height; - slopeheight = flat_height - sidewall_height; - r1 = head_size/2; - r2 = r1 - tan(angle)*slopeheight; - n = segs(r1); - prof1 = teardrop ? teardrop2d(r=r1,$fn=n) : circle(r=r1, $fn=n); - prof2 = teardrop ? teardrop2d(r=r2,$fn=n) : circle(r=r2, $fn=n); - skin([prof2,prof1,prof1], z=[-flat_height, -flat_height+slopeheight, counterbore],slices=0); - } - if (head!="flat" && counterbore==0) { - if (in_list(head,["round","pan round","button","fillister","cheese"])) { - base = head=="fillister" ? 0.75*head_height : - head=="pan round" ? .6 * head_height : - head=="cheese" ? .7 * head_height : - 0.1 * head_height; // round and button - head_size2 = head=="cheese" ? head_size-2*tan(5)*head_height : head_size; // 5 deg slope on cheese head - segs = segs(head_size); - cyl(l=base, d1=head_size, d2=head_size2,anchor=BOTTOM, $fn=segs) - attach(TOP) - zrot(180) // Needed to align facets when $fn is odd - rotate_extrude($fn=segs) // ensure same number of segments for cap as for head body - intersection(){ - arc(points=[[-head_size2/2,0], [0,-base+head_height * (head=="button"?4/3:1)], [head_size2/2,0]]); - square([head_size2, head_height-base]); + attachable(){ + union(){ + if (head!="flat" && counterbore>0){ + d = head=="hex"? 2*head_size/sqrt(3) : head_size; + if (teardrop) + teardrop(d=d, l=counterbore, orient=BACK, anchor=BACK); + else + cyl(d=d, l=counterbore, anchor=BOTTOM); + } + if (head=="flat") { // For flat head, counterbore is integrated + angle = struct_val(screw_info, "head_angle")/2; + sharpsize = struct_val(screw_info, "head_size_sharp")+head_oversize; + sidewall_height = (sharpsize - head_size)/2 / tan(angle); + cylheight = counterbore + sidewall_height; + slopeheight = flat_height - sidewall_height; + r1 = head_size/2; + r2 = r1 - tan(angle)*slopeheight; + n = segs(r1); + prof1 = teardrop ? teardrop2d(r=r1,$fn=n) : circle(r=r1, $fn=n); + prof2 = teardrop ? teardrop2d(r=r2,$fn=n) : circle(r=r2, $fn=n); + skin([prof2,prof1,prof1], z=[-flat_height, -flat_height+slopeheight, counterbore],slices=0); + } + if (head!="flat" && counterbore==0) { + if (in_list(head,["round","pan round","button","fillister","cheese"])) { + base = head=="fillister" ? 0.75*head_height : + head=="pan round" ? .6 * head_height : + head=="cheese" ? .7 * head_height : + 0.1 * head_height; // round and button + head_size2 = head=="cheese" ? head_size-2*tan(5)*head_height : head_size; // 5 deg slope on cheese head + segs = segs(head_size); + cyl(l=base, d1=head_size, d2=head_size2,anchor=BOTTOM, $fn=segs) + attach(TOP) + zrot(180) // Needed to align facets when $fn is odd + rotate_extrude($fn=segs) // ensure same number of segments for cap as for head body + intersection(){ + arc(points=[[-head_size2/2,0], [0,-base+head_height * (head=="button"?4/3:1)], [head_size2/2,0]]); + square([head_size2, head_height-base]); + } + } + if (head=="pan flat") + cyl(l=head_height, d=head_size, rounding2=0.2*head_size, anchor=BOTTOM); + if (head=="socket") + cyl(l=head_height, d=head_size, anchor=BOTTOM, chamfer2=details? adj_diam/10:undef); + if (head=="socket ribbed"){ + // These numbers are based on ISO specifications that dictate how much oversizsed a ribbed socket head can be + // We are making our ribbed heads the same size as unribbed (by cutting the ribbing away), but these numbers are presumably a good guide + rib_size = [[2, .09], + [3, .09], + [6, .11], + [12, .135], + [20, .165]]; + intersection() { + cyl(h=head_height/4, d=head_size, anchor=BOT) + attach(TOP) cyl(l=head_height*3/4, d=head_size, anchor=BOT, texture="trunc_ribs", tex_counts=[31,1], tex_scale=-lookup(adj_diam,rib_size)); + cyl(h=head_height,d=head_size, chamfer2=adj_diam/10, anchor=BOT); } - } - if (head=="pan flat") - cyl(l=head_height, d=head_size, rounding2=0.2*head_size, anchor=BOTTOM); - if (head=="socket") - cyl(l=head_height, d=head_size, anchor=BOTTOM, chamfer2=details? adj_diam/10:undef); - if (head=="socket ribbed"){ - // These numbers are based on ISO specifications that dictate how much oversizsed a ribbed socket head can be - // We are making our ribbed heads the same size as unribbed (by cutting the ribbing away), but these numbers are presumably a good guide - rib_size = [[2, .09], - [3, .09], - [6, .11], - [12, .135], - [20, .165]]; - intersection() { - cyl(h=head_height/4, d=head_size, anchor=BOT) - attach(TOP) cyl(l=head_height*3/4, d=head_size, anchor=BOT, texture="trunc_ribs", tex_counts=[31,1], tex_scale=-lookup(adj_diam,rib_size)); - cyl(h=head_height,d=head_size, chamfer2=adj_diam/10, anchor=BOT); - } - } - if (head=="hex") - up(head_height/2)_nutshape(head_size,head_height,"hex",false,true); + } + if (head=="hex") + up(head_height/2)_nutshape(head_size,head_height,"hex",false,true); + } + } + union(){}; } } From 34489a7b4416fa09b65bd910a27f9dee36eaa308 Mon Sep 17 00:00:00 2001 From: Adrian Mariano Date: Mon, 19 Jun 2023 00:53:01 -0400 Subject: [PATCH 3/3] merge --- gears.scad | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/gears.scad b/gears.scad index 1d8dc2a..dd23150 100644 --- a/gears.scad +++ b/gears.scad @@ -135,6 +135,36 @@ // shaft_diam=5, helical=ang2, slices=12, // $fa=1, $fs=1 // ); +// Example(Anim,Frames=36,VPT=[0,0,0],VPR=[55,0,25],VPD=375): Planetary Gear Assembly +// rteeth=56; pteeth=16; cteeth=24; +// pitch=5; thick=10; pa=20; +// prad = (pitch_radius(pitch,rteeth) + +// pitch_radius(pitch,cteeth)) / 2; +// rrad = outer_radius(pitch,rteeth,interior=true) + 5; +// diff() +// cyl(r=rrad,l=thick) +// tag("remove") +// spur_gear( +// pitch=pitch, teeth=rteeth, thickness=thick+1, +// pressure_angle=pa, interior=true); +// for (a=[0:3]) { +// zrot($t*90+a*90) back(prad) { +// color("green") +// spur_gear( +// pitch=pitch, teeth=pteeth, +// thickness=thick, +// shaft_diam=5, +// pressure_angle=pa, +// spin=-$t*90*rteeth/pteeth); +// } +// } +// color("orange") +// zrot($t*90*rteeth/cteeth+$t*90+180/cteeth) +// spur_gear( +// pitch=pitch, teeth=cteeth, +// thickness=thick, +// shaft_diam=5, +// pressure_angle=pa); function spur_gear( pitch = 3, teeth = 11,