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

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