use key_interface_size = 18; key_interface_corner_r = 5; key_interface_thickness = 1.484; // Chosen to let board fit inside housing_inner_h = 6; housing_inner_w = 21; housing_flat = 8; thickness = 1.7; board_gap = 0.125; wiring_l = 12; extra_flare = wiring_l; pico_board_l = 51.0; pico_board_w = 21.0; pico_board_h = 1.0; pico_total_h = 3.7; $fs = .1; $fa = 3; slop = 128; epsilon = 1/64; module pico_hole(d, x, y) { translate([x, y, -slop/2]) cylinder(h=slop, d = d); } module pico_board(gap = 0) { translate([-gap, -gap, -gap]) cube([pico_board_l + 2*gap, pico_board_w + 2*gap, pico_board_h + 2*gap]); } module pico_w(hole_d = 2.1) { // Dimensions from measuring and/or // https://datasheets.raspberrypi.com/picow/pico-w-datasheet.pdf board_l = pico_board_l; board_w = pico_board_w; hole_x1 = 2.0; hole_x2 = board_l - 2.0; hole_y_spacing = 11.4; hole_y = (board_w - hole_y_spacing)/2; difference() { color("green") pico_board(); pico_hole(hole_d, hole_x1, hole_y); pico_hole(hole_d, hole_x2, hole_y); pico_hole(hole_d, hole_x1, hole_y + hole_y_spacing); pico_hole(hole_d, hole_x2, hole_y + hole_y_spacing); } total_l = 52.3; total_h = pico_total_h; usb_w = 8.0; usb_l = 5.6; usb_h = 3.0; color("lightgray") translate([board_l - total_l, (board_w-usb_w)/2, total_h-usb_h]) cube([usb_l, usb_w, usb_h]); button_l = 4.2; button_w = 3.4; button_h = 3.5; button_x = 9.9; button_y = 5.2; color("white") translate([button_x, button_y, epsilon]) cube([button_l, button_w, button_h]); wifi_l = 10.0; wifi_w = 12.0; wifi_h = 2.8; wifi_x = 33.0; color("lightgray") translate([wifi_x, (board_w-wifi_w)/2, epsilon]) cube([wifi_l, wifi_w, wifi_h]); } module at_key() { translate([pico_board_l + wiring_l, 0, 0]) rotate([45, 0, 0]) rotate([0, 90, 0]) children(); } module key_interface_shape(thick = key_interface_thickness, outline = thickness) { inner = key_interface_size - 2*key_interface_corner_r; linear_extrude(thick) minkowski() { square([inner, inner], center=true); circle(r=key_interface_corner_r + outline); } } module key_interface() { at_key() difference() { key_interface_shape(); translate([0, 0, 6 - epsilon]) cherry_switch_void(tolerance=0.05); } } module housing_shape(outline = thickness) { housing_w = housing_inner_w + 2 * outline; housing_h = housing_inner_h + 2 * outline; squish = housing_h / (housing_w - housing_flat); scale([1, squish]) minkowski() { circle(d = housing_w - housing_flat); square([housing_flat, epsilon], center=true); } } module housing(length = pico_board_l - extra_flare) { rotate([90, 0, 0]) rotate([0, 90, 0]) linear_extrude(length) difference() { housing_shape(); housing_shape(0); } } module flare_shape(outline, extra_len) { hull() { at_key() key_interface_shape(epsilon + extra_len, outline); translate([pico_board_l-extra_flare, 0, 0]) translate([-extra_len, 0, 0]) rotate([90, 0, 0]) rotate([0, 90, 0]) linear_extrude(epsilon+extra_len) housing_shape(outline); } } module flare() { difference() { flare_shape(thickness, 0); flare_shape(0, epsilon); } } module at_board() { translate([0, -pico_board_w/2, -pico_board_h]) children(); } module tattlekey_case() { key_interface(); difference() { union() { housing(); flare(); } at_board() pico_board(board_gap); } } module preview() { at_board() pico_w(); render() tattlekey_case(); } //preview(); tattlekey_case();