$fn = 64; // --- PARAMETERS --- num_slots = 3; // Number of holding slots wall_thickness = 4; // Thickness of rigid dividers relief_gap = 3; // Gap behind the spring arm for flexing spring_thickness = 2; // Thickness of the flexible spring arm grip_gap = 16; // Resting width of the slot for pliers depth = 30; // Depth of the holder height = 30; // Height of the holder back_thickness = 5; // Thickness of the mounting backplate // Calculated dimensions slot_spacing = wall_thickness + relief_gap + spring_thickness + grip_gap; total_width = num_slots * slot_spacing + wall_thickness; // --- MODULES --- // Generates the 2D profile of the flexible spring arm module arm_profile() { r = spring_thickness / 2; // Control points for the spring arm curve p0 = [wall_thickness + relief_gap + r, -0.1]; p1 = [wall_thickness + relief_gap + r, depth * 0.25]; p2 = [wall_thickness + relief_gap + r + 4, depth * 0.65]; // Pinch point p3 = [wall_thickness + relief_gap + r + 1, depth * 0.9]; // Flared opening // Build continuous smooth arm using hulled circles hull() { translate(p0) circle(r); translate(p1) circle(r); } hull() { translate(p1) circle(r); translate(p2) circle(r); } hull() { translate(p2) circle(r); translate(p3) circle(r); } } // Generates the countersunk mounting hole module mounting_hole() { translate([0, -back_thickness - 0.2, 0]) rotate([-90, 0, 0]) { // Screw shaft clearance (M4 screw size) cylinder(d=4.5, h=back_thickness + 0.4); // Countersink for screw head translate([0, 0, back_thickness - 2]) cylinder(d1=4.5, d2=8.5, h=2.5); } } // --- MAIN GEOMETRY --- // Best printed on its bottom (Z=0 plane) for optimal spring layer strength difference() { union() { // Backplate translate([0, -back_thickness, 0]) cube([total_width, back_thickness, height]); // Rigid Dividers for (i = [0 : num_slots]) { translate([i * slot_spacing, -0.1, 0]) { // Main wall cube([wall_thickness, depth + 0.1 - wall_thickness/2, height]); // Rounded front edge translate([wall_thickness/2, depth + 0.1 - wall_thickness/2, 0]) cylinder(d=wall_thickness, h=height); } } // Spring Arms for (i = [0 : num_slots - 1]) { translate([i * slot_spacing, 0, 0]) linear_extrude(height) arm_profile(); } } // Mounting Holes (Placed in the center of the first and last slots) hole_offset = wall_thickness + relief_gap + spring_thickness + (grip_gap / 2); z_center = height / 2; // Hole 1 (First slot) translate([hole_offset, 0, z_center]) mounting_hole(); // Hole 2 (Last slot) translate([(num_slots - 1) * slot_spacing + hole_offset, 0, z_center]) mounting_hole(); }