瀏覽代碼

work on 3d design

Thomas Buck 1 年之前
父節點
當前提交
40e6d5ce33
共有 1 個文件被更改,包括 390 次插入91 次删除
  1. 390
    91
      hardware/trackball.scad

+ 390
- 91
hardware/trackball.scad 查看文件

@@ -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
 }

Loading…
取消
儲存