////////////////////////////////////////////////////////////// // PARAMETRIC 120mm FAN‑MOUNTED DRIVE BRACKET // 4× SAS (15mm) + 2× SATA (7mm) with 4mm air gaps // HARD LIMIT: No geometry may extend more than 10mm // below the fan-hole center (Y = 15 → min Y = 5) // Spine rebuilt, arms extended, gussets restored, dual SSD holes ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // CHUNK 1 — SPINE WITH REAL M5 FAN HOLES (REBUILT CLEANLY) ////////////////////////////////////////////////////////////// spine_length = 120; fan_hole_spacing = 105; spine_height = 30; spine_thickness = 4; m5_radius = 2.8; // Fan-hole center = 15 mm // Allowed minimum Y = 5 mm // Spine runs from Y = 5 → 35 (height = 30) module spine() { // Spine bottom stays at Y = 5 // Spine top must be Y = 25 (10mm above fan-hole center) // New spine height = 20mm translate([0, 5, 0]) cube([spine_length, 20, spine_thickness], center=false); } module fan_mount_holes() { left_x = (spine_length - fan_hole_spacing) / 2; right_x = left_x + fan_hole_spacing; // Fan-hole center at Y = 15 translate([left_x, 15, -100]) cylinder(h = 300, r = m5_radius, center = false, $fn = 64); translate([right_x, 15, -100]) cylinder(h = 300, r = m5_radius, center = false, $fn = 64); } ////////////////////////////////////////////////////////////// // CHUNK 2 — ARM GEOMETRY (UPDATED FOR 50% GAP REDUCTION) // Arm bottom must be EXACTLY Y = 5 mm // First hole center: now 18.3mm from spine face (was 24.6) // Second hole center: +76.6mm further out (unchanged spacing) // Arm length shortened by 6.3mm (110 → 103.7) ////////////////////////////////////////////////////////////// drop = -6.25; leg_width = 10; tip_Y = 2.5; // Arm shortened by 6.3 mm arm_length = 103.7; m3_radius = 1.6; // Gusset geometry gusset_height = 6; gusset_length = 8; gusset_thick = 2; // Updated hole positions first_hole_z = 18.3 - spine_thickness; // 50% reduced gap second_hole_z = first_hole_z + 76.6; // preserve spacing module one_arm() { // Vertical leg translate([-leg_width/2, -drop - tip_Y/2, 0]) cube([leg_width, drop + tip_Y/2, spine_thickness]); // Left gusset translate([-leg_width/2, -drop - tip_Y/2, spine_thickness]) polyhedron( points = [ [0, 0, 0], [0, gusset_height, 0], [0, 0, gusset_length], [gusset_thick, 0, 0], [gusset_thick, gusset_height, 0], [gusset_thick, 0, gusset_length] ], faces = [ [0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0] ] ); // Right gusset translate([leg_width/2 - gusset_thick, -drop - tip_Y/2, spine_thickness]) polyhedron( points = [ [0, 0, 0], [0, gusset_height, 0], [0, 0, gusset_length], [gusset_thick, 0, 0], [gusset_thick, gusset_height, 0], [gusset_thick, 0, gusset_length] ], faces = [ [0,1,2], [3,5,4], [0,3,4,1], [1,4,5,2], [2,5,3,0] ] ); // Tip block with two through-holes translate([-leg_width/2, -drop - tip_Y/2, spine_thickness]) difference() { cube([leg_width, tip_Y, arm_length], center = false); // First hole (reduced gap) translate([leg_width/2, -drop, first_hole_z]) rotate([90, 0, 0]) cylinder( h = 200, r = m3_radius, center = true, $fn = 48 ); // Second hole (same spacing) translate([leg_width/2, -drop, second_hole_z]) rotate([90, 0, 0]) cylinder( h = 200, r = m3_radius, center = true, $fn = 48 ); } } ////////////////////////////////////////////////////////////// // CHUNK 3 — PARAMETRIC ARM SPACING (MATCHES ORIGINAL) ////////////////////////////////////////////////////////////// drive_thicknesses = [15,15,15,15,7,7]; air_gap = 4; function cum_thick(i) = i <= 0 ? 0 : drive_thicknesses[i-1] + cum_thick(i-1); function total_thick() = cum_thick(len(drive_thicknesses)); function total_width() = total_thick() + (len(drive_thicknesses)-1) * air_gap; fan_center_x = spine_length/2; // = 60mm function stack_left_x() = fan_center_x - total_width()/2; function drive_center_x(i) = stack_left_x() + cum_thick(i) + i*air_gap + drive_thicknesses[i]/2; function arm_center_x(i) = drive_center_x(i); module arms_parametric() { for (i = [0 : len(drive_thicknesses)-1]) { translate([arm_center_x(i), 0, 0]) one_arm(); } } ////////////////////////////////////////////////////////////// // CHUNK 4 — FINAL ASSEMBLY ////////////////////////////////////////////////////////////// difference() { union() { spine(); arms_parametric(); } fan_mount_holes(); }