My self-made 3D-printable designs, mainly in OpenSCAD
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

threads.scad 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. * ISO-standard metric threads, following this specification:
  3. * http://en.wikipedia.org/wiki/ISO_metric_screw_thread
  4. *
  5. * Copyright 2017 Dan Kirshner - dan_kirshner@yahoo.com
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * See <http://www.gnu.org/licenses/>.
  17. *
  18. * Version 2.3. 2017-08-31 Default for leadin: 0 (best for internal threads).
  19. * Version 2.2. 2017-01-01 Correction for angle; leadfac option. (Thanks to
  20. * Andrew Allen <a2intl@gmail.com>.)
  21. * Version 2.1. 2016-12-04 Chamfer bottom end (low-z); leadin option.
  22. * Version 2.0. 2016-11-05 Backwards compatibility (earlier OpenSCAD) fixes.
  23. * Version 1.9. 2016-07-03 Option: tapered.
  24. * Version 1.8. 2016-01-08 Option: (non-standard) angle.
  25. * Version 1.7. 2015-11-28 Larger x-increment - for small-diameters.
  26. * Version 1.6. 2015-09-01 Options: square threads, rectangular threads.
  27. * Version 1.5. 2015-06-12 Options: thread_size, groove.
  28. * Version 1.4. 2014-10-17 Use "faces" instead of "triangles" for polyhedron
  29. * Version 1.3. 2013-12-01 Correct loop over turns -- don't have early cut-off
  30. * Version 1.2. 2012-09-09 Use discrete polyhedra rather than linear_extrude ()
  31. * Version 1.1. 2012-09-07 Corrected to right-hand threads!
  32. */
  33. // Examples.
  34. //
  35. // Standard M8 x 1.
  36. // metric_thread (diameter=8, pitch=1, length=4);
  37. // Square thread.
  38. // metric_thread (diameter=8, pitch=1, length=4, square=true);
  39. // Non-standard: long pitch, same thread size.
  40. //metric_thread (diameter=8, pitch=4, length=4, thread_size=1, groove=true);
  41. // Non-standard: 20 mm diameter, long pitch, square "trough" width 3 mm,
  42. // depth 1 mm.
  43. //metric_thread (diameter=20, pitch=8, length=16, square=true, thread_size=6,
  44. // groove=true, rectangle=0.333);
  45. // English: 1/4 x 20.
  46. //english_thread (diameter=1/4, threads_per_inch=20, length=1);
  47. // Tapered. Example -- pipe size 3/4" -- per:
  48. // http://www.engineeringtoolbox.com/npt-national-pipe-taper-threads-d_750.html
  49. // english_thread (diameter=1.05, threads_per_inch=14, length=3/4, taper=1/16);
  50. // Thread for mounting on Rohloff hub.
  51. //difference () {
  52. // cylinder (r=20, h=10, $fn=100);
  53. //
  54. // metric_thread (diameter=34, pitch=1, length=10, internal=true, n_starts=6);
  55. //}
  56. // ----------------------------------------------------------------------------
  57. function segments (diameter) = min (50, ceil (diameter*6));
  58. // ----------------------------------------------------------------------------
  59. // diameter - outside diameter of threads in mm. Default: 8.
  60. // pitch - thread axial "travel" per turn in mm. Default: 1.
  61. // length - overall axial length of thread in mm. Default: 1.
  62. // internal - true = clearances for internal thread (e.g., a nut).
  63. // false = clearances for external thread (e.g., a bolt).
  64. // (Internal threads should be "cut out" from a solid using
  65. // difference ()).
  66. // n_starts - Number of thread starts (e.g., DNA, a "double helix," has
  67. // n_starts=2). See wikipedia Screw_thread.
  68. // thread_size - (non-standard) axial width of a single thread "V" - independent
  69. // of pitch. Default: same as pitch.
  70. // groove - (non-standard) subtract inverted "V" from cylinder (rather than
  71. // add protruding "V" to cylinder).
  72. // square - Square threads (per
  73. // https://en.wikipedia.org/wiki/Square_thread_form).
  74. // rectangle - (non-standard) "Rectangular" thread - ratio depth/(axial) width
  75. // Default: 1 (square).
  76. // angle - (non-standard) angle (deg) of thread side from perpendicular to
  77. // axis (default = standard = 30 degrees).
  78. // taper - diameter change per length (National Pipe Thread/ANSI B1.20.1
  79. // is 1" diameter per 16" length). Taper decreases from 'diameter'
  80. // as z increases.
  81. // leadin - 0 (default): no chamfer; 1: chamfer (45 degree) at max-z end;
  82. // 2: chamfer at both ends, 3: chamfer at z=0 end.
  83. // leadfac - scale of leadin chamfer (default: 1.0 = 1/2 thread).
  84. module metric_thread (diameter=8, pitch=1, length=1, internal=false, n_starts=1,
  85. thread_size=-1, groove=false, square=false, rectangle=0,
  86. angle=30, taper=0, leadin=0, leadfac=1.0)
  87. {
  88. // thread_size: size of thread "V" different than travel per turn (pitch).
  89. // Default: same as pitch.
  90. local_thread_size = thread_size == -1 ? pitch : thread_size;
  91. local_rectangle = rectangle ? rectangle : 1;
  92. n_segments = segments (diameter);
  93. h = (square || rectangle) ? local_thread_size*local_rectangle/2 : local_thread_size / (2 * tan(angle));
  94. h_fac1 = (square || rectangle) ? 0.90 : 0.625;
  95. // External thread includes additional relief.
  96. h_fac2 = (square || rectangle) ? 0.95 : 5.3/8;
  97. tapered_diameter = diameter - length*taper;
  98. difference () {
  99. union () {
  100. if (! groove) {
  101. metric_thread_turns (diameter, pitch, length, internal, n_starts,
  102. local_thread_size, groove, square, rectangle, angle,
  103. taper);
  104. }
  105. difference () {
  106. // Solid center, including Dmin truncation.
  107. if (groove) {
  108. cylinder (r1=diameter/2, r2=tapered_diameter/2,
  109. h=length, $fn=n_segments);
  110. } else if (internal) {
  111. cylinder (r1=diameter/2 - h*h_fac1, r2=tapered_diameter/2 - h*h_fac1,
  112. h=length, $fn=n_segments);
  113. } else {
  114. // External thread.
  115. cylinder (r1=diameter/2 - h*h_fac2, r2=tapered_diameter/2 - h*h_fac2,
  116. h=length, $fn=n_segments);
  117. }
  118. if (groove) {
  119. metric_thread_turns (diameter, pitch, length, internal, n_starts,
  120. local_thread_size, groove, square, rectangle,
  121. angle, taper);
  122. }
  123. }
  124. }
  125. // chamfer z=0 end if leadin is 2 or 3
  126. if (leadin == 2 || leadin == 3) {
  127. difference () {
  128. cylinder (r=diameter/2 + 1, h=h*h_fac1*leadfac, $fn=n_segments);
  129. cylinder (r2=diameter/2, r1=diameter/2 - h*h_fac1*leadfac, h=h*h_fac1*leadfac,
  130. $fn=n_segments);
  131. }
  132. }
  133. // chamfer z-max end if leadin is 1 or 2.
  134. if (leadin == 1 || leadin == 2) {
  135. translate ([0, 0, length + 0.05 - h*h_fac1*leadfac]) {
  136. difference () {
  137. cylinder (r=diameter/2 + 1, h=h*h_fac1*leadfac, $fn=n_segments);
  138. cylinder (r1=tapered_diameter/2, r2=tapered_diameter/2 - h*h_fac1*leadfac, h=h*h_fac1*leadfac,
  139. $fn=n_segments);
  140. }
  141. }
  142. }
  143. }
  144. }
  145. // ----------------------------------------------------------------------------
  146. // Input units in inches.
  147. // Note: units of measure in drawing are mm!
  148. module english_thread (diameter=0.25, threads_per_inch=20, length=1,
  149. internal=false, n_starts=1, thread_size=-1, groove=false,
  150. square=false, rectangle=0, angle=30, taper=0, leadin=0,
  151. leadfac=1.0)
  152. {
  153. // Convert to mm.
  154. mm_diameter = diameter*25.4;
  155. mm_pitch = (1.0/threads_per_inch)*25.4;
  156. mm_length = length*25.4;
  157. echo (str ("mm_diameter: ", mm_diameter));
  158. echo (str ("mm_pitch: ", mm_pitch));
  159. echo (str ("mm_length: ", mm_length));
  160. metric_thread (mm_diameter, mm_pitch, mm_length, internal, n_starts,
  161. thread_size, groove, square, rectangle, angle, taper, leadin,
  162. leadfac);
  163. }
  164. // ----------------------------------------------------------------------------
  165. module metric_thread_turns (diameter, pitch, length, internal, n_starts,
  166. thread_size, groove, square, rectangle, angle,
  167. taper)
  168. {
  169. // Number of turns needed.
  170. n_turns = floor (length/pitch);
  171. intersection () {
  172. // Start one below z = 0. Gives an extra turn at each end.
  173. for (i=[-1*n_starts : n_turns+1]) {
  174. translate ([0, 0, i*pitch]) {
  175. metric_thread_turn (diameter, pitch, internal, n_starts,
  176. thread_size, groove, square, rectangle, angle,
  177. taper, i*pitch);
  178. }
  179. }
  180. // Cut to length.
  181. translate ([0, 0, length/2]) {
  182. cube ([diameter*3, diameter*3, length], center=true);
  183. }
  184. }
  185. }
  186. // ----------------------------------------------------------------------------
  187. module metric_thread_turn (diameter, pitch, internal, n_starts, thread_size,
  188. groove, square, rectangle, angle, taper, z)
  189. {
  190. n_segments = segments (diameter);
  191. fraction_circle = 1.0/n_segments;
  192. for (i=[0 : n_segments-1]) {
  193. rotate ([0, 0, i*360*fraction_circle]) {
  194. translate ([0, 0, i*n_starts*pitch*fraction_circle]) {
  195. //current_diameter = diameter - taper*(z + i*n_starts*pitch*fraction_circle);
  196. thread_polyhedron ((diameter - taper*(z + i*n_starts*pitch*fraction_circle))/2,
  197. pitch, internal, n_starts, thread_size, groove,
  198. square, rectangle, angle);
  199. }
  200. }
  201. }
  202. }
  203. // ----------------------------------------------------------------------------
  204. module thread_polyhedron (radius, pitch, internal, n_starts, thread_size,
  205. groove, square, rectangle, angle)
  206. {
  207. n_segments = segments (radius*2);
  208. fraction_circle = 1.0/n_segments;
  209. local_rectangle = rectangle ? rectangle : 1;
  210. h = (square || rectangle) ? thread_size*local_rectangle/2 : thread_size / (2 * tan(angle));
  211. outer_r = radius + (internal ? h/20 : 0); // Adds internal relief.
  212. //echo (str ("outer_r: ", outer_r));
  213. // A little extra on square thread -- make sure overlaps cylinder.
  214. h_fac1 = (square || rectangle) ? 1.1 : 0.875;
  215. inner_r = radius - h*h_fac1; // Does NOT do Dmin_truncation - do later with
  216. // cylinder.
  217. translate_y = groove ? outer_r + inner_r : 0;
  218. reflect_x = groove ? 1 : 0;
  219. // Make these just slightly bigger (keep in proportion) so polyhedra will
  220. // overlap.
  221. x_incr_outer = (! groove ? outer_r : inner_r) * fraction_circle * 2 * PI * 1.02;
  222. x_incr_inner = (! groove ? inner_r : outer_r) * fraction_circle * 2 * PI * 1.02;
  223. z_incr = n_starts * pitch * fraction_circle * 1.005;
  224. /*
  225. (angles x0 and x3 inner are actually 60 deg)
  226. /\ (x2_inner, z2_inner) [2]
  227. / \
  228. (x3_inner, z3_inner) / \
  229. [3] \ \
  230. |\ \ (x2_outer, z2_outer) [6]
  231. | \ /
  232. | \ /|
  233. z |[7]\/ / (x1_outer, z1_outer) [5]
  234. | | | /
  235. | x | |/
  236. | / | / (x0_outer, z0_outer) [4]
  237. | / | / (behind: (x1_inner, z1_inner) [1]
  238. |/ | /
  239. y________| |/
  240. (r) / (x0_inner, z0_inner) [0]
  241. */
  242. x1_outer = outer_r * fraction_circle * 2 * PI;
  243. z0_outer = (outer_r - inner_r) * tan(angle);
  244. //echo (str ("z0_outer: ", z0_outer));
  245. //polygon ([[inner_r, 0], [outer_r, z0_outer],
  246. // [outer_r, 0.5*pitch], [inner_r, 0.5*pitch]]);
  247. z1_outer = z0_outer + z_incr;
  248. // Give internal square threads some clearance in the z direction, too.
  249. bottom = internal ? 0.235 : 0.25;
  250. top = internal ? 0.765 : 0.75;
  251. translate ([0, translate_y, 0]) {
  252. mirror ([reflect_x, 0, 0]) {
  253. if (square || rectangle) {
  254. // Rule for face ordering: look at polyhedron from outside: points must
  255. // be in clockwise order.
  256. polyhedron (
  257. points = [
  258. [-x_incr_inner/2, -inner_r, bottom*thread_size], // [0]
  259. [x_incr_inner/2, -inner_r, bottom*thread_size + z_incr], // [1]
  260. [x_incr_inner/2, -inner_r, top*thread_size + z_incr], // [2]
  261. [-x_incr_inner/2, -inner_r, top*thread_size], // [3]
  262. [-x_incr_outer/2, -outer_r, bottom*thread_size], // [4]
  263. [x_incr_outer/2, -outer_r, bottom*thread_size + z_incr], // [5]
  264. [x_incr_outer/2, -outer_r, top*thread_size + z_incr], // [6]
  265. [-x_incr_outer/2, -outer_r, top*thread_size] // [7]
  266. ],
  267. faces = [
  268. [0, 3, 7, 4], // This-side trapezoid
  269. [1, 5, 6, 2], // Back-side trapezoid
  270. [0, 1, 2, 3], // Inner rectangle
  271. [4, 7, 6, 5], // Outer rectangle
  272. // These are not planar, so do with separate triangles.
  273. [7, 2, 6], // Upper rectangle, bottom
  274. [7, 3, 2], // Upper rectangle, top
  275. [0, 5, 1], // Lower rectangle, bottom
  276. [0, 4, 5] // Lower rectangle, top
  277. ]
  278. );
  279. } else {
  280. // Rule for face ordering: look at polyhedron from outside: points must
  281. // be in clockwise order.
  282. polyhedron (
  283. points = [
  284. [-x_incr_inner/2, -inner_r, 0], // [0]
  285. [x_incr_inner/2, -inner_r, z_incr], // [1]
  286. [x_incr_inner/2, -inner_r, thread_size + z_incr], // [2]
  287. [-x_incr_inner/2, -inner_r, thread_size], // [3]
  288. [-x_incr_outer/2, -outer_r, z0_outer], // [4]
  289. [x_incr_outer/2, -outer_r, z0_outer + z_incr], // [5]
  290. [x_incr_outer/2, -outer_r, thread_size - z0_outer + z_incr], // [6]
  291. [-x_incr_outer/2, -outer_r, thread_size - z0_outer] // [7]
  292. ],
  293. faces = [
  294. [0, 3, 7, 4], // This-side trapezoid
  295. [1, 5, 6, 2], // Back-side trapezoid
  296. [0, 1, 2, 3], // Inner rectangle
  297. [4, 7, 6, 5], // Outer rectangle
  298. // These are not planar, so do with separate triangles.
  299. [7, 2, 6], // Upper rectangle, bottom
  300. [7, 3, 2], // Upper rectangle, top
  301. [0, 5, 1], // Lower rectangle, bottom
  302. [0, 4, 5] // Lower rectangle, top
  303. ]
  304. );
  305. }
  306. }
  307. }
  308. }