No Description
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.

table.scad 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. /*
  2. * Resources used:
  3. * https://www.thingiverse.com/thing:16627
  4. * https://www.chiefdelphi.com/t/timing-pulley-design-tutorial/383204
  5. *
  6. * Hardware required:
  7. * https://www.banggood.com/15pcs-Transparent-Pulley-Wheel-with-625zz-Double-Bearing-for-V-slot-3D-Printer-p-1575067.html?cur_warehouse=CN&rmmds=search
  8. * 2x NEMA17 stepper
  9. * 2040 extrusions, lengths see console output
  10. * 2020 extrusions, lengths see console output
  11. * GT2 belt, lengths see console output
  12. */
  13. include <config.scad>;
  14. use <gt2_pulley.scad>;
  15. use <common.scad>;
  16. $fn = 42;
  17. /***********************************
  18. ********** Printed Parts **********
  19. ***********************************/
  20. module belt_pulley(tc, dia, for_motor = 1) {
  21. difference() {
  22. union() {
  23. cylinder(d = dia + belt_pulley_rim * 2, h = (belt_pulley_width - belt_pulley_tooth_width) / 2);
  24. translate([0, 0, (belt_pulley_width - belt_pulley_tooth_width) / 2])
  25. gt2_2mm_pulley(tc, belt_pulley_tooth_width);
  26. cylinder(d = dia, h = (belt_pulley_width - belt_pulley_tooth_width) / 2);
  27. translate([0, 0, (belt_pulley_width - belt_pulley_tooth_width) / 2 + belt_pulley_tooth_width])
  28. cylinder(d = dia + belt_pulley_rim * 2, h = (belt_pulley_width - belt_pulley_tooth_width) / 2);
  29. }
  30. if (for_motor) {
  31. // motor shaft hole
  32. translate([0, 0, -1])
  33. cylinder(d = belt_pulley_axis_hole, h = belt_pulley_width + 2);
  34. // grub screw
  35. for (i = [0, 90])
  36. translate([0, 0, belt_pulley_width / 2])
  37. rotate([90, 0, i])
  38. cylinder(d = belt_pulley_fix_dia, h = dia / 2 + 1);
  39. } else {
  40. // bearing hole
  41. translate([0, 0, -1])
  42. cylinder(d = bearing_outer, h = belt_pulley_width + 2);
  43. // grub screw
  44. for (i = [0, 90, 180, 270])
  45. translate([0, 0, (i > 90 ? 1 : -1) * 2])
  46. translate([0, 0, belt_pulley_width / 2])
  47. rotate([90, 0, i])
  48. cylinder(d = belt_pulley_fix_dia, h = dia / 2 + 1);
  49. }
  50. }
  51. }
  52. module belt_tensioner_diff() {
  53. translate([-50, -belt_tensioner_diff_len, -belt_tensioner_diff_height / 2])
  54. cube([100, belt_tensioner_diff_len, belt_tensioner_diff_height]);
  55. translate([-belt_tensioner_diff_width / 2, -belt_tensioner_diff_len, -50])
  56. cube([belt_tensioner_diff_width, belt_tensioner_diff_len, 100]);
  57. }
  58. module belt_tensioner_mount_rail(height) {
  59. echo("belt tensioner", "t-nut", str(height * 2, "x"), str(motor_mount_hole_size_nominal, "mm"));
  60. difference() {
  61. if (height == 1) {
  62. for (i = [ 10, -10 - belt_tensioner_wall ])
  63. translate([i, 0, 0])
  64. cube([belt_tensioner_wall, belt_tensioner_mount_depth, 20 + belt_tensioner_wall]);
  65. } else {
  66. for (i = [ 10, -10 - belt_tensioner_wall ])
  67. translate([i, 0, -20])
  68. cube([belt_tensioner_wall, belt_tensioner_mount_depth, 40 + belt_tensioner_wall]);
  69. }
  70. for (i = [ 10, -10 ])
  71. translate([-10 - belt_tensioner_wall - 1, belt_tensioner_mount_depth / 2, i])
  72. rotate([0, 90, 0])
  73. cylinder(d = motor_mount_hole_size, h = 20 + 2 * belt_tensioner_wall + 2);
  74. }
  75. }
  76. module belt_tensioner_mount(height) {
  77. echo("belt tensioner", "screw", "1x", str("M", belt_tensioner_screw), str(">", belt_tensioner_diff_len + belt_tensioner_wall + 5 - real_belt_pulley_dia, "mm"));
  78. echo("belt tensioner", "nut", "1x", str("M", belt_tensioner_screw));
  79. belt_tensioner_mount_rail(height);
  80. difference() {
  81. hull() {
  82. if (height == 1) {
  83. for (i = [ 10, -10 - belt_tensioner_wall ])
  84. translate([i, 0, 0])
  85. cube([belt_tensioner_wall, 1, 20 + belt_tensioner_wall]);
  86. } else {
  87. for (i = [ 10, -10 - belt_tensioner_wall ])
  88. translate([i, 0, -20])
  89. cube([belt_tensioner_wall, 1, 40 + belt_tensioner_wall]);
  90. }
  91. translate([-10, -belt_tensioner_diff_len - belt_tensioner_wall - 5, 25 - 21])
  92. cube([20, belt_tensioner_wall, 20 + 1]);
  93. }
  94. translate([-10 - belt_tensioner_wall - 1, 0, -22])
  95. cube([20 + 2 * belt_tensioner_wall + 2, 50, 50]);
  96. translate([-10, 0, -22])
  97. cube([20, 50, 50]);
  98. translate([0, 0, 10 + belt_pulley_off])
  99. belt_tensioner_diff();
  100. translate([0, -belt_tensioner_diff_len - belt_tensioner_wall - 5 + 30 - 1, real_belt_pulley_dia / 2 + 0.175])
  101. rotate([90, 0, 0])
  102. cylinder(d = belt_tensioner_screw_hole, h = 30);
  103. }
  104. }
  105. module belt_tensioner_moving() {
  106. %color("red")
  107. translate([-belt_pulley_width / 2, 0, 0])
  108. rotate([0, 90, 0])
  109. rotate([0, 0, -acos(anim_pos_x * -2 + 1)])
  110. belt_pulley(teethcount, real_belt_pulley_dia, 0);
  111. color("cyan")
  112. difference() {
  113. for (i = [-1, 1])
  114. scale([i, 1, 1])
  115. translate([belt_pulley_width / 2 + belt_tensioner_moving_gap, belt_tensioner_moving_overlap - belt_tensioner_moving_len, -belt_tensioner_moving_height / 2])
  116. cube([belt_tensioner_wall, belt_tensioner_moving_len, belt_tensioner_moving_height]);
  117. translate([-belt_pulley_width / 2 - belt_tensioner_wall - belt_tensioner_moving_gap - 1, 0, 0])
  118. rotate([0, 90, 0])
  119. cylinder(d = axis_hole_diameter, h = belt_pulley_width + 2 * (belt_tensioner_wall + belt_tensioner_moving_gap) + 2);
  120. }
  121. color("cyan")
  122. translate([-belt_pulley_width / 2 - belt_tensioner_moving_gap, -belt_tensioner_moving_len + belt_tensioner_moving_overlap, -belt_tensioner_moving_height / 2])
  123. difference() {
  124. cube([belt_pulley_width + 2 * belt_tensioner_moving_gap, belt_tensioner_wall, belt_tensioner_moving_height]);
  125. translate([belt_pulley_width / 2 + belt_tensioner_moving_gap, belt_tensioner_wall + 1, belt_tensioner_moving_height / 2])
  126. rotate([90, 0, 0])
  127. cylinder(d = belt_tensioner_screw_hole, h = belt_tensioner_wall + 2);
  128. }
  129. }
  130. module belt_tensioner(height, length = 100, visual = 1) {
  131. if (visual)
  132. %translate([-10, 0, 0])
  133. if (length > 0) {
  134. if (height == 1) {
  135. rail_2020_y(length, "only for visualization");
  136. } else {
  137. rail_2040_y(length, "only for visualization");
  138. }
  139. }
  140. translate([0, -belt_tensioner_travel * $t, 0])
  141. translate([0, -real_belt_pulley_dia / 2, 10 + belt_pulley_off])
  142. belt_tensioner_moving();
  143. color("orange")
  144. belt_tensioner_mount(height);
  145. %color("yellow")
  146. translate([-belt_width / 2, -real_belt_pulley_dia / 2, 10 + real_belt_pulley_dia / 2 + belt_pulley_off - belt_thickness / 2])
  147. cube([belt_width, length + real_belt_pulley_dia / 2 + nema17_size / 2, belt_thickness]);
  148. %color("yellow")
  149. translate([-belt_width / 2, -real_belt_pulley_dia / 2, 10 - real_belt_pulley_dia / 2 - belt_thickness / 2 + belt_pulley_off])
  150. cube([belt_width, length + real_belt_pulley_dia / 2 + nema17_size / 2, belt_thickness]);
  151. }
  152. module motor_mount(height) {
  153. echo("motor mount", "t-nut", str(height * 2, "x"), str(motor_mount_hole_size_nominal, "mm"));
  154. echo("motor mount", "screw", "4x", str("M", nema17_hole_size), str(motor_mount_height + 2, "-", motor_mount_height + 4, "mm"));
  155. %color("yellow")
  156. translate([-nema17_len, 0, nema17_size - belt_pulley_off])
  157. rotate([0, 90, 0])
  158. nema17(nema17_len);
  159. %color("red")
  160. translate([motor_mount_height - belt_pulley_width / 2 + 10, nema17_size / 2, nema17_size / 2 - belt_pulley_off])
  161. rotate([0, 90, 0])
  162. rotate([0, 0, -acos(anim_pos_x * -2 + 1)])
  163. belt_pulley(teethcount, real_belt_pulley_dia, 1);
  164. color("cyan")
  165. difference() {
  166. hull() {
  167. translate([0, 0, -belt_pulley_off])
  168. cube([motor_mount_height, nema17_size, nema17_size]);
  169. translate([0, nema17_size, (nema17_size - 20) / 2])
  170. cube([motor_mount_height, motor_mount_length, height * 20]);
  171. }
  172. translate([0, 0, -belt_pulley_off])
  173. translate([-nema17_len, 0, nema17_size])
  174. rotate([0, 90, 0]) {
  175. nema17_holes_face(nema17_len, motor_mount_height + 5, nema17_hole_size + screw_gap);
  176. translate([nema17_size / 2, nema17_size / 2, nema17_len - 1])
  177. cylinder(d = nema17_center_size + 2, h = motor_mount_height + 2);
  178. }
  179. for (i = [0, motor_mount_hole_off])
  180. for (j = [0, 20 * (height - 1)])
  181. translate([0, i, j])
  182. translate([-1, nema17_size - motor_mount_hole_off / 2 + motor_mount_length / 2, nema17_size / 2])
  183. rotate([0, 90, 0]) {
  184. cylinder(d = motor_mount_hole_size, h = motor_mount_height + 2);
  185. }
  186. }
  187. }
  188. /***********************************
  189. ************** Plate **************
  190. ***********************************/
  191. module plate_holes(h) {
  192. for (i = [-1, 1])
  193. for (j = [-1, 1])
  194. translate([i * plate_mount_screws_distance_x / 2, j * plate_mount_screws_distance_y / 2, -1])
  195. cylinder(d = plate_mount_screw_hole, h = h + 2);
  196. }
  197. module plate() {
  198. echo("alu plate", "bed", plate_x, plate_y, "holes", plate_mount_screws_distance_x, plate_mount_screws_distance_y);
  199. difference() {
  200. cube([plate_x, plate_y, plate_z]);
  201. translate([plate_x / 2, plate_y / 2, 0])
  202. plate_holes(plate_z);
  203. }
  204. }
  205. /************************************
  206. ************** Y-Axis **************
  207. ************************************/
  208. module belt_mount(h) {
  209. difference() {
  210. hull() {
  211. translate([-belt_mount_width / 2, -belt_mount_depth / 2, 0])
  212. cube([belt_mount_width, belt_mount_depth, h]);
  213. translate([-belt_mount_full_width / 2, belt_mount_depth / 2, 0])
  214. cube([belt_mount_full_width, 1, h]);
  215. }
  216. translate([-belt_slot_width / 2, -belt_slot_depth / 2, -1])
  217. cube([belt_slot_width, belt_slot_depth, h + 2]);
  218. translate([-belt_mount_full_width / 2, -belt_mount_depth / 2 - 0.1, h / 2])
  219. rotate([-90, 0, 0])
  220. prism(belt_mount_full_width, h / 2 + 0.1, belt_mount_depth + 0.1);
  221. }
  222. }
  223. module eccentric() {
  224. translate([0, 0, eccentric_height_add]) {
  225. cylinder(d = eccentric_dia_main, h = eccentric_height_main);
  226. translate([0, 0, -eccentric_height_inset])
  227. cylinder(d = eccentric_dia_inset, h = eccentric_height_inset);
  228. }
  229. }
  230. module y_carriage_post() {
  231. rotate([0, 0, 90])
  232. difference() {
  233. cylinder(d = y_carriage_post_dia, h = y_carriage_post_len, $fn = 6);
  234. translate([0, 0, -1])
  235. cylinder(d = y_carriage_post_screw_hole, h = (y_carriage_post_len - y_carriage_post_center) / 2 + 1);
  236. translate([y_carriage_post_hole_off, 0, (y_carriage_post_len + y_carriage_post_center) / 2])
  237. cylinder(d = y_carriage_post_screw_hole, h = (y_carriage_post_len - y_carriage_post_center) / 2 + 1);
  238. }
  239. }
  240. module y_carriage_posts() {
  241. for (i = [-1, 1])
  242. for (j = [-1, 1])
  243. translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, 0]) {
  244. if (use_custom_eccentric) {
  245. color("yellow")
  246. eccentric();
  247. %color("yellow")
  248. translate([0, eccentric_hole_off, y_carriage_pulley_off])
  249. rail_wheel();
  250. } else {
  251. color("blue")
  252. y_carriage_post();
  253. %color("yellow")
  254. translate([0, y_carriage_post_hole_off, y_carriage_pulley_off])
  255. rail_wheel();
  256. }
  257. }
  258. }
  259. module carriage_spacer() {
  260. difference() {
  261. cube([y_carriage_x, y_carriage_y, carriage_spacer_height]);
  262. translate([y_carriage_x / 2, y_carriage_y / 2, 0])
  263. plate_holes(carriage_spacer_height);
  264. translate([carriage_spacer_cut_x / 2 * sqrt(2) + y_carriage_x / 2, -1, -1])
  265. rotate([0, -90, 45])
  266. prism(carriage_spacer_height + 2, carriage_spacer_cut_x, carriage_spacer_cut_x);
  267. translate([-carriage_spacer_cut_x / 2 * sqrt(2) + y_carriage_x / 2, y_carriage_y + 1, -1])
  268. rotate([0, -90, 225])
  269. prism(carriage_spacer_height + 2, carriage_spacer_cut_x, carriage_spacer_cut_x);
  270. translate([-1, y_carriage_y / 2 - carriage_spacer_cut_y / 2 * sqrt(2), -1])
  271. rotate([0, -90, -45])
  272. prism(carriage_spacer_height + 2, carriage_spacer_cut_y, carriage_spacer_cut_y);
  273. translate([y_carriage_x + 1, y_carriage_y / 2 + carriage_spacer_cut_y / 2 * sqrt(2), -1])
  274. rotate([0, -90, -225])
  275. prism(carriage_spacer_height + 2, carriage_spacer_cut_y, carriage_spacer_cut_y);
  276. }
  277. }
  278. // also used as base for x-carriage
  279. // axis = 0 --> all holes, usable for both
  280. // axis = 1 --> holes for x-carriage
  281. // axis = 2 --> holes for y-carriage
  282. module y_carriage(axis = 0) {
  283. if (axis == 1) {
  284. echo("t-nut", "x-carriage", "2");
  285. }
  286. if (use_custom_eccentric) {
  287. echo("eccentric", "carriage", "4");
  288. echo("screw", "carriage", "M5x30", "4");
  289. echo("nut", "carriage", "M5", "4");
  290. }
  291. color("green")
  292. difference() {
  293. union() {
  294. cube([y_carriage_x, y_carriage_y, y_carriage_h]);
  295. translate([y_carriage_x / 2, y_carriage_y / 2, 0])
  296. for (i = [-1, 1])
  297. translate([0, i * (y_carriage_y + belt_mount_depth) / 2, 0])
  298. scale([1, -i, 1])
  299. belt_mount(y_carriage_h);
  300. // additional "meat" for eccentric inset
  301. translate([y_carriage_x / 2, y_carriage_y / 2, y_carriage_h])
  302. for (i = [-1, 1])
  303. for (j = [-1, 1])
  304. translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, 0])
  305. if (use_custom_eccentric)
  306. cylinder(d = eccentric_inset_wall, h = eccentric_height_add);
  307. }
  308. translate([y_carriage_x / 2, y_carriage_y / 2, 0])
  309. plate_holes(y_carriage_h);
  310. // holes to mount y-axis to x-carriage
  311. if ((axis == 0) || (axis == 1)) {
  312. translate([(y_carriage_x - plate_mount_screws_distance_x) / 2, 0, 0])
  313. for (i = [0, 1])
  314. translate([i * plate_mount_screws_distance_x, y_carriage_y / 2, -1])
  315. cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2);
  316. for (i = [x_carriage_holder_l - x_carriage_holder_hole_off, y_carriage_y - x_carriage_holder_l + x_carriage_holder_hole_off])
  317. translate([y_carriage_x / 2, i, -1])
  318. cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2);
  319. }
  320. // holes for wheel posts
  321. translate([y_carriage_x / 2, y_carriage_y / 2, 0])
  322. for (i = [-1, 1])
  323. for (j = [-1, 1])
  324. translate([i * y_carriage_wheel_x_dist / 2, j * y_carriage_wheel_y_dist / 2, -1])
  325. if (use_custom_eccentric) {
  326. cylinder(d = eccentric_screw_hole, h = y_carriage_h + 2);
  327. translate([0, 0, y_carriage_h + eccentric_height_add + 1 - eccentric_inset_hole])
  328. cylinder(d = eccentric_dia_inset, h = eccentric_inset_hole + 1);
  329. cylinder(d = eccentric_screw_hole_dia, h = eccentric_screw_hole_h + 1);
  330. } else {
  331. cylinder(d = y_carriage_post_screw_hole, h = y_carriage_h + 2);
  332. }
  333. }
  334. %translate([y_carriage_x / 2, y_carriage_y / 2, y_carriage_h])
  335. y_carriage_posts();
  336. }
  337. module y_axis() {
  338. translate([y_carriage_x / 2, y_axis_animation_position, 20 + y_carriage_h + y_carriage_rail_dist])
  339. rotate([0, 180, 0]) {
  340. y_carriage(2);
  341. color("cyan")
  342. translate([0, 0, -carriage_spacer_height - 0.01])
  343. carriage_spacer();
  344. }
  345. color("grey")
  346. translate([-10, 0, 0])
  347. rail_2040_y(y_axis_rail_len, "y-axis");
  348. translate([- motor_mount_height - 10, y_axis_rail_len + nema17_size, nema17_size / 2 + 10])
  349. rotate([180, 0, 0])
  350. motor_mount(2);
  351. translate([10 + endstop_mount_depth, y_axis_rail_len - endstop_mount_width, -20])
  352. rotate([0, 0, 90])
  353. endstop_mount();
  354. belt_tensioner(2, y_axis_rail_len, 0);
  355. }
  356. /************************************
  357. ************** X-Axis **************
  358. ************************************/
  359. module x_carriage_holder() {
  360. echo("t-nut", "x-carriage-holder", "2");
  361. difference() {
  362. union() {
  363. cube([x_carriage_holder_l, x_carriage_holder_w, x_carriage_holder_h]);
  364. cube([x_carriage_holder_h, x_carriage_holder_w, 20]);
  365. }
  366. translate([0, (x_carriage_holder_w - x_carriage_holder_rail_hole_dist) / 2, 0])
  367. for (i = [0, x_carriage_holder_rail_hole_dist])
  368. translate([-1, i, 10])
  369. rotate([0, 90, 0])
  370. cylinder(d = y_carriage_post_screw_hole, h = x_carriage_holder_h + 2);
  371. translate([-(y_carriage_y - plate_mount_screws_distance_y) / 2, y_carriage_x / 2, 0])
  372. rotate([0, 0, 90])
  373. plate_holes(x_carriage_holder_h);
  374. translate([x_carriage_holder_hole_off, x_carriage_holder_w / 2, -1])
  375. cylinder(d = y_carriage_post_screw_hole, h = x_carriage_holder_h + 2);
  376. }
  377. }
  378. module x_carriage() {
  379. translate([0, -y_carriage_x / 2, y_carriage_h + y_carriage_rail_dist + 20])
  380. rotate([0, 180, -90])
  381. y_carriage(1);
  382. /*
  383. color("purple")
  384. for (i = [-1, 1])
  385. translate([y_carriage_y / 2, 0, 0])
  386. scale([i, 1, 1])
  387. translate([y_carriage_y / 2 - x_carriage_holder_l, 0, 0])
  388. translate([0, -x_carriage_holder_w / 2, 20 + y_carriage_h + y_carriage_rail_dist])
  389. x_carriage_holder();
  390. */
  391. }
  392. module x_axis() {
  393. translate([x_axis_animation_position + 10, 0, 0])
  394. x_carriage();
  395. color("grey")
  396. translate([0, -10, 0])
  397. rail_2040_x(x_axis_rail_len, "x-axis");
  398. translate([x_axis_rail_len + nema17_size, motor_mount_height + 10, nema17_size / 2 + 10])
  399. rotate([0, 180, 90])
  400. motor_mount(2);
  401. translate([x_axis_rail_len - endstop_mount_width, -10 - endstop_mount_depth, -20])
  402. endstop_mount();
  403. rotate([0, 0, -90])
  404. belt_tensioner(2, x_axis_rail_len, 0);
  405. }
  406. /*************************************
  407. *************** Stuff ***************
  408. *************************************/
  409. psu_width = 98.0;
  410. psu_height = 43.0;
  411. psu_length = 160;
  412. psu_cut_gap = 1.0;
  413. psu_cut_w = psu_width + psu_cut_gap;
  414. psu_cut_h = psu_height + psu_cut_gap;
  415. psu_wall = 4;
  416. psu_mount_len = 40 + psu_wall;
  417. psu_mount_w = psu_cut_w + 2 * psu_wall;
  418. psu_mount_h = psu_cut_h + 2 * psu_wall;
  419. psu_mount_hole_off = 10;
  420. psu_mount_tri = 3;
  421. psu_mount_del = psu_mount_tri;
  422. psu_assembly_mount_off_y = 25;
  423. psu_assembly_mount_off_z = 6;
  424. psu_hole_dia = 4.2;
  425. psu_back_hole_x = 9.5;
  426. psu_back_hole_y = 18.0;
  427. psu_cable_hole = 8.0;
  428. psu_cable_hole_off = 13.0;
  429. //psu_side_hole_y = 26.0;
  430. //psu_side_Hole_z = 20.0;
  431. power_socket_width = 48.0;
  432. power_socket_height = 28.0;
  433. power_socket_depth = 30;
  434. power_socket_hole = 2.7;
  435. power_socket_hole_off = 11.0 - 2.8 - 1.6;
  436. power_socket_rim = 11;
  437. power_socket_wr = power_socket_width + 2 * power_socket_rim;
  438. power_socket_hr = power_socket_height + 2 * power_socket_rim;
  439. power_box_width = 70;
  440. power_box_height = psu_mount_h;
  441. power_box_depth = 50;
  442. module power_socket() {
  443. translate([-power_socket_width / 2, -power_socket_height / 2, -power_socket_depth])
  444. cube([power_socket_width, power_socket_height, power_socket_depth]);
  445. difference() {
  446. translate([-power_socket_wr / 2, -power_socket_hr / 2, 0])
  447. cube([power_socket_wr, power_socket_hr, 2.0]);
  448. for (i = [-1, 1])
  449. translate([0, i * (power_socket_height / 2 + power_socket_hole_off), -1])
  450. cylinder(d = power_socket_hole, h = 4.0);
  451. }
  452. }
  453. module power_box() {
  454. %color("yellow")
  455. translate([power_box_width / 2, power_box_depth, power_box_height / 2])
  456. rotate([-90, 0, 0])
  457. power_socket();
  458. color("cyan")
  459. difference() {
  460. translate([0, power_box_depth - psu_wall, 0])
  461. cube([power_box_width, psu_wall, power_box_height]);
  462. translate([(power_box_width - power_socket_width) / 2, power_box_depth - 9, (power_box_height - power_socket_height) / 2])
  463. cube([power_socket_width, 10, power_socket_height]);
  464. for (i = [1, -1])
  465. translate([power_box_width / 2, power_box_depth + 1, (power_box_height - i * power_socket_height) / 2 - power_socket_hole_off * i])
  466. rotate([90, 0, 0])
  467. cylinder(d = power_socket_hole, h = psu_wall + 15);
  468. }
  469. }
  470. module psu_holder_tab() {
  471. difference() {
  472. translate([psu_mount_del, 0, 0])
  473. cube([20 - psu_mount_del, psu_wall, psu_mount_len]);
  474. for (i = [psu_mount_hole_off, psu_mount_len - psu_mount_hole_off])
  475. translate([10, -1, i])
  476. rotate([-90, 0, 0])
  477. cylinder(d = motor_mount_hole_size, h = psu_wall + 2);
  478. }
  479. }
  480. module psu_holder_box(remove_back = 0) {
  481. if (!remove_back)
  482. translate([-psu_mount_w / 2, -psu_mount_h / 2 - psu_assembly_mount_off_z, 0])
  483. cube([psu_mount_w, psu_mount_h, psu_wall]);
  484. for (i = [-psu_mount_h / 2, psu_mount_h / 2 - psu_wall])
  485. translate([-psu_mount_w / 2, i - psu_assembly_mount_off_z, 0])
  486. cube([psu_mount_w, psu_wall, psu_mount_len]);
  487. for (i = [-psu_mount_w / 2, psu_mount_w / 2 - psu_wall])
  488. translate([i, -psu_mount_h / 2 - psu_assembly_mount_off_z, 0])
  489. cube([psu_wall, psu_mount_h, psu_mount_len]);
  490. for (i = [/* psu_mount_w / 2, */ -psu_mount_w / 2 - 20])
  491. for (j = [10, -10 - psu_wall])
  492. translate([i, j, 0])
  493. psu_holder_tab();
  494. for (i = [0, 1])
  495. translate([-psu_mount_w / 2 - i * psu_mount_tri, -psu_mount_tri - 10 - psu_wall + i * (psu_mount_tri + 20 + psu_wall * 2), 0])
  496. rotate([0, -90, i * -90])
  497. prism(psu_mount_len, psu_mount_tri, psu_mount_tri);
  498. }
  499. module psu_holder(part) {
  500. // 0 is "back side" of psu
  501. // 1 is "front" / cable side of psu
  502. difference() {
  503. union() {
  504. color("cyan")
  505. translate([0, 0, part * psu_mount_len])
  506. scale([1, 1, 1 + part * -2])
  507. psu_holder_box(part);
  508. if (part == 1) {
  509. color("cyan")
  510. translate([0, -psu_mount_h / 2 - psu_assembly_mount_off_z, psu_mount_len])
  511. hull() {
  512. translate([-power_box_width / 2, 0, power_box_depth - psu_wall - 1])
  513. cube([power_box_width, power_box_height, 1]);
  514. translate([-psu_mount_w / 2, 0, 0])
  515. cube([psu_mount_w, psu_mount_h, 1]);
  516. }
  517. translate([-power_box_width / 2, psu_mount_h / 2 - psu_assembly_mount_off_z, psu_mount_len])
  518. rotate([90, 0, 0])
  519. power_box();
  520. }
  521. }
  522. if (part == 0) {
  523. translate([-psu_mount_w / 2 + psu_back_hole_x + psu_wall, psu_mount_h / 2 - psu_assembly_mount_off_z + 1, psu_back_hole_y + psu_wall])
  524. rotate([90, 0, 0])
  525. cylinder(d = psu_hole_dia, h = psu_wall + 2);
  526. } else {
  527. translate([0, -psu_mount_h / 2 - psu_assembly_mount_off_z, psu_mount_len])
  528. hull() {
  529. translate([-power_socket_width / 2, power_socket_height / 2 - psu_wall / 2, power_box_depth - psu_wall])
  530. cube([power_socket_width, power_socket_height, 1]);
  531. translate([-psu_mount_w / 2 + psu_wall, psu_wall, -1])
  532. cube([psu_mount_w - 2 * psu_wall, psu_mount_h - 2 * psu_wall, 1]);
  533. }
  534. for (i = [-1, 0, 1])
  535. translate([i * psu_cable_hole_off, 0, 0])
  536. translate([0, -psu_mount_h / 2 + 5, psu_mount_len + power_box_depth / 4])
  537. rotate([90, 0, 0])
  538. cylinder(d = psu_cable_hole, h = psu_wall + 10);
  539. }
  540. }
  541. }
  542. module psu_holder_assembly() {
  543. color("yellow")
  544. translate([-psu_width / 2, psu_wall, -psu_height / 2 + psu_assembly_mount_off_z])
  545. cube([psu_width, psu_length, psu_height]);
  546. for (i = [0, 1])
  547. translate([0, i * (psu_length - psu_mount_len + 2 * psu_wall), 0])
  548. rotate([-90, 0, 0])
  549. psu_holder(i);
  550. }
  551. module rail_foot() {
  552. difference() {
  553. union() {
  554. sphere(d = foot_dia);
  555. translate([0, 0, foot_dia / 2])
  556. sphere(d = foot_nut_base_dia);
  557. }
  558. translate([-foot_dia / 2 - 1, -foot_dia / 2 - 1, -foot_dia / 2 - 1])
  559. cube([foot_dia + 2, foot_dia + 2, foot_dia / 2 + 1]);
  560. translate([-foot_nut_base_dia / 2 - 1, -foot_nut_base_dia / 2 - 1, foot_dia / 2])
  561. cube([foot_nut_base_dia + 2, foot_nut_base_dia + 2, foot_nut_base_dia / 2 + 1]);
  562. translate([0, 0, -1])
  563. cylinder(d = foot_screw_dia, h = foot_dia / 2 + 2);
  564. translate([0, 0, -1])
  565. cylinder(d = foot_screw_head_dia, h = foot_screw_head_height + 1);
  566. }
  567. }
  568. /************************************
  569. ************* Assembly *************
  570. ************************************/
  571. module assembly_y_axis_plate() {
  572. translate([0, -y_carriage_y / 2 - y_axis_animation_position, 0])
  573. y_axis();
  574. %translate([-plate_x / 2, -plate_y / 2, 20 + y_carriage_h + y_carriage_rail_dist + carriage_spacer_height])
  575. plate();
  576. }
  577. module assembly_x_axis() {
  578. x_axis();
  579. translate([x_axis_animation_position + y_carriage_y / 2, -y_axis_rail_len / 2, 20 + y_carriage_h + y_carriage_rail_dist])
  580. translate([10, y_axis_animation_position + y_carriage_y / 2, 20])
  581. assembly_y_axis_plate();
  582. }
  583. module assembly() {
  584. translate([-x_axis_rail_len / 2, 0, 20]) {
  585. assembly_x_axis();
  586. if (use_double_supports) {
  587. color("grey")
  588. for (i = [1, -1])
  589. scale([1, i, 1])
  590. translate([left_support_off, -left_support_len - 10, -20])
  591. rail_2020_y(left_support_len, "left support");
  592. color("grey")
  593. for (i = [1, -1])
  594. scale([1, i, 1])
  595. translate([x_axis_rail_len - 20 - right_support_off, -right_support_len - 10, -20])
  596. rail_2020_y(right_support_len, "right support");
  597. for (i = [0, 1])
  598. for (j = [1, -1])
  599. translate([i * x_axis_rail_len - (i * 2 - 1) * (right_support_off + 10), j * (right_support_len - 10), -40 - 0]) {
  600. %color("grey")
  601. cylinder(d = 5.0, h = 25);
  602. %color("green")
  603. rail_foot();
  604. }
  605. // TODO psu
  606. } else {
  607. color("grey")
  608. translate([x_axis_rail_len / 2, 0, -40])
  609. for (i = [1, -1])
  610. scale([i, 1, 1])
  611. translate([x_axis_rail_len / 2 - bottom_support_off, -bottom_support_len / 2, 0])
  612. rail_2020_y(bottom_support_len, "bottom supports");
  613. for (i = [0, 1])
  614. for (j = [1, -1])
  615. translate([i * x_axis_rail_len - (i * 2 - 1) * (bottom_support_off - 10), j * (bottom_support_len / 2 - 40), -40 - 20]) {
  616. %color("grey")
  617. cylinder(d = 5.0, h = 25);
  618. %color("green")
  619. rail_foot();
  620. }
  621. }
  622. translate([bottom_support_off + psu_mount_w / 2, 10 + psu_assembly_mount_off_y, 10 - 40])
  623. psu_holder_assembly();
  624. }
  625. }
  626. module xy_table() {
  627. translate([-point_that_reaches_everywhere_x, -point_that_reaches_everywhere_y, -40 + -40 + (y_carriage_rail_dist + y_carriage_h) * -2 + -plate_z - carriage_spacer_height])
  628. assembly();
  629. }
  630. /***********************************
  631. ************ Rendering ************
  632. ***********************************/
  633. //dispenser();
  634. //rail_2020_x(100);
  635. //rail_wheel();
  636. //rail_foot();
  637. //psu_holder(0);
  638. //psu_holder(1);
  639. //psu_holder_assembly();
  640. //motor_mount(1);
  641. //motor_mount(2);
  642. //belt_pulley(teethcount, real_belt_pulley_dia, 1);
  643. //belt_tensioner_mount(2);
  644. //belt_tensioner_moving();
  645. //belt_tensioner(1);
  646. //belt_tensioner(2);
  647. //belt_pulley(teethcount, real_belt_pulley_dia, 0);
  648. //y_carriage_post();
  649. //x_carriage_holder();
  650. //translate([0, -50, 0])
  651. //y_carriage(0);
  652. //y_carriage(1);
  653. //y_carriage(2);
  654. //x_carriage();
  655. //carriage_spacer();
  656. //y_axis();
  657. //x_axis();
  658. //assembly();
  659. xy_table();