|
@@ -4,10 +4,9 @@
|
4
|
4
|
*
|
5
|
5
|
* Required parts:
|
6
|
6
|
* - 1x Raspberry Pi Pico
|
7
|
|
- * - 5x Cherry MX compatible switches and keycaps
|
|
7
|
+ * - 4x Cherry MX compatible switches and keycaps
|
8
|
8
|
* - 1x Billard ball, diameter 38mm
|
9
|
9
|
* - 3x Si3N4 static bearing balls, diameter 3mm
|
10
|
|
- * - 3x spring, diameter 2mm, length 10mm
|
11
|
10
|
* - 1x PMW3360 sensor with breakout board
|
12
|
11
|
* - 8x M2 screw, length 5mm
|
13
|
12
|
* - 8x M2 heat melt insert, length 4mm
|
|
@@ -31,26 +30,35 @@
|
31
|
30
|
// https://www.thingiverse.com/thing:421524
|
32
|
31
|
use <external/cherry_mx.scad>
|
33
|
32
|
|
|
33
|
+// https://www.printables.com/model/210898-raspberry-pi-pico-case
|
|
34
|
+use <external/pico_case.scad>
|
|
35
|
+
|
34
|
36
|
// ######################
|
35
|
37
|
// ## Rendering Select ##
|
36
|
38
|
// ######################
|
37
|
39
|
|
38
|
40
|
//ball_and_roller();
|
39
|
|
-//pico();
|
|
41
|
+//pico_wrap();
|
40
|
42
|
//sensor();
|
41
|
43
|
//mx_switch_cutout(wall);
|
42
|
44
|
//mx_switch_test();
|
43
|
45
|
//roller_mount_test();
|
44
|
46
|
|
45
|
|
-roller_mount_tri();
|
46
|
|
-
|
47
|
47
|
//roller_holder();
|
48
|
|
-//trackball();
|
|
48
|
+//roller_mount_tri();
|
|
49
|
+
|
|
50
|
+//trackball_top();
|
|
51
|
+trackball_bottom();
|
|
52
|
+
|
|
53
|
+//assembly();
|
|
54
|
+//print();
|
49
|
55
|
|
50
|
56
|
// #######################
|
51
|
57
|
// #### Configuration ####
|
52
|
58
|
// #######################
|
53
|
59
|
|
|
60
|
+$fn = 200;//42;
|
|
61
|
+
|
54
|
62
|
ball_dia = 38.0;
|
55
|
63
|
roller_dia = 3.0;
|
56
|
64
|
|
|
@@ -61,8 +69,14 @@ wall = 3.0;
|
61
|
69
|
$c = 0.1;
|
62
|
70
|
$e = 0.01;
|
63
|
71
|
|
|
72
|
+left_hand_version = false;
|
|
73
|
+
|
64
|
74
|
cut_roller_holder = false;
|
65
|
75
|
draw_supports = false;
|
|
76
|
+draw_ball_roller = true;
|
|
77
|
+draw_switches = true;
|
|
78
|
+draw_sensor = true;
|
|
79
|
+use_external_pico_model = true;
|
66
|
80
|
|
67
|
81
|
// #######################
|
68
|
82
|
// ## Raspberry Pi Pico ##
|
|
@@ -70,19 +84,17 @@ draw_supports = false;
|
70
|
84
|
|
71
|
85
|
pico_w = 21;
|
72
|
86
|
pico_l = 51;
|
73
|
|
-pico_d = 1.6; // todo
|
|
87
|
+pico_d = 1.0;
|
74
|
88
|
pico_hole_d = 2.1;
|
75
|
89
|
pico_hole_x = 4.8;
|
76
|
90
|
pico_hole_y = 2.0;
|
77
|
91
|
pico_hole_d_x = 11.4;
|
78
|
92
|
pico_hole_d_y = pico_l - 2 * pico_hole_y;
|
79
|
93
|
pico_usb_w = 8.0;
|
80
|
|
-pico_usb_h = 3.0; // todo
|
81
|
|
-pico_usb_d = 10.0; // todo
|
|
94
|
+pico_usb_h = 2.8;
|
|
95
|
+pico_usb_d = 6.0;
|
82
|
96
|
pico_usb_off = 1.3;
|
83
|
97
|
|
84
|
|
-pico_h = pico_d + 1; // todo
|
85
|
|
-
|
86
|
98
|
// ######################
|
87
|
99
|
// ### PMW3360 Sensor ###
|
88
|
100
|
// ######################
|
|
@@ -154,7 +166,7 @@ mx_travel = 3.9;
|
154
|
166
|
// ### Implementation ###
|
155
|
167
|
// ######################
|
156
|
168
|
|
157
|
|
-base_dia = pico_l + 9;
|
|
169
|
+base_dia = 62;
|
158
|
170
|
|
159
|
171
|
m3_thread = 2.7;
|
160
|
172
|
m2_thread = 1.8;
|
|
@@ -174,7 +186,61 @@ ball_h = 15; // todo
|
174
|
186
|
|
175
|
187
|
switch_test_w = 25;
|
176
|
188
|
|
177
|
|
-$fn = 100;
|
|
189
|
+roller_mount_holder_gap = 0.8;
|
|
190
|
+sensor_pcb_mount_gap = 2.0;
|
|
191
|
+
|
|
192
|
+sensor_pcb_support_h = 1.6 + 3.4;
|
|
193
|
+
|
|
194
|
+sw1_rot_x = -5;
|
|
195
|
+sw1_rot_z = -30 * (left_hand_version ? -1 : 1);
|
|
196
|
+sw1_trans_x = 0;
|
|
197
|
+sw1_trans_y = -base_dia / 2 - 0;
|
|
198
|
+sw1_trans_z = -17;
|
|
199
|
+
|
|
200
|
+sw2_rot_x = -5;
|
|
201
|
+sw2_rot_z = 15 * (left_hand_version ? -1 : 1);
|
|
202
|
+sw2_trans_x = 0;
|
|
203
|
+sw2_trans_y = -base_dia / 2 - 0;
|
|
204
|
+sw2_trans_z = -17;
|
|
205
|
+
|
|
206
|
+sw3_rot_x = -5;
|
|
207
|
+sw3_rot_z = 125 * (left_hand_version ? -1 : 1);
|
|
208
|
+sw3_trans_x = 0;
|
|
209
|
+sw3_trans_y = -base_dia / 2 - 0;
|
|
210
|
+sw3_trans_z = -17;
|
|
211
|
+
|
|
212
|
+sw4_rot_x = -5;
|
|
213
|
+sw4_rot_z = -125 * (left_hand_version ? -1 : 1);
|
|
214
|
+sw4_trans_x = 0;
|
|
215
|
+sw4_trans_y = -base_dia / 2 - 0;
|
|
216
|
+sw4_trans_z = -17;
|
|
217
|
+
|
|
218
|
+sw_mount_w = mx_co_w + 7;
|
|
219
|
+sw_mount_co_l = 10;
|
|
220
|
+
|
|
221
|
+bottom_base_wall = wall + 0.5;
|
|
222
|
+bottom_base_below_zero = bottom_base_wall + 4.5;
|
|
223
|
+
|
|
224
|
+pico_co_w = pico_w + 1;
|
|
225
|
+pico_co_l = pico_l + 1;
|
|
226
|
+
|
|
227
|
+reset_button_dia = 4.0;
|
|
228
|
+reset_button_off_x = 7;
|
|
229
|
+reset_button_off_y = 12.15;
|
|
230
|
+
|
|
231
|
+pico_support_w = 6.5;
|
|
232
|
+pico_support_l = 5;
|
|
233
|
+
|
|
234
|
+pico_screw_depth = 6;
|
|
235
|
+pico_screw_d = 1.8;
|
|
236
|
+
|
|
237
|
+usb_cutout_grow_l = 10;
|
|
238
|
+usb_cutout_grow_x = 20;
|
|
239
|
+usb_cutout_grow_y = 40;
|
|
240
|
+usb_cutout_w_add = 1;
|
|
241
|
+usb_cutout_h_add = 0.6;
|
|
242
|
+
|
|
243
|
+assembly_dist = 20;
|
178
|
244
|
|
179
|
245
|
function sphere_r_at_h(h, r) = r * sin(acos(h / r));
|
180
|
246
|
function sphere_angle_at_rh(h, r) = acos(h / r);
|
|
@@ -219,7 +285,7 @@ module mx_switch_test() {
|
219
|
285
|
mx_switch($t);
|
220
|
286
|
}
|
221
|
287
|
|
222
|
|
-module pico() {
|
|
288
|
+module pico_own() {
|
223
|
289
|
translate([-pico_w / 2, -pico_l / 2, 0])
|
224
|
290
|
difference() {
|
225
|
291
|
union() {
|
|
@@ -237,6 +303,14 @@ module pico() {
|
237
|
303
|
}
|
238
|
304
|
}
|
239
|
305
|
|
|
306
|
+module pico_wrap() {
|
|
307
|
+ //if (use_external_pico_model)
|
|
308
|
+ translate([-pico_w / 2, -pico_l / 2, 0])
|
|
309
|
+ pico();
|
|
310
|
+ //else
|
|
311
|
+ pico_own();
|
|
312
|
+}
|
|
313
|
+
|
240
|
314
|
module sensor_lens_cutout_intern() {
|
241
|
315
|
cylinder(d = sensor_lens_cutout_r * 2, h = $e);
|
242
|
316
|
|
|
@@ -365,72 +439,58 @@ module roller_mount_test() {
|
365
|
439
|
roller_mount();
|
366
|
440
|
}
|
367
|
441
|
|
368
|
|
-roller_mount_holder_gap = 0.8;
|
369
|
|
-sensor_pcb_mount_gap = 2.0;
|
370
|
|
-
|
371
|
|
-sensor_pcb_support_h = 1.6 + 3.4;
|
|
442
|
+module roller_mount_tri_hull() {
|
|
443
|
+ for (r = [0 : roller_count - 1])
|
|
444
|
+ rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
|
445
|
+ translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
|
446
|
+ rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
|
447
|
+ translate([0, 0, -roller_h])
|
|
448
|
+ cylinder(d = roller_mount_dia + wall + 1, h = roller_h - 3);
|
|
449
|
+
|
|
450
|
+ translate([0, 0, -ball_dia / 2 - 11])
|
|
451
|
+ cylinder(d = base_dia, h = $e);
|
|
452
|
+}
|
372
|
453
|
|
373
|
|
-module roller_mount_tri() {
|
374
|
|
- %ball_and_roller();
|
|
454
|
+module roller_mount_tri_body() {
|
|
455
|
+ // space for roller holder
|
|
456
|
+ for (r = [0 : roller_count - 1])
|
|
457
|
+ rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
|
458
|
+ translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
|
459
|
+ rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
|
460
|
+ translate([0, 0, -roller_h])
|
|
461
|
+ cylinder(d = roller_mount_dia + roller_mount_holder_gap, h = ball_dia / 2 + roller_h);
|
375
|
462
|
|
376
|
|
- difference() {
|
377
|
|
- union() {
|
378
|
|
- difference() {
|
379
|
|
- hull() {
|
380
|
|
- for (r = [0 : roller_count - 1])
|
381
|
|
- rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
382
|
|
- translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
383
|
|
- rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
384
|
|
- translate([0, 0, -roller_h])
|
385
|
|
- cylinder(d = roller_mount_dia + wall + 1, h = roller_h - 3);
|
386
|
|
-
|
387
|
|
- translate([0, 0, -ball_dia / 2 - 11])
|
388
|
|
- cylinder(d = base_dia, h = $e);
|
389
|
|
- }
|
390
|
|
-
|
391
|
|
- for (r = [0 : roller_count - 1])
|
392
|
|
- rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
393
|
|
- translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
394
|
|
- rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
395
|
|
- translate([0, 0, -roller_h])
|
396
|
|
- cylinder(d = roller_mount_dia + roller_mount_holder_gap, h = ball_dia / 2 + roller_h);
|
397
|
|
-
|
398
|
|
- sphere($fn = $fn * 2, d = ball_dia + $c * 2 + 4);
|
399
|
|
- }
|
400
|
|
- }
|
401
|
|
-
|
402
|
|
- for (r = [0 : roller_count - 1])
|
403
|
|
- rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
404
|
|
- translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
405
|
|
- rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
406
|
|
- translate([0, 0, -roller_h/2])
|
407
|
|
- rotate([0,-90,0])
|
408
|
|
- translate([-2, 0, 2]) {
|
409
|
|
- cylinder(d = m2_thread, h = ball_dia);
|
410
|
|
-
|
411
|
|
- translate([0, 0, roller_mount_dia / 4 + wall])
|
412
|
|
- cylinder(d = m2_thread + 1, h = ball_dia);
|
413
|
|
- }
|
414
|
|
-
|
415
|
|
- translate([0, 0, -ball_dia / 2 - ball_h])
|
416
|
|
- translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
417
|
|
- translate([0, -sensor_l / 2 + sensor_cut_off_y + sensor_cut_h - sensor_cut_edge_to_pin1 - sensor_pin1_to_optical_center, 0])
|
418
|
|
- sensor_lens_cutout();
|
|
463
|
+ // room for ball itself
|
|
464
|
+ sphere($fn = $fn * 2, d = ball_dia + $c * 2 + 4);
|
419
|
465
|
|
420
|
|
- translate([-1, -1, -ball_dia / 2 - ball_h])
|
421
|
|
- translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
422
|
|
- translate([-sensor_w / 2, -sensor_l / 2, -10])
|
423
|
|
- cube([sensor_w + 2, sensor_l + 2, sensor_pcb_h + 10 + sensor_pcb_mount_gap]);
|
424
|
|
-
|
425
|
|
- // TODO test cable cutout
|
426
|
|
- translate([-6, 0, -30.1])
|
427
|
|
- cube([12, 50, 2]);
|
|
466
|
+ // grub screws
|
|
467
|
+ for (r = [0 : roller_count - 1])
|
|
468
|
+ rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
|
469
|
+ translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
|
470
|
+ rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
|
471
|
+ translate([0, 0, -roller_h/2])
|
|
472
|
+ rotate([0,-90,0])
|
|
473
|
+ translate([-2, 0, 2]) {
|
|
474
|
+ cylinder(d = m2_thread, h = ball_dia);
|
428
|
475
|
|
429
|
|
- if (cut_roller_holder)
|
430
|
|
- translate([0, -base_dia / 2 - 1, -40])
|
431
|
|
- cube([base_dia / 2 + 1, base_dia + 2, 40]);
|
|
476
|
+ translate([0, 0, roller_mount_dia / 4 + wall])
|
|
477
|
+ cylinder(d = m2_thread + 1, h = ball_dia);
|
432
|
478
|
}
|
|
479
|
+
|
|
480
|
+ // sensor lens
|
|
481
|
+ translate([0, 0, -ball_dia / 2 - ball_h])
|
|
482
|
+ translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
|
483
|
+ translate([0, -sensor_l / 2 + sensor_cut_off_y + sensor_cut_h - sensor_cut_edge_to_pin1 - sensor_pin1_to_optical_center, 0])
|
|
484
|
+ sensor_lens_cutout();
|
433
|
485
|
|
|
486
|
+ // sensor pcb
|
|
487
|
+ translate([-1, -1, -ball_dia / 2 - ball_h])
|
|
488
|
+ translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
|
489
|
+ translate([-sensor_w / 2, -sensor_l / 2, -10])
|
|
490
|
+ cube([sensor_w + 2, sensor_l + 2, sensor_pcb_h + 10 + sensor_pcb_mount_gap]);
|
|
491
|
+}
|
|
492
|
+
|
|
493
|
+module roller_mount_sensor_pcb_support() {
|
434
|
494
|
translate([-sensor_w / 2, -sensor_l / 2, sensor_pcb_h])
|
435
|
495
|
translate([0, 0, -ball_dia / 2 - ball_h])
|
436
|
496
|
translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
|
@@ -458,31 +518,270 @@ module roller_mount_tri() {
|
458
|
518
|
if (((x == 0) && (y != 0)) || ((x != 0) && (y == 0)))
|
459
|
519
|
translate([x, y + 2, -30])
|
460
|
520
|
cylinder(d = sensor_hole_dia + 0.5, h = 8.5);
|
461
|
|
-
|
|
521
|
+
|
|
522
|
+ if (draw_sensor)
|
462
|
523
|
%translate([0, 0, -ball_dia / 2 - ball_h])
|
463
|
524
|
translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
464
|
525
|
sensor();
|
465
|
526
|
}
|
466
|
527
|
|
467
|
|
-module trackball() {
|
468
|
|
- %translate([0, 0, ball_dia / 2 + ball_h])
|
469
|
|
- ball_and_roller();
|
|
528
|
+// TODO holes for pcb screws not going into body!!
|
|
529
|
+
|
|
530
|
+module roller_mount_tri() {
|
|
531
|
+ if (draw_ball_roller)
|
|
532
|
+ %ball_and_roller();
|
|
533
|
+
|
|
534
|
+ difference() {
|
|
535
|
+ hull()
|
|
536
|
+ roller_mount_tri_hull();
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+ roller_mount_tri_body();
|
|
540
|
+
|
|
541
|
+ // TODO test cable cutout
|
|
542
|
+ translate([-6, 0, -30.1])
|
|
543
|
+ cube([12, 50, 2]);
|
|
544
|
+
|
|
545
|
+ if (cut_roller_holder)
|
|
546
|
+ translate([0, -base_dia / 2 - 1, -40])
|
|
547
|
+ cube([base_dia / 2 + 1, base_dia + 2, 40]);
|
|
548
|
+ }
|
|
549
|
+
|
|
550
|
+ roller_mount_sensor_pcb_support();
|
|
551
|
+}
|
|
552
|
+
|
|
553
|
+module trackball_top() {
|
|
554
|
+ translate([0, 0, ball_dia / 2 + ball_h]) {
|
|
555
|
+ if (draw_ball_roller)
|
|
556
|
+ %ball_and_roller();
|
|
557
|
+
|
|
558
|
+ difference() {
|
|
559
|
+ color("orange")
|
|
560
|
+ hull() {
|
|
561
|
+ roller_mount_tri_hull();
|
|
562
|
+
|
|
563
|
+ rotate([0, 0, sw1_rot_z])
|
|
564
|
+ translate([sw1_trans_x, sw1_trans_y, sw1_trans_z])
|
|
565
|
+ rotate([90 + sw1_rot_x, 0, 0])
|
|
566
|
+ translate([0, 0, -0.5])
|
|
567
|
+ cube([sw_mount_w, sw_mount_w, 1], center = true);
|
|
568
|
+
|
|
569
|
+ rotate([0, 0, sw2_rot_z])
|
|
570
|
+ translate([sw2_trans_x, sw2_trans_y, sw2_trans_z])
|
|
571
|
+ rotate([90 + sw2_rot_x, 0, 0])
|
|
572
|
+ translate([0, 0, -0.5])
|
|
573
|
+ cube([sw_mount_w, sw_mount_w, 1], center = true);
|
|
574
|
+
|
|
575
|
+ rotate([0, 0, sw3_rot_z])
|
|
576
|
+ translate([sw3_trans_x, sw3_trans_y, sw3_trans_z])
|
|
577
|
+ rotate([90 + sw3_rot_x, 0, 0])
|
|
578
|
+ translate([0, 0, -0.5])
|
|
579
|
+ cube([sw_mount_w, sw_mount_w, 1], center = true);
|
|
580
|
+
|
|
581
|
+ rotate([0, 0, sw4_rot_z])
|
|
582
|
+ translate([sw4_trans_x, sw4_trans_y, sw4_trans_z])
|
|
583
|
+ rotate([90 + sw4_rot_x, 0, 0])
|
|
584
|
+ translate([0, 0, -0.5])
|
|
585
|
+ cube([sw_mount_w, sw_mount_w, 1], center = true);
|
|
586
|
+ }
|
|
587
|
+
|
|
588
|
+ roller_mount_tri_body();
|
|
589
|
+
|
|
590
|
+ if (cut_roller_holder)
|
|
591
|
+ translate([0, -base_dia / 2 - 1, -40])
|
|
592
|
+ cube([base_dia / 2 + 1, base_dia + 2, 40]);
|
|
593
|
+
|
|
594
|
+ rotate([0, 0, sw1_rot_z])
|
|
595
|
+ translate([sw1_trans_x, sw1_trans_y, sw1_trans_z])
|
|
596
|
+ rotate([90 + sw1_rot_x, 0, 0])
|
|
597
|
+ translate([0, 0, -sw_mount_co_l]) {
|
|
598
|
+ mx_switch_cutout(sw_mount_co_l + 1);
|
|
599
|
+
|
|
600
|
+ translate([0, 0, 2])
|
|
601
|
+ rotate([90, 0, 0])
|
|
602
|
+ cylinder(d = 4, h = 20);
|
|
603
|
+ }
|
|
604
|
+
|
|
605
|
+ rotate([0, 0, sw2_rot_z])
|
|
606
|
+ translate([sw2_trans_x, sw2_trans_y, sw2_trans_z])
|
|
607
|
+ rotate([90 + sw2_rot_x, 0, 0])
|
|
608
|
+ translate([0, 0, -sw_mount_co_l]) {
|
|
609
|
+ mx_switch_cutout(sw_mount_co_l + 1);
|
|
610
|
+
|
|
611
|
+ translate([0, 0, 2])
|
|
612
|
+ rotate([90, 0, 0])
|
|
613
|
+ cylinder(d = 4, h = 20);
|
|
614
|
+ }
|
|
615
|
+
|
|
616
|
+ rotate([0, 0, sw3_rot_z])
|
|
617
|
+ translate([sw3_trans_x, sw3_trans_y, sw3_trans_z])
|
|
618
|
+ rotate([90 + sw3_rot_x, 0, 0])
|
|
619
|
+ translate([0, 0, -sw_mount_co_l]) {
|
|
620
|
+ mx_switch_cutout(sw_mount_co_l + 1);
|
|
621
|
+
|
|
622
|
+ translate([0, 0, 2])
|
|
623
|
+ rotate([90, 0, 0])
|
|
624
|
+ cylinder(d = 4, h = 20);
|
|
625
|
+ }
|
|
626
|
+
|
|
627
|
+ rotate([0, 0, sw4_rot_z])
|
|
628
|
+ translate([sw4_trans_x, sw4_trans_y, sw4_trans_z])
|
|
629
|
+ rotate([90 + sw4_rot_x, 0, 0])
|
|
630
|
+ translate([0, 0, -sw_mount_co_l]) {
|
|
631
|
+ mx_switch_cutout(sw_mount_co_l + 1);
|
|
632
|
+
|
|
633
|
+ translate([0, 0, 2])
|
|
634
|
+ rotate([90, 0, 0])
|
|
635
|
+ cylinder(d = 4, h = 20);
|
|
636
|
+ }
|
|
637
|
+
|
|
638
|
+ /*
|
|
639
|
+ hull() {
|
|
640
|
+ rotate([0, 0, sw1_rot_z])
|
|
641
|
+ translate([sw1_trans_x, sw1_trans_y, sw1_trans_z])
|
|
642
|
+ rotate([90 + sw1_rot_x, 0, 0])
|
|
643
|
+ translate([0, 0, -sw_mount_co_l + 5])
|
|
644
|
+ mx_switch_cutout(sw_mount_co_l - 10);
|
|
645
|
+
|
|
646
|
+ rotate([0, 0, sw2_rot_z])
|
|
647
|
+ translate([sw2_trans_x, sw2_trans_y, sw2_trans_z])
|
|
648
|
+ rotate([90 + sw2_rot_x, 0, 0])
|
|
649
|
+ translate([0, 0, -sw_mount_co_l + 5])
|
|
650
|
+ mx_switch_cutout(sw_mount_co_l - 10);
|
|
651
|
+ }
|
|
652
|
+ */
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+ for (r = screw_angles)
|
|
656
|
+ rotate([0, 0, r])
|
|
657
|
+ translate([screw_off, 0, -ball_dia / 2 - 11 -1]) {
|
|
658
|
+ cylinder(d = screw_insert_dia, h = screw_insert_h + 1);
|
|
659
|
+ }
|
|
660
|
+ }
|
|
661
|
+
|
|
662
|
+ roller_mount_sensor_pcb_support();
|
470
|
663
|
|
|
664
|
+ if (draw_switches) {
|
|
665
|
+ %rotate([0, 0, sw1_rot_z])
|
|
666
|
+ translate([sw1_trans_x, sw1_trans_y, sw1_trans_z])
|
|
667
|
+ rotate([90 + sw1_rot_x, 0, 0])
|
|
668
|
+ mx_switch($t);
|
|
669
|
+
|
|
670
|
+ %rotate([0, 0, sw2_rot_z])
|
|
671
|
+ translate([sw2_trans_x, sw2_trans_y, sw2_trans_z])
|
|
672
|
+ rotate([90 + sw2_rot_x, 0, 0])
|
|
673
|
+ mx_switch($t);
|
|
674
|
+
|
|
675
|
+ %rotate([0, 0, sw3_rot_z])
|
|
676
|
+ translate([sw3_trans_x, sw3_trans_y, sw3_trans_z])
|
|
677
|
+ rotate([90 + sw3_rot_x, 0, 0])
|
|
678
|
+ mx_switch($t);
|
|
679
|
+
|
|
680
|
+ %rotate([0, 0, sw4_rot_z])
|
|
681
|
+ translate([sw4_trans_x, sw4_trans_y, sw4_trans_z])
|
|
682
|
+ rotate([90 + sw4_rot_x, 0, 0])
|
|
683
|
+ mx_switch($t);
|
|
684
|
+ }
|
|
685
|
+ }
|
|
686
|
+}
|
|
687
|
+
|
|
688
|
+bottom_add_wall = 4;
|
|
689
|
+
|
|
690
|
+module trackball_bottom_wrap() {
|
471
|
691
|
%rotate([0, 180, 0])
|
472
|
|
- pico();
|
|
692
|
+ pico_wrap();
|
473
|
693
|
|
474
|
|
- %translate([0, sensor_l / 2 - sensor_cut_off_y - sensor_cut_h + sensor_cut_edge_to_pin1 + sensor_pin1_to_optical_center, ball_h + sensor_chip_h - sensor_ball_to_chip_bottom])
|
475
|
|
- sensor();
|
|
694
|
+ color("magenta")
|
|
695
|
+ translate([0, 0, -bottom_base_below_zero])
|
|
696
|
+ difference() {
|
|
697
|
+ cylinder(d = base_dia, h = bottom_base_below_zero + ball_h - 11);
|
|
698
|
+
|
|
699
|
+ translate([0, 0, bottom_base_wall])
|
|
700
|
+ cylinder(d = base_dia - bottom_base_wall * 2 - bottom_add_wall, h = bottom_base_below_zero + ball_h - 11);
|
|
701
|
+
|
|
702
|
+ translate([-pico_co_w / 2, -pico_co_l / 2, bottom_base_wall])
|
|
703
|
+ cube([pico_co_w, pico_co_l, bottom_base_below_zero + ball_h - 11]);
|
|
704
|
+
|
|
705
|
+ translate([pico_w / 2 - reset_button_off_x, pico_l / 2 - reset_button_off_y, -1])
|
|
706
|
+ cylinder(d = reset_button_dia, h = bottom_base_wall + 2);
|
|
707
|
+
|
|
708
|
+ if (cut_roller_holder)
|
|
709
|
+ translate([-base_dia / 2 - 1, -base_dia / 2 - 1, -10])
|
|
710
|
+ cube([base_dia / 2 + 1, base_dia + 2, 40]);
|
|
711
|
+ }
|
476
|
712
|
|
477
|
|
- translate([0, 0, ball_dia / 2 + ball_h])
|
478
|
|
- for (r = [0 : roller_count - 1])
|
479
|
|
- rotate([0, 0, roller_mount_angle_off + 360 / roller_count * r])
|
480
|
|
- translate([sphere_r_at_h(roller_ball_h - ball_dia / 2, ball_dia / 2), 0, -ball_dia / 2 + roller_ball_h])
|
481
|
|
- rotate([0, 180 + sphere_angle_at_rh(roller_ball_h - ball_dia / 2, ball_dia / 2), 0])
|
482
|
|
- translate([0, 0, -roller_dia / 2])
|
483
|
|
- roller_mount();
|
|
713
|
+ color("cyan")
|
|
714
|
+ for (x = [-1, 1])
|
|
715
|
+ for (y = [-1, 1])
|
|
716
|
+ translate([x * (pico_co_w - pico_support_w) / 2, y * (pico_co_l - pico_support_l) / 2, 0])
|
|
717
|
+ translate([-pico_support_w / 2, -pico_support_l / 2, -bottom_base_below_zero + bottom_base_wall])
|
|
718
|
+ cube([pico_support_w, pico_support_l, bottom_base_below_zero - bottom_base_wall - pico_d]);
|
|
719
|
+
|
|
720
|
+ color("cyan")
|
|
721
|
+ for (r = screw_angles)
|
|
722
|
+ rotate([0, 0, r])
|
|
723
|
+ translate([screw_off, 0, -bottom_base_below_zero + bottom_base_wall])
|
|
724
|
+ cylinder(d = screw_head_d + 4, h = bottom_base_below_zero + ball_h - 11 - bottom_base_wall);
|
|
725
|
+}
|
|
726
|
+
|
|
727
|
+module usb_cutout() {
|
|
728
|
+ hull() {
|
|
729
|
+ translate([-usb_cutout_w_add / 2, 0, -usb_cutout_h_add / 2])
|
|
730
|
+ cube([pico_usb_w + usb_cutout_w_add, 1, pico_usb_h + usb_cutout_h_add]);
|
|
731
|
+
|
|
732
|
+ translate([-usb_cutout_grow_x / 2, usb_cutout_grow_l, -usb_cutout_grow_y / 2])
|
|
733
|
+ cube([pico_usb_w + usb_cutout_grow_x, 1, pico_usb_h + usb_cutout_grow_y]);
|
|
734
|
+ }
|
|
735
|
+}
|
|
736
|
+
|
|
737
|
+screw_dia = 3.2;
|
|
738
|
+screw_off = base_dia / 2 - 10;
|
|
739
|
+screw_head_d = 6.0;
|
|
740
|
+screw_head_h = 3.5;
|
|
741
|
+screw_angles = [ 15, -15, 180 + 15, 180 - 15 ];
|
|
742
|
+screw_insert_dia = 4.8;
|
|
743
|
+screw_insert_h = 8.0;
|
|
744
|
+
|
|
745
|
+module trackball_bottom() {
|
|
746
|
+ difference() {
|
|
747
|
+ trackball_bottom_wrap();
|
|
748
|
+
|
|
749
|
+ for (x = [0, pico_hole_d_x])
|
|
750
|
+ for (y = [0, pico_hole_d_y])
|
|
751
|
+ translate([-pico_w / 2, -pico_l / 2, 0])
|
|
752
|
+ translate([pico_hole_x + x, pico_hole_y + y, -pico_d - pico_screw_depth])
|
|
753
|
+ cylinder(d = pico_screw_d, h = pico_d + pico_screw_depth + 1);
|
|
754
|
+
|
|
755
|
+ rotate([0, 180, 0])
|
|
756
|
+ translate([-pico_w / 2, -pico_l / 2, 0])
|
|
757
|
+ translate([(pico_w - pico_usb_w) / 2, pico_l - 1 + pico_usb_off, pico_d])
|
|
758
|
+ usb_cutout();
|
|
759
|
+
|
|
760
|
+ for (r = screw_angles)
|
|
761
|
+ rotate([0, 0, r])
|
|
762
|
+ translate([screw_off, 0, -bottom_base_below_zero - 1]) {
|
|
763
|
+ cylinder(d = screw_dia, h = bottom_base_below_zero + 30);
|
|
764
|
+ cylinder(d = screw_head_d, h = screw_head_h + 1);
|
|
765
|
+ }
|
|
766
|
+ }
|
|
767
|
+}
|
|
768
|
+
|
|
769
|
+module assembly() {
|
|
770
|
+ translate([0, 0, assembly_dist / 2])
|
|
771
|
+ trackball_top();
|
484
|
772
|
|
485
|
|
- color("grey")
|
486
|
|
- translate([0, 0, -8])
|
487
|
|
- cylinder(d = base_dia, h = wall);
|
|
773
|
+ translate([0, 0, -assembly_dist / 2])
|
|
774
|
+ trackball_bottom();
|
|
775
|
+}
|
|
776
|
+
|
|
777
|
+module print() {
|
|
778
|
+ translate([-40, 0, -4])
|
|
779
|
+ trackball_top();
|
|
780
|
+
|
|
781
|
+ translate([40, 0, bottom_base_below_zero])
|
|
782
|
+ trackball_bottom();
|
|
783
|
+
|
|
784
|
+ for (y = [-20, 0, 20])
|
|
785
|
+ translate([0, y, 8.5])
|
|
786
|
+ roller_holder();
|
488
|
787
|
}
|