From 3ebbe5dd2cbc406e93418ac9fb06fbbf175785ba Mon Sep 17 00:00:00 2001 From: Joshua Shreve Date: Thu, 2 Sep 2021 20:51:42 -0400 Subject: Added PCB controller mount feature options. Also, working on modular trackball, though ball bearings make it difficult to decouple as they typically land in the middle of the walls and webs. --- src/dactyl_manuform.py | 177 +++++++++++++++++++++++++++++++++++++----- src/generate_configuration.py | 44 ++++++++--- src/helpers_blender.py | 3 +- src/helpers_cadquery.py | 31 +++++--- src/helpers_solid.py | 31 +++++--- src/run_config.json | 50 ++++++++++-- 6 files changed, 277 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/dactyl_manuform.py b/src/dactyl_manuform.py index a04a291..9913086 100644 --- a/src/dactyl_manuform.py +++ b/src/dactyl_manuform.py @@ -4,6 +4,7 @@ import os.path as path import getopt, sys import json import os +import copy from scipy.spatial import ConvexHull as sphull @@ -273,30 +274,37 @@ def single_plate(cylinder_segments=100, side="right"): return plate def trackball_cutout(segments=100, side="right"): - shape = cylinder(trackball_hole_diameter / 2, trackball_hole_height) + if trackball_modular: + hole_diameter = ball_diameter + 2 * (ball_gap + ball_wall_thickness + trackball_modular_clearance+trackball_modular_lip_width)-.1 + shape = cylinder(hole_diameter / 2, trackball_hole_height) + else: + shape = cylinder(trackball_hole_diameter / 2, trackball_hole_height) return shape def trackball_socket(segments=100, side="right"): - # shape = sphere(ball_diameter / 2) - # cyl = cylinder(ball_diameter / 2 + 4, 20) - # cyl = translate(cyl, (0, 0, -8)) - # shape = union([shape, cyl]) + if trackball_modular: + hole_diameter = ball_diameter + 2 * (ball_gap + ball_wall_thickness + trackball_modular_clearance) + ring_diameter = hole_diameter + 2 * trackball_modular_lip_width + ring_height = trackball_modular_ring_height + ring_z_offset = mount_thickness - trackball_modular_ball_height + shape = cylinder(ring_diameter / 2, ring_height) + shape = translate(shape, (0, 0, -ring_height / 2 + ring_z_offset)) - tb_file = path.join(parts_path, r"trackball_socket_body_34mm") - tbcut_file = path.join(parts_path, r"trackball_socket_cutter_34mm") - sens_file = path.join(parts_path, r"trackball_sensor_mount") - senscut_file = path.join(parts_path, r"trackball_sensor_cutter") + cutter = cylinder(hole_diameter / 2, ring_height + .2) + cutter = translate(cutter, (0, 0, -ring_height / 2 + ring_z_offset)) + sensor = None - # shape = import_file(tb_file) - # # shape = difference(shape, [import_file(senscut_file)]) - # # shape = union([shape, import_file(sens_file)]) - # cutter = import_file(tbcut_file) + else: + tb_file = path.join(parts_path, r"trackball_socket_body_34mm") + tbcut_file = path.join(parts_path, r"trackball_socket_cutter_34mm") + sens_file = path.join(parts_path, r"trackball_sensor_mount") + senscut_file = path.join(parts_path, r"trackball_sensor_cutter") - shape = import_file(tb_file) - sensor = import_file(sens_file) - cutter = import_file(tbcut_file) - cutter = union([cutter, import_file(senscut_file)]) + shape = import_file(tb_file) + sensor = import_file(sens_file) + cutter = import_file(tbcut_file) + cutter = union([cutter, import_file(senscut_file)]) # return shape, cutter return shape, cutter, sensor @@ -3233,8 +3241,130 @@ def external_mount_hole(): ) return shape -def generate_trackball(pos, rot): + +pcb_mount_ref_position = key_position( + #TRRS POSITION IS REFERENCE BY CONVENIENCE + list(np.array(wall_locate3(0, 1)) + np.array([0, (mount_height / 2), 0])), 0, 0 +) + +pcb_mount_ref_position[0] = pcb_mount_ref_position[0] + pcb_mount_ref_offset[0] +pcb_mount_ref_position[1] = pcb_mount_ref_position[1] + pcb_mount_ref_offset[1] +pcb_mount_ref_position[2] = 0.0 + pcb_mount_ref_offset[2] + +def pcb_usb_hole(): + debugprint('pcb_holder()') + pcb_usb_position = copy.deepcopy(pcb_mount_ref_position) + pcb_usb_position[0] = pcb_usb_position[0] + pcb_usb_hole_offset[0] + pcb_usb_position[1] = pcb_usb_position[1] + pcb_usb_hole_offset[1] + pcb_usb_position[2] = pcb_usb_position[2] + pcb_usb_hole_offset[2] + + shape = box(*pcb_usb_hole_size) + shape = translate(shape, + ( + pcb_usb_position[0], + pcb_usb_position[1], + pcb_usb_hole_size[2] / 2 + pcb_usb_hole_z_offset + usb_holder_thickness, + ) + ) + return shape + + + +pcb_holder_position = copy.deepcopy(pcb_mount_ref_position) +pcb_holder_position[0] = pcb_holder_position[0] + pcb_holder_offset[0] +pcb_holder_position[1] = pcb_holder_position[1] + pcb_holder_offset[1] +pcb_holder_position[2] = pcb_holder_position[2] + pcb_holder_offset[2] +pcb_holder_thickness = pcb_holder_size[2] + +def pcb_holder(): + debugprint('pcb_holder()') + shape = box(*pcb_holder_size) + shape = translate(shape, + ( + pcb_holder_position[0], + pcb_holder_position[1] - pcb_holder_size[1] / 2, + pcb_holder_thickness / 2, + ) + ) + return shape + + +def wall_thinner(): + debugprint('wall_thinner()') + shape = box(*wall_thinner_size) + shape = translate(shape, + ( + pcb_holder_position[0], + pcb_holder_position[1] - wall_thinner_size[1]/2, + wall_thinner_size[2]/2 + pcb_holder_thickness, + ) + ) + return shape + + + + +def trrs_hole(): + debugprint('trrs_hole()') + trrs_position = copy.deepcopy(pcb_mount_ref_position) + trrs_position[0] = trrs_position[0] + trrs_offset[0] + trrs_position[1] = trrs_position[1] + trrs_offset[1] + trrs_position[2] = trrs_position[2] + trrs_offset[2] + + trrs_hole_size = [3, 20] + + + shape = cylinder(*trrs_hole_size) + shape = rotate(shape, [0, 90, 90]) + shape = translate(shape, + ( + trrs_position[0], + trrs_position[1], + trrs_hole_size[0] + pcb_holder_thickness, + ) + ) + return shape + +pcb_screw_position = copy.deepcopy(pcb_mount_ref_position) +pcb_screw_position[1] = pcb_screw_position[1] + pcb_screw_y_offset + +def pcb_screw_hole(): + debugprint('pcb_screw_hole()') + holes = [] + hole = cylinder(*pcb_screw_hole_size) + hole = translate(hole, pcb_screw_position) + hole = translate(hole, (0, 0, pcb_screw_hole_size[1]/2-.1)) + holes.append(translate(hole, (pcb_screw_x_offsets[0], 0, 0))) + holes.append(translate(hole, (pcb_screw_x_offsets[1], 0, 0))) + holes.append(translate(hole, (pcb_screw_x_offsets[2], 0, 0))) + + return holes + + +if oled_center_row is not None: + base_pt1 = key_position( + list(np.array([-mount_width/2, 0, 0]) + np.array([0, (mount_height / 2), 0])), 0, oled_center_row-1 + ) + base_pt2 = key_position( + list(np.array([-mount_width/2, 0, 0]) + np.array([0, (mount_height / 2), 0])), 0, oled_center_row+1 + ) + base_pt0 = key_position( + list(np.array([-mount_width / 2, 0, 0]) + np.array([0, (mount_height / 2), 0])), 0, oled_center_row + ) + + oled_mount_location_xyz = (np.array(base_pt1)+np.array(base_pt2))/2. + np.array(((-left_wall_x_offset/2), 0, 0)) + np.array(oled_translation_offset) + oled_mount_location_xyz[2] = (oled_mount_location_xyz[2] + base_pt0[2])/2 + + angle_x = np.arctan2(base_pt1[2] - base_pt2[2], base_pt1[1] - base_pt2[1]) + angle_z = np.arctan2(base_pt1[0] - base_pt2[0], base_pt1[1] - base_pt2[1]) + + oled_mount_rotation_xyz = (rad2deg(angle_x), 0, -rad2deg(angle_z)) + np.array(oled_rotation_offset) + + + + +def generate_trackball(pos, rot): precut = trackball_cutout() precut = rotate(precut, tb_socket_rotation_offset) precut = translate(precut, tb_socket_translation_offset) @@ -3883,7 +4013,14 @@ def model_side(side="right"): if controller_mount_type in ['EXTERNAL']: s2 = difference(s2, [external_mount_hole()]) - if controller_mount_type in ['None']: + if controller_mount_type in ['PCB_MOUNT']: + s2 = difference(s2, [pcb_usb_hole()]) + s2 = difference(s2, [trrs_hole()]) + s2 = union([s2, pcb_holder()]) + s2 = difference(s2, [wall_thinner()]) + s2 = difference(s2, pcb_screw_hole()) + + if controller_mount_type in [None, 'None']: 0 # do nothing, only here to expressly state inaction. s2 = difference(s2, [union(screw_insert_holes(side=side))]) @@ -3922,7 +4059,7 @@ def model_side(side="right"): if show_caps: shape = add([shape, ball]) - if (trackball_in_wall or ('TRACKBALL' in thumb_style)) and (side == ball_side or ball_side == 'both'): + if ('TRACKBALL' in thumb_style) and (side == ball_side or ball_side == 'both'): tbprecut, tb, tbcutout, sensor, ball = generate_trackball_in_cluster() shape = difference(shape, [tbprecut]) diff --git a/src/generate_configuration.py b/src/generate_configuration.py index f5fa716..1fb89bf 100644 --- a/src/generate_configuration.py +++ b/src/generate_configuration.py @@ -21,7 +21,7 @@ shape_config = { 'save_dir': '.', 'config_name': "DM", - 'show_caps': True, + 'show_caps': False, 'show_pcbs': False, #only runs if caps are shown, easist place to initially inject geometry 'nrows': 5, #5, # key rows @@ -44,11 +44,16 @@ shape_config = { 11 # controls overall height# original=9 with centercol=3# use 16 for centercol=2 ), + 'web_thickness': 4.0, + 'post_size': 0.1, + # post_adj': post_size / 2 + 'post_adj': 0, + ############################## # THUMB PARAMETERS ############################## # 'DEFAULT' 6-key, 'MINI' 5-key, 'CARBONFET' 6-key, 'MINIDOX' 3-key, 'TRACKBALL_ORBYL', 'TRACKBALL_CJ' - 'thumb_style': 'TRACKBALL_ORBYL', + 'thumb_style': 'CARBONFET', 'default_1U_cluster': True, # only used with default, makes top right thumb cluster key 1U # Thumb key size. May need slight oversizing, check w/ caps. Additional spacing will be automatically added for larger keys. 'minidox_Usize': 1.6, @@ -109,9 +114,11 @@ shape_config = { ################################### ## Trackball General ## ################################### - # EXPERIMENTAL - 'trackball_modular': False, # May add removable trackball in subsequent releases, no current use. - # END EXPERIMENTAL + 'trackball_modular': False, # Added, creates a hole with space for the lip size listed below. + 'trackball_modular_lip_width': 3.0, # width of lip cleared out in ring location + 'trackball_modular_ball_height': 3.0, # height of ball from ring , used to create identical position to fixed. + 'trackball_modular_ring_height': 10.0, # height mount ring down from ball height. Covers gaps on elevated ball. + 'trackball_modular_clearance': 0.5, # height of ball from ring, used to create identical position to fixed. 'trackball_Usize': 1.5, # size for inner key near trackball 'ball_side': 'right', #'left', 'right', or 'both' @@ -294,10 +301,7 @@ shape_config = { 'oled_clip_z_gap': .2, } }, - 'web_thickness': 4.0, - 'post_size': 0.1, - # post_adj': post_size / 2 - 'post_adj': 0, + 'screws_offset': 'INSIDE', #'OUTSIDE', 'INSIDE', 'ORIGINAL' 'screw_insert_height': 3.8, @@ -322,7 +326,7 @@ shape_config = { # 'USB_TEENSY' = Teensy holder, no RJ9 # 'EXTERNAL' = square cutout for a holder such as the one from lolligagger. # 'NONE' = No openings in the back. - 'controller_mount_type': 'EXTERNAL', + 'controller_mount_type': 'PCB_MOUNT', 'external_holder_height': 12.5, 'external_holder_width': 28.75, @@ -331,6 +335,26 @@ shape_config = { # Offset is from the top inner corner of the top inner key. + ################################### + ## PCB Screw Mount ## + ################################### + "pcb_mount_ref_offset": [0, -5, 0], + "pcb_holder_size": [34.6, 7, 4], + "pcb_holder_offset": [8.9, 0, 0], + + "pcb_usb_hole_size": [7.5, 10.0, 4], + "pcb_usb_hole_offset": [15, 0, 4.5], + + "wall_thinner_size": [34, 7, 10], + + "trrs_hole_size": [3, 20], + "trrs_offset": [0, 0, 1.5], + + "pcb_screw_hole_size": [.5, 10], + "pcb_screw_x_offsets": [- 5.5, 7.75, 22], # for the screw positions off of reference + "pcb_screw_y_offset": -2, + + ################################### ## Bottom Plate Dimensions ################################### diff --git a/src/helpers_blender.py b/src/helpers_blender.py index 9213488..00da8e5 100644 --- a/src/helpers_blender.py +++ b/src/helpers_blender.py @@ -82,7 +82,8 @@ def add(shapes): def difference(shape, shapes): debugprint('difference()') for item in shapes: - shape -= item + if item is not None: + shape -= item return shape diff --git a/src/helpers_cadquery.py b/src/helpers_cadquery.py index 5dc78d1..58a876a 100644 --- a/src/helpers_cadquery.py +++ b/src/helpers_cadquery.py @@ -30,6 +30,8 @@ def cone(r1, r2, height): def rotate(shape, angle): + if shape is None: + return None origin = (0, 0, 0) shape = shape.rotate(axisStartPoint=origin, axisEndPoint=(1, 0, 0), angleDegrees=angle[0]) shape = shape.rotate(axisStartPoint=origin, axisEndPoint=(0, 1, 0), angleDegrees=angle[1]) @@ -38,6 +40,8 @@ def rotate(shape, angle): def translate(shape, vector): + if shape is None: + return None return shape.translate(tuple(vector)) @@ -50,10 +54,11 @@ def union(shapes): debugprint('union()') shape = None for item in shapes: - if shape is None: - shape = item - else: - shape = shape.union(item) + if item is not None: + if shape is None: + shape = item + else: + shape = shape.union(item) return shape @@ -61,23 +66,27 @@ def add(shapes): debugprint('union()') shape = None for item in shapes: - if shape is None: - shape = item - else: - shape = shape.add(item) + if item is not None: + if shape is None: + shape = item + else: + shape = shape.add(item) return shape def difference(shape, shapes): debugprint('difference()') for item in shapes: - shape = shape.cut(item) + if item is not None: + shape = shape.cut(item) return shape def intersect(shape1, shape2): - return shape1.intersect(shape2) - + if shape2 is not None: + return shape1.intersect(shape2) + else: + return shape1 def face_from_points(points): # debugprint('face_from_points()') diff --git a/src/helpers_solid.py b/src/helpers_solid.py index 174d65a..2557e01 100644 --- a/src/helpers_solid.py +++ b/src/helpers_solid.py @@ -23,10 +23,14 @@ def cone(r1, r2, height): def rotate(shape, angle): + if shape is None: + return None return sl.rotate(angle)(shape) def translate(shape, vector): + if shape is None: + return None return sl.translate(tuple(vector))(shape) @@ -47,10 +51,11 @@ def union(shapes): debugprint('union()') shape = None for item in shapes: - if shape is None: - shape = item - else: - shape += item + if item is not None: + if shape is None: + shape = item + else: + shape += item return shape @@ -58,23 +63,27 @@ def add(shapes): debugprint('union()') shape = None for item in shapes: - if shape is None: - shape = item - else: - shape += item + if item is not None: + if shape is None: + shape = item + else: + shape += item return shape def difference(shape, shapes): debugprint('difference()') for item in shapes: - shape -= item + if item is not None: + shape -= item return shape def intersect(shape1, shape2): - return sl.intersection()(shape1, shape2) - + if shape2 is not None: + return sl.intersection()(shape1, shape2) + else: + return shape1 def hull_from_points(points): return sl.hull()(*points) diff --git a/src/run_config.json b/src/run_config.json index 48bde38..3b1da65 100644 --- a/src/run_config.json +++ b/src/run_config.json @@ -2,7 +2,7 @@ "ENGINE": "solid", "save_dir": ".", "config_name": "DM", - "show_caps": true, + "show_caps": false, "show_pcbs": false, "nrows": 5, "ncols": 6, @@ -20,7 +20,10 @@ 7 ], "keyboard_z_offset": 11, - "thumb_style": "TRACKBALL_ORBYL", + "web_thickness": 4.0, + "post_size": 0.1, + "post_adj": 0, + "thumb_style": "CARBONFET", "default_1U_cluster": true, "minidox_Usize": 1.6, "thumb_plate_tr_rotation": 0.0, @@ -116,6 +119,10 @@ "tbcj_thickness": 2, "tbcj_outer_diameter": 53, "trackball_modular": false, + "trackball_modular_lip_width": 3.0, + "trackball_modular_ball_height": 3.0, + "trackball_modular_ring_height": 10.0, + "trackball_modular_clearance": 0.5, "trackball_Usize": 1.5, "ball_side": "right", "ball_diameter": 34.0, @@ -308,9 +315,6 @@ "oled_clip_z_gap": 0.2 } }, - "web_thickness": 4.0, - "post_size": 0.1, - "post_adj": 0, "screws_offset": "INSIDE", "screw_insert_height": 3.8, "screw_insert_bottom_radius": 2.655, @@ -318,11 +322,45 @@ "wire_post_height": 7, "wire_post_overhang": 3.5, "wire_post_diameter": 2.6, - "controller_mount_type": "EXTERNAL", + "controller_mount_type": "PCB_MOUNT", "external_holder_height": 12.5, "external_holder_width": 28.75, "external_holder_xoffset": -5.0, "external_holder_yoffset": -4.5, + "pcb_mount_ref_y_offset": -5, + "pcb_holder_size": [ + 34.6, + 7, + 4 + ], + "pcb_holder_x_offset": 8.9, + "pcb_usb_hole_x_offset": 15, + "pcb_usb_hole_z_offset": 4.5, + "pcb_usb_hole_size": [ + 7.5, + 10.0, + 4 + ], + "wall_thinner_size": [ + 34, + 7, + 10 + ], + "trrs_hole_size": [ + 3, + 20 + ], + "trrs_z_offset": 1.5, + "pcb_screw_hole_size": [ + 0.5, + 10 + ], + "pcb_screw_x_offsets": [ + -5.5, + 7.75, + 22 + ], + "pcb_screw_y_offset": -2, "screw_hole_diameter": 2, "base_thickness": 3.0, "base_offset": 3.0, -- cgit v1.2.3