3D printed Arduino Airsoft Chronograph
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

openchrono.scad 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. outer_dia = 55;
  2. inner_dia = 8.5;
  3. height = 100;
  4. body_gap = 0.1;
  5. body_screw_off = 10;
  6. body_screw_pos = 20;
  7. body_screw_dia = 3.3;
  8. body_screw_head = 6.0;
  9. body_screw_depth = 3.2;
  10. body_screw_insert_dia = 4.8;
  11. body_screw_insert_height = 12.0;
  12. lcd_pcb_w = 29.0;
  13. lcd_pcb_h = 29.0;
  14. lcd_pcb_d = 5.2;
  15. lcd_hole_dia = 1.9;
  16. lcd_hole_w = 6.0;
  17. lcd_hole_h = 2.5;
  18. lcd_off = 10.0;
  19. lcd_hole_off_x = 23.1;
  20. lcd_hole_off_y = 23.65;
  21. lcd_hole_off_y_total = 0.4;
  22. lcd_hole_screw_len = 10.0;
  23. arduino_w = 19.0;
  24. arduino_h = 46.5 + 10;
  25. arduino_d = 10.0;
  26. bat_w = 11.5;
  27. bat_l = 45.5;
  28. bat_tab_w = 9.5;
  29. bat_tab_h = 8.5;
  30. bat_tab_d = 2.5; // TODO?
  31. bat_tab_con_w = 5.0; // TODO?
  32. bat_tab_con_h = 6.5; // TODO?
  33. bat_spring_w = 7.5; // TODO?
  34. bat_spring_dist = 7.5; // TODO?
  35. bat_wall = 1.0;
  36. bat_angle = 48;
  37. led_dia = 3.3;
  38. led_l = 4.5;
  39. led_off = 15;
  40. led_ridge_dia = 4.2;
  41. led_ridge_h = 1.6;
  42. switch_w = 12.0;
  43. switch_h = 6.5;
  44. switch_d = 10.0;
  45. switch_plate_w = 20.5;
  46. switch_plate_h = switch_h;
  47. switch_dia = 2.4;
  48. switch_screw_l = 10.0;
  49. switch_screw_d = 15.0;
  50. switch_off = 15;
  51. // 1911
  52. thread_profile_1911 = [
  53. true, // type is_male
  54. 12.0, // diameter
  55. 1.0, // pitch
  56. 0.0, // offset
  57. 9.0, // length
  58. 0.0, // offset dia
  59. 9.1, // inner hole
  60. true, // is cw thread
  61. ];
  62. // M14x1.0 CW female thread
  63. thread_profile_m14_cw = [
  64. false, // type is_male
  65. 14.0, // diameter
  66. 1.0, // pitch
  67. 0.0, // offset
  68. 12.0, // length
  69. 0.0, // offset dia
  70. 8.5, // inner hole
  71. true, // is cw thread
  72. ];
  73. // M14x1.0 CCW female thread
  74. thread_profile_m14_ccw = [
  75. false, // type is_male
  76. 14.0, // diameter
  77. 1.0, // pitch
  78. 0.0, // offset
  79. 12.0, // length
  80. 0.0, // offset dia
  81. 8.5, // inner hole
  82. false, // is cw thread
  83. ];
  84. // ASG / KWC Cobray Ingram M11 CO2 NBB 6mm
  85. thread_profile_mac11 = [
  86. false, // type is_male
  87. 16.5, // diameter
  88. 1.5, // pitch
  89. 9.0, // offset
  90. 10.0, // length
  91. 20.0, // offset dia
  92. 8.5, // inner hole
  93. true, // is cw thread
  94. ];
  95. thread_profile_giant = [
  96. false, // type is_male
  97. 34.0, // diameter
  98. 1.0, // pitch
  99. 0.0, // offset
  100. 10.0, // length
  101. 0.0, // offset dia
  102. 8.5, // inner hole
  103. true, // is cw thread
  104. ];
  105. thread_profiles = [
  106. thread_profile_1911,
  107. thread_profile_m14_cw,
  108. thread_profile_m14_ccw,
  109. thread_profile_mac11,
  110. thread_profile_giant
  111. ];
  112. thread_base = 5.0;
  113. test_bat_w = 47;
  114. test_bat_h = 59;
  115. test_bat_d = 15;
  116. test_bat_dia = 2.9;
  117. test_bat_off = 30.5;
  118. test_bat_l = 8;
  119. thread_adapter_screw_inset = 5;
  120. thread_adapter_in_body = 5;
  121. thread_adapter_h = body_screw_insert_height - thread_adapter_in_body;
  122. text1 = [
  123. "OpenChrono",
  124. "Liberation Sans:style=Bold",
  125. 12.0,
  126. 2.0,
  127. 55
  128. ];
  129. text2 = [
  130. "by xythobuz.de",
  131. "Liberation Sans:style=Bold",
  132. 9.0,
  133. 2.0,
  134. -60
  135. ];
  136. text3 = [
  137. "OpenChrono",
  138. "Liberation Sans:style=Bold",
  139. 12.0 - 4,
  140. 1.0,
  141. 70
  142. ];
  143. text4 = [
  144. "by xythobuz.de",
  145. "Liberation Sans:style=Bold",
  146. 9.0 - 2,
  147. 1.0,
  148. -70
  149. ];
  150. texts_left = [ text1, text2 ];
  151. texts_lipo = [ text3, text4 ];
  152. lipo_lid_height = 65;
  153. lipo_lid_width = 80;
  154. lipo_lid_d = 3.0;
  155. lipo_lid_gap = 0.5;
  156. lipo_lid_gap_d = 0.2;
  157. lipo_lid_screw_d_small = 2.8;
  158. lipo_lid_screw_d_big = 3.3;
  159. lipo_lid_screw_area = 10;
  160. lipo_lid_screw_len = 10.0;
  161. lipo_lid_screw_off = 5.0;
  162. lipo_lid_compartment_d = 15.0;
  163. lipo_lid_compartment_w = lipo_lid_width - 2 * lipo_lid_screw_area - 5;
  164. lipo_pcb_w = 18.0;
  165. lipo_pcb_h = 29.0;
  166. lipo_pcb_d = 5.0;
  167. lipo_pcb_usb_w = 9.0;
  168. lipo_pcb_usb_h = 3.6;
  169. lipo_pcb_usb_off = 1.4;
  170. lipo_pcb_usb_wall = 1.5;
  171. lipo_pcb_led_dia = 2.0;
  172. lipo_pcb_led_dist = 5.0;
  173. lipo_pcb_led_off_x = 1.75;
  174. lipo_pcb_led_off_z = 7.0;
  175. lipo_w = 30.0;
  176. lipo_h = 43.0;
  177. lipo_d = 9.0;
  178. enable_gap_support = true;
  179. include_uv_leds = true;
  180. lipo_lid_angle = circum_angle(lipo_lid_width - lipo_lid_gap * 2, outer_dia);
  181. lipo_lid_angle_hole = circum_angle(lipo_lid_width, outer_dia);
  182. lipo_lid_angle_compartment = circum_angle(lipo_lid_compartment_w, outer_dia);
  183. bat_h = bat_l + bat_spring_dist + 2 * bat_wall + 2 * bat_tab_d;
  184. $fn = 42;
  185. echo("sensor_distance", height - 2 * led_off);
  186. if (include_uv_leds)
  187. echo("uv_led_distance", led_off / 2);
  188. // https://dkprojects.net/openscad-threads/
  189. include <extern/threads.scad>
  190. // how deep things on the outside have to be set in
  191. function circle_offset_deviation(off, dia) =
  192. dia * (1 - sin(acos(off * 2 / dia))) / 2;
  193. // circumference to angle
  194. function circum_angle(width, dia) = width / dia * 180 / 3.141;
  195. // from https://3dprinting.stackexchange.com/questions/10638/creating-pie-slice-in-openscad
  196. module pie_slice(r, a) {
  197. intersection() {
  198. circle(r = r);
  199. square(r);
  200. rotate(a - 90)
  201. square(r);
  202. }
  203. }
  204. module lcd_cutout() {
  205. difference() {
  206. cube([lcd_pcb_w, lcd_pcb_h, lcd_pcb_d + 10]);
  207. for (x = [0, lcd_pcb_w - lcd_hole_w])
  208. for (y = [0, lcd_pcb_h - lcd_hole_w])
  209. translate([x, y, -1])
  210. cube([lcd_hole_w, lcd_hole_w, lcd_hole_h + 1]);
  211. // TODO hacky
  212. if (enable_gap_support)
  213. translate([0, (lcd_pcb_w - 1) / 2, 1])
  214. cube([lcd_pcb_w, 1, 8]);
  215. }
  216. for (x = [0, lcd_hole_off_x])
  217. for (y = [0, lcd_hole_off_y])
  218. translate([x + lcd_hole_w / 2, y + lcd_hole_w / 2 - lcd_hole_off_y_total, lcd_hole_h - lcd_hole_screw_len])
  219. cylinder(d = lcd_hole_dia, h = lcd_hole_screw_len + 1);
  220. }
  221. module arduino_cutout() {
  222. cube([arduino_w, arduino_h, arduino_d]);
  223. }
  224. module bat_cutout() {
  225. // battery
  226. translate([0, 0, bat_tab_d + bat_wall])
  227. cube([bat_w, bat_w, bat_l + bat_spring_dist]);
  228. // negative terminal
  229. for (z = [0, bat_l + bat_spring_dist + 2 * bat_wall + bat_tab_d])
  230. translate([(bat_w - bat_tab_w) / 2, (bat_w - bat_tab_h) / 2, z])
  231. cube([bat_tab_w, bat_tab_h + (bat_w - bat_tab_h) / 2, bat_tab_d]);
  232. // spring
  233. for (z = [bat_tab_d, bat_l + bat_spring_dist + bat_wall + bat_tab_d])
  234. translate([(bat_w - bat_spring_w) / 2, (bat_w - bat_spring_w) / 2, z - 0.1])
  235. cube([bat_spring_w, bat_spring_w + (bat_w - bat_spring_w) / 2, bat_wall + 0.2]);
  236. }
  237. module switch_cutout() {
  238. translate([-switch_w / 2, -10, -switch_h / 2])
  239. cube([switch_w, switch_d + 10, switch_h]);
  240. translate([-switch_plate_w / 2, -switch_d, -switch_plate_h / 2])
  241. cube([switch_plate_w, 10, switch_plate_h]);
  242. for (x = [1, -1])
  243. scale([x, 1, 1])
  244. translate([-switch_screw_d / 2, -10, 0])
  245. rotate([-90, 0, 0])
  246. cylinder(d = switch_dia, h = switch_screw_l + 10);
  247. }
  248. module thread(profile, thread_draw) {
  249. if (profile[0]) {
  250. // male thread
  251. difference() {
  252. union() {
  253. cylinder(d = outer_dia, h = thread_base + body_screw_depth);
  254. scale([1, profile[7] ? 1 : -1, 1])
  255. metric_thread(profile[1], profile[2], profile[4] + thread_base + body_screw_depth, test=!thread_draw);
  256. }
  257. translate([0, 0, -1])
  258. cylinder(d = profile[6], h = profile[4] + thread_base + body_screw_depth + 2);
  259. }
  260. } else {
  261. // female thread
  262. difference() {
  263. cylinder(d = outer_dia, h = thread_base + body_screw_depth + profile[4] + profile[3]);
  264. translate([0, 0, -1])
  265. scale([1, profile[7] ? 1 : -1, 1])
  266. metric_thread(profile[1], profile[2], profile[4] + thread_base + body_screw_depth + 2, true, test=!thread_draw);
  267. translate([0, 0, thread_base + body_screw_depth + profile[4]])
  268. cylinder(d = profile[5], h = profile[3] + 1);
  269. translate([0, 0, -1])
  270. cylinder(d = profile[6], h = profile[4] + thread_base + profile[3] + 2);
  271. }
  272. }
  273. }
  274. module thread_profile_adapter(profile, draw_profile) {
  275. difference() {
  276. thread(profile, draw_profile);
  277. for (r = [45, -45])
  278. for (r2 = [0, 180])
  279. rotate([0, 0, r + r2])
  280. translate([0, (outer_dia - body_screw_insert_dia) / 2 - thread_adapter_screw_inset, 0]) {
  281. translate([0, 0, -1])
  282. cylinder(d = body_screw_dia, h = 50);
  283. translate([0, 0, thread_base])
  284. cylinder(d = body_screw_head, h = 50);
  285. }
  286. }
  287. }
  288. module mac11_extender() {
  289. difference() {
  290. cylinder(d = outer_dia, h = 15);
  291. translate([0, 0, -1])
  292. cylinder(d = 20, h = 15 + 2);
  293. for (r = [45, -45])
  294. for (r2 = [0, 180])
  295. rotate([0, 0, r + r2])
  296. translate([0, (outer_dia - body_screw_insert_dia) / 2 - thread_adapter_screw_inset, 0]) {
  297. translate([0, 0, -1])
  298. cylinder(d = body_screw_dia, h = 50);
  299. }
  300. }
  301. }
  302. module thread_adapter() {
  303. difference() {
  304. cylinder(d = outer_dia, h = thread_adapter_h);
  305. translate([0, 0, -1])
  306. cylinder(d = inner_dia, h = thread_adapter_h + 2);
  307. for (r = [45, -45])
  308. rotate([0, 0, r])
  309. translate([0, (outer_dia - body_screw_insert_dia) / 2 - thread_adapter_screw_inset, -thread_adapter_in_body])
  310. cylinder(d = body_screw_insert_dia, h = body_screw_insert_height + 1);
  311. }
  312. }
  313. module half_body(right_side) {
  314. difference() {
  315. union() {
  316. // body
  317. cylinder(d = outer_dia, h = height);
  318. translate([0, 0, height])
  319. thread_adapter();
  320. }
  321. // inner tube
  322. translate([0, 0, -1])
  323. cylinder(d = inner_dia, h = height + 2);
  324. // remove half of cylinder
  325. translate([-outer_dia / 2 - 1, -outer_dia + body_gap / 2, -1])
  326. cube([outer_dia + 2, outer_dia, height + 2]);
  327. // led cutouts
  328. for (x = [1, -1])
  329. scale([x, 1, 1])
  330. for (z = [led_off, height - led_off])
  331. translate([inner_dia / 2 - 1, 0, z])
  332. rotate([0, 90, 0]) {
  333. cylinder(d = led_dia, h = led_l + led_ridge_h + 1);
  334. translate([0, 0, led_l + 1])
  335. cylinder(d = led_ridge_dia, h = led_ridge_h);
  336. }
  337. if (include_uv_leds)
  338. for (x = [1, -1])
  339. scale([x, 1, 1])
  340. translate([inner_dia / 2 - 1, 0, led_off / 2])
  341. rotate([0, 90, 0]) {
  342. cylinder(d = led_dia, h = led_l + led_ridge_h + 1);
  343. translate([0, 0, led_l + 1])
  344. cylinder(d = led_ridge_dia, h = led_ridge_h);
  345. }
  346. // TODO hacky sensor cable, arduino side
  347. for (z = [1, -1])
  348. translate([0, 0, height / 2])
  349. scale([right_side ? -1 : 1, 1, z])
  350. translate([0, 0, height / 2 - led_off])
  351. hull() {
  352. for (x = [0, 5])
  353. translate([-inner_dia / 2 - led_l - led_ridge_h - x, 0, 0])
  354. rotate([0, 90, 0])
  355. cylinder(d = led_ridge_dia, h = led_ridge_h);
  356. translate([-inner_dia / 2 - led_l - led_ridge_h - 5, 0, -10])
  357. cylinder(d = led_ridge_dia, h = led_ridge_h);
  358. if (include_uv_leds)
  359. if (z < 0)
  360. for (x = [0, 5])
  361. translate([-inner_dia / 2 - led_l - led_ridge_h - x, 0, led_off / 2])
  362. rotate([0, 90, 0])
  363. cylinder(d = led_ridge_dia, h = led_ridge_h);
  364. }
  365. // TODO hacky led cable, led side
  366. for (z = [1, -1])
  367. translate([0, 0, height / 2])
  368. scale([right_side ? 1 : -1, 1, z])
  369. translate([0, 0, height / 2 - led_off])
  370. hull() {
  371. for (x = [0, 5])
  372. translate([-inner_dia / 2 - led_l - led_ridge_h - x, 0, 0])
  373. rotate([0, 90, 0])
  374. cylinder(d = led_ridge_dia, h = led_ridge_h);
  375. translate([-inner_dia / 2 - led_l - led_ridge_h - 5, 0, -height / 2 + led_off - 1])
  376. cube([led_ridge_dia + 2, led_ridge_dia - 2, led_ridge_h]);
  377. if (include_uv_leds)
  378. if (z < 0)
  379. for (x = [0, 5])
  380. translate([-inner_dia / 2 - led_l - led_ridge_h - x, 0, led_off / 2])
  381. rotate([0, 90, 0])
  382. cylinder(d = led_ridge_dia, h = led_ridge_h);
  383. }
  384. }
  385. }
  386. module screw_holes(with_head) {
  387. for (x = [body_screw_pos, -body_screw_pos])
  388. for (z = [body_screw_off, height - body_screw_off])
  389. translate([x, 0, z])
  390. rotate([-90, 0, 0]) {
  391. translate([0, 0, -1])
  392. if (with_head)
  393. cylinder(d = body_screw_dia, h = outer_dia / 2 + 2);
  394. else
  395. cylinder(d = body_screw_insert_dia, h = body_screw_insert_height);
  396. if (with_head)
  397. translate([0, 0, outer_dia / 2 - circle_offset_deviation(body_screw_pos + body_screw_head / 2, outer_dia) - body_screw_depth - 2])
  398. cylinder(d = body_screw_head, h = 50);
  399. }
  400. }
  401. module left_half() {
  402. difference() {
  403. half_body(false);
  404. translate([-outer_dia / 2 - 1, -outer_dia / 2 - 1 + body_gap / 2, height - 1])
  405. cube([outer_dia + 2, outer_dia / 2 + 1, 50]);
  406. screw_holes(false);
  407. translate([0, outer_dia / 2 - circle_offset_deviation(lcd_pcb_h / 2, outer_dia) - lcd_pcb_d, height / 2 + lcd_off])
  408. rotate([0, 90, 0])
  409. translate([lcd_pcb_w / 2, 0, -lcd_pcb_h / 2])
  410. rotate([90, 0, 180])
  411. lcd_cutout();
  412. translate([-outer_dia / 2 + ((outer_dia / 2) - (inner_dia / 2) - arduino_w) / 2, arduino_d / 2, -arduino_h / 2 + height / 2])
  413. rotate([90, 0, 0])
  414. arduino_cutout();
  415. translate([0, outer_dia / 2 - circle_offset_deviation(switch_plate_w / 2, outer_dia), height / 2 - switch_off])
  416. rotate([0, 0, 180])
  417. switch_cutout();
  418. // TODO hacky switch cable
  419. translate([-16, -10, height / 2 - switch_off])
  420. rotate([-90, 0, -27])
  421. cylinder(d = switch_h - 2, h = outer_dia);
  422. // TODO hacky lcd cable
  423. translate([-15, -10, 60])
  424. rotate([-90, 0, -12])
  425. cylinder(d = 6.0, h = outer_dia);
  426. // TODO hacky led cable
  427. translate([0, 0, height / 2 + 3]) {
  428. translate([inner_dia / 2 + led_l + led_ridge_dia / 2, led_ridge_h + inner_dia / 2 + 2, 0])
  429. rotate([90, 0, 0])
  430. cylinder(d = led_ridge_dia, h = led_ridge_h + inner_dia / 2 + 2);
  431. hull() {
  432. translate([inner_dia / 2 + led_l + led_ridge_dia / 2, led_ridge_h + inner_dia / 2 + 2, 0])
  433. rotate([90, 0, 0])
  434. cylinder(d = led_ridge_dia, h = led_ridge_h);
  435. translate([inner_dia / 2 + led_l + led_ridge_dia / 2 - 5, led_ridge_h + inner_dia / 2 + 2, 0])
  436. rotate([0, 90, 0])
  437. cylinder(d = led_ridge_dia, h = led_ridge_h + 5);
  438. }
  439. translate([inner_dia / 2 + led_l + led_ridge_dia / 2 - 25, led_ridge_h + inner_dia / 2 + 2, 0])
  440. rotate([0, 90, 0])
  441. cylinder(d = led_ridge_dia, h = led_ridge_h + 25);
  442. hull() {
  443. translate([inner_dia / 2 + led_l + led_ridge_dia / 2 - 25, led_ridge_h + inner_dia / 2 + 2, 0])
  444. rotate([90, 0, 0])
  445. cylinder(d = led_ridge_dia, h = led_ridge_h + 10);
  446. translate([inner_dia / 2 + led_l + led_ridge_dia / 2 - 25, led_ridge_h + inner_dia / 2 + 2, 0])
  447. rotate([0, 90, 0])
  448. cylinder(d = led_ridge_dia, h = led_ridge_h);
  449. }
  450. }
  451. for (t = texts_left)
  452. rotate([0, 0, -t[4]])
  453. translate([0, outer_dia / 2 - t[3], (height + thread_adapter_h) / 2])
  454. rotate([0, -90, -90])
  455. linear_extrude(height = t[3] + 1)
  456. text(t[0], size = t[2], font = t[1], halign = "center", valign="center");
  457. }
  458. }
  459. module right_half() {
  460. difference() {
  461. half_body(true);
  462. translate([-outer_dia / 2 - 1, -outer_dia / 2 - 1 + body_gap / 2, height - 1])
  463. cube([outer_dia + 2, outer_dia / 2 + 1, 50]);
  464. screw_holes(true);
  465. translate([outer_dia / 2 - arduino_w -((outer_dia / 2) - (inner_dia / 2) - arduino_w) / 2, arduino_d / 2, -arduino_h / 2 + height / 2])
  466. rotate([90, 0, 0])
  467. arduino_cutout();
  468. }
  469. }
  470. module right_half_aaa_bat() {
  471. difference() {
  472. right_half();
  473. for (a = [0, bat_angle, -bat_angle])
  474. rotate([0, 0, a])
  475. translate([-bat_w / 2, outer_dia / 2 - bat_w, (height - bat_h) / 2])
  476. bat_cutout();
  477. }
  478. }
  479. module right_halt_aa_bat() {
  480. difference() {
  481. right_half();
  482. difference() {
  483. translate([-test_bat_w / 2, outer_dia / 2 - circle_offset_deviation(test_bat_w / 2, outer_dia), (height - test_bat_h) / 2])
  484. cube([test_bat_w, test_bat_d + 1, test_bat_h]);
  485. // TODO hacky
  486. if (enable_gap_support)
  487. translate([-0.5, 14 + 1, 20])
  488. cube([1, 12, test_bat_h + 2]);
  489. }
  490. for (x = [test_bat_off / 2, -test_bat_off / 2])
  491. translate([x, outer_dia / 2 - circle_offset_deviation(test_bat_w / 2, outer_dia) - test_bat_l, height / 2])
  492. rotate([-90, 0, 0])
  493. cylinder(d = test_bat_dia, h = outer_dia / 2);
  494. // TODO hacky power cable
  495. translate([15, -10, 60])
  496. rotate([-90, 0, 12])
  497. cylinder(d = 6.0, h = outer_dia);
  498. }
  499. }
  500. module lipo_pcb_cutout() {
  501. translate([-lipo_pcb_w / 2, 0, lipo_pcb_usb_wall])
  502. cube([lipo_pcb_w, lipo_pcb_d, lipo_pcb_h]);
  503. translate([-lipo_pcb_usb_w / 2, lipo_pcb_usb_off, -1])
  504. cube([lipo_pcb_usb_w, lipo_pcb_usb_h, lipo_pcb_usb_wall + 2]);
  505. for (z = [0, lipo_pcb_led_off_z])
  506. translate([lipo_pcb_w / 2 - lipo_pcb_led_off_x, 0, lipo_pcb_usb_wall + lipo_pcb_led_off_z + z])
  507. rotate([-90, 0, 0])
  508. cylinder(d = lipo_pcb_led_dia, h = 42);
  509. }
  510. module lipo_lid() {
  511. difference() {
  512. rotate([0, 0, 90 - lipo_lid_angle / 2])
  513. linear_extrude(lipo_lid_height - lipo_lid_gap * 2)
  514. difference() {
  515. pie_slice(outer_dia / 2, lipo_lid_angle);
  516. pie_slice(outer_dia / 2 - lipo_lid_d + lipo_lid_gap_d, lipo_lid_angle);
  517. }
  518. // screw holes
  519. for (z = [0, lipo_lid_height - 2 * lipo_lid_screw_off])
  520. for (r = [1, -1])
  521. rotate([0, 0, r * (lipo_lid_angle / 2 - circum_angle(lipo_lid_screw_area / 2, outer_dia))])
  522. translate([0, outer_dia / 2 + 1, lipo_lid_screw_off - lipo_lid_gap + z])
  523. rotate([90, 0, 0])
  524. cylinder(d = lipo_lid_screw_d_big, h = lipo_lid_d + 2);
  525. }
  526. }
  527. module right_half_lipo() {
  528. difference() {
  529. right_half();
  530. // space for lid
  531. translate([0, 0, (height - lipo_lid_height) / 2])
  532. rotate([0, 0, 90 - lipo_lid_angle_hole / 2])
  533. linear_extrude(lipo_lid_height)
  534. difference() {
  535. pie_slice(outer_dia / 2 + 1, lipo_lid_angle_hole);
  536. pie_slice(outer_dia / 2 - lipo_lid_d, lipo_lid_angle_hole);
  537. }
  538. // compartment behind lid
  539. translate([0, 0, (height - lipo_lid_height) / 2])
  540. rotate([0, 0, 90 - lipo_lid_angle_compartment / 2])
  541. linear_extrude(lipo_lid_height)
  542. difference() {
  543. pie_slice(outer_dia / 2 - lipo_lid_d + 1, lipo_lid_angle_compartment);
  544. pie_slice(outer_dia / 2 - lipo_lid_d - lipo_lid_compartment_d, lipo_lid_angle_compartment);
  545. }
  546. // screw holes
  547. for (z = [0, lipo_lid_height - 2 * lipo_lid_screw_off])
  548. for (r = [1, -1])
  549. rotate([0, 0, r * (lipo_lid_angle / 2 - circum_angle(lipo_lid_screw_area / 2, outer_dia))])
  550. translate([0, outer_dia / 2, (height - lipo_lid_height) / 2 + lipo_lid_screw_off + z])
  551. rotate([90, 0, 0])
  552. cylinder(d = lipo_lid_screw_d_small, h = lipo_lid_d + lipo_lid_screw_len);
  553. // charging pcb
  554. translate([0, outer_dia / 2 - 11, 0]) {
  555. lipo_pcb_cutout();
  556. %translate([-(lipo_pcb_w - 1) / 2, 0.5, lipo_pcb_usb_wall])
  557. cube([lipo_pcb_w - 1, lipo_pcb_d - 1, lipo_pcb_h + 1]);
  558. }
  559. translate([-lipo_w / 2, outer_dia / 2 - lipo_lid_d - lipo_d - circle_offset_deviation(lipo_w / 2, outer_dia - (lipo_lid_d * 2)) - 1, 32]) {
  560. cube([lipo_w, lipo_d + 20, lipo_h]);
  561. %cube([lipo_w, lipo_d, lipo_h]);
  562. }
  563. // TODO hacky power cable
  564. translate([15, -10, 27])
  565. rotate([-90, 0, 15])
  566. cylinder(d = 6.0, h = outer_dia);
  567. for (t = texts_lipo)
  568. rotate([0, 0, -t[4]])
  569. translate([0, outer_dia / 2 - t[3], (height + thread_adapter_h) / 2])
  570. rotate([0, -90, -90])
  571. linear_extrude(height = t[3] + 1)
  572. text(t[0], size = t[2], font = t[1], halign = "center", valign="center");
  573. }
  574. // TODO hacky
  575. if (enable_gap_support) {
  576. translate([-0.5, 10, 17.5])
  577. cube([1, 17, lipo_lid_height + 1]);
  578. for (x = [-12, 11])
  579. translate([x, 10, 31])
  580. cube([1, 10, 45]);
  581. }
  582. }
  583. module assembly_right_half_lipo() {
  584. right_half_lipo();
  585. color("green")
  586. translate([0, 0, (height - lipo_lid_height) / 2 + lipo_lid_gap])
  587. lipo_lid();
  588. }
  589. module assembly_closed() {
  590. //right_half_aaa_bat();
  591. //right_halt_aa_bat();
  592. assembly_right_half_lipo();
  593. rotate([0, 0, 180])
  594. left_half();
  595. translate([0, 0, height + thread_adapter_h + 0.5])
  596. thread_profile_adapter(thread_profiles[0], false);
  597. }
  598. module assembly_opened(angle) {
  599. translate([-outer_dia / 2, 0, 0]) {
  600. rotate([0, 0, angle / 2])
  601. translate([outer_dia / 2, 0, 0])
  602. //right_half_aaa_bat();
  603. //right_halt_aa_bat();
  604. assembly_right_half_lipo();
  605. rotate([0, 0, -angle / 2])
  606. translate([outer_dia / 2, 0, 0])
  607. rotate([0, 0, 180])
  608. left_half();
  609. }
  610. }
  611. module print_all_thread_adapters() {
  612. for (p = [0 : len(thread_profiles) - 1])
  613. translate([(p - floor(len(thread_profiles) / 2)) * (outer_dia + 5), -outer_dia / 2 - 5, 0])
  614. thread_profile_adapter(thread_profiles[p], true);
  615. }
  616. module print(all_thread_adapters) {
  617. translate([outer_dia / 2 + 5, 0, 0])
  618. left_half();
  619. translate([-outer_dia / 2 - 5, 0, 0])
  620. //right_half_aaa_bat();
  621. //right_halt_aa_bat();
  622. right_half_lipo();
  623. if (all_thread_adapters)
  624. print_all_thread_adapters();
  625. }
  626. //lcd_cutout();
  627. //left_half();
  628. //right_half();
  629. //right_half_aaa_bat();
  630. //right_halt_aa_bat();
  631. //right_half_lipo();
  632. //lipo_lid();
  633. //assembly_right_half_lipo();
  634. //assembly_closed();
  635. //assembly_opened(90);
  636. //print(true);
  637. //print(false);
  638. //print_all_thread_adapters();
  639. //thread_profile_adapter(thread_profile_1911, true);
  640. //thread_profile_adapter(thread_profile_m14_cw, true);
  641. //thread_profile_adapter(thread_profile_m14_ccw, true);
  642. //thread_profile_adapter(thread_profile_giant, true);
  643. thread_profile_adapter(thread_profile_mac11, true);
  644. //mac11_extender();