include use use // bend radius on hdd inlet R = 2; // size of the core box W = tray_width; H = tray_height; // strap dimensions SW=5; SH=1.5; module front(capped_bottom=true) { total_height = num_hdd_y*H + (capped_bottom ? 4 : hrail_height); translate([0, 0, capped_bottom ? -(hrail_height/2 - 3) : -hrail_height/2]) intersection() { union() { translate([0, 0, 0*H]) tray(front_depth, inlet=[1], power_hole=false, support_bar=false, straps=false); for (i = [1:num_hdd_y-1]) translate([0, 0, i*H]) tray(front_depth); translate([0, 0, num_hdd_y*H]) tray(front_depth, inlet=[-1], rail=[1]); } translate([0, 0, num_hdd_y*H/2 + (capped_bottom ? (hrail_height/2 - 2) : 0)]) ccube([2*W, front_depth, total_height]); } } module back(capped_bottom=true) { total_height = num_hdd_y*H + (capped_bottom ? 4 : hrail_height); translate([0, 0, capped_bottom ? -(hrail_height/2 - 3) : -hrail_height/2]) intersection() { union() { translate([0, 0, 0*H]) tray(back_depth, inlet=[1], power_hole=false, support_bar=false, straps=false); for (i = [1:num_hdd_y-1]) translate([0, 0, i*H]) tray(back_depth, power_hole=false, straps=false); translate([0, 0, num_hdd_y*H]) tray(back_depth, inlet=[-1], rail=[1], power_hole=false, straps=false); } translate([0, 0, num_hdd_y*H/2 + (capped_bottom ? (hrail_height/2 - 2) : 0)]) ccube([2*W, back_depth, total_height]); } } module tray(D, power_hole=true, straps=true, inlet=[-1,1], rail=[0,1], support_bar=true) union() { difference() { union() { // horizontal rail ccube([hdd_width, D, hrail_height]); // vertical rails for (i = [-1,1]) translate([i*(W/2 - vrail_width/8), 0, 0]) ccube([vrail_width/4, D, H]); } // round corners for easy hdd insertion for (i = inlet) translate([0, 0, i*(hdd_height + hrail_height)/2]) hdd_inlet(D); // notches to attach cable strap if (straps) { // horizontal strap holes for (i = [-0.55, -0.18, 0.18, 0.55]) for (k = [-1, 1]) translate([i*hdd_width/2, 0, k*(hrail_height/2 - SH/2)]) strap_hole(D); // vertical strap holes for (i = [-1, 1]) translate([i * (hdd_width/2 + SH/2 - epsilon), 0, -hrail_height*3/4]) rotate([0, 90, 0]) strap_hole(D); } // hole for support bar if (support_bar) translate([0, D/4, 0]) ccube([W, D, support_bar_width]); // hole to insert SATA power cables if (power_hole) translate([-hdd_width/2 + 15, 0, (support_bar_width - spc_width)/2 - 1.5]) { translate([0, 0, 0]) ccube([5*spc_width, D, spc_width]); translate([-2 * spc_width, 0, hrail_height/4]) ccube([spc_width, D, hrail_height/2]); } // space for rail for (j = rail) for (i = [0,1]) mirror([i, 0, 0]) translate([-hdd_width/2 - rail_thickness, -D, hrail_height/2 - rail_thickness - j*H]) rail(); // female side connectors for (i = [-1,1]) connector_pos(D, i, -1); } // male side connectors for (i = [-1,1]) connector_pos(D, i, 1); } module connector_pos(D, lr, gender, z=1) translate([z*lr*(W/2 + vrail_width/4), -D/2, H*lr*gender*0.3]) connector(); module connector() { intersection() { translate([0, 2.5, 0]) ccube([connector_width, 5, 10]); rotate([45, 0, 0]) ccube([connector_width, 5, 5]); } } module strap_hole(D) { ccube([SW, D, SH]); } module hdd_inlet(D) render() for (i = [0,1]) mirror([i, 0, 0]) for (j = [0,1]) mirror([0, j, 0]) for (k = [0,1]) mirror([0, 0, k]) difference() { union() { translate([0, D/2-R, 0]) cube([hdd_width/2 + R, D, hdd_height/2 + R]); cube([hdd_width/2, D/2-R, hdd_height/2]); }; translate([hdd_width/2 + R, D/2-R, 0]) rotate([0, 0, 0]) cylinder(r=R, h=H, center=true); translate([0, D/2-R, hdd_height/2 + R]) rotate([0, 90, 0]) cylinder(r=R, h=W, center=true); } tray();