omdl  v0.9.8
OpenSCAD Mechanical Design Library
screws.scad
Go to the documentation of this file.
1 //! Screws, bolts and fastener bores.
2 /***************************************************************************//**
3  \file
4  \author Roy Allen Sutton
5  \date 2025
6 
7  \copyright
8 
9  This file is part of [omdl] (https://github.com/royasutton/omdl),
10  an OpenSCAD mechanical design library.
11 
12  The \em omdl is free software; you can redistribute it and/or modify
13  it under the terms of the [GNU Lesser General Public License]
14  (http://www.gnu.org/licenses/lgpl.html) as published by the Free
15  Software Foundation; either version 2.1 of the License, or (at
16  your option) any later version.
17 
18  The \em omdl is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  Lesser General Public License for more details.
22 
23  You should have received a copy of the GNU Lesser General Public
24  License along with the \em omdl; if not, write to the Free Software
25  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26  02110-1301, USA; or see <http://www.gnu.org/licenses/>.
27 
28  \details
29 
30  \amu_define group_name (Screws and Bolts)
31  \amu_define group_brief (Screws, bolts and fastener bores.)
32 
33  \amu_include (include/amu/pgid_path_pstem_pg.amu)
34 *******************************************************************************/
35 
36 //----------------------------------------------------------------------------//
37 // group and macros.
38 //----------------------------------------------------------------------------//
39 
40 /***************************************************************************//**
41  \amu_include (include/amu/group_in_parent_start.amu)
42  \amu_include (include/amu/includes_required.amu)
43 *******************************************************************************/
44 
45 //----------------------------------------------------------------------------//
46 
47 //! Flat and beveled-head fastener bore with nut, nut slot, and bore tolerance.
48 /***************************************************************************//**
49  \param d <decimal> bore diameter.
50 
51  \param l <decimal> bore length.
52 
53  \param h <decimal-list-5> fastener head; a list [hs, hf, hb, hg,
54  hr], the head size, flat-height, bevel-height, side
55  geometry (flat side count), and rotation. The head size
56  is measured flat-to-flat when \p hg is specified.
57 
58  \param n <decimal-list-5> fastener nut; a list [ns, nf, nb, ng, nr,
59  no], the nut size, flat-height, bevel-height, side
60  geometry (flat side count), rotation, and bottom offset.
61  The nut size is measured flat-to-flat.
62 
63  \param t <decimal-list-2> bore tolerance; a list [tx, ty], the
64  tolerance along the x and/or y axis.
65 
66  \param s <decimal-list-list-3> nut slot cutout; a list of lists
67  [sx, sy, sz], the list of slot sizes along the x, y,
68  and/or z axis. Each of sx, sy, or sz can be a decimal
69  list, such as [lower, upper], or a single decimal value,
70  to cover [0, value].
71 
72  \param f <decimal-list-2 | decimal> bore scale factor; a list [fd,
73  fh], the bore diameter and bore height scale factors, or
74  a single decimal to specify \p fd only. The default
75  values for both are 1 (\p fh scales only the fastener
76  head and nut heights).
77 
78  \param a <integer> z-alignment index; one of eight presets.
79 
80  \details
81 
82  Construct a bore for a fastener hole, fastener head, and/or
83  fastener nut. Both the head and nut are optional. A tolerance can
84  be specified along the bore x and y axis. A nut slot cutout can be
85  specified along the x, y, or z axis. The following example uses
86  both tolerance and a nut slot along the y axis. For convenience,
87  exact fastener dimensions can be specified along with the an
88  appropriately selected scale factor \p f to slightly increase the
89  bore for acceptable fastener fit.
90 
91  \amu_define scope_id (example_bore)
92  \amu_define title (Fastener bore examples)
93  \amu_define image_views (top front diag)
94  \amu_define image_size (sxga)
95 
96  \amu_include (include/amu/scope_diagrams_3d.amu)
97 *******************************************************************************/
98 module screw_bore
99 (
100  d = 1,
101  l = 1,
102 
103  h,
104  n,
105 
106  t,
107  s,
108 
109  f,
110  a
111 )
112 {
113  function cdc(s, n, m=0) = (m == 0) ? s * fd : s * fd / cos(180/n);
114 
115  // diameter and height scale factors
116  fd = defined_eon_or(f, 0, 1);
117  fh = defined_e_or(f, 1, 1);
118 
119  // fastener bore
120  bd = cdc(d);
121 
122  // fastener head
123  hs = defined_e_or(h, 0, 0);
124  hf = defined_e_or(h, 1, 0) * fh;
125  hb = defined_e_or(h, 2, 0) * fh;
126  hg = defined_e_or(h, 3, $fn);
127  hr = defined_e_or(h, 4, 0);
128 
129  hd = is_undef(h[3]) ? cdc(hs) : cdc(hs, hg, 1);
130 
131  // nut
132  ns = defined_e_or(n, 0, 0);
133  nf = defined_e_or(n, 1, 0) * fh;
134  nb = defined_e_or(n, 2, 0) * fh;
135  ng = defined_e_or(n, 3, 6);
136  nr = defined_e_or(n, 4, 0);
137  no = defined_e_or(n, 5, 0);
138 
139  nd = cdc(ns, ng, 1);
140 
141  // tolerance
142  tx = defined_e_or(t, 0, 0);
143  ty = defined_e_or(t, 1, 0);
144 
145  // slot
146  sx = defined_e_or(s, 0, 0);
147  sy = defined_e_or(s, 1, 0);
148  sz = defined_e_or(s, 2, 0);
149 
150  az =
151  [
152  0, -l/2, -l/2+hf/2, -l/2+hf, -l/2+hf+hb,
153  +l/2-nb-nf-no, +l/2-nf-no, +l/2-nf/2-no, +l/2-no, +l/2
154  ];
155 
156  //
157  // construct
158  //
159 
160  translate([0, 0, select_ci(az, a, false)])
161  union()
162  {
163  hfo = [0, 0, +l/2 - hf/2 + eps*2];
164  hbo = [0, 0, +l/2 - hf - hb/2 + eps*4];
165  nbo = [0, 0, -l/2 + nf + nb/2 + no - eps*4];
166  nfo = [0, 0, -l/2 + nf/2 + no - eps*2];
167 
168  if ( is_undef(t) && is_undef(s) )
169  {
170  // fastener hole
171  cylinder(d=bd, h=l, center=true);
172 
173  // head flat height
174  translate(hfo)
175  rotate([0, 0, hr])
176  cylinder(d=hd, h=hf, center=true, $fn=hg);
177 
178  // head bevel height
179  translate(hbo)
180  cylinder(d1=bd, d2=cdc(hs), h=hb, center=true);
181 
182  // nut bevel height
183  translate(nbo)
184  cylinder(d2=bd, d1=cdc(ns), h=nb, center=true);
185 
186  // nut flat height
187  translate(nfo)
188  rotate([0, 0, nr])
189  cylinder(d=nd, h=nf, center=true, $fn=ng);
190  }
191  else
192  { // slower equivalent with support for tolerance and nut slot
193  hull() for( v=[-1, 1], w=[-1, 1] )
194  translate([tx/2*v, ty/2*w, 0])
195  cylinder(d=bd, h=l, center=true);
196 
197  hull() for( v=[-1, 1], w=[-1, 1] )
198  translate(hfo + [tx/2*v, ty/2*w, 0])
199  rotate([0, 0, hr])
200  cylinder(d=hd, h=hf, center=true, $fn=hg);
201 
202  hull() for( v=[-1, 1], w=[-1, 1] )
203  translate(hbo + [tx/2*v, ty/2*w, 0])
204  cylinder(d1=bd, d2=cdc(hs), h=hb, center=true);
205 
206  // start slot from origin
207  ix = is_list(sx) ? sx : [0, sx];
208  iy = is_list(sy) ? sy : [0, sy];
209  iz = is_list(sz) ? sz : [0, sz];
210 
211  hull() for( v=[-1, 1], w=[-1, 1], x=ix, y=iy, z=iz )
212  translate(nbo + [tx/2*v + x, ty/2*w + y, z])
213  cylinder(d2=bd, d1=cdc(ns), h=nb, center=true);
214 
215  hull() for( v=[-1, 1], w=[-1, 1], x=ix, y=iy, z=iz )
216  translate(nfo + [tx/2*v + x, ty/2*w + y, z])
217  rotate([0, 0, nr])
218  cylinder(d=nd, h=nf, center=true, $fn=ng);
219  }
220  }
221 }
222 
223 //! Gapped fastener bore with engagement cylinders for self-forming threads.
224 /***************************************************************************//**
225  \param d <decimal> fastener diameter.
226 
227  \param l <decimal> bore length.
228 
229  \param t <datastruct> thread engagement (see below).
230 
231  \param a <integer> z-alignment index; one of five presets.
232 
233  \details
234 
235  Construct a fastener bore with a gap for chip expansion and radial
236  cylinders that engage with the inserted fastener threads to
237  self-form counter-threads along the cylinder lengths. The bore is
238  enlarged by a configurable gap which facilitates thread formation
239  with reduced stress accumulation to the bore internal dimensions.
240 
241  \note When 3D printing a bore horizontally, it is best practice to
242  use 3 cylinders and orient one cylinder at the 6 o-clock
243  position. This prevents the formation of cliffs which would
244  otherwise require print support. Vertically printed bores can
245  use increase cylinder count for increase holding strength at
246  the cost of greater bore thread formation stress.
247 
248  ## Multi-value and structured parameters
249 
250  ### thread engagement
251 
252  #### Data structure fields: t
253 
254  e | data type | default value | parameter description
255  ---:|:-----------------:|:-----------------:|:------------------------------------
256  0 | <decimal> | 5 | radial engagement percentage
257  1 | <decimal> | 5 | radial gap percentage
258  2 | <decimal> | 0 | rotational offset
259  3 | <decimal> | 0 | radial offset
260  4 | <integer> | 3 | cylinder count
261  5 | <decimal-list-2 \| decimal> | [8/10, 10] | cylinder upper taper: [f, h%]
262  6 | <decimal-list-2 \| decimal> | [ 0, 10] | cylinder lower taper: [f, h%]
263 
264  #### Data structure fields: t[5-6]: cylinder upper and lower taper
265 
266  The diameter of the thread engagement cylinders can be configured
267  to gradually change along the bore height from either the bottom,
268  top, or both. The first element sets the cylinder diameter-scale
269  factor and the second sets the length over which the scaling is
270  performed. For \p f > 1, the cylinder diameter will increase in
271  size, and for \p f < 1, the cylinder diameter will decrease in
272  size.
273 
274  \amu_define scope_id (example_bore_tsf)
275  \amu_define title (Screw bore example)
276  \amu_define image_views (top front diag)
277  \amu_define image_size (sxga)
278 
279  \amu_include (include/amu/scope_diagrams_3d.amu)
280 *******************************************************************************/
281 module screw_bore_tsf
282 (
283  d = 1,
284  l = 1,
285  t,
286  a
287 )
288 {
289  e = defined_e_or(t, 0, 5) * d/50; // radial engagement percentage (r=d/2)
290  g = defined_e_or(t, 1, 5) * d/50; // radial gap percentage
291  r = defined_e_or(t, 2, 0); // rotational offset
292  o = defined_e_or(t, 3, 0); // radial offset
293  c = defined_e_or(t, 4, 3); // cylinder count
294  n = defined_e_or(t, 5, undef); // upper taper
295  m = defined_e_or(t, 6, undef); // lower taper
296 
297  // top taper: cylinder diameter-scale and scale-length percentage
298  td = defined_eon_or(n, 0, 8/10);
299  tl = defined_e_or (n, 1, 10) * l/100;
300 
301  // bottom taper: cylinder diameter-scale and scale-length percentage
302  bd = defined_eon_or(m, 0, 0);
303  bl = defined_e_or (m, 1, 10) * l/100;
304 
305  // bore diameter
306  b = d + g;
307 
308  // self-forming thread engagement cylinder diameter
309  s = e + g;
310 
311  // taper extrusion configuration
312  nl = let
313  (
314  tt = (td != 0 && tl > 0),
315  tb = (bd != 0 && bl > 0),
316 
317  ml = (l - (tb ? bl : 0) - (tt ? tl : 0))
318  )
319  [
320  if (tb) [bl, [bd, 1]],
321  if (ml > 0) ml,
322  if (tt) [tl, [1, td]]
323  ];
324 
325  az = [ 0, -l/2, -l/2+tl, +l/2-bl, +l/2 ];
326 
327  //
328  // construct
329  //
330 
331  translate([0, 0, select_ci(az, a, false)])
332  difference()
333  {
334  // bore cylinder
335  extrude_linear_mss(l, center=true)
336  circle( d=b );
337 
338  // self-forming thread engagement cylinders
339  for (i = [0:c-1])
340  {
341  rotate([0, 0, 360/c * i + r])
342  translate([b/2 + o, 0, 0])
343  extrude_linear_mss(nl, center=true)
344  circle( d=s );
345  }
346  }
347 }
348 
349 //! @}
350 //! @}
351 
352 
353 //----------------------------------------------------------------------------//
354 // openscad-amu auxiliary scripts
355 //----------------------------------------------------------------------------//
356 
357 /*
358 BEGIN_SCOPE example_bore;
359  BEGIN_OPENSCAD;
360  include <omdl-base.scad>;
361  include <models/3d/fastener/screws.scad>;
362 
363  $fn = 36;
364 
365  // fastener bore with tolerance and nut-slot from front to back
366  %difference()
367  {
368  cube([10, 15, 18], center=true);
369  screw_bore(2.75, 18+eps*8, h=[6,1,3], n=[6,2,0,6,30,3], t=[0,5], s=[0,[-6,6],0], f=1.15);
370  }
371 
372  // show actual minimal space required
373  screw_bore(2.75, 18, h=[6,1,3], n=[6,2,0,6,30,3]);
374 
375  // end_include
376  END_OPENSCAD;
377 
378  BEGIN_MFSCRIPT;
379  include --path "${INCLUDE_PATH}" {var_init,var_gen_png2eps}.mfs;
380  table_unset_all sizes;
381 
382  images name "sizes" types "sxga";
383  views name "views" views "top front diag";
384 
385  variables set_opts_combine "sizes views";
386  variables add_opts "--viewall --autocenter --view=axes";
387 
388  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
389  END_MFSCRIPT;
390 END_SCOPE;
391 
392 BEGIN_SCOPE example_bore_tsf;
393  BEGIN_OPENSCAD;
394  include <omdl-base.scad>;
395  include <models/3d/fastener/screws.scad>;
396 
397  $fn = 36;
398 
399  translate([+15, 0, 0])
400  difference()
401  {
402  cube([15, 15, 20], center=true);
403  screw_bore_tsf( d=10, l=20+eps*4);
404  }
405 
406  %translate([-15, 0, 0])
407  difference()
408  {
409  %cube([15, 15, 20], center=true);
410  #%screw_bore_tsf( d=10, l=20+eps*8);
411  }
412  translate([-15, 0, 0])
413  cylinder(d=10, h=30, center=true);
414 
415  // end_include
416  END_OPENSCAD;
417 
418  BEGIN_MFSCRIPT;
419  include --path "${INCLUDE_PATH}" {var_init,var_gen_png2eps}.mfs;
420  table_unset_all sizes;
421 
422  images name "sizes" types "sxga";
423  views name "views" views "top front diag";
424 
425  variables set_opts_combine "sizes views";
426  variables add_opts "--viewall --autocenter --view=axes";
427 
428  include --path "${INCLUDE_PATH}" scr_make_mf.mfs;
429  END_MFSCRIPT;
430 END_SCOPE;
431 */
432 
433 //----------------------------------------------------------------------------//
434 // end of file
435 //----------------------------------------------------------------------------//
436 
eps
<decimal> Epsilon, small distance to deal with overlapping shapes.
Definition: constants.scad:195
function defined_e_or(v, i, d)
Return an element of an iterable when it exists or a default value otherwise.
function defined_eon_or(v, i, d)
Return the list element or scalar numeric value, if either is defined, otherwise the default value.
function select_ci(v, i, l=true)
Select specified element from list or return a default.
module screw_bore(d=1, l=1, h, n, t, s, f, a)
Flat and beveled-head fastener bore with nut, nut slot, and bore tolerance.
Definition: screws.scad:358
module screw_bore_tsf(d=1, l=1, t, a)
Gapped fastener bore with engagement cylinders for self-forming threads.
Definition: screws.scad:695
module extrude_linear_mss(h, center=false, c=true)
Linearly extrude a 2d shape with multi-segment uniformly-spaced profile scaling.
Definition: extrude.scad:748