// arcade controller thing // Copyright (c) 2017 Clinton Ebadi // GPLv3 or (at your option) any later version // .. insert license text here ... // todo: // - hinge // - screw holes + captive nut to mount // - internal mount for mcu and battery // - hole for usb panel mount // - bevel lid // maybe/wishlist: // - wire routing clips on panel? // - buttons on side for pinball? // - vent under mcu/battery? // - slant panel toward player? // bugs: // - hinge is not aligned -- either male arm length or connector placement is wrong use use use // PREVIEW preview(); module preview () { rotate ([-10, 0, 0]) translate ([0, 0, box_depth+20]) panel (); case (); for (i = [2 ,4]) translate ([panel_width+hinge_joint_width*i, 0, 0]) hinge_male (); } // CONFIGURATION panel_width = 250; panel_height = 130; box_depth = 80; box_wall = 2; box_base_thickness = 5; $button_d = 30; // I think this should be special joystick_width = 85; joystick_height = 40; // fixme: these are a bit confused hinge_joint_width = 8; hinge_joint_thickness = 5; hinge_box_base_thicknesseight = 10; hinge_joint_height = 10; hinge_arm_length = 50; // gunk that should be elsewhere... // bcube parameters, clean up cr = box_wall*2; cres = 0; // PANEL COMPONENTS module button (bezel = $button_d+4) { circle (d=$button_d); %circle(d=bezel); } module joystick () { bolt_d = 8; center_hole_d = 24; for (x = [-joystick_width/2, joystick_width/2], y = [-joystick_height/2, joystick_height/2]) { translate ([x, y, 0]) circle (d=bolt_d); // need slot instead } circle (d=center_hole_d); %square ([joystick_width, joystick_height], center=true); // not right... } // CASE module case_base (h=box_base_thickness) { bcube([panel_width, panel_height, h], cr, cres); } module case_walls () { difference () { union () { difference() { bcube([panel_width, panel_height, box_depth-box_base_thickness], cr, cres); bcube([panel_width-box_wall*2, panel_height-box_wall*2, box_depth+1], cr, cres); } attach (case_connector_wall (x=10), hinge_connector_back ()) hinge_female_base (); } attach (case_connector_wall (x=10), hinge_connector_back ()) hinge_female_cut (); } %connector (case_connector_wall (x=10)); } module case () { case_base (); translate ([0, 0, box_depth/2]) case_walls (); } // todo: // specify which wall (rear, front, left, right). vector addition may help... // offset from center of wall, as vector (and use vector subtraction!) // optional: inside/outside function case_connector_wall (x=0, y=0, z=0) = [ [panel_width/2-x, panel_height/2-y, (box_depth-box_base_thickness)/2-z], [0,-1, 0], 0 ]; // HINGE // hinge todo: // calculate z offset so that hinge will align when closed // calculate offset into panel surface for length of peg // attach to case, calculating offset from wall as fixed value + width // add connector for pin to socket so that can easily be test fit in // software instead of guessing // should panel connector be on its side? Limits motion to 90⁰ Or // maybe just walls only + fillet with no base... function hinge_connector_back (th=hinge_joint_thickness*2, h=hinge_box_base_thicknesseight) = [ [0, th/2, h/2], [0,1, 0], 0 ]; // todo: // gusset support underneath // split into base and negative so that a hole can be punched into case wall module hinge_female_base () { w = hinge_joint_width * 2; th = hinge_joint_thickness * 2; %connector (hinge_connector_back ()); cube ([w, th, hinge_box_base_thicknesseight], center=true); } module hinge_female_cut () { w = hinge_joint_width * 2; th = hinge_joint_thickness * 2; // cruft from earlier hacking, remove... jt = hinge_joint_thickness; jw = hinge_joint_width; joint_male_negative(male_joint_width=jw, male_joint_thickness=jt, forward_rom=90, backward_rom=90, male_joint_height=hinge_joint_height); } module hinge_female () { difference () { hinge_female_base (); hinge_female_cut (); } } module hinge_male () { for (i=[0,1]) mirror ([0, i, 0]) translate ([0, -hinge_arm_length/4, 0]) joint_male(male_joint_width=hinge_joint_width, male_joint_thickness=hinge_joint_thickness, male_joint_height=hinge_arm_length/2, side=true); } // hinge to panel... // mount hinge on panel arm_length back from edge // fixme: wall thickness is not taken into account // PANEL // cleanup after general case_connector_wall() is done panel_c = [ [panel_width/2-10, panel_height/2-hinge_arm_length, -box_base_thickness/2+0.01], [0,0, 1], 180 ]; module panel () { difference () { case_base (); linear_extrude (box_base_thickness*2,center=true) panel_layout (); } %connector (panel_c); attach (panel_c, hinge_connector_back ()) hinge_female (); } module panel_attach (position, angle=0) { x = position[0]; y = position[1]; c1 = [ [x, y, box_base_thickness/2], [0,0,1], angle ]; a1 = [ [0,0, 0], [0,0,0], 0 ]; // %connector (c1); // fixme: don't use 2d for layout attach (c1, a1) children (); } // panel layout inspired by the Neo Geo layout module panel_layout () { translate ([-panel_width/2 + 40, 0, 0]) { panel_attach ([0, 0], 90) joystick (); // p1, coin (floating off in the distance...) translate ([140, 0, 0]) { $button_d=16; for (x = [0, $button_d+10]) { panel_attach ([x, 42]) button (); } } // a, b, c, d translate ([60, -20, 0]) { panel_attach ([0, 0]) button (); for (i = [ 1 : 3 ]) { panel_attach ([i*($button_d+10)-10, $button_d]) button (); } } } }