$fn = 64; // --- Parameters --- num_slots = 3; slot_spacing = 45; block_depth = 40; block_height = 25; slot_width = 12; // Width of the main slot slot_depth = 25; // Depth of the slot spring_thick = 2.5; // Thickness of the flexible cantilever arms relief_width = 3; // Width of the flex clearance bump_radius = 2.5; // Size of the gripping bump hole_dia = 4.5; // Screw hole diameter (M4) head_dia = 8.5; // Screw head diameter head_depth = 17; // Depth of screw counterbore corner_r = 3; block_width = num_slots * slot_spacing; // --- Main Assembly --- difference() { // Extrude the 2D profile into the 3D block linear_extrude(block_height) { difference() { // Base rounded block hull() { translate([corner_r, corner_r]) circle(r=corner_r); translate([block_width - corner_r, corner_r]) circle(r=corner_r); translate([corner_r, block_depth - corner_r]) circle(r=corner_r); translate([block_width - corner_r, block_depth - corner_r]) circle(r=corner_r); } // Cut out each spring slot for (i = [0 : num_slots - 1]) { translate([slot_spacing/2 + i * slot_spacing, 0]) { slot_profile(); } } } } // Mounting holes (placed between slots) for (i = [1 : num_slots - 1]) { translate([i * slot_spacing, 15, -1]) { // Through hole cylinder(h = block_height + 2, d = hole_dia); // Counterbore for screw head translate([0, 0, block_height - head_depth + 1]) cylinder(h = head_depth + 2, d = head_dia); } } } // --- Modules --- module slot_profile() { sw = slot_width; sd = slot_depth; st = spring_thick; rw = relief_width; difference() { union() { // Main central slot translate([-sw/2, block_depth - sd]) square([sw, sd + 1]); // Rounded bottom of the slot translate([0, block_depth - sd]) circle(d=sw); // Left relief cut and rounded bottom translate([-sw/2 - st - rw, block_depth - sd - 4]) square([rw, sd + 5]); translate([-sw/2 - st - rw/2, block_depth - sd - 4]) circle(d=rw); // Right relief cut and rounded bottom translate([sw/2 + st, block_depth - sd - 4]) square([rw, sd + 5]); translate([sw/2 + st + rw/2, block_depth - sd - 4]) circle(d=rw); // Entry chamfer/flare to guide tools in polygon([ [-sw/2, block_depth - 4], [sw/2, block_depth - 4], [sw/2 + 5, block_depth + 1], [-sw/2 - 5, block_depth + 1] ]); } // Gripping bumps (kept solid by subtracting them from the cutout space) translate([-sw/2, block_depth - sd + 10]) circle(r=bump_radius); translate([sw/2, block_depth - sd + 10]) circle(r=bump_radius); } }