// 11 potentiometers: // 10 steps // 1 to set clock rate (if onboard clock is used) // 11 SPDT switches: // 10 steps // 1 for 5v / 2.5v output mode // 10 LEDs - one per step // 1 rotary switch - number of steps // 5 sockets: // CLOCK in // CLOCK out // RESET in // GATE out // CV out /* [Default values] */ // Line segments for circles FN = 100; // [1:1:360] // Unit size (mm) U = 44.45; // Horizontal pitch size (mm) HP = 5.07; // 5.07 for a little bit of margin // Futura Light typeface for labels default_label_font = "Futura Md BT:style=Medium"; font_for_title = "QuentinEF:style=Medium"; title_font_size = 12; label_font_size = 5; $fn=FN; /* [Panel] */ // Height of module (mm) - Would not change this if you are using Eurorack height = 128.5; // A little less then 3U // Thickness of module (mm) - Would not change this if you are using Eurorack thickness = 2; // Website specifies a thickness of 2mm - but adjust to fit printer specs - often the first layer will be thinner than this printer_z_fix = 0.2; // this gets added to the base panel's thickness to account for squishing // for inset labels, translating to this height controls label depth label_inset_height = thickness-1; // Width of module (HP) width = 36; // [1:1:84] /* [Holes] */ // Four hole threshold (HP) four_hole_threshold = 10; // Center two holes two_holes_type = "opposite"; // [center, opposite, mirror] // Hole radius (mm) hole_r = 1.7; // Hole distance from the side (HP) hole_dist_side = hp_mm(1.5); // Hole distance from the top (mm) hole_dist_top = 2.5; rail_clearance = 9; // mm from very top/bottom edge and where it is safe to put reinforcing walls; i.e. the thickness of the rail + a safety margin // margins from edges h_margin = hole_dist_side + thickness; v_margin = hole_dist_top*2 + thickness; width_mm = hp_mm(width); // where to put the output jacks output_column = width_mm - h_margin; input_column = h_margin; working_height = height - v_margin*2 - title_font_size; working_increment = working_height / 6; // generally-useful spacing amount for vertical columns of stuff col_left = h_margin; col_right = width_mm - h_margin; out_row_1 = v_margin+12; out_row_2 = working_increment*1 + out_row_1; out_row_3 = working_increment*2 + out_row_1; out_row_4 = working_increment*3 + out_row_1; out_row_5 = working_increment*4 + out_row_1; out_row_6 = working_increment*5 + out_row_1; out_row_7 = working_increment*6 + out_row_1; //special-case the knob spacing on the right sub-panel top_row = height - rail_clearance - thickness*2 - 16.5/2; // 16.5 is the diameter of the round part of a pot rotary_knob_row = top_row - 30; working_width = width_mm - h_margin; left_rib_x = thickness * 1; right_rib_x = width_mm - thickness*2; // How much horizontal space needed for left-hand and right-hand sub-panels left_panel_width = 40; // widest element is rotary, at 30mm right_panel_width = 12; // overkill; currently three 3.5mm jacks needing 8mm slider_spacing = 12.5; // space between centers of each sliding pot; these are actually 8.8mm but require more on the circuit board for a single through-hole on one side //calculated x value of exact middle of slider panel (between steps 5 and 6); middle of panel after deducting left/right sub-panels slider_center = (width_mm - left_panel_width - right_panel_width)/2 + left_panel_width; slider_bottom = v_margin+12; // draw panel, subtract holes union() { difference(){ color([.1,.1,.1]) panel(width); // Top left: clock in, speed // clock in translate([col_left, top_row, 0]) audio_jack_3_5mm(); //clock rate translate([col_left+20, top_row, 0]) rotate([0, 0, 180]) pot_p160(); // Left side: meta-step controls // step rotary switch - this needs a _big_ knob, these are not easy to actuate, plus space for well-aligned, well-printed numbers translate([col_left+15, rotary_knob_row, 0]) rotary_switch(); // step (manual) -- this is actually a pushbutton momentary, but roughly same dimensions as toggle switch translate([col_left+5, out_row_3, 0]) toggle_switch_6mm(); // reset (manual) -- this is actually a pushbutton momentary, but roughly same dimensions as toggle switch translate([col_left+20, out_row_3, 0]) toggle_switch_6mm(); // run/stop (switch) translate([col_left+5, out_row_2, 0]) toggle_switch_6mm(); // once/continuous (switch) translate([col_left+20, out_row_2, 0]) toggle_switch_6mm(); // cv range (switch between 2.5v and 5v max) translate([col_left+15, out_row_1, 0]) toggle_switch_6mm(); // clock out translate([col_right, out_row_3, 0]) audio_jack_3_5mm(); // gate out translate([col_right, out_row_2, 0]) audio_jack_3_5mm(); // cv out translate([col_right, out_row_1, 0]) audio_jack_3_5mm(); // steps: slider, led, switch // Note: don't mess with the multipliers here, tweak the variables themselves translate([slider_center-slider_spacing*.5, slider_bottom, 0]) make_step(); translate([slider_center-slider_spacing*1.5, slider_bottom, 0]) make_step(); translate([slider_center-slider_spacing*2.5, slider_bottom, 0]) make_step(); translate([slider_center-slider_spacing*3.5, slider_bottom, 0]) make_step(); translate([slider_center-slider_spacing*4.5, slider_bottom, 0]) make_step(); translate([slider_center+slider_spacing*.5, slider_bottom, 0]) make_step(); translate([slider_center+slider_spacing*1.5, slider_bottom, 0]) make_step(); translate([slider_center+slider_spacing*2.5, slider_bottom, 0]) make_step(); translate([slider_center+slider_spacing*3.5, slider_bottom, 0]) make_step(); translate([slider_center+slider_spacing*4.5, slider_bottom, 0]) make_step(); } // ribs - reinforcements and barriers against shorts on the rails translate([left_rib_x, rail_clearance, 0]) v_wall(h=4, l=height-rail_clearance*2-thickness); translate([right_rib_x, rail_clearance, 0]) v_wall(h=4, l=height-rail_clearance*2-thickness); // top horizontal rib translate([left_rib_x, height-rail_clearance-thickness, 0]) h_wall(h=4, l=right_rib_x); // bottom horizontal rib translate([left_rib_x, rail_clearance, 0]) h_wall(h=4, l=right_rib_x); } module make_surface(filename, h) { for (a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) linear_extrude(height=a/h, convexity=10) projection(cut = true) surface(filename, center=true); } // h[p] module panel(h) { width_mm = hp_mm(h); difference() { // translate([0, 0, -printer_z_fix]) cube(size = [width_mm, height, thickness+printer_z_fix]); if (h < four_hole_threshold) { if (two_holes_type == "center") { translate([width_mm/2, hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); translate([width_mm/2, height-hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); } else if (two_holes_type == "opposite") { translate([hole_dist_side, hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); translate([width_mm - hole_dist_side, height-hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); } else if (two_holes_type == "mirror") { translate([hole_dist_side, hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); translate([hole_dist_side, height-hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); } } else { translate([hole_dist_side, hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); translate([hole_dist_side, height - hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); translate([width_mm - hole_dist_side, hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); translate([width_mm - hole_dist_side, height - hole_dist_top, -1]) cylinder(r=hole_r, h=thickness*2); } } } // http://www.rean-connectors.com/en/products/din-chassis-connectors/nys325 module nys325_midi_socket() { cylinder(r=7.55, h=thickness*2+1); translate([0, 11.3, -1]) cylinder(r=1.6, h=thickness*2+1); translate([0, -11.3, -1]) cylinder(r=1.6, h=thickness*2+1); } module audio_jack_3_5mm(vertical=true) { translate([0, 0, -1]) cylinder(r=3, h=thickness*2+1); if (vertical) { translate([-9/2, -10.5/2, 0]) cube([9, 10.5, .0001]); } else { translate([-10.5/2, -9/2, 0]) cube([10.5, 9, .0001]); } } module toggle_switch_6mm() { translate([0, 0, -1]) cylinder(r=3, h=thickness*2+1); translate([-8/2, -13/2, 0]) cube([8, 13, .0001]); } module toggle_switch_6_8mm() { translate([0, 0, -1]) cylinder(r=3.4, h=thickness*2+1); } module rotary_switch(){ translate([0, 0, -1]) cylinder(r=5, h=thickness*2); //hole for anchor translate([17.36/2 + 3/2, 0, -1]) cylinder(r=1.5, h=thickness); // visual indicator of space switch takes up translate([0, 0, 0]) cylinder(r=14, h=.0001); } // module pot_p160(anchor_hole="left") { translate([0, 0, -1]) cylinder(r=3.75, h=thickness*2); // hole for anchor; with translate() ends up being h-1 deep if (anchor_hole=="left" || anchor_hole=="both") { translate([7.8, 0, -1]) cylinder(r=1.5, h=thickness); translate([0, 13/2, 0]) cube([17, 13, .0001], center=true); } if (anchor_hole=="right" || anchor_hole=="both") { translate([-7.8, 0, -1]) cylinder(r=1.5, h=thickness); translate([0, 0, 0]) cube([17, 13, .0001], center=true); } // visual indicator of space pot body takes up translate([0, 0, 0]) cylinder(r=16.5/2, h=.0001); } module pot_wh148() { translate([0, 0, -1]) cylinder(r=3.6, h=thickness*2); // hole for anchor; with translate() ends up being h-1 deep translate([7.8, 0, -1]) cylinder(r=1.3, h=thickness); } module pot_0547() { // slider pot slit translate([-1.25, 0, -1]) cube([2.5, 52, thickness*2]); // visual indicator translate([-8.8/2, -4, 0]) cube([8.8, 60.25, .0001]); } module led_5mm() { // make a hole for a 5mm led, with a hair of margin translate([0, 0, -1]) cylinder(r=2.575, h=thickness*2+2); } module make_step(bottom_element="switch") { // generate holes for a pot, an LED, and a switch if (bottom_element=="pot"){ pot_0547(); translate([0, 55+8, 0]) led_5mm(); translate([0, 55+24, 0]) toggle_switch_6mm(); } else if (bottom_element=="switch") { toggle_switch_6mm(); translate([0, 16, 0]) pot_0547(); translate([0, 55+24, 0]) led_5mm(); } } module label(string, size=4, halign="center", height=thickness+1, font=default_label_font) { color([1,0,0]) linear_extrude(height) text(string, size, halign=halign, font=font); } module title(string, size=12, halign="center", font=font_for_title) { color([1,0,0]) linear_extrude(thickness+1) text(string, size, halign=halign, font=font); } // draw a "vertical" wall // h = z height, i.e. how tall the wall is coming out of the panel // l = length of the wall along the panel module v_wall(h, l, th=thickness) { translate([0, 0, -h]) cube(size = [th, l, h]); } // draw a horizontal wall (across the panel) // h = z height, how far the wall comes out of the panel // l = length of the wall along the panel module h_wall(h, l, th=thickness) { translate([0, 0, -h]) cube(size = [l, th, h]); } // draws two walls in parallel, close together so a PCB can fit between // h = how deep to make the walls; a little extra is probably good // l = length of the side of the board that will be seated in the slit, with tolerances // th = thickness of the PCB, with tolerances // wall_thickness = how thick to make each wall of the holder // e.g.: Radio Shaek is 51mm x 70mm and 1.2mm thick module pcb_holder(h, l, th, wall_thickness=thickness) { translate([0-(wall_thickness+th)/2, 0, 0]) v_wall(h, l, wall_thickness); translate([(wall_thickness+th)/2, 0, 0]) v_wall(h, l, wall_thickness); } // https://www.elfa.se/Web/Downloads/_t/ds/els-511sygwa-s530-e1_eng_tds.pdf module x1_7seg_14_22mm_display() { cube([12.25, 19.25, thickness]); } module x2_7seg_14_22mm_display() { cube([25, 19.25, thickness]); } // https://www.elfa.se/Web/Downloads/2e/wa/qmCC56-12EWA.pdf module x4_7seg_14_22mm_display() { cube([50.5, 19.25, thickness]); } // https://cdn.sparkfun.com/datasheets/Components/Switches/MX%20Series.pdf module cherry_mx_button() { union(){ cube([14,14,thickness]); translate([-1,1,0]) cube([14+2*1,thickness,thickness]); translate([-1,14-1-3,0]) cube([14+2*1,3,thickness]); } } // 1U = 1.75" = 44.45mm // 1HP = 1/5" = 5.08mm // u[nits] function units_mm(u) = u * U; // h[p] function hp_mm(h) = h * HP;