Octathingy_EM200.scad 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. //
  2. // Spherical Harmonics Ear Project (*SpHEAR)
  3. //
  4. // OctaSpHEAR or Octathingy, Second Order Ambisonics Microphone
  5. //
  6. // based on:
  7. // "A second-order soundfield microphone with improved polar pattern shape"
  8. // by Eric Benjamin, Audio Engineering Society Convention Paper 8728,
  9. // October 2012, San Francisco
  10. //
  11. // Microphone optimized for EM200 14mm capsules and Zapnspark interface
  12. //
  13. // Copyright 2015-2019, Fernando Lopez-Lezcano, All Rights Reserved
  14. // nando@ccrma.stanford.edu
  15. //
  16. // This program is free software: you can redistribute it and/or modify
  17. // it under the terms of the GNU General Public License as published by
  18. // the Free Software Foundation, either version 3 of the License, or
  19. // (at your option) any later version.
  20. //
  21. // This program is distributed in the hope that it will be useful,
  22. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. // GNU General Public License for more details.
  25. //
  26. // You should have received a copy of the GNU General Public License
  27. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. //
  29. // 3d Models released under the Creative Commons license as follows:
  30. // Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
  31. // http://creativecommons.org/licenses/by-nc-sa/4.0/
  32. // microphone version
  33. // 1 -> original
  34. // 2 -> flower power
  35. mic_version = 2;
  36. // printed circuit board version
  37. // 1 -> single layer, milled in house
  38. // 2 -> double layer with ground plane, smaller, fabricated
  39. pcb_version = 2;
  40. // type of octathingy (for mic_version -> 1)
  41. // 0 -> regular octathingy (equilateral triangles in the square antiprism)
  42. // 1 -> tetrahedral compatible octathingy (same elevation angle as the tetrahedral mic)
  43. tetra_compat = 1;
  44. // dimensions of the EM200 electret microphone capsule
  45. capsule_radius = 14.55 / 2;
  46. capsule_height = 4.75;
  47. // radius of capsule array
  48. mic_radius = (mic_version == 1) ? 18 : 20.5;
  49. // include shared modules
  50. //
  51. // http://dkprojects.net/openscad-threads/
  52. include <threads.scad>;
  53. include <SpHEAR_common.scad>
  54. include <Octathingy_common.scad>;
  55. include <SpHEAR_windscreen.scad>;
  56. include <Octathingy_mount_pcb.scad>;
  57. include <polygons.scad>;
  58. ////
  59. //// overrides and parameters
  60. ////
  61. // override Octathingy_common fudge (0.15)
  62. // 0.17 for Ultimaker 2+
  63. // 0.12 for Ultimaker 3
  64. fudge = 0.12;
  65. // mic_version 1: make triangular legs have the right height
  66. connect = 4;
  67. leg_thick = capsule_height * 0.55;
  68. // radius of windscreen thread
  69. //
  70. // adjusted with offset so that it is inset with respect to the body
  71. // so that the new shock mount sleeve fits over the thread into the body
  72. //
  73. // octa_pcb_radius for pcb v2 is 27.42, the radius used is 25.6
  74. windscreen_thread_offset = (pcb_version == 2 ? -1.82 : -1.82);
  75. windscreen_thread_radius = octa_pcb_radius + windscreen_thread_offset;
  76. windscreen_radius = windscreen_thread_radius + 5.0;
  77. // windscreen thread for pcb version 1
  78. // this is used for the upper part of the windscreen
  79. windscreen_thread_radius_pcb1 = 31.425;
  80. windscreen_radius_pcb1 = windscreen_thread_radius_pcb1 + 5.0;
  81. // do we need to override thread height?
  82. windscreen_thread_height = 8;
  83. windscreen_height = pcb_version == 2 ? 68.5 : 72;
  84. windscreen_thread_fit = 5 * fit;
  85. //
  86. ridge_width = 1.5;
  87. // up from 1.7 in _common.scad
  88. capsule_cable_diam = 2.0;
  89. cable_wall = wall;
  90. ////////
  91. //// ready to print individual parts
  92. ////////
  93. // NOTE: remove the "*" at the beginning of a line to render that part
  94. // make sure mic_version and pcb_version are set to the right version
  95. // single capsule holder
  96. *if (mic_version == 2) {
  97. // 3d print with support
  98. rotate([180, 0, 0]) capsule_holder(holder_ratio, transition_ratio);
  99. } else {
  100. // upper
  101. render_octa_capsule_top(0);
  102. // lower
  103. *render_octa_capsule_bot(0);
  104. }
  105. // capsule array core and stalk
  106. //
  107. if (mic_version == 2) {
  108. // upper half (3d print with support)
  109. *capsule_holder_core(mount_radius + wall, stalk_height, 1);
  110. // lower half (with stalk - 3d print with support)
  111. *rotate([180, 0, 0]) capsule_holder_core(mount_radius + wall, stalk_height, -1);
  112. // connection ring
  113. *translate([0, 0, 0]) capsule_holder_ring(shift = -0.2);
  114. } else {
  115. *render_octa_capsule_stalk(0);
  116. }
  117. // flare from body to capsule array stalk
  118. *rotate([0, 0, -22.5]) render_octa_capsule_flare(0);
  119. // body
  120. *rotate([0, 0, -22.5]) render_octa_pcb_mount(0, 1);
  121. // flare from body to db25 connector
  122. // (3d print with support)
  123. *rotate([0, 0, 0 + 22.5]) {
  124. conn_offset = 2.0;
  125. octa_mount_flare_dsub(pcb_low_clear + pcb_low_exp - 5, mount_lip, 33 - 13,
  126. octa_pcb_radius,
  127. conn_core_o_diam / 2, conn_core_o_diam + conn_offset);
  128. }
  129. // shock mount
  130. //
  131. // sleeve
  132. *octa_shock_mount_sleeve(octa_pcb_radius, internal_ring_height, true, true);
  133. // external ring
  134. *render_octa_shock_mount_external_ring(0);
  135. // quick lock microphone stand mount
  136. *render_octa_shock_mount_stand(0);
  137. // threaded microphone stand mount
  138. *shock_mount_threaded_stand(20, 2, 1);
  139. // windscreen
  140. //
  141. *if (pcb_version == 2) {
  142. // tapered lower windscreen for pcb2 (from pcb2 to pcb1 diameter)
  143. render_sphear_lower_tapered_windscreen(windscreen_radius - 3, windscreen_radius_pcb1, 0);
  144. } else {
  145. // regular lower windscreen for pcb1
  146. render_sphear_lower_windscreen(windscreen_radius, 0);
  147. }
  148. // upper windscreen
  149. *render_sphear_upper_windscreen(windscreen_thread_radius_pcb1 + 5.0, 0);
  150. // windscreen or shock mount attachment ring
  151. *sphear_windscreen_round_mount(windscreen_thread_height, windscreen_thread_radius, windscreen_radius - 1.75, 2 * wall, true);
  152. ////////
  153. //// full microphone with height offset for different parts
  154. ////////
  155. // set to true to render printed circuit board and components for testing
  156. render_pcb = false;
  157. // reduce resolution for quick tests
  158. // facets = 64;
  159. // cfacets = 64;
  160. difference() {
  161. // separate the parts slightly to show joints
  162. stretch = 0.1;
  163. //
  164. union() {
  165. // the capsule array
  166. //
  167. *if (mic_version == 1) {
  168. // version 1 capsule array
  169. //
  170. rotate([0, 0, -22.5]) render_octa_capsule_array(202.8);
  171. // stalk from flare to capsule array
  172. rotate([0, 0, -22.5]) render_octa_capsule_stalk(pcb_version == 2 ? 43.2 : 49.2);
  173. } else {
  174. // version 2 flower power capsule array
  175. //
  176. translate([0, 0, 194.2]) rotate([0, 0, -22.5]) {
  177. difference() {
  178. union() {
  179. // capsule array
  180. render_octa_capsule_holder_array();
  181. // upper half of spherical core
  182. capsule_holder_core(mount_radius + wall, stalk_height, 1);
  183. // lower half of spherical core (with stalk)
  184. translate([0, 0, -0.05]) capsule_holder_core(mount_radius + wall, stalk_height, -1);
  185. // connection ring
  186. *translate([0, 0, 0]) capsule_holder_ring(shift = -0.2);
  187. }
  188. *rotate([0, 0, 0]) translate([-50, -25, -25]) cube([50, 50, 50]);
  189. }
  190. }
  191. }
  192. // flare from body to stalk
  193. *rotate([0, 0, -22.5]) render_octa_capsule_flare(pcb_version == 2 ? 42.4 + stretch : 49.2);
  194. // body
  195. *rotate([0, 0, -22.5]) render_octa_pcb_mount(0, 1);
  196. // flare from body to db25 connector
  197. *rotate([180, 0, 90 - 22.5]) {
  198. conn_offset = 2.0;
  199. translate([0, 0, -mount_lip]) octa_mount_flare_dsub(pcb_low_clear + pcb_low_exp - 5, mount_lip, 33 - 13,
  200. octa_pcb_radius,
  201. conn_core_o_diam / 2, conn_core_o_diam + conn_offset);
  202. }
  203. // thread cover (protects thread or locks down shock mount when windscreen not used)
  204. *translate([0, 0, pcb_mount_height - 10 + 15]) {
  205. sphear_windscreen_round_mount(windscreen_thread_height, windscreen_thread_radius,
  206. windscreen_radius - 1.75, 2 * wall, true);
  207. }
  208. //
  209. // windscreen
  210. //
  211. *if (pcb_version == 2) {
  212. // tapered lower windscreen for pcb2 (from pcb2 to pcb1 diameter)
  213. render_sphear_lower_tapered_windscreen(windscreen_radius - 3, windscreen_radius_pcb1, pcb_mount_height - 10 + 15);
  214. } else {
  215. // regular lower windscreen for pcb1
  216. render_sphear_lower_windscreen(windscreen_radius, pcb_mount_height - 10 + 15);
  217. }
  218. // upper windscreen for both designs
  219. *render_sphear_upper_windscreen(windscreen_thread_radius_pcb1 + 5.0, pcb_mount_height - 10 + 15 + windscreen_height);
  220. //
  221. // shock mount
  222. //
  223. // internal sleeve (slides over body from the top)
  224. *translate([0, 0, pcb_version == 2 ? 3.0 : 9.1]) rotate([0, 0, 0]) {
  225. octa_shock_mount_sleeve(octa_pcb_radius, internal_ring_height, true, true);
  226. }
  227. // external ring
  228. *translate([0, 0, (pcb_version == 2 ? 3.0 : 9.1) + (internal_ring_height/2) - (external_ring_height/2)]) {
  229. render_octa_shock_mount_external_ring(0);
  230. }
  231. // quick lock microphone stand mount
  232. *translate([pcb_version == 2 ? 72.5 : 76, 0, pcb_version == 2 ? -25.5 : -19.5]) {
  233. render_octa_shock_mount_stand(0);
  234. }
  235. }
  236. //
  237. // render to have a cutout view of microphone for debugging
  238. //
  239. z_rotation = 0;
  240. *rotate([0, 0, z_rotation]) translate([-100, -100, -100]) {
  241. cube([100, 100, 400]);
  242. }
  243. }
  244. // serial number tests
  245. //
  246. *difference() {
  247. union() {
  248. // add a serial number
  249. *translate([-25.5, 0, 43.2 + 7]) rotate([90, 0, -90]) scale ([0.2, 0.2, 0.5])
  250. linear_extrude(0.5) text("8S004", halign = "center");
  251. }
  252. }
  253. ////
  254. //// old versions
  255. ////
  256. // the whole body
  257. *translate([0, 0, -20]) render_octa_body(0, 10, 0);
  258. // the whole microphone
  259. // or use render_octa_microphone_cutout(0, 0) for a "transparent" view
  260. //
  261. *rotate([0, 0, 90 - 22.5]) render_octa_microphone_cutout(0, 0, 0);
  262. *rotate([0, 0, 90 - 22.5]) render_octa_microphone(0, 0, 0);
  263. ////
  264. //// old microphone shock mount
  265. ////
  266. // sleeve (body slips into it)
  267. *rotate([180, 0, 0]) translate([0, 0, -55/2 - 21 - (pcb_version == 2 ? -5 : 0)]) {
  268. octa_shock_mount_internal_ring(internal_ring_height, octa_pcb_radius, 20, 0, 0);
  269. }