1//////////////////////////////////////////////////////////////////////
2// LibFile: threading.scad
3// Provides generic threading support and specialized support for standard triangular (UTS/ISO) threading,
4// trapezoidal threading (ACME), pipe threading, buttress threading, square threading and ball screws.
5// Includes:
6// include <BOSL2/std.scad>
7// include <BOSL2/threading.scad>
8// FileGroup: Threaded Parts
9// FileSummary: Various types of threaded rods and nuts.
10//////////////////////////////////////////////////////////////////////
11
12
13// Section: Thread Ends and Options
14// A standard process for making machine screws is to begin with round stock that has
15// beveled ends. This stock is then rolled between flat, grooved plates to form the threads.
16// The result is a bolt that looks like this at the end:
17// Figure(3D,Med,NoAxes,VPR=[83.7,0,115.5],VPT=[1.37344,1.26411,-0.299415],VPD=35.5861):
18// threaded_rod(d=13,pitch=2,l=10,blunt_start=false,$fn=80);
19// Figure(2D,Med,NoAxes): A properly mated screw and bolt with beveled ends
20// $fn=32;
21// projection(cut=true)
22// xrot(-90){
23// down(2.5)difference(){
24// cuboid([20,20,5]);
25// zrot(20)
26// threaded_rod(d=13.2, pitch=2,l=5.1,blunt_start=false,internal=true);
27// }
28// up(2.85-2)threaded_rod(d=13, pitch=2, l=10, blunt_start=false);
29//
30// }
31// Continues:
32// Cross threading occurs when the bolt is misaligned with the threads in the nut.
33// It can destroy the threads, or cause the nut to jam. The standard beveled end process
34// makes cross threading a possibility because the beveled partial threads can pass
35// each other when the screw enters the nut.
36// Figure(2D,Med,NoAxes):
37// $fn=32;
38// projection(cut=true)
39// xrot(-90){
40// down(2.5)difference(){
41// cuboid([20,20,5]);
42// zrot(20)
43// threaded_rod(d=13.2, pitch=2,l=5.1,blunt_start=false,internal=true);
44// }
45// left(.6)up(2.99)yrot(-atan(2/13)-1)rot(180+30)threaded_rod(d=13, pitch=2, l=10, blunt_start=false);
46// }
47// Continues:
48// In addition, those partial screw threads may be weak, and easily broken. They do
49// not contribute to the strength of the assembly.
50// In 1891 Clinton A. Higbee received a patent for a modification to screw threads
51// https://patents.google.com/patent/US447775A meant to address these limitations.
52// Instead of beveling the end of the screw, Higbee said to remove the partial thread.
53// The resulting screw might look like this:
54// Figure(3D,Med,NoAxes,VPR=[72,0,294],VPT=[0,0,0],VPD=44):
55// $fn=48;
56// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,lead_in_shape="cut",end_len=.2);
57// Continues:
58// Because the threads are complete everywhere, cross threading is unlikely to occur.
59// This type of threading has been called "Higbee threads", but in recent machinist
60// handbooks it is called "blunt start" threading.
61// This style of thread is not commonly used in metal fasteners because it requires
62// machining the threads, which is much more costly than the rolling procedure described
63// above. However, plastic threads usually have some sort of gradual thread end.
64// For models that will be 3D printed, there is no reason to choose the standard
65// bevel end bolt, so in this library the blunt start threads are the default.
66// If you need standard bevel-end threads, you can choose them with the `blunt_start` options.
67// Note that blunt start threads are more efficient.
68// .
69// Various options exist for controlling the ends of threads. You can specify bevels on threaded rods.
70// In conventional threading, bevels are needed on the ends to remove sharp, thin edges, and
71// the bevel is sized to the full outer diameter of the threaded rod.
72// With blunt start threading, the bevel appears on the unthreaded part of the rod.
73// On a threaded rod, a bevel value of `true` or a positive bevel value cut off the corner.
74// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=44):
75// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,bevel=true,$fn=80);
76// Continues:
77// A negative bevel value produces a flaring bevel, that might be useful if the rod needs to mate with another part.
78// You can also set `bevel="reverse"` to get a flaring bevel of the default size.
79// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=44): Negative bevel on a regular threaded rod.
80// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,bevel=-2,$fn=80);
81// Continues:
82// If you set `internal=true` to create a mask for a threaded hole, then bevels are reversed: positive bevels flare outward so that when you subtract
83// the threaded rod it gives a beveled edge to the hole. In this case, negative bevels go inward, which might be useful to
84// create a bevel at the bottom of a threaded hole.
85// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=44): Threaded rod mask produced using `internal=true` with regular bevel at the top and reversed bevel at the bottom.
86// threaded_rod(d=13,pitch=2,l=10,blunt_start=true,bevel2=true,bevel1="reverse",internal=true,$fn=80);
87// Continues:
88// You can also extend the unthreaded section using the `end_len` parameters. A long unthreaded section will make
89// it impossible to tilt the bolt and produce misaligned threads, so it could make assembly easier.
90// Figure(3D,Med,NoAxes,VPR=[72,0,54],VPT=[0,0,0],VPD=48): Negative bevel on a regular threaded rod.
91// threaded_rod(d=13,pitch=2,l=15,end_len2=5,blunt_start=true,bevel=true,$fn=80);
92// Continues:
93// It is also possible to adjust the length of the lead-in section of threads, or the
94// shape of that lead-in section. The lead-in length can be set using the `lead_in` arguments
95// to specify a length or the `lead_in_ang` arguments to specify an angle. For general
96// threading applications, making the lead in long creates a smaller thread that could
97// be more fragile and more prone to cross threading.
98// Figure(3D,Med,NoAxes,VPR=[52,0,300],VPT=[0,0,4],VPD=35.5861):
99// threaded_rod(d=13,pitch=2,l=10,lead_in=6,blunt_start=true,bevel=false,$fn=80);
100// Continues:
101// To change the form of the thread end you use the `lead_in_shape` argument.
102// You can specify "sqrt", "cut" or "smooth" shapes. The "sqrt" shape is the historical
103// shape used in the library. The "cut" shape is available to model Higbee pattern threads, but
104// is not as good as the others in practice, because the flat faces on the threads can hit each other.
105// The lead-in shape is produced by applying a scale factor to the thread cross section that varies along the lead-in length.
106// You can also specify a custom shape
107// by giving a function literal, `f(x,L)` where `L` will be the total linear
108// length of the lead-in section and `x` will be a value between 0 and 1 giving
109// the position in the lead in, with 0 being the tip and 1 being the full height thread.
110// The return value must be a 2-vector giving the thread width scale and thread height
111// scale at that location. If `x<0` the function must return a thread height scale
112// of zero, but it is usually best if the thread width scale does not go to zero,
113// because that will give a sharply pointed thread end. If `x>1` the function must
114// return `[1,1]`.
115// Figure(3D,Med,NoAxes,VPR=[75,0,338],VPT=[-2,0,3.3],VPD=25): The standard lead in shapes
116// left_half()zrot(0){
117// up(2) threaded_rod(d=13,pitch=2,l=2,blunt_start=true,bevel=false,$fn=128,anchor=BOT);
118// up(4) threaded_rod(d=13,pitch=2,l=2.5,blunt_start=true,bevel=false,$fn=128,lead_in_shape="cut",end_len2=.5,anchor=BOT);
119// threaded_rod(d=13,pitch=2,l=2,blunt_start=true,bevel=false,$fn=128,lead_in_shape="smooth",anchor=BOT);
120// }
121// $fn=64;
122// s=.85;
123// color("black")
124// up(3.5)left(4.5)fwd(6)rot($vpr){
125// back(1.9)text3d("cut",size=s);
126// text3d("sqrt",size=s);
127// fwd(1.9)text3d("smooth",size=s);
128// }
129
130
131// Section: Standard (UTS/ISO) Threading
132
133// Module: threaded_rod()
134// Synopsis: Creates an UTS/ISO triangular threaded rod.
135// SynTags: Geom
136// Topics: Threading, Screws
137// See Also: threaded_nut()
138// Usage:
139// threaded_rod(d, l|length, pitch, [internal=], ...) [ATTACHMENTS];
140// Description:
141// Constructs a standard ISO (metric) or UTS (English) threaded rod. These threads are close to triangular,
142// with a 60 degree thread angle. You can give diameter value which specifies the outer diameter and will produce
143// the "basic form" or you can
144// set d to a triplet [d_min, d_pitch, d_major] where are parameters determined by the ISO and UTS specifications
145// that define clearance sizing for the threading. See screws.scad for how to make screws
146// using the specification parameters.
147// Arguments:
148// d = Outer diameter of threaded rod, or a triplet of [d_min, d_pitch, d_major].
149// l / length / h / height = length of threaded rod.
150// pitch = Length between threads.
151// ---
152// left_handed = if true, create left-handed threads. Default = false
153// starts = The number of lead starts. Default: 1
154// bevel = if true, bevel the thread ends. Default: false
155// bevel1 = if true bevel the bottom end.
156// bevel2 = if true bevel the top end.
157// internal = If true, make this a mask for making internal threads.
158// d1 = Bottom outside diameter of threads.
159// d2 = Top outside diameter of threads.
160// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
161// blunt_start1 = If true apply truncated blunt start threads bottom end.
162// blunt_start2 = If true apply truncated blunt start threads top end.
163// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
164// end_len1 = Specify unthreaded length at the bottom
165// end_len2 = Specify unthreaded length at the top
166// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
167// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
168// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
169// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
170// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
171// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
172// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
173// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
174// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
175// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
176// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
177// Example(2D):
178// projection(cut=true)
179// threaded_rod(d=10, l=15, pitch=1.5, orient=BACK);
180// Examples(Med):
181// threaded_rod(d=25, height=20, pitch=2, $fa=1, $fs=1);
182// threaded_rod(d=10, l=20, pitch=1.25, left_handed=true, $fa=1, $fs=1);
183// threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1, end_len=1.5, bevel=true);
184// threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1, blunt_start=false);
185// Example(Big,NoAxes): Diamond threading where both left-handed and right-handed nuts travel (in the same direction) on the threaded rod:
186// $fn=32;
187// $slop = 0.075;
188// d = 3/8*INCH;
189// pitch = 1/16*INCH;
190// starts=3;
191// xdistribute(19){
192// intersection(){
193// threaded_rod(l=40, pitch=pitch, d=d,starts=starts,anchor=BOTTOM,end_len=.44);
194// threaded_rod(l=40, pitch=pitch, d=d, left_handed=true,starts=starts,anchor=BOTTOM);
195// }
196// threaded_nut(nutwidth=4.5/8*INCH,id=d,h=3/8*INCH,pitch=pitch,starts=starts,anchor=BOTTOM);
197// threaded_nut(nutwidth=4.5/8*INCH,id=d,h=3/8*INCH,pitch=pitch,starts=starts,left_handed=true,anchor=BOTTOM);
198// }
199function threaded_rod(
200 d, l, pitch,
201 left_handed=false,
202 bevel,bevel1,bevel2,starts=1,
203 internal=false,
204 d1, d2, length, h, height,
205 blunt_start, blunt_start1, blunt_start2,
206 lead_in, lead_in1, lead_in2,
207 lead_in_ang, lead_in_ang1, lead_in_ang2,
208 end_len, end_len1, end_len2,
209 lead_in_shape="default",
210 anchor, spin, orient
211) = no_function("threaded_rod");
212
213module threaded_rod(
214 d, l, pitch,
215 left_handed=false,
216 bevel,bevel1,bevel2,starts=1,
217 internal=false,
218 d1, d2, length, h, height,
219 blunt_start, blunt_start1, blunt_start2,
220 lead_in, lead_in1, lead_in2,
221 lead_in_ang, lead_in_ang1, lead_in_ang2,
222 end_len, end_len1, end_len2,
223 lead_in_shape="default",
224 anchor, spin, orient
225) {
226 dummy1=
227 assert(all_positive(pitch))
228 assert(all_positive(d) || (is_undef(d) && all_positive([d1,d2])));
229 basic = is_num(d) || is_undef(d) || is_def(d1) || is_def(d2);
230 dummy2 = assert(basic || is_vector(d,3));
231 depth = basic ? cos(30) * 5/8
232 : (d[2] - d[0])/2/pitch;
233 crestwidth = basic ? 1/8 : 1/2 - (d[2]-d[1])/sqrt(3)/pitch;
234 profile = [
235 [-depth/sqrt(3)-crestwidth/2, -depth],
236 [ -crestwidth/2, 0],
237 [ crestwidth/2, 0],
238 [ depth/sqrt(3)+crestwidth/2, -depth]
239 ];
240 oprofile = internal? [
241 [-6/16, -depth],
242 [-1/16, 0],
243 [-1/32, 0.02],
244 [ 1/32, 0.02],
245 [ 1/16, 0],
246 [ 6/16, -depth]
247 ] : [
248 [-7/16, -depth*1.07],
249 [-6/16, -depth],
250 [-1/16, 0],
251 [ 1/16, 0],
252 [ 6/16, -depth],
253 [ 7/16, -depth*1.07]
254 ];
255 generic_threaded_rod(
256 d=basic ? d : d[2], d1=d1, d2=d2, l=l,
257 pitch=pitch,
258 profile=profile,starts=starts,
259 left_handed=left_handed,
260 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
261 internal=internal, length=length, height=height, h=h,
262 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
263 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
264 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
265 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
266 anchor=anchor,
267 spin=spin,
268 orient=orient
269 ) children();
270}
271
272
273
274// Module: threaded_nut()
275// Synopsis: Creates an UTS/ISO triangular threaded nut.
276// SynTags: Geom
277// Topics: Threading, Screws
278// See Also: threaded_rod()
279// Usage:
280// threaded_nut(nutwidth, id, h|height|thickness, pitch,...) [ATTACHMENTS];
281// Description:
282// Constructs a hex nut or square nut for an ISO (metric) or UTS (English) threaded rod.
283// The inner diameter is measured from the bottom of the threads.
284// Arguments:
285// nutwidth = flat to flat width of nut
286// id = inner diameter of threaded hole, measured from bottom of threads
287// h / height / l / length / thickness = height/thickness of nut.
288// pitch = Distance between threads, or zero for no threads.
289// ---
290// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
291// left_handed = if true, create left-handed threads. Default = false
292// starts = The number of lead starts. Default: 1
293// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
294// bevel1 = if true, bevel the outside of the nut bottom.
295// bevel2 = if true, bevel the outside of the nut top.
296// bevang = set the angle for the outside nut bevel. Default: 30
297// ibevel = if true, bevel the inside (the hole). Default: true
298// ibevel1 = if true bevel the inside, bottom end.
299// ibevel2 = if true bevel the inside, top end.
300// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
301// blunt_start1 = If true apply truncated blunt start threads bottom end.
302// blunt_start2 = If true apply truncated blunt start threads top end.
303// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
304// end_len1 = Specify unthreaded length at the bottom
305// end_len2 = Specify unthreaded length at the top
306// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
307// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
308// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
309// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
310// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
311// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
312// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
313// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
314// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
315// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
316// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
317// Examples(Med):
318// threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, $slop=0.05, $fa=1, $fs=1);
319// threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, left_handed=true, bevel=false, $slop=0.1, $fa=1, $fs=1);
320// threaded_nut(shape="square", nutwidth=16, id=8, h=8, pitch=1.25, $slop=0.1, $fa=1, $fs=1);
321// threaded_nut(shape="square", nutwidth=16, id=8, h=8, pitch=1.25, bevel2=true, $slop=0.1, $fa=1, $fs=1);
322// rot(90)threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25,blunt_start=false, $slop=0.1, $fa=1, $fs=1);
323function threaded_nut(
324 nutwidth, id, h,
325 pitch, starts=1, shape="hex", left_handed=false, bevel, bevel1, bevel2, id1,id2,
326 ibevel1, ibevel2, ibevel, bevang=30, thickness, height,
327 length, l,
328 blunt_start, blunt_start1, blunt_start2,
329 lead_in, lead_in1, lead_in2,
330 lead_in_ang, lead_in_ang1, lead_in_ang2,
331 end_len, end_len1, end_len2,
332 lead_in_shape="default",
333 anchor, spin, orient
334)=no_function("threaded_nut");
335module threaded_nut(
336 nutwidth, id, h,
337 pitch, starts=1, shape="hex", left_handed=false, bevel, bevel1, bevel2, id1,id2,
338 ibevel1, ibevel2, ibevel, bevang=30, thickness, height,
339 length, l,
340 blunt_start, blunt_start1, blunt_start2,
341 lead_in, lead_in1, lead_in2,
342 lead_in_ang, lead_in_ang1, lead_in_ang2,
343 end_len, end_len1, end_len2,
344 lead_in_shape="default",
345 anchor, spin, orient
346) {
347 dummy1=
348 assert(all_nonnegative(pitch), "Nut pitch must be nonnegative")
349 assert(all_positive(id), "Nut inner diameter must be positive")
350 assert(all_positive(h),"Nut thickness must be positive");
351 basic = is_num(id) || is_undef(id) || is_def(id1) || is_def(id2);
352 dummy2 = assert(basic || is_vector(id,3));
353 depth = basic ? cos(30) * 5/8
354 : (id[2] - id[0])/2/pitch;
355 crestwidth = basic ? 1/8 : 1/2 - (id[2]-id[1])/sqrt(3)/pitch;
356 profile = [
357 [-depth/sqrt(3)-crestwidth/2, -depth],
358 [ -crestwidth/2, 0],
359 [ crestwidth/2, 0],
360 [ depth/sqrt(3)+crestwidth/2, -depth]
361 ];
362 oprofile = [
363 [-6/16, -depth/pitch],
364 [-1/16, 0],
365 [-1/32, 0.02],
366 [ 1/32, 0.02],
367 [ 1/16, 0],
368 [ 6/16, -depth/pitch]
369 ];
370 generic_threaded_nut(
371 nutwidth=nutwidth,
372 id=basic ? id : id[2], id1=id1, id2=id2,
373 h=h,
374 pitch=pitch,
375 profile=profile,starts=starts,shape=shape,
376 left_handed=left_handed,
377 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
378 ibevel1=ibevel1, ibevel2=ibevel2, ibevel=ibevel,
379 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
380 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
381 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
382 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
383 l=l,length=length,
384 anchor=anchor, spin=spin,
385 orient=orient
386 ) children();
387}
388
389// Section: Trapezoidal Threading
390
391
392// Module: trapezoidal_threaded_rod()
393// Synopsis: Creates a trapezoidal threaded rod.
394// SynTags: Geom
395// Topics: Threading, Screws
396// See Also: trapezoidal_threaded_nut()
397// Usage:
398// trapezoidal_threaded_rod(d, l|length, pitch, [thread_angle=|flank_angle=], [thread_depth=], [internal=], ...) [ATTACHMENTS];
399// Description:
400// Constructs a threaded rod with a symmetric trapezoidal thread. Trapezoidal threads are used for lead screws because
401// they are one of the strongest symmetric profiles. This tooth shape is stronger than a similarly
402// sized square thread becuase of its wider base. However, it does place a radial load on the nut, unlike the square thread.
403// For loads in only one direction the asymmetric buttress thread profile can bear greater loads.
404// .
405// By default produces the nominal dimensions
406// for metric trapezoidal threads: a thread angle of 30 degrees and a depth set to half the pitch.
407// You can also specify your own trapezoid parameters. For ACME threads see acme_threaded_rod().
408// Figure(2D,Med,NoAxes):
409// pa_delta = tan(15)/4;
410// rr1 = -1/2;
411// z1 = 1/4-pa_delta;
412// z2 = 1/4+pa_delta;
413// profile = [
414// [-z2, rr1],
415// [-z1, 0],
416// [ z1, 0],
417// [ z2, rr1],
418// ];
419// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
420// stroke(fullprofile,width=1);
421// dir = fullprofile[2]-fullprofile[3];
422// dir2 = fullprofile[5]-fullprofile[4];
423// curve = arc(32,angle=[75,105],r=67.5);
424// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
425// color("red"){
426// stroke([fullprofile[2]+.1*dir, fullprofile[2]+.4*dir], width=1);
427// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
428// stroke(move(-curve[0]+avgpt,p=curve), width=1,endcaps="arrow2");
429// back(10)text("thread",size=4,halign="center");
430// back(3)text("angle",size=4,halign="center");
431// }
432// Figure(2D,Med,NoAxes):
433// pa_delta = tan(15)/4;
434// rr1 = -1/2;
435// z1 = 1/4-pa_delta;
436// z2 = 1/4+pa_delta;
437// profile = [
438// [-z2, rr1],
439// [-z1, 0],
440// [ z1, 0],
441// [ z2, rr1],
442// ];
443// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
444// stroke(fullprofile,width=1);
445// dir = fullprofile[2]-fullprofile[3];
446// dir2 = fullprofile[5]-fullprofile[4];
447// curve = arc(15,angle=[75,87],r=40 /*67.5*/);
448// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
449// color("red"){
450// stroke([fullprofile[4]+[0,1], fullprofile[4]+[0,37]], width=1);
451// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
452// stroke(move(-curve[0]+avgpt,p=curve), width=0.71,endcaps="arrow2");
453// right(14)back(19)text("flank",size=4,halign="center");
454// right(14)back(14)text("angle",size=4,halign="center");
455// }
456// Arguments:
457// d = Outer diameter of threaded rod.
458// l / length / h / height = Length of threaded rod.
459// pitch = Thread spacing.
460// ---
461// thread_angle = Angle between two thread faces. Default: 30
462// thread_depth = Depth of threads. Default: pitch/2
463// flank_angle = Angle of thread faces to plane perpendicular to screw.
464// left_handed = If true, create left-handed threads. Default: false
465// starts = The number of lead starts. Default: 1
466// bevel = if true, bevel the thread ends. Default: false
467// bevel1 = if true bevel the bottom end.
468// bevel2 = if true bevel the top end.
469// internal = If true, make this a mask for making internal threads. Default: false
470// d1 = Bottom outside diameter of threads.
471// d2 = Top outside diameter of threads.
472// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
473// blunt_start1 = If true apply truncated blunt start threads bottom end.
474// blunt_start2 = If true apply truncated blunt start threads top end.
475// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
476// end_len1 = Specify unthreaded length at the bottom
477// end_len2 = Specify unthreaded length at the top
478// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
479// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
480// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
481// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
482// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
483// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
484// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
485// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
486// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
487// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
488// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
489// Example(2D):
490// projection(cut=true)
491// trapezoidal_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
492// Examples(Med):
493// trapezoidal_threaded_rod(d=10, l=40, pitch=2, $fn=32); // Standard metric threading
494// rot(-65)trapezoidal_threaded_rod(d=10, l=17, pitch=2, blunt_start=false, $fn=32); // Standard metric threading
495// trapezoidal_threaded_rod(d=10, l=17, pitch=2, bevel=true, $fn=32); // Standard metric threading
496// trapezoidal_threaded_rod(d=10, h=30, pitch=2, left_handed=true, $fa=1, $fs=1); // Standard metric threading
497// trapezoidal_threaded_rod(d=10, l=40, pitch=3, left_handed=true, starts=3, $fn=36);
498// trapezoidal_threaded_rod(l=25, d=10, pitch=2, starts=3, $fa=1, $fs=1, bevel=true, orient=RIGHT, anchor=BOTTOM);
499// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, blunt_start=false, $fa=2, $fs=2);
500// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, end_len=0, $fa=2, $fs=2);
501// trapezoidal_threaded_rod(d=60, l=16, pitch=8, thread_depth=3, thread_angle=90, left_handed=true, starts=4, $fa=2, $fs=2,end_len=0);
502// trapezoidal_threaded_rod(d=16, l=40, pitch=2, thread_angle=60);
503// trapezoidal_threaded_rod(d=25, l=40, pitch=10, thread_depth=8/3, thread_angle=100, starts=4, anchor=BOT, $fa=2, $fs=2,end_len=-2);
504// trapezoidal_threaded_rod(d=50, l=35, pitch=8, thread_angle=60, starts=11, lead_in=3, $fn=120);
505// trapezoidal_threaded_rod(d=10, l=40, end_len2=10, pitch=2, $fn=32); // Unthreaded top end section
506// Example(Med): Using as a Mask to Make Internal Threads
507// bottom_half() difference() {
508// cube(50, center=true);
509// trapezoidal_threaded_rod(d=40, l=51, pitch=5, thread_angle=30, internal=true, bevel=true, orient=RIGHT, $fn=36);
510// }
511function trapezoidal_threaded_rod(
512 d, l, pitch,
513 thread_angle,
514 thread_depth,
515 flank_angle,
516 left_handed=false,
517 bevel,bevel1,bevel2,
518 starts=1,
519 internal=false,
520 d1, d2, length, h, height,
521 blunt_start, blunt_start1, blunt_start2,
522 lead_in, lead_in1, lead_in2,
523 lead_in_ang, lead_in_ang1, lead_in_ang2,
524 end_len, end_len1, end_len2,
525 lead_in_shape="default",
526 anchor, spin, orient
527) = no_function("trapezoidal_threaded_rod");
528module trapezoidal_threaded_rod(
529 d, l, pitch,
530 thread_angle,
531 thread_depth,
532 flank_angle,
533 left_handed=false,
534 bevel,bevel1,bevel2,
535 starts=1,
536 internal=false,
537 d1, d2, length, h, height,
538 blunt_start, blunt_start1, blunt_start2,
539 lead_in, lead_in1, lead_in2,
540 lead_in_ang, lead_in_ang1, lead_in_ang2,
541 end_len, end_len1, end_len2,
542 lead_in_shape="default",
543 anchor, spin, orient
544) {
545 dummy0 = assert(num_defined([thread_angle,flank_angle])<=1, "Cannot define both flank angle and thread angle");
546 thread_angle = first_defined([thread_angle, u_mul(2,flank_angle), 30]);
547 dummy1 = assert(all_nonnegative(pitch),"Must give a positive pitch value")
548 assert(thread_angle>=0 && thread_angle<180, "Invalid thread angle or flank angle")
549 assert(thread_angle<=90 || all_positive([thread_depth]),
550 "Thread angle (2*flank_angle) must be smaller than 90 degrees with default thread depth of pitch/2");
551 depth = first_defined([thread_depth,pitch/2]);
552 pa_delta = 0.5*depth*tan(thread_angle/2) / pitch;
553 dummy2 = assert(pa_delta<=1/4, "Specified thread geometry is impossible");
554 rr1 = -depth/pitch;
555 z1 = 1/4-pa_delta;
556 z2 = 1/4+pa_delta;
557 profile = [
558 [-z2, rr1],
559 [-z1, 0],
560 [ z1, 0],
561 [ z2, rr1],
562 ];
563 generic_threaded_rod(d=d,l=l,pitch=pitch,profile=profile,
564 left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts,d1=d1,d2=d2,
565 internal=internal, length=length, height=height, h=h,
566 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
567 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
568 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
569 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
570 anchor=anchor,spin=spin,orient=orient)
571 children();
572}
573
574
575// Module: trapezoidal_threaded_nut()
576// Synopsis: Creates a trapezoidal threaded nut.
577// SynTags: Geom
578// Topics: Threading, Screws
579// See Also: trapezoidal_threaded_rod()
580// Usage:
581// trapezoidal_threaded_nut(nutwidth, id, h|height|thickness, pitch, [thread_angle=|flank_angle=], [thread_depth], ...) [ATTACHMENTS];
582// Description:
583// Constructs a hex nut or square nut for a symmetric trapzoidal threaded rod. By default produces
584// the nominal dimensions for metric trapezoidal threads: a thread angle of 30 degrees and a depth
585// set to half the pitch. You can also specify your own trapezoid parameters. For ACME threads see
586// acme_threaded_nut().
587// Arguments:
588// nutwidth = flat to flat width of nut
589// id = inner diameter of threaded hole, measured from bottom of threads
590// h / height / l / length / thickness = height/thickness of nut.
591// pitch = Thread spacing.
592// ---
593// thread_angle = Angle between two thread faces. Default: 30
594// thread_depth = Depth of the threads. Default: pitch/2
595// flank_angle = Angle of thread faces to plane perpendicular to screw.
596// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
597// left_handed = if true, create left-handed threads. Default = false
598// starts = The number of lead starts. Default = 1
599// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
600// bevel1 = if true, bevel the outside of the nut bottom.
601// bevel2 = if true, bevel the outside of the nut top.
602// bevang = set the angle for the outside nut bevel. Default: 30
603// ibevel = if true, bevel the inside (the hole). Default: true
604// ibevel1 = if true bevel the inside, bottom end.
605// ibevel2 = if true bevel the inside, top end.
606// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
607// blunt_start1 = If true apply truncated blunt start threads bottom end.
608// blunt_start2 = If true apply truncated blunt start threads top end.
609// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
610// end_len1 = Specify unthreaded length at the bottom
611// end_len2 = Specify unthreaded length at the top
612// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
613// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
614// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
615// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
616// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
617// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
618// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
619// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
620// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
621// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
622// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
623// Examples(Med):
624// trapezoidal_threaded_nut(nutwidth=16, id=8, h=8, pitch=2, $slop=0.1, anchor=UP);
625// trapezoidal_threaded_nut(nutwidth=16, id=8, h=8, pitch=2, bevel=false, $slop=0.05, anchor=UP);
626// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, $slop=0.1, left_handed=true);
627// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15);
628// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=2, starts=3, $fa=1, $fs=1, $slop=0.15, blunt_start=false);
629// trapezoidal_threaded_nut(nutwidth=17.4, id=10, h=10, pitch=0, $slop=0.2); // No threads
630function trapezoidal_threaded_nut(
631 nutwidth,
632 id,
633 h,
634 pitch,
635 thread_angle,
636 thread_depth, shape="hex",
637 flank_angle,
638 left_handed=false,
639 starts=1,
640 bevel,bevel1,bevel2,bevang=30,
641 ibevel1,ibevel2,ibevel,
642 thickness,height,
643 id1,id2,
644 length, l,
645 blunt_start, blunt_start1, blunt_start2,
646 lead_in, lead_in1, lead_in2,
647 lead_in_ang, lead_in_ang1, lead_in_ang2,
648 end_len, end_len1, end_len2,
649 lead_in_shape="default",
650 anchor, spin, orient
651) = no_function("trapezoidal_threaded_nut");
652module trapezoidal_threaded_nut(
653 nutwidth,
654 id,
655 h,
656 pitch,
657 thread_angle,
658 thread_depth, shape="hex",
659 flank_angle,
660 left_handed=false,
661 starts=1,
662 bevel,bevel1,bevel2,bevang=30,
663 ibevel1,ibevel2,ibevel,
664 thickness,height,
665 id1,id2,
666 length, l,
667 blunt_start, blunt_start1, blunt_start2,
668 lead_in, lead_in1, lead_in2,
669 lead_in_ang, lead_in_ang1, lead_in_ang2,
670 end_len, end_len1, end_len2,
671 lead_in_shape="default",
672 anchor, spin, orient
673) {
674 dummy0 = assert(num_defined([thread_angle,flank_angle])<=1, "Cannot define both flank angle and thread angle");
675 thread_angle = first_defined([thread_angle, u_mul(2,flank_angle), 30]);
676 dummy1 = assert(all_nonnegative(pitch),"Must give a positive pitch value")
677 assert(thread_angle>=0 && thread_angle<180, "Invalid thread angle or flank angle")
678 assert(thread_angle<=90 || all_positive([thread_depth]),
679 "Thread angle (2*flank_angle) must be smaller than 90 degrees with default thread depth of pitch/2");
680 depth = first_defined([thread_depth,pitch/2]);
681 pa_delta = 0.5*depth*tan(thread_angle/2) / pitch;
682 dummy2 = assert(pitch==0 || pa_delta<1/4, "Specified thread geometry is impossible");
683 rr1 = -depth/pitch;
684 z1 = 1/4-pa_delta;
685 z2 = 1/4+pa_delta;
686 profile = [
687 [-z2, rr1],
688 [-z1, 0],
689 [ z1, 0],
690 [ z2, rr1],
691 ];
692 generic_threaded_nut(nutwidth=nutwidth,id=id,h=h,pitch=pitch,profile=profile,id1=id1,id2=id2,
693 shape=shape,left_handed=left_handed,bevel=bevel,bevel1=bevel1,bevel2=bevel2,starts=starts,
694 ibevel=ibevel,ibevel1=ibevel1,ibevel2=ibevel2,bevang=bevang,height=height,thickness=thickness,
695 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
696 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
697 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
698 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
699 l=l,length=length,
700 anchor=anchor,spin=spin,orient=orient)
701 children();
702}
703
704
705// Module: acme_threaded_rod()
706// Synopsis: Creates an ACME threaded rod.
707// SynTags: Geom
708// Topics: Threading, Screws
709// See Also: acme_threaded_nut()
710// Usage:
711// acme_threaded_rod(d, l|length, tpi|pitch=, [internal=], ...) [ATTACHMENTS];
712// Description:
713// Constructs an ACME trapezoidal threaded screw rod. This form has a 29 degree thread angle with a
714// symmetric trapezoidal thread.
715// Arguments:
716// d = Outer diameter of threaded rod.
717// l / length / h / height = Length of threaded rod.
718// tpi = threads per inch.
719// ---
720// pitch = thread spacing (alternative to tpi)
721// starts = The number of lead starts. Default = 1
722// left_handed = if true, create left-handed threads. Default = false
723// bevel = if true, bevel the thread ends. Default: false
724// bevel1 = if true bevel the bottom end.
725// bevel2 = if true bevel the top end.
726// internal = If true, this is a mask for making internal threads.
727// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
728// blunt_start1 = If true apply truncated blunt start threads bottom end.
729// blunt_start2 = If true apply truncated blunt start threads top end.
730// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
731// end_len1 = Specify unthreaded length at the bottom
732// end_len2 = Specify unthreaded length at the top
733// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
734// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
735// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
736// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
737// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
738// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
739// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
740// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
741// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
742// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
743// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
744// Example(2D):
745// projection(cut=true)
746// acme_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
747// Examples(Med):
748// acme_threaded_rod(d=3/8*INCH, l=20, pitch=1/8*INCH, $fn=32);
749// acme_threaded_rod(d=10, l=30, pitch=2, starts=3, $fa=1, $fs=1);
750function acme_threaded_rod(
751 d, l, tpi, pitch,
752 starts=1,
753 left_handed=false,
754 bevel,bevel1,bevel2,
755 internal=false,
756 d1, d2, length, h, height,
757 blunt_start, blunt_start1, blunt_start2,
758 lead_in, lead_in1, lead_in2,
759 lead_in_ang, lead_in_ang1, lead_in_ang2,
760 end_len, end_len1, end_len2,
761 lead_in_shape="default",
762 anchor, spin, orient
763) = no_function("acme_threaded_rod");
764module acme_threaded_rod(
765 d, l, tpi, pitch,
766 starts=1,
767 left_handed=false,
768 bevel,bevel1,bevel2,
769 internal=false,
770 d1, d2, length, h, height,
771 blunt_start, blunt_start1, blunt_start2,
772 lead_in, lead_in1, lead_in2,
773 lead_in_ang, lead_in_ang1, lead_in_ang2,
774 end_len, end_len1, end_len2,
775 lead_in_shape="default",
776 anchor, spin, orient
777) {
778 dummy = assert(num_defined([pitch,tpi])==1,"Must give exactly one of pitch and tpi");
779 pitch = is_undef(pitch) ? INCH/tpi : pitch;
780 trapezoidal_threaded_rod(
781 d=d, l=l, pitch=pitch,
782 thread_angle=29,
783 thread_depth=pitch/2,
784 starts=starts,
785 left_handed=left_handed,
786 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
787 internal=internal, length=length, height=height, h=h,
788 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
789 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
790 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
791 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
792 anchor=anchor,
793 spin=spin,
794 orient=orient
795 ) children();
796}
797
798
799
800// Module: acme_threaded_nut()
801// Synopsis: Creates an ACME threaded nut.
802// SynTags: Geom
803// Topics: Threading, Screws
804// See Also: acme_threaded_rod()
805// Usage:
806// acme_threaded_nut(nutwidth, id, h|height|thickness, tpi|pitch=, [shape=], ...) [ATTACHMENTS];
807// Description:
808// Constructs a hexagonal or square nut for an ACME threaded screw rod.
809// Arguments:
810// nutwidth = flat to flat width of nut.
811// id = inner diameter of threaded hole, measured from bottom of threads
812// h / height / l / length / thickness = height/thickness of nut.
813// tpi = threads per inch
814// ---
815// pitch = Thread spacing (alternative to tpi)
816// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
817// left_handed = if true, create left-handed threads. Default = false
818// starts = Number of lead starts. Default: 1
819// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
820// bevel1 = if true, bevel the outside of the nut bottom.
821// bevel2 = if true, bevel the outside of the nut top.
822// bevang = set the angle for the outside nut bevel. Default: 30
823// ibevel = if true, bevel the inside (the hole). Default: true
824// ibevel1 = if true bevel the inside, bottom end.
825// ibevel2 = if true bevel the inside, top end.
826// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
827// blunt_start1 = If true apply truncated blunt start threads bottom end.
828// blunt_start2 = If true apply truncated blunt start threads top end.
829// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
830// end_len1 = Specify unthreaded length at the bottom
831// end_len2 = Specify unthreaded length at the top
832// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
833// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
834// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
835// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
836// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
837// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
838// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
839// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
840// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
841// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
842// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
843// Examples(Med):
844// acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=8, tpi=8, $slop=0.05);
845// acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1, ibevel=false);
846// acme_threaded_nut(nutwidth=16, id=3/8*INCH, h=10, tpi=12, starts=3, $slop=0.1, $fa=1, $fs=1, blunt_start=false);
847function acme_threaded_nut(
848 nutwidth, id, h, tpi, pitch,
849 starts=1,
850 left_handed=false,shape="hex",
851 bevel,bevel1,bevel2,bevang=30,
852 ibevel,ibevel1,ibevel2,
853 height,thickness,
854 length, l,
855 blunt_start, blunt_start1, blunt_start2,
856 lead_in, lead_in1, lead_in2,
857 lead_in_ang, lead_in_ang1, lead_in_ang2,
858 end_len, end_len1, end_len2,
859 lead_in_shape="default",
860 anchor, spin, orient
861) = no_function("acme_threaded_nut");
862module acme_threaded_nut(
863 nutwidth, id, h, tpi, pitch,
864 starts=1,
865 left_handed=false,shape="hex",
866 bevel,bevel1,bevel2,bevang=30,
867 ibevel,ibevel1,ibevel2,
868 height,thickness,
869 length, l,
870 blunt_start, blunt_start1, blunt_start2,
871 lead_in, lead_in1, lead_in2,
872 lead_in_ang, lead_in_ang1, lead_in_ang2,
873 end_len, end_len1, end_len2,
874 lead_in_shape="default",
875 anchor, spin, orient
876) {
877 dummy = assert(num_defined([pitch,tpi])==1,"Must give exactly one of pitch and tpi");
878 pitch = is_undef(pitch) ? INCH/tpi : pitch;
879 dummy2=assert(is_num(pitch) && pitch>=0);
880 trapezoidal_threaded_nut(
881 nutwidth=nutwidth, id=id, h=h, pitch=pitch,
882 thread_depth = pitch/2,
883 thread_angle=29,shape=shape,
884 left_handed=left_handed,
885 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
886 ibevel=ibevel,ibevel1=ibevel1,ibevel2=ibevel2,
887 height=height,thickness=thickness,
888 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
889 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
890 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
891 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
892 l=l,length=length,
893 starts=starts,
894 anchor=anchor,
895 spin=spin,
896 orient=orient
897 ) children();
898}
899
900
901
902
903// Section: Pipe Threading
904
905// Module: npt_threaded_rod()
906// Synopsis: Creates NPT pipe threading.
907// SynTags: Geom
908// Topics: Threading, Screws
909// See Also: acme_threaded_rod()
910// Usage:
911// npt_threaded_rod(size, [internal=], ...) [ATTACHMENTS];
912// Description:
913// Constructs a standard NPT pipe end threading. If `internal=true`, creates a mask for making
914// internal pipe threads. Tapers smaller upwards if `internal=false`. Tapers smaller downwards
915// if `internal=true`. If `hollow=true` and `internal=false`, then the pipe threads will be
916// hollowed out into a pipe with the apropriate internal diameter.
917// Arguments:
918// 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"
919// ---
920// left_handed = If true, create left-handed threads. Default = false
921// bevel = if true, bevel the thread ends. Default: false
922// bevel1 = if true bevel the bottom end.
923// bevel2 = if true bevel the top end.
924// hollow = If true, create a pipe with the correct internal diameter.
925// internal = If true, make this a mask for making internal threads.
926// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
927// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
928// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
929// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
930// Example(2D): The straight gray rectangle reveals the tapered threads.
931// projection(cut=true) npt_threaded_rod(size=1/4, orient=BACK);
932// right(.533*INCH/2) color("gray") rect([2,0.5946*INCH],anchor=LEFT);
933// Examples(Med):
934// npt_threaded_rod(size=3/8, $fn=72);
935// npt_threaded_rod(size=1/2, $fn=72, bevel=true);
936// npt_threaded_rod(size=1/2, left_handed=true, $fn=72);
937// npt_threaded_rod(size=3/4, hollow=true, $fn=96);
938// Example:
939// diff("remove"){
940// cuboid([40,40,40])
941// tag("remove"){
942// up(.01)position(TOP)
943// npt_threaded_rod(size=3/4, $fn=96, internal=true, $slop=0.1, anchor=TOP);
944// cyl(d=3/4*INCH, l=42, $fn=32);
945// }
946// }
947function npt_threaded_rod(
948 size=1/2,
949 left_handed=false,
950 bevel,bevel1,bevel2,
951 hollow=false,
952 internal=false,
953 anchor, spin, orient
954)=no_function("npt_threaded_rod");
955module npt_threaded_rod(
956 size=1/2,
957 left_handed=false,
958 bevel,bevel1,bevel2,
959 hollow=false,
960 internal=false,
961 anchor, spin, orient
962) {
963 assert(is_finite(size));
964 assert(is_bool(left_handed));
965 assert(is_undef(bevel) || is_bool(bevel));
966 assert(is_bool(hollow));
967 assert(is_bool(internal));
968 assert(!(internal&&hollow), "Cannot created a hollow internal threads mask.");
969 info_table = [
970 // Size len OD TPI
971 [ 1/16, [ 0.3896, 0.308, 27 ]],
972 [ 1/8, [ 0.3924, 0.401, 27 ]],
973 [ 1/4, [ 0.5946, 0.533, 18 ]],
974 [ 3/8, [ 0.6006, 0.668, 18 ]],
975 [ 1/2, [ 0.7815, 0.832, 14 ]],
976 [ 3/4, [ 0.7935, 1.043, 14 ]],
977 [ 1, [ 0.9845, 1.305, 11.5]],
978 [ 1+1/4, [ 1.0085, 1.649, 11.5]],
979 [ 1+1/2, [ 1.0252, 1.888, 11.5]],
980 [ 2, [ 1.0582, 2.362, 11.5]],
981 ];
982 info = [for (data=info_table) if(approx(size,data[0])) data[1]][0];
983 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");
984 l = INCH * info[0];
985 d = INCH * info[1];
986 pitch = INCH / info[2];
987 rr = d/2;
988 rr2 = rr - l/32;
989 r1 = internal? rr2 : rr;
990 r2 = internal? rr : rr2;
991 depth = pitch * cos(30) * 5/8;
992 profile = internal? [
993 [-6/16, -depth/pitch],
994 [-1/16, 0],
995 [-1/32, 0.02],
996 [ 1/32, 0.02],
997 [ 1/16, 0],
998 [ 6/16, -depth/pitch]
999 ] : [
1000 [-7/16, -depth/pitch*1.07],
1001 [-6/16, -depth/pitch],
1002 [-1/16, 0],
1003 [ 1/16, 0],
1004 [ 6/16, -depth/pitch],
1005 [ 7/16, -depth/pitch*1.07]
1006 ];
1007 attachable(anchor,spin,orient, l=l, r1=r1, r2=r2) {
1008 difference() {
1009 generic_threaded_rod(
1010 d1=2*r1, d2=2*r2, l=l,
1011 pitch=pitch,
1012 profile=profile,
1013 left_handed=left_handed,
1014 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1015 internal=internal,
1016 blunt_start=true
1017 );
1018 if (hollow) cylinder(h=l+1, d=size*INCH, center=true);
1019 }
1020 children();
1021 }
1022}
1023
1024
1025
1026// Section: Buttress Threading
1027
1028// Module: buttress_threaded_rod()
1029// Synopsis: Creates a buttress-threaded rod.
1030// SynTags: Geom
1031// Topics: Threading, Screws
1032// See Also: buttress_threaded_nut()
1033// Usage:
1034// buttress_threaded_rod(d, l|length, pitch, [internal=], ...) [ATTACHMENTS];
1035// Description:
1036// Constructs a simple buttress threaded rod with a 45 degree angle. The buttress thread or sawtooth thread has low friction and high loading
1037// in one direction at the cost of higher friction and inferior loading in the other direction. Buttress threads are sometimes used on
1038// vises, which are loaded only in one direction.
1039// Arguments:
1040// d = Outer diameter of threaded rod.
1041// l / length / h / height = Length of threaded rod.
1042// pitch = Thread spacing.
1043// ---
1044// left_handed = if true, create left-handed threads. Default = false
1045// starts = Number of lead starts. Default: 1
1046// bevel = if true, bevel the thread ends. Default: false
1047// bevel1 = if true bevel the bottom end.
1048// bevel2 = if true bevel the top end.
1049// internal = If true, this is a mask for making internal threads.
1050// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1051// blunt_start1 = If true apply truncated blunt start threads bottom end.
1052// blunt_start2 = If true apply truncated blunt start threads top end.
1053// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1054// end_len1 = Specify unthreaded length at the bottom
1055// end_len2 = Specify unthreaded length at the top
1056// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1057// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1058// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1059// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1060// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1061// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1062// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1063// d1 = Bottom outside diameter of threads.
1064// d2 = Top outside diameter of threads.
1065// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1066// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1067// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1068// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1069// Example(2D):
1070// projection(cut=true)
1071// buttress_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
1072// Examples(Med):
1073// buttress_threaded_rod(d=25, l=20, pitch=2, $fa=1, $fs=1,end_len=0);
1074// buttress_threaded_rod(d=10, l=20, pitch=1.25, left_handed=true, $fa=1, $fs=1);
1075function buttress_threaded_rod(
1076 d, l, pitch,
1077 left_handed=false, starts=1,
1078 bevel,bevel1,bevel2,
1079 internal=false,
1080 d1, d2, length, h, height,
1081 blunt_start, blunt_start1, blunt_start2,
1082 lead_in, lead_in1, lead_in2,
1083 lead_in_ang, lead_in_ang1, lead_in_ang2,
1084 end_len, end_len1, end_len2,
1085 lead_in_shape="default",
1086 anchor, spin, orient
1087) = no_function("buttress_threaded_rod");
1088module buttress_threaded_rod(
1089 d, l, pitch,
1090 left_handed=false, starts=1,
1091 bevel,bevel1,bevel2,
1092 internal=false,
1093 d1, d2, length, h, height,
1094 blunt_start, blunt_start1, blunt_start2,
1095 lead_in, lead_in1, lead_in2,
1096 lead_in_ang, lead_in_ang1, lead_in_ang2,
1097 end_len, end_len1, end_len2,
1098 lead_in_shape="default",
1099 anchor, spin, orient
1100) {
1101 depth = pitch * 3/4;
1102 profile = [
1103 [ -1/2, -0.77],
1104 [ -7/16, -0.75],
1105 [ 5/16, 0],
1106 [ 7/16, 0],
1107 [ 7/16, -0.75],
1108 [ 1/2, -0.77],
1109 ];
1110 generic_threaded_rod(
1111 d=d, l=l, pitch=pitch,
1112 profile=profile,
1113 left_handed=left_handed,
1114 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1115 internal=internal, length=length, height=height, h=h,
1116 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1117 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1118 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1119 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1120 d1=d1,d2=d2,
1121 anchor=anchor,
1122 spin=spin,starts=starts,
1123 orient=orient
1124 ) children();
1125}
1126
1127
1128
1129// Module: buttress_threaded_nut()
1130// Synopsis: Creates a buttress-threaded nut.
1131// SynTags: Geom
1132// Topics: Threading, Screws
1133// See Also: buttress_threaded_rod()
1134// Usage:
1135// buttress_threaded_nut(nutwidth, id, h|height|thickness, pitch, ...) [ATTACHMENTS];
1136// Description:
1137// Constructs a hexagonal or square nut for a simple buttress threaded screw rod.
1138// Arguments:
1139// nutwidth = diameter of the nut.
1140// id = inner diameter of threaded hole, measured from bottom of threads
1141// h / height / l / length / thickness = height/thickness of nut.
1142// pitch = Thread spacing.
1143// ---
1144// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
1145// left_handed = if true, create left-handed threads. Default = false
1146// starts = The number of lead starts. Default: 1
1147// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
1148// bevel1 = if true, bevel the outside of the nut bottom.
1149// bevel2 = if true, bevel the outside of the nut top.
1150// bevang = set the angle for the outside nut bevel. Default: 30
1151// ibevel = if true, bevel the inside (the hole). Default: true
1152// ibevel1 = if true bevel the inside, bottom end.
1153// ibevel2 = if true bevel the inside, top end.
1154// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1155// blunt_start1 = If true apply truncated blunt start threads bottom end.
1156// blunt_start2 = If true apply truncated blunt start threads top end.
1157// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1158// end_len1 = Specify unthreaded length at the bottom
1159// end_len2 = Specify unthreaded length at the top
1160// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1161// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1162// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1163// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1164// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1165// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1166// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1167// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1168// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1169// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1170// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1171// Examples(Med):
1172// buttress_threaded_nut(nutwidth=16, id=8, h=8, pitch=1.25, left_handed=true, $slop=0.05, $fa=1, $fs=1);
1173function buttress_threaded_nut(
1174 nutwidth, id, h,
1175 pitch, shape="hex", left_handed=false,
1176 bevel,bevel1,bevel2,bevang=30,starts=1,
1177 ibevel,ibevel1,ibevel2,height,thickness,
1178 length, l,
1179 blunt_start, blunt_start1, blunt_start2,
1180 lead_in, lead_in1, lead_in2,
1181 lead_in_ang, lead_in_ang1, lead_in_ang2,
1182 end_len, end_len1, end_len2,
1183 lead_in_shape="default",
1184 anchor, spin, orient
1185) = no_function("buttress_threaded_nut");
1186module buttress_threaded_nut(
1187 nutwidth, id, h,
1188 pitch, shape="hex", left_handed=false,
1189 bevel,bevel1,bevel2,bevang=30,starts=1,
1190 ibevel,ibevel1,ibevel2,height,thickness,
1191 length, l,
1192 blunt_start, blunt_start1, blunt_start2,
1193 lead_in, lead_in1, lead_in2,
1194 lead_in_ang, lead_in_ang1, lead_in_ang2,
1195 end_len, end_len1, end_len2,
1196 lead_in_shape="default",
1197 anchor, spin, orient
1198) {
1199 depth = pitch * 3/4;
1200 profile = [
1201 [ -1/2, -0.77],
1202 [ -7/16, -0.75],
1203 [ 5/16, 0],
1204 [ 7/16, 0],
1205 [ 7/16, -0.75],
1206 [ 1/ 2, -0.77],
1207 ];
1208 generic_threaded_nut(
1209 nutwidth=nutwidth, id=id, h=h,
1210 pitch=pitch,
1211 profile=profile,
1212 shape=shape,
1213 left_handed=left_handed,starts=starts,
1214 bevel=bevel,bevel1=bevel1,bevel2=bevel2,bevang=bevang,
1215 ibevel=ibevel,ibevel1=ibevel1,ibevel2=ibevel2,
1216 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1217 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1218 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1219 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1220 l=l,length=length,
1221 anchor=anchor, spin=spin, height=height, thickness=thickness,
1222 orient=orient
1223 ) children();
1224}
1225
1226
1227
1228// Section: Square Threading
1229
1230// Module: square_threaded_rod()
1231// Synopsis: Creates a square-threaded rod.
1232// SynTags: Geom
1233// Topics: Threading, Screws
1234// See Also: square_threaded_nut()
1235// Usage:
1236// square_threaded_rod(d, l|length, pitch, [internal=], ...) [ATTACHMENTS];
1237// Description:
1238// Constructs a square profile threaded screw rod. The greatest advantage of square threads is
1239// that they have the least friction and a much higher intrinsic efficiency than trapezoidal threads.
1240// They produce no radial load on the nut. However, square threads cannot carry as much load as trapezoidal threads.
1241// Arguments:
1242// d = Outer diameter of threaded rod.
1243// l / length / h / height = Length of threaded rod.
1244// pitch = Thread spacing.
1245// ---
1246// left_handed = if true, create left-handed threads. Default = false
1247// starts = The number of lead starts. Default = 1
1248// bevel = if true, bevel the thread ends. Default: false
1249// bevel1 = if true bevel the bottom end.
1250// bevel2 = if true bevel the top end.
1251// internal = If true, this is a mask for making internal threads.
1252// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1253// blunt_start1 = If true apply truncated blunt start threads bottom end.
1254// blunt_start2 = If true apply truncated blunt start threads top end.
1255// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1256// end_len1 = Specify unthreaded length at the bottom
1257// end_len2 = Specify unthreaded length at the top
1258// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1259// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1260// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1261// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1262// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1263// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1264// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1265// d1 = Bottom outside diameter of threads.
1266// d2 = Top outside diameter of threads.
1267// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1268// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1269// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1270// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1271// Example(2D):
1272// projection(cut=true)
1273// square_threaded_rod(d=10, l=15, pitch=2, orient=BACK);
1274// Examples(Med):
1275// square_threaded_rod(d=10, l=20, pitch=2, starts=2, $fn=32);
1276function square_threaded_rod(
1277 d, l, pitch,
1278 left_handed=false,
1279 bevel,bevel1,bevel2,
1280 starts=1,
1281 internal=false,
1282 d1, d2, length, h, height,
1283 blunt_start, blunt_start1, blunt_start2,
1284 lead_in, lead_in1, lead_in2,
1285 lead_in_ang, lead_in_ang1, lead_in_ang2,
1286 end_len, end_len1, end_len2,
1287 lead_in_shape="default",
1288 anchor, spin, orient
1289) = no_function("square_threaded_rod");
1290module square_threaded_rod(
1291 d, l, pitch,
1292 left_handed=false,
1293 bevel,bevel1,bevel2,
1294 starts=1,
1295 internal=false,
1296 d1, d2, length, h, height,
1297 blunt_start, blunt_start1, blunt_start2,
1298 lead_in, lead_in1, lead_in2,
1299 lead_in_ang, lead_in_ang1, lead_in_ang2,
1300 end_len, end_len1, end_len2,
1301 lead_in_shape="default",
1302 anchor, spin, orient
1303) {
1304 trapezoidal_threaded_rod(
1305 d=d, l=l, pitch=pitch,
1306 thread_angle=0.1,
1307 left_handed=left_handed,
1308 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1309 starts=starts,
1310 internal=internal, length=length, height=height, h=h,
1311 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1312 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1313 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1314 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1315 d1=d1,
1316 d2=d2,
1317 anchor=anchor,
1318 spin=spin,
1319 orient=orient
1320 ) children();
1321}
1322
1323
1324
1325// Module: square_threaded_nut()
1326// Synopsis: Creates a square-threaded nut.
1327// SynTags: Geom
1328// Topics: Threading, Screws
1329// See Also: square_threaded_rod()
1330// Usage:
1331// square_threaded_nut(nutwidth, id, h|height|thickness, pitch, ...) [ATTACHMENTS];
1332// Description:
1333// Constructs a hexagonal or square nut for a square profile threaded screw rod.
1334// Arguments:
1335// nutwidth = diameter of the nut.
1336// id = inner diameter of threaded hole, measured from bottom of threads
1337// h / height / l / length / thickness = height/thickness of nut.
1338// pitch = Length between threads.
1339// ---
1340// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
1341// left_handed = if true, create left-handed threads. Default = false
1342// starts = The number of lead starts. Default = 1
1343// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
1344// bevel1 = if true, bevel the outside of the nut bottom.
1345// bevel2 = if true, bevel the outside of the nut top.
1346// bevang = set the angle for the outside nut bevel. Default: 30
1347// ibevel = if true, bevel the inside (the hole). Default: true
1348// ibevel1 = if true bevel the inside, bottom end.
1349// ibevel2 = if true bevel the inside, top end.
1350// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1351// blunt_start1 = If true apply truncated blunt start threads bottom end.
1352// blunt_start2 = If true apply truncated blunt start threads top end.
1353// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1354// end_len1 = Specify unthreaded length at the bottom
1355// end_len2 = Specify unthreaded length at the top
1356// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1357// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1358// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1359// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1360// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1361// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1362// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1363// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1364// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1365// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1366// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1367// Examples(Med):
1368// square_threaded_nut(nutwidth=16, id=10, h=10, pitch=2, starts=2, $slop=0.1, $fn=32);
1369function square_threaded_nut(
1370 nutwidth, id, h,
1371 pitch,
1372 left_handed=false,
1373 bevel,bevel1,bevel2,bevang=30,
1374 ibevel,ibevel1,ibevel2,
1375 height,thickness,
1376 length, l,
1377 blunt_start, blunt_start1, blunt_start2,
1378 lead_in, lead_in1, lead_in2,
1379 lead_in_ang, lead_in_ang1, lead_in_ang2,
1380 end_len, end_len1, end_len2,
1381 lead_in_shape="default",
1382 starts=1,
1383 anchor, spin, orient
1384) = no_function("square_threaded_nut");
1385module square_threaded_nut(
1386 nutwidth, id, h,
1387 pitch,
1388 left_handed=false,
1389 bevel,bevel1,bevel2,bevang=30,
1390 ibevel,ibevel1,ibevel2,
1391 height,thickness,
1392 length, l,
1393 blunt_start, blunt_start1, blunt_start2,
1394 lead_in, lead_in1, lead_in2,
1395 lead_in_ang, lead_in_ang1, lead_in_ang2,
1396 end_len, end_len1, end_len2,
1397 lead_in_shape="default",
1398 starts=1,
1399 anchor, spin, orient
1400) {
1401 assert(is_num(pitch) && pitch>=0)
1402 trapezoidal_threaded_nut(
1403 nutwidth=nutwidth, id=id, h=h, pitch=pitch,
1404 thread_angle=0,
1405 left_handed=left_handed,
1406 bevel=bevel,bevel1=bevel1,bevel2=bevel2, bevang=bevang,
1407 ibevel=ibevel, ibevel1=ibevel1, ibevel2=ibevel2,
1408 height=height,thickness=thickness,
1409 starts=starts,
1410 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1411 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1412 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1413 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1414 l=l,length=length,
1415 anchor=anchor,
1416 spin=spin,
1417 orient=orient
1418 ) children();
1419}
1420
1421
1422// Section: Ball Screws
1423
1424// Module: ball_screw_rod()
1425// Synopsis: Creates a ball screw rod.
1426// SynTags: Geom
1427// Topics: Threading, Screws
1428// Usage:
1429// ball_screw_rod(d, l|length, pitch, [ball_diam], [ball_arc], [internal=], ...) [ATTACHMENTS];
1430// Description:
1431// Constructs a ball screw rod. This type of rod is used with ball bearings.
1432// Arguments:
1433// d = Outer diameter of threaded rod.
1434// l / length / h / height = Length of threaded rod.
1435// pitch = Thread spacing. Also, the diameter of the ball bearings used.
1436// ball_diam = The diameter of the ball bearings to use with this ball screw.
1437// ball_arc = The arc portion that should touch the ball bearings. Default: 120 degrees.
1438// ---
1439// left_handed = if true, create left-handed threads. Default = false
1440// starts = The number of lead starts. Default = 1
1441// bevel = if true, bevel the thread ends. Default: false
1442// bevel1 = if true bevel the bottom end.
1443// bevel2 = if true bevel the top end.
1444// internal = If true, make this a mask for making internal threads.
1445// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1446// blunt_start1 = If true apply truncated blunt start threads bottom end.
1447// blunt_start2 = If true apply truncated blunt start threads top end.
1448// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1449// end_len1 = Specify unthreaded length at the bottom
1450// end_len2 = Specify unthreaded length at the top
1451// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1452// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1453// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1454// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1455// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1456// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1457// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1458// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1459// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1460// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1461// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1462// Example(2D): Thread Profile, ball_diam=4, ball_arc=100
1463// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=4, ball_arc=100, orient=BACK, $fn=24, blunt_start=false);
1464// Example(2D): Thread Profile, ball_diam=4, ball_arc=120
1465// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=4, ball_arc=120, orient=BACK, $fn=24, blunt_start=false);
1466// Example(2D): Thread Profile, ball_diam=3, ball_arc=120
1467// projection(cut=true) ball_screw_rod(d=10, l=15, pitch=5, ball_diam=3, ball_arc=120, orient=BACK, $fn=24, blunt_start=false);
1468// Examples(Med):
1469// ball_screw_rod(d=15, l=20, pitch=8, ball_diam=5, ball_arc=120, $fa=1, $fs=0.5, blunt_start=false);
1470// ball_screw_rod(d=15, l=20, pitch=5, ball_diam=4, ball_arc=120, $fa=1, $fs=0.5, blunt_start=false);
1471// ball_screw_rod(d=15, l=20, pitch=5, ball_diam=4, ball_arc=120, left_handed=true, $fa=1, $fs=0.5, blunt_start=false);
1472function ball_screw_rod(
1473 d, l, pitch,
1474 ball_diam=5, ball_arc=100,
1475 starts=1,
1476 left_handed=false,
1477 internal=false,
1478 length, h, height,
1479 bevel, bevel1, bevel2,
1480 blunt_start, blunt_start1, blunt_start2,
1481 lead_in, lead_in1, lead_in2,
1482 lead_in_ang, lead_in_ang1, lead_in_ang2,
1483 end_len, end_len1, end_len2,
1484 lead_in_shape="default",
1485 anchor, spin, orient
1486) = no_function("ball_screw_rod");
1487module ball_screw_rod(
1488 d, l, pitch,
1489 ball_diam=5, ball_arc=100,
1490 starts=1,
1491 left_handed=false,
1492 internal=false,
1493 length, h, height,
1494 bevel, bevel1, bevel2,
1495 blunt_start, blunt_start1, blunt_start2,
1496 lead_in, lead_in1, lead_in2,
1497 lead_in_ang, lead_in_ang1, lead_in_ang2,
1498 end_len, end_len1, end_len2,
1499 lead_in_shape="default",
1500 anchor, spin, orient
1501) {
1502 n = max(3,ceil(segs(ball_diam/2)*ball_arc/2/360));
1503 depth = ball_diam * (1-cos(ball_arc/2))/2;
1504 cpy = ball_diam/2/pitch*cos(ball_arc/2);
1505 profile = [
1506 each arc(n=n, d=ball_diam/pitch, cp=[-0.5,cpy], start=270, angle=ball_arc/2),
1507 each arc(n=n, d=ball_diam/pitch, cp=[+0.5,cpy], start=270-ball_arc/2, angle=ball_arc/2)
1508 ];
1509 generic_threaded_rod(
1510 d=d, l=l, pitch=pitch,
1511 profile=profile,
1512 left_handed=left_handed,
1513 starts=starts,
1514 bevel=bevel,bevel1=bevel1,bevel2=bevel2,
1515 internal=internal, length=length, height=height, h=h,
1516 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1517 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1518 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1519 end_len=end_len, end_len1=end_len1, end_len2=end_len2,
1520 anchor=anchor,
1521 spin=spin,
1522 orient=orient
1523 ) children();
1524}
1525
1526
1527// Section: Generic Threading
1528
1529// Module: generic_threaded_rod()
1530// Synopsis: Creates a generic threaded rod.
1531// SynTags: Geom
1532// Topics: Threading, Screws
1533// See Also: generic_threaded_nut()
1534// Usage:
1535// generic_threaded_rod(d, l|length, pitch, profile, [internal=], ...) [ATTACHMENTS];
1536// Description:
1537// Constructs a generic threaded rod using an arbitrary thread profile that you supply. The rod can be tapered
1538// (e.g. for pipe threads). For specific thread types use other modules that supply the appropriate profile.
1539// .
1540// You give the profile as a 2D path that will be scaled by the pitch to produce the final thread shape. The profile
1541// X values must be between -1/2 and 1/2. The Y=0 point will align with the specified rod diameter, so generally you
1542// want a Y value of zero at the peak (which makes your specified diameter the outer diameter of the threads). The
1543// value in the valleys of the thread should then be `-depth/pitch` due to the scaling by the thread pitch. The first
1544// and last points should generally have the same Y value, but it is not necessary to give values at X=1/2 or X=-1/2
1545// if unless the Y values differ from the interior points in the profile. Generally you should center the profile
1546// horizontally in the interval [-1/2, 1/2].
1547// .
1548// If internal is true then produce a thread mask to difference from an object. When internal is true the rod
1549// diameter is enlarged to correct for the polygonal nature of circles to ensure that the internal diameter is the
1550// specified size. The diameter is also increased by `4 * $slop` to create clearance for threading by allowing a `2 *
1551// $slop` gap on each side. If bevel is set to true and internal is false then the ends of the rod will be beveled.
1552// 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
1553// bevel when subtracted from an object. The bevel is at 45 deg and is the depth of the threads.
1554// .
1555// Blunt start threading, which is the default, specifies that the thread ends abruptly at its full width instead of
1556// running off the end of the shaft and leaving a sharp edged partial thread at the end of the screw. This makes
1557// screws easier to start and prevents cross threading. Blunt start threads should always be superior, and they are
1558// faster to model, but if you really need standard threads that run off the end you can set `blunt_start=false`.
1559// Arguments:
1560// d = Outer diameter of threaded rod.
1561// l / length / h / height = Length of threaded rod.
1562// pitch = Thread spacing.
1563// profile = A 2D path giving the shape of a thread
1564// ---
1565// left_handed = If true, create left-handed threads. Default: false
1566// starts = The number of lead starts. Default: 1
1567// internal = If true, make this a mask for making internal threads. Default: false
1568// d1 = Bottom outside diameter of threads.
1569// d2 = Top outside diameter of threads.
1570// bevel = set to true to bevel both ends, a number to specify a bevel size, false for no bevel, and "reverse" for an inverted bevel
1571// bevel1 = set bevel for bottom end.
1572// bevel2 = set bevel for top end.
1573// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1574// blunt_start1 = If true apply truncated blunt start threads bottom end.
1575// blunt_start2 = If true apply truncated blunt start threads top end.
1576// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1577// end_len1 = Specify unthreaded length at the bottom
1578// end_len2 = Specify unthreaded length at the top
1579// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1580// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1581// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1582// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1583// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1584// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1585// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1586// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1587// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1588// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1589// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1590// Example(2DMed): Example Tooth Profile
1591// pitch = 2;
1592// depth = pitch * cos(30) * 5/8;
1593// profile = [
1594// [-7/16, -depth/pitch*1.07],
1595// [-6/16, -depth/pitch],
1596// [-1/16, 0],
1597// [ 1/16, 0],
1598// [ 6/16, -depth/pitch],
1599// [ 7/16, -depth/pitch*1.07]
1600// ];
1601// stroke(profile, width=0.02);
1602// Example:
1603// pitch = 2;
1604// depth = pitch * cos(30) * 5/8;
1605// profile = [
1606// [-7/16, -depth/pitch*1.07],
1607// [-6/16, -depth/pitch],
1608// [-1/16, 0],
1609// [ 1/16, 0],
1610// [ 6/16, -depth/pitch],
1611// [ 7/16, -depth/pitch*1.07]
1612// ];
1613// generic_threaded_rod(d=10, l=40, pitch=2, profile=profile);
1614
1615function generic_threaded_rod(
1616 d, l, pitch, profile,
1617 left_handed=false, internal=false,
1618 bevel, bevel1, bevel2,
1619 starts=1,
1620 d1, d2, length, h, height,
1621 blunt_start, blunt_start1, blunt_start2,
1622 lead_in, lead_in1, lead_in2,
1623 lead_in_ang, lead_in_ang1, lead_in_ang2,
1624 end_len, end_len1, end_len2,
1625 lead_in_shape="default",
1626 anchor, spin, orient
1627) = no_function("generic_threaded_rod");
1628module generic_threaded_rod(
1629 d, l, pitch, profile,
1630 left_handed=false, internal=false,
1631 bevel, bevel1, bevel2,
1632 starts=1,
1633 d1, d2, length, h, height,
1634 blunt_start, blunt_start1, blunt_start2,
1635 lead_in, lead_in1, lead_in2,
1636 lead_in_ang, lead_in_ang1, lead_in_ang2,
1637 end_len, end_len1, end_len2,
1638 lead_in_shape="default",
1639 anchor, spin, orient
1640) {
1641 len = one_defined([l,length,h,height],"l,length,h,height");
1642 bevel1 = first_defined([bevel1,bevel]);
1643 bevel2 = first_defined([bevel2,bevel]);
1644 blunt_start1 = first_defined([blunt_start1, blunt_start, true]);
1645 blunt_start2 = first_defined([blunt_start2, blunt_start, true]);
1646 r1 = get_radius(d1=d1, d=d);
1647 r2 = get_radius(d1=d2, d=d);
1648 lead_in1 = first_defined([lead_in1, lead_in]);
1649 lead_in2 = first_defined([lead_in2, lead_in]);
1650 lead_in_func = is_func(lead_in_shape) ? lead_in_shape
1651 : assert(is_string(lead_in_shape),"lead_in_shape must be a function or string")
1652 let(ind = search([lead_in_shape], _lead_in_table,0)[0])
1653 assert(ind!=[],str("Unknown lead_in_shape, \"",lead_in_shape,"\""))
1654 _lead_in_table[ind[0]][1];
1655 dummy0 =
1656 assert(all_positive([pitch]),"Thread pitch must be a positive value")
1657 assert(all_positive([len]),"Length must be a postive value")
1658 assert(is_path(profile),"Profile must be a path")
1659 assert(is_bool(blunt_start1), "blunt_start1/blunt_start must be boolean")
1660 assert(is_bool(blunt_start2), "blunt_start2/blunt_start must be boolean")
1661 assert(is_bool(left_handed))
1662 assert(all_positive([r1,r2]), "Must give d or both d1 and d2 as positive values")
1663 assert(is_undef(bevel1) || is_num(bevel1) || is_bool(bevel1) || bevel1=="reverse", "bevel1/bevel must be a number, boolean or \"reverse\"")
1664 assert(is_undef(bevel2) || is_num(bevel2) || is_bool(bevel2) || bevel2=="reverse", "bevel2/bevel must be a number, boolean or \"reverse\"");
1665 sides = quantup(segs(max(r1,r2)), starts);
1666 rsc = internal? (1/cos(180/sides)) : 1; // Internal radius adjusted for faceting
1667 islop = internal? 2*get_slop() : 0;
1668 r1adj = r1 * rsc + islop;
1669 r2adj = r2 * rsc + islop;
1670
1671 extreme = internal? max(column(profile,1)) : min(column(profile,1));
1672 profile = !internal ? profile
1673 : let(
1674 maxidx = [for(i=idx(profile)) if (profile[i].y==extreme) i],
1675 cutpt = len(maxidx)==1 ? profile(maxidx[0]).x
1676 : mean([profile[maxidx[0]].x, profile[maxidx[1]].x])
1677 )
1678 [
1679 for(entry=profile) if (entry.x>=cutpt) [entry.x-cutpt-1/2,entry.y],
1680 for(entry=profile) if (entry.x<cutpt) [entry.x-cutpt+1/2,entry.y]
1681 ];
1682 profmin = pitch * min(column(profile,1));
1683 pmax = pitch * max(column(profile,1));
1684 rmax = max(r1adj,r2adj)+pmax;
1685
1686 // These parameters give the size of the bevel, negative for an outward bevel (e.g. on internal thread mask)
1687 bev1 = (bevel1=="reverse"?-1:1)*(internal?-1:1) *
1688 ( is_num(bevel1)? bevel1
1689 : bevel1==false? 0
1690 : blunt_start1? (bevel1==undef?0
1691 :internal ? r1/6
1692 :(r1+profmin)/6)
1693 : pmax-profmin);
1694 bev2 = (bevel2=="reverse"?-1:1)*(internal?-1:1) *
1695 ( is_num(bevel2)? bevel2
1696 : bevel2==false? 0
1697 : blunt_start2? (bevel2==undef?0
1698 :internal ? r2/6
1699 :(r2+profmin)/6)
1700 : pmax-profmin);
1701 // This is the bevel size used for constructing the polyhedron. The bevel is integrated when blunt start is on, but
1702 // applied later via difference/union if blunt start is off, so set bevel to zero in the latter case.
1703 bevel_size1 = blunt_start1?bev1:0;
1704 bevel_size2 = blunt_start2?bev2:0;
1705 // This is the bevel size for clipping, which is only done when blunt start is off
1706 clip_bev1 = blunt_start1?0:bev1;
1707 clip_bev2 = blunt_start2?0:bev2;
1708 end_len1_base = !blunt_start1? 0 : first_defined([end_len1,end_len, 0]);
1709 end_len2_base = !blunt_start2? 0 : first_defined([end_len2,end_len, 0]);
1710 // Enlarge end lengths to give sufficient room for requested bevel
1711 end_len1 = abs(bevel_size1)>0 ? max(end_len1_base, abs(bevel_size1)) : end_len1_base;
1712 end_len2 = abs(bevel_size2)>0 ? max(end_len2_base, abs(bevel_size2)) : end_len2_base;
1713 // length to create below/above z=0, with an extra revolution in non-blunt-start case so
1714 // the threads can continue to the specified length and we can clip off the blunt start
1715 len1 = -len/2 - (blunt_start1?0:pitch);
1716 len2 = len/2 + (blunt_start2?0:pitch);
1717
1718 // Thread turns below and above z=0, with extra to ensure we go beyond the length needed
1719 turns1 = len1/pitch-1;
1720 turns2 = len2/pitch+1;
1721 dir = left_handed? -1 : 1;
1722 dummy2=
1723 assert(abs(bevel_size1)+abs(bevel_size2)<len, "Combined bevel size exceeds length of screw")
1724 assert(r1adj+extreme*pitch-bevel_size1>0, "bevel1 is too large to fit screw diameter")
1725 assert(r2adj+extreme*pitch-bevel_size2>0, "bevel2 is too large to fit screw diameter");
1726
1727 margin1 = profile[0].y==extreme ? profile[0].x : -1/2;
1728 margin2 = last(profile).y==extreme? last(profile).x : 1/2;
1729 lead_in_default = pmax-profmin;//2*pitch;
1730 // 0*360/10;// /4/32*360; higlen_default;//0*4/32*360; //2/32*360;//360*max(pitch/2, pmax-depth)/(2*PI*r2adj);
1731 // lead_in length needs to be quantized to match the samples
1732 lead_in_ang1 = !blunt_start1? 0 :
1733 let(
1734 user_ang = first_defined([lead_in_ang1,lead_in_ang])
1735 )
1736 assert(is_undef(user_ang) || is_undef(lead_in1), "Cannot define lead_in/lead_in1 by both length and angle")
1737 quantup(
1738 is_def(user_ang) ? user_ang : default(lead_in1, lead_in_default)*360/(2*PI*r1adj)
1739 , 360/sides);
1740 lead_in_ang2 = !blunt_start2? 0 :
1741 let(
1742 user_ang = first_defined([lead_in_ang2,lead_in_ang])
1743 )
1744 assert(is_undef(user_ang) || is_undef(lead_in2), "Cannot define lead_in/lead_in2 by both length and angle")
1745 quantup(
1746 is_def(user_ang) ? user_ang : default(lead_in2, lead_in_default)*360/(2*PI*r2adj)
1747 , 360/sides);
1748 // cut_ang also need to be quantized, but the comparison is offset by 36*turns1/starts, so we need to pull that factor out
1749 // of the quantization. (The loop over angle starts at 360*turns1/starts, not at a multiple of 360/sides.)
1750// cut_ang1 = 360 * (len1/pitch-margin1+end_len1/pitch) / starts + lead_in_ang1;
1751// cut_ang2 = 360 * (len2/pitch-margin2-end_len2/pitch) / starts - lead_in_ang2;
1752 cut_ang1 = quantup(360 * (len1/pitch-margin1+end_len1/pitch) / starts + lead_in_ang1-360*turns1/starts,360/sides)+360*turns1/starts;
1753 cut_ang2 = quantdn(360 * (len2/pitch-margin2-end_len2/pitch) / starts - lead_in_ang2-360*turns1/starts,360/sides)+360*turns1/starts;
1754 dummy1 =
1755 assert(cut_ang1<cut_ang2, "lead in length are too long for the amount of thread: they overlap")
1756 assert(is_num(lead_in_ang1), "lead_in1/lead_in must be a number")
1757 assert(r1adj+profmin>0 && r2adj+profmin>0, "Screw profile deeper than rod radius");
1758 map_threads = right((r1adj + r2adj) / 2) // Shift profile out to thread radius
1759 * affine3d_skew(sxz=(r2adj-r1adj)/len) // Skew correction for tapered threads
1760 * frame_map(x=[0,0,1], y=[1,0,0]) // Map profile to 3d, parallel to z axis
1761 * scale(pitch); // scale profile by pitch
1762 start_steps = sides / starts;
1763
1764 // This is the location for clipping the polyhedron, below the bevel, if one is present, or at length otherwise
1765 // Clipping is done before scaling to pitch, so we need to divide by the pitch
1766 rod_clip1 = (len1+abs(bevel_size1))/pitch;
1767 rod_clip2 = (len2-abs(bevel_size2))/pitch;
1768 prof3d=path3d(profile,1);
1769 thread_verts = [
1770 // Outer loop constructs a vertical column of the screw at each angle
1771 // covering 360/starts degrees of the cylinder.
1772 for (step = [0:1:start_steps])
1773 let(
1774 ang = 360 * step/sides,
1775 dz = step / start_steps, // z offset for threads at this angle
1776 rot_prof = zrot(ang*dir)*map_threads, // Rotate profile to correct angular location
1777 full_profile = [ // profile for the entire rod
1778 for (turns = [turns1:1:turns2])
1779 let(
1780 tang = turns/starts * 360 + ang,
1781 // EPSILON offset prevents funny looking extensions of the thread from its very tip
1782 // by forcing values near the tip to evaluate as less than zero = beyond the tip end
1783 hsc = tang < cut_ang1 ? lead_in_func(-EPSILON+1-(cut_ang1-tang)/lead_in_ang1,PI*2*r1adj*lead_in_ang1/360 )
1784 : tang > cut_ang2 ? lead_in_func(-EPSILON+1-(tang-cut_ang2)/lead_in_ang2,PI*2*r2adj*lead_in_ang2/360 )
1785 : [1,1],
1786 shift_and_scale = [[hsc.x, 0], [0,hsc.y], [dz+turns,(1-hsc.y)*extreme]]
1787 )
1788 // This is equivalent to apply(right(dz+turns)*higscale, profile)
1789 //
1790 // The right movement finds the position of the thread along
1791 // what will be the z axis after the profile is mapped to 3d,
1792 // and higscale creates a taper and the end of the threads.
1793 each prof3d*shift_and_scale
1794 ],
1795 // Clip profile at the ends of the rod and add a z coordinate
1796 full_profile_clipped = [
1797 for(pts=full_profile) [max(rod_clip1,min(rod_clip2,pts.x)), pts.y, 0]
1798 ]
1799 )
1800 [
1801 [0,0,len1],
1802 //if (true) apply(rot_prof, [len1/pitch,extreme+2/pitch ,0]),
1803 if (bevel_size1) apply(rot_prof, [len1/pitch,extreme-bevel_size1/pitch ,0]),
1804 each apply(rot_prof, full_profile_clipped),
1805 if (bevel_size2) apply(rot_prof, [len2/pitch,extreme-bevel_size2/pitch ,0]),
1806 //if (true) apply(rot_prof, [len2/pitch,extreme+2/pitch ,0]),
1807 [0, 0, len2]
1808 ]
1809 ];
1810 style=internal?"concave":"convex";
1811 thread_vnf = vnf_join([
1812 for (i=[0:1:starts-1])
1813 zrot(i*360/starts, p=vnf_vertex_array(thread_verts, reverse=left_handed, style=style,col_wrap=false)),
1814 ]);
1815 slope = (r1adj-r2adj)/len;
1816 dummy3 =
1817 assert(r1adj+pmax-clip_bev1>0, "bevel1 is too large to fit screw diameter")
1818 assert(r2adj+pmax-clip_bev2>0, "bevel2 is too large to fit screw diameter")
1819 assert(abs(clip_bev1)+abs(clip_bev2)<len, "Combined bevel size exceeds length of screw");
1820 attachable(anchor,spin,orient, r1=r1adj, r2=r2adj, l=len) {
1821 union(){
1822 difference() {
1823 vnf_polyhedron(thread_vnf,convexity=10);
1824 if (clip_bev1>0)
1825 rotate_extrude()
1826 polygon([[ 0,-len/2],
1827 [r1adj+pmax-clip_bev1 ,-len/2],
1828 [r1adj+pmax-slope*clip_bev1,-len/2+clip_bev1],
1829 [ rmax+1,-len/2+clip_bev1],
1830 [ rmax+1, len1-1],
1831 [ 0, len1-1]]);
1832 if (clip_bev2>0)
1833 rotate_extrude()
1834 polygon([[ 0, len/2],
1835 [r2adj+pmax-clip_bev2 , len/2],
1836 [r2adj+pmax+slope*clip_bev2, len/2-clip_bev2],
1837 [ rmax+1, len/2-clip_bev2],
1838 [ rmax+1, len2+1],
1839 [ 0, len2+1]]);
1840 if (!blunt_start1 && clip_bev1<=0)
1841 down(len/2) cuboid([2*rmax+1,2*rmax+1, -len1+1], anchor=TOP);
1842 if (!blunt_start2 && clip_bev2<=0)
1843 up(len/2) cuboid([2*rmax+1,2*rmax+1, len2+1], anchor=BOTTOM);
1844 }
1845
1846 // Add bevel for internal thread mask
1847 if (clip_bev1<0)
1848 down(len/2+.001)cyl(l=-clip_bev1, r2=r1adj+profmin, r1=r1adj+profmin+slope*clip_bev1-clip_bev1,anchor=BOTTOM);
1849 if (clip_bev2<0)
1850 up(len/2+.001)cyl(l=-clip_bev2, r1=r2adj+profmin, r2=r2adj+profmin+slope*clip_bev1-clip_bev2,anchor=TOP);
1851 }
1852 children();
1853 }
1854}
1855
1856
1857
1858// Module: generic_threaded_nut()
1859// Synopsis: Creates a generic threaded nut.
1860// SynTags: Geom
1861// Topics: Threading, Screws
1862// See Also: generic_threaded_rod()
1863// Usage:
1864// generic_threaded_nut(nutwidth, id, h|height|thickness, pitch, profile, [$slop], ...) [ATTACHMENTS];
1865// Description:
1866// Constructs a hexagonal or square nut for an generic threaded rod using a user-supplied thread profile.
1867// See {{generic_threaded_rod()}} for details on the profile specification.
1868// Arguments:
1869// nutwidth = outer dimension of nut from flat to flat.
1870// id = inner diameter of threaded hole, measured from bottom of threads
1871// h / height / thickness = height/thickness of nut.
1872// pitch = Thread spacing.
1873// profile = Thread profile.
1874// ---
1875// shape = specifies shape of nut, either "hex" or "square". Default: "hex"
1876// left_handed = if true, create left-handed threads. Default = false
1877// starts = The number of lead starts. Default = 1
1878// id1 = inner diameter at the bottom
1879// id2 = inner diameter at the top
1880// bevel = if true, bevel the outside of the nut. Default: true for hex nuts, false for square nuts
1881// bevel1 = if true, bevel the outside of the nut bottom.
1882// bevel2 = if true, bevel the outside of the nut top.
1883// bevang = set the angle for the outside nut bevel. Default: 30
1884// ibevel = if true, bevel the inside (the hole). Default: true
1885// ibevel1 = if true bevel the inside, bottom end.
1886// ibevel2 = if true bevel the inside, top end.
1887// blunt_start = If true apply truncated blunt start threads at both ends. Default: true
1888// blunt_start1 = If true apply truncated blunt start threads bottom end.
1889// blunt_start2 = If true apply truncated blunt start threads top end.
1890// end_len = Specify the unthreaded length at the end after blunt start threads. Default: 0
1891// end_len1 = Specify unthreaded length at the bottom
1892// end_len2 = Specify unthreaded length at the top
1893// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
1894// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
1895// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
1896// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
1897// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
1898// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
1899// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
1900// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
1901// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
1902// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
1903// $slop = The printer-specific slop value, which adds clearance (`4*$slop`) to internal threads.
1904function generic_threaded_nut(
1905 nutwidth,
1906 id,
1907 h,
1908 pitch,
1909 profile,
1910 shape="hex",
1911 left_handed=false,
1912 starts=1,
1913 bevel,bevel1,bevel2,bevang=30,
1914 ibevel, ibevel1, ibevel2,
1915 id1,id2, height, thickness,
1916 length, l,
1917 blunt_start, blunt_start1, blunt_start2,
1918 lead_in, lead_in1, lead_in2,
1919 lead_in_ang, lead_in_ang1, lead_in_ang2,
1920 end_len, end_len1, end_len2,
1921 lead_in_shape="default",
1922 anchor, spin, orient
1923) = no_function("generic_threaded_nut");
1924module generic_threaded_nut(
1925 nutwidth,
1926 id,
1927 h,
1928 pitch,
1929 profile,
1930 shape="hex",
1931 left_handed=false,
1932 starts=1,
1933 bevel,bevel1,bevel2,bevang=30,
1934 ibevel, ibevel1, ibevel2,
1935 id1,id2, height, thickness,
1936 length, l,
1937 blunt_start, blunt_start1, blunt_start2,
1938 lead_in, lead_in1, lead_in2,
1939 lead_in_ang, lead_in_ang1, lead_in_ang2,
1940 end_len, end_len1, end_len2,
1941 lead_in_shape="default",
1942 anchor, spin, orient
1943) {
1944
1945 extra = 0.01;
1946 id1 = first_defined([id1,id]);
1947 id2 = first_defined([id2,id]);
1948 h = one_defined([h,height,thickness,l,length],"h,height,thickness,l,length");
1949 dummyA = assert(is_num(pitch) && pitch>=0, "pitch must be a nonnegative number")
1950 assert(is_num(h) && h>0, "height/thickness must be a positive number")
1951 assert(in_list(shape,["square","hex"]), "shape must be \"hex\" or \"square\"")
1952 assert(all_positive([id1,id2]), "Inner diameter(s) of nut must be positive number(s)");
1953 slope = (id2-id1)/h;
1954 full_id1 = id1-slope*extra/2;
1955 full_id2 = id2+slope*extra/2;
1956 ibevel1 = first_defined([ibevel1,ibevel,true]);
1957 ibevel2 = first_defined([ibevel2,ibevel,true]);
1958 bevel1 = first_defined([bevel1,bevel,shape=="hex"?true:false]);
1959 bevel2 = first_defined([bevel2,bevel,shape=="hex"?true:false]);
1960 depth = -pitch*min(column(profile,1));
1961 IBEV=0.05;
1962 vnf = linear_sweep(hexagon(id=nutwidth), height=h, center=true);
1963 attachable(anchor,spin,orient, size=shape=="square" ? [nutwidth,nutwidth,h] : undef, vnf=shape=="hex" ? vnf : undef) {
1964 difference() {
1965 _nutshape(nutwidth,h, shape,bevel1,bevel2);
1966 if (pitch==0)
1967 cyl(l=h+extra, d1=full_id1+4*get_slop(), d2=full_id2+4*get_slop(),
1968 chamfer1=ibevel1?-IBEV*full_id1:undef,
1969 chamfer2=ibevel2?-IBEV*full_id2:undef);
1970 else
1971 generic_threaded_rod(
1972 d1=full_id1,d2=full_id2,
1973 l=h+extra,
1974 pitch=pitch,
1975 profile=profile,
1976 left_handed=left_handed,
1977 starts=starts,
1978 internal=true,
1979 bevel1=ibevel1,bevel2=ibevel2,
1980 blunt_start=blunt_start, blunt_start1=blunt_start1, blunt_start2=blunt_start2,
1981 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2, lead_in_shape=lead_in_shape,
1982 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
1983 end_len=end_len, end_len1=end_len1, end_len2=end_len2
1984 );
1985 }
1986 children();
1987 }
1988}
1989
1990
1991module _nutshape(nutwidth, h, shape, bevel1, bevel2)
1992{
1993 bevel_d=0.9;
1994 intersection(){
1995 if (shape=="hex")
1996 cyl(d=nutwidth, circum=true, $fn=6, l=h, chamfer1=bevel1?0:nutwidth*.01, chamfer2=bevel2?0:nutwidth*.01);
1997 //vnf_polyhedron(vnf);
1998 else
1999 cuboid([nutwidth,nutwidth,h],chamfer=nutwidth*.01, except=[if (bevel1) BOT, if(bevel2) TOP]);
2000 fn = quantup(segs(r=nutwidth/2),shape=="hex"?6:4);
2001 d = shape=="hex" ? 2*nutwidth/sqrt(3) : sqrt(2)*nutwidth;
2002 chamfsize = (d-nutwidth)/2/bevel_d;
2003 cyl(d=d*.99,h=h+.01,realign=true,circum=true,$fn=fn,chamfer1=bevel1?chamfsize:0,chamfer2=bevel2?chamfsize:0,chamfang=30);
2004 }
2005}
2006
2007
2008// Module: thread_helix()
2009// Synopsis: Creates a thread helix to add to a cylinder.
2010// SynTags: Geom
2011// Topics: Threading, Screws
2012// See Also: generic_threaded_rod()
2013// Usage:
2014// thread_helix(d, pitch, [thread_depth], [flank_angle], [turns], [profile=], [left_handed=], [higbee=], [internal=]);
2015// Description:
2016// Creates a right-handed helical thread with optional end tapering. Unlike
2017// {{generic_threaded_rod()}, this module just generates the thread, and you specify the total
2018// angle of threading that you want, which makes it easy to put complete threads onto a longer
2019// shaft. It also optionally makes a finely divided taper at the thread ends. However, it takes
2020// 2-3 times as long to render compared to {{generic_threaded_rod()}}. This module was designed
2021// to handle threads found in plastic and glass bottles.
2022// .
2023// You can specify a thread_depth and flank_angle, in which case you get a symmetric trapezoidal
2024// thread, whose inner diameter (the base of the threads for external threading) is d (so the
2025// total diameter will be d + thread_depth). This differs from the threaded_rod modules, where
2026// the specified diameter is the outer diameter. Alternatively you can give a profile, following
2027// the same rules as for general_threaded_rod. The Y=0 point will align with the specified
2028// diameter, and the profile should range in X from -1/2 to 1/2. You cannot specify both the
2029// profile and the thread_depth or flank_angle.
2030// .
2031// Unlike {{generic_threaded_rod()}, when internal=true this module generates the threads, not a thread mask.
2032// The profile needs to be inverted to produce the proper thread form. If you use the built-in trapezoidal
2033// thread you get the inverted thread, designed so that the inner diameter is d. If you supply a custom profile
2034// you must invert it yourself to get internal threads. With adequate clearance
2035// this thread will mate with the thread that uses the same parameters but has internal=false. Note that
2036// unlike the threaded_rod modules, thread_helix does not adjust the diameter for faceting, nor does it
2037// subtract any $slop for clearance.
2038// .
2039// The taper options specify tapering at of the threads at each end, and is given as the linear distance
2040// over which to taper. If taper is positive the threads are lengthened by the specified distance; if taper
2041// is negative, the taper is included in the thread length specified by `turns`. Tapering works on both internal and external threads.
2042// Figure(2D,Med,NoAxes):
2043// pa_delta = tan(15)/4;
2044// rr1 = -1/2;
2045// z1 = 1/4-pa_delta;
2046// z2 = 1/4+pa_delta;
2047// profile = [
2048// [-z2, rr1],
2049// [-z1, 0],
2050// [ z1, 0],
2051// [ z2, rr1],
2052// ];
2053// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
2054// stroke(fullprofile,width=1);
2055// dir = fullprofile[2]-fullprofile[3];
2056// dir2 = fullprofile[5]-fullprofile[4];
2057// curve = arc(15,angle=[75,87],r=40 /*67.5*/);
2058// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
2059// color("red"){
2060// stroke([fullprofile[4]+[0,1], fullprofile[4]+[0,37]], width=1);
2061// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
2062// stroke(move(-curve[0]+avgpt,p=curve), width=0.71,endcaps="arrow2");
2063// right(14)back(19)text("flank",size=4,halign="center");
2064// right(14)back(14)text("angle",size=4,halign="center");
2065// }
2066// Figure(2D,Med,NoAxes):
2067// pa_delta = tan(15)/4;
2068// rr1 = -1/2;
2069// z1 = 1/4-pa_delta;
2070// z2 = 1/4+pa_delta;
2071// profile = [
2072// [-z2, rr1],
2073// [-z1, 0],
2074// [ z1, 0],
2075// [ z2, rr1],
2076// ];
2077// fullprofile = 50*left(1/2,p=concat(profile, right(1, p=profile)));
2078// stroke(fullprofile,width=1);
2079// dir = fullprofile[2]-fullprofile[3];
2080// dir2 = fullprofile[5]-fullprofile[4];
2081// curve = arc(32,angle=[75,105],r=67.5);
2082// avgpt = mean([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2]);
2083// color("red"){
2084// stroke([fullprofile[2]+.1*dir, fullprofile[2]+.4*dir], width=1);
2085// stroke([fullprofile[5]+.1*dir2, fullprofile[5]+.4*dir2], width=1);
2086// stroke(move(-curve[0]+avgpt,p=curve), width=1,endcaps="arrow2");
2087// back(10)text("thread",size=4,halign="center");
2088// back(3)text("angle",size=4,halign="center");
2089// }
2090// Arguments:
2091// d = Base diameter of threads. Default: 10
2092// pitch = Distance between threads. Default: 2
2093// ---
2094// thread_depth = Depth of threads from top to bottom.
2095// flank_angle = Angle of thread faces to plane perpendicular to screw. Default: 15 degrees.
2096// turns = Number of revolutions to rotate thread around.
2097// thread_angle = Angle between two thread faces.
2098// profile = If an asymmetrical thread profile is needed, it can be specified here.
2099// starts = The number of thread starts. Default: 1
2100// left_handed = If true, thread has a left-handed winding.
2101// internal = if true make internal threads. The only effect this has is to change how the threads taper if tapering is selected. When true, threads taper towards the outside; when false, they taper towards the inside. Default: false
2102// d1 = Bottom inside base diameter of threads.
2103// d2 = Top inside base diameter of threads.
2104// thread_angle = Angle between
2105// lead_in = Specify linear length of the lead in section of the threading with blunt start threads
2106// lead_in1 = Specify linear length of the lead in section of the threading at the bottom with blunt start threads
2107// lead_in2 = Specify linear length of the lead in section of the threading at the top with blunt start threads
2108// lead_in_ang = Specify angular length in degrees of the lead in section of the threading with blunt start threads
2109// lead_in_ang1 = Specify angular length in degrees of the lead in section of the threading at the bottom with blunt start threads
2110// lead_in_ang2 = Specify angular length in degrees of the lead in section of the threading at the top with blunt start threads
2111// lead_in_shape = Specify the shape of the thread lead in by giving a text string or function. Default: "default"
2112// lead_in_sample = Factor to increase sample rate in the lead-in section. Default: 10
2113// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
2114// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
2115// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
2116// Example(2DMed): Typical Tooth Profile
2117// pitch = 2;
2118// depth = pitch * cos(30) * 5/8;
2119// profile = [
2120// [-6/16, 0 ],
2121// [-1/16, depth/pitch ],
2122// [ 1/16, depth/pitch ],
2123// [ 6/16, 0 ],
2124// ];
2125// stroke(profile, width=0.02);
2126// Examples:
2127// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, $fn=72);
2128// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2.5, lead_in=1, $fn=72);
2129// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=2, lead_in=2, internal=true, $fn=72);
2130// thread_helix(d=10, pitch=2, thread_depth=0.75, flank_angle=15, turns=1, left_handed=true, lead_in=1, $fn=36);
2131function thread_helix(
2132 d, pitch, thread_depth, flank_angle, turns,
2133 profile, starts=1, left_handed=false, internal=false,
2134 d1, d2, thread_angle,
2135 lead_in_shape,
2136 lead_in, lead_in1, lead_in2,
2137 lead_in_ang, lead_in_ang1, lead_in_ang2,
2138 lead_in_sample=10,
2139 anchor, spin, orient
2140) = no_function("thread_helix");
2141module thread_helix(
2142 d, pitch, thread_depth, flank_angle, turns,
2143 profile, starts=1, left_handed=false, internal=false,
2144 d1, d2, thread_angle,
2145 lead_in_shape,
2146 lead_in, lead_in1, lead_in2,
2147 lead_in_ang, lead_in_ang1, lead_in_ang2,
2148 lead_in_sample=10,
2149 anchor, spin, orient
2150) {
2151 dummy1=assert(num_defined([thread_angle,flank_angle])<=1, "Cannot define both flank angle and thread angle")
2152 assert(is_undef(profile) || !any_defined([thread_depth, flank_angle]),
2153 "Cannot give thread_depth or flank_angle with a profile")
2154 assert(all_positive([turns]), "The turns parameter must be a positive number")
2155 assert(all_positive(pitch), "pitch must be a positive number")
2156 assert(num_defined([flank_angle,thread_angle])<=1, "Cannot give both thread_angle and flank_angle")
2157 assert(is_def(profile) || is_def(thread_depth), "If profile is not given, must give thread depth");
2158 flank_angle = first_defined([flank_angle,u_mul(0.5,thread_angle),15]);
2159 h = pitch*starts*abs(turns);
2160 r1 = get_radius(d1=d1, d=d, dflt=10);
2161 r2 = get_radius(d1=d2, d=d, dflt=10);
2162 profile = is_def(profile) ? profile :
2163 let(
2164 tdp = thread_depth / pitch,
2165 dz = tdp * tan(flank_angle),
2166 cap = (1 - 2*dz)/2
2167 )
2168 assert(cap/2+dz<=0.5, "Invalid geometry: incompatible thread depth and thread_angle/flank_angle")
2169 internal?
2170 [
2171 [-cap/2-dz, tdp],
2172 [-cap/2, 0 ],
2173 [+cap/2, 0 ],
2174 [+cap/2+dz, tdp],
2175 ]
2176 :
2177 [
2178 [+cap/2+dz, 0 ],
2179 [+cap/2, tdp],
2180 [-cap/2, tdp],
2181 [-cap/2-dz, 0 ],
2182 ];
2183
2184 pline = mirror([-1,1], p = profile * pitch);
2185 dir = left_handed? -1 : 1;
2186 attachable(anchor,spin,orient, r1=r1, r2=r2, l=h) {
2187 union(){
2188 zrot_copies(n=starts)
2189 spiral_sweep(pline, h=h, r1=r1, r2=r2, turns=turns*dir, internal=internal,
2190 lead_in_shape=lead_in_shape,
2191 lead_in=lead_in, lead_in1=lead_in1, lead_in2=lead_in2,
2192 lead_in_ang=lead_in_ang, lead_in_ang1=lead_in_ang1, lead_in_ang2=lead_in_ang2,
2193 lead_in_sample=lead_in_sample,anchor=CENTER);
2194 }
2195 children();
2196 }
2197}
2198
2199
2200
2201// Questions
2202// Should nut modules take d1/d2 for tapered nuts?
2203//
2204// Need explanation of what exactly the diff is between threaded_rod and helix_threads.
2205//
2206// What about blunt_start for ball screws?
2207// Should default bevel be capped at 1mm or 2mm or something like that? Including/especially inner bevel on nuts
2208
2209// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
2210