Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

trackball.scad 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * Trackball
  3. *
  4. * Copyright (c) 2022 - 2023 Thomas Buck (thomas@xythobuz.de)
  5. * Philipp Schönberger (mail@phschoen.de)
  6. *
  7. * Required parts:
  8. * - 1x Raspberry Pi Pico
  9. * - 4x Cherry MX compatible switches and keycaps
  10. * - 1x Billard ball, diameter 38mm
  11. * - 3x Si3N4 static bearing balls, diameter 3mm
  12. * - 1x PMW3360 sensor with breakout board
  13. * - 8x M2 screw, length 5mm
  14. * - 8x M2 heat melt insert, length 4mm
  15. *
  16. * For the PMW3360 breakout board get this:
  17. * https://github.com/jfedor2/pmw3360-breakout
  18. *
  19. * This program is free software: you can redistribute it and/or modify
  20. * it under the terms of the GNU General Public License as published by
  21. * the Free Software Foundation, either version 3 of the License, or
  22. * (at your option) any later version.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. * GNU General Public License for more details.
  28. *
  29. * See <http://www.gnu.org/licenses/>.
  30. */
  31. include<mx_switch.scad>; // need include since the parameters are in there
  32. include <pico.scad>; // need include since the parameters are in there
  33. use<usbc.scad>;
  34. use<sensor_pmw3360.scad>;
  35. use<pico.scad>;
  36. use<bearing.scad>;
  37. use<ball_and_bearing.scad>;
  38. use<util.scad>;
  39. use<external/led_ring.scad>;
  40. include<config.scad>;
  41. translate([$t*assembly_dist,$t*-assembly_dist,0])
  42. top_hand_wrest();
  43. trackball_top();
  44. translate([0,0,-$t*assembly_dist])
  45. trackball_bot();
  46. // %translate([-13,38,5-trackball_dia/2])
  47. // scale(150)
  48. // rotate([0,0,-133])
  49. // import("external/mouse_scan_v1.stl");
  50. module trackball_bot()
  51. {
  52. difference() {
  53. color("green")
  54. trans_bot_of_top_part()
  55. translate([0,0,-wall])
  56. linear_extrude(wall)
  57. {
  58. hull()
  59. projection() {
  60. trackball_top();
  61. }
  62. projection() {
  63. top_hand_wrest();
  64. }
  65. }
  66. trackball_bot_screw_cuts();
  67. }
  68. }
  69. module trackball_bot_screw_cuts(e=2)
  70. {
  71. pos= [
  72. // offset angle
  73. [ trackball_dia/2 + 15, 52 + 15 ],
  74. [ trackball_dia/2 + 15, 52 - 40 ],
  75. [ trackball_dia/2 + 15, 52 - 15 + 180 ],
  76. [ trackball_dia/2 + 15, 52 + 40 + 180 ],
  77. [ trackball_dia/2 + 75, 52 - 90 -10],
  78. [ trackball_dia/2 + 75, 52 - 90 +10],
  79. ];
  80. for(p = pos)
  81. rotate([0,0,p[1]])
  82. translate([p[0],0,0])
  83. translate([0,0,7-$e*2])
  84. trans_bot_of_top_part()
  85. rotate([0,180,0])
  86. {
  87. m3_screw_insert_cut(8);
  88. }
  89. }
  90. module trackball_top()
  91. {
  92. if (draw_ball_bearing_holder)
  93. %ball_and_bearing_holder();
  94. difference()
  95. {
  96. hull()
  97. {
  98. intersection_top_part(is_wristrest = false)
  99. trackball_top_hull(with_bot_cuts=true);
  100. trans_bot_of_top_part()
  101. linear_extrude($e)
  102. projection() {
  103. intersection_top_part(is_wristrest = false)
  104. trackball_top_hull(with_bot_cuts=true);
  105. }
  106. }
  107. top_body_cutouts();
  108. }
  109. }
  110. module intersection_top_part(is_wristrest = false)
  111. {
  112. intersection()
  113. {
  114. rotate([0,0,-38])
  115. translate([37.1,-50,-50])
  116. trans_bot_of_top_part()
  117. if(is_wristrest == true)
  118. cube([100,200,200]);
  119. else
  120. translate([-100,0,0])
  121. cube([100,200,200]);
  122. children();
  123. }
  124. }
  125. module m3_screw_insert_cut(l=20)
  126. {
  127. // screw thread cutout
  128. color("silver")
  129. cylinder(d=3,h=50);
  130. // insert cutout itself
  131. color("gold")
  132. cylinder(d=4.6+$c*2,h=7);
  133. // screw head cutout for sliding in
  134. translate([0,0,l])
  135. color("silver")
  136. cylinder(d=6+$c*2,h=50);
  137. // insert iself
  138. // % color("gold")
  139. // cylinder(d=4.6,h=5.7);
  140. }
  141. module wrest_screw_cutout()
  142. {
  143. for(i=[1,-1])
  144. rotate([0,0,-38])
  145. translate([31,i*15,14])
  146. trans_bot_of_top_part()
  147. rotate([0,20,0])
  148. rotate([0,90,0])
  149. {
  150. m3_screw_insert_cut(20);
  151. }
  152. }
  153. module top_hand_wrestv1()
  154. {
  155. difference()
  156. {
  157. intersection_top_part(is_wristrest = true)
  158. rotate([0,0,-38])
  159. translate([60,0,0])
  160. trans_bot_of_top_part()
  161. intersection()
  162. {
  163. scale([3.5,1.5,1])
  164. cylinder(r = 20, h = trackball_dia+17);
  165. translate([15,0,20-trackball_dia/2])
  166. rotate([0,30,0])
  167. scale([1.3,1.4,1])
  168. sphere(d=70);
  169. }
  170. // screw cutout for attaching the wrist rest to the top part
  171. wrest_screw_cutout();
  172. // screw cutouts for the bottom plate
  173. translate([0,0,-$e])
  174. trackball_bot_screw_cuts(e=0);
  175. // pi pico cutout
  176. rotate([0,0,50])
  177. trans_bot_of_top_part()
  178. translate([3,-80,3])
  179. {
  180. %if(draw_pico) pico_wrap();
  181. pico_cutout(20);
  182. }
  183. }
  184. }
  185. module top_hand_wrest()
  186. {
  187. difference()
  188. {
  189. intersection_top_part(is_wristrest = true)
  190. rotate([0,0,-38])
  191. translate([60,0,0])
  192. trans_bot_of_top_part()
  193. intersection() {
  194. translate([-200,-200,0])
  195. cube([400,400,100]);
  196. minkowski() {
  197. intersection()
  198. {
  199. scale([3.5,1.5,1])
  200. cylinder(r = 20, h = trackball_dia+17);
  201. translate([15,0,20-trackball_dia/2])
  202. rotate([0,30,0])
  203. scale([1.3,1.4,1])
  204. sphere(d=70);
  205. }
  206. sphere(r = 3);
  207. }
  208. }
  209. // screw cutout for attaching the wrist rest to the top part
  210. wrest_screw_cutout();
  211. // screw cutouts for the bottom plate
  212. translate([0,0,-$e])
  213. trackball_bot_screw_cuts(e=0);
  214. // pi pico cutout
  215. rotate([0,0,50])
  216. trans_bot_of_top_part()
  217. translate([3,-80,3])
  218. {
  219. %if(draw_pico) pico_wrap();
  220. pico_cutout(20);
  221. }
  222. }
  223. }
  224. module pico_cutout(extra)
  225. {
  226. translate([-pico_w / 2, -pico_l / 2, -extra]) {
  227. // pcb cutout
  228. cube([pico_w, pico_l, 4 + extra]);
  229. // screw cutouts
  230. for (x = [0, pico_hole_d_x])
  231. for (y = [0, pico_hole_d_y])
  232. translate([pico_hole_x + x, pico_hole_y + y, extra])
  233. cylinder(d = pico_hole_d, h = pico_d + 2+5);
  234. // cable channels
  235. translate([pico_w/2-9/2,pico_l-10,0])
  236. cube([9, trackball_dia+10, 4 + extra+2]);
  237. }
  238. }
  239. module top_body_cutouts()
  240. {
  241. // space for roller holder
  242. bearing_rot_trans()
  243. translate([0,0,-bearing_h])
  244. cylinder(d = bearing_mount_dia + 1, h = trackball_dia / 2 + bearing_h);
  245. // room for ball itself
  246. sphere($fn = $fn * 2, d = trackball_dia + $c * 2 + 4);
  247. // grub screws for the bearing holder
  248. bearing_rot_trans()
  249. rotate([0,-90,90])
  250. translate([-bearing_h+4, 0, 0])
  251. {
  252. cylinder(d = grub_screw_dia, h = trackball_dia);
  253. translate([0, 0, bearing_mount_grub_screw_l]) // outside of wall
  254. translate([0, 0, bearing_mount_dia/2 +wall/2]) // outside of wall
  255. cylinder(d = grub_channel_dia, h = trackball_dia);
  256. }
  257. // sensor lens
  258. sensor_cutout();
  259. %if(draw_sensor) sensor_pos();
  260. // switch cutouts
  261. //translate([0, 0, trackball_dia / 2 + ball_h])
  262. switch_rot_trans(0)
  263. translate([10,10,0])
  264. {
  265. // switch cutout itself
  266. mx_switch_cutout(mx_co_depth);
  267. %if(draw_switches)
  268. translate([0,0,10])
  269. mx_switch();
  270. }
  271. switch_rot_trans(0,false)
  272. translate([10,10,0])
  273. {
  274. // cable channel
  275. rotate([-40,0,0])
  276. rotate([0,180,0])
  277. cylinder(d=3,h=trackball_dia);
  278. }
  279. // led ring
  280. translate([0,0,-trackball_dia/2])
  281. {
  282. led_ring(cutout=true, extra = trackball_dia/2);
  283. %if(draw_led) led_ring();
  284. }
  285. // screw cutouts for the wrist rest
  286. wrest_screw_cutout();
  287. // screw cutouts for the bottom plate
  288. translate([0,0,-$e])
  289. trackball_bot_screw_cuts(e=0);
  290. // pico cutout
  291. rotate([0,0,50])
  292. trans_bot_of_top_part()
  293. translate([3,-80,3])
  294. {
  295. pico_cutout(20);
  296. pico_cutout(20);
  297. }
  298. // usb cutout
  299. rotate([0,0,180+50])
  300. trans_bot_of_top_part()
  301. translate([0,-trackball_dia/2-8,2])
  302. {
  303. %if(draw_usb_c)usb_c();
  304. usb_c_cutout();
  305. }
  306. }
  307. module switch_rot_trans(r,x_rot=true)
  308. {
  309. for ( i = [0:len(sw)-1] )
  310. {
  311. rotate([0,0,sw[i][0][2]])
  312. translate(sw[i][1])
  313. rotate([90+(x_rot ? sw[i][0][0] : 0),0,sw[i][0][1]])
  314. translate([-sw_mount_w/2 - r, -sw_mount_w/2 - r, -r - r/2])
  315. children();
  316. }
  317. }
  318. module trans_bot_of_top_part()
  319. {
  320. translate([0, 0, -trackball_dia / 2 -11])
  321. children();
  322. }
  323. module trackball_top_hull(with_bot_cuts=true)
  324. {
  325. difference() {
  326. color("orange")
  327. union(){
  328. hull() {
  329. // bearing holder cylinders
  330. bearing_rot_trans()
  331. bearing_holder_mount();
  332. // base circle
  333. trans_bot_of_top_part()
  334. cylinder(d = base_dia, h = $e);
  335. // switch
  336. switch_rot_trans(sw_mount_r)
  337. translate([0,0,sw_mount_r*2])
  338. fully_rounded_cube([sw_mount_w + sw_mount_r*2,
  339. sw_mount_w + sw_mount_r*2,
  340. mx_co_depth], sw_mount_r);
  341. }
  342. }
  343. }
  344. }