$fn = 128; // --- Parametric Dimensions --- base_radius = 45; base_height = 10; pillar_height = 90; stand_angle = 35; backplate_w = 75; backplate_h = 210; backplate_t = 6; phone_thickness = 14; spring_start_y = 195; grip_y = 148; // --- Main Assembly --- union() { // Sturdy elongated base hull() { translate([0, 30, 0]) cylinder(r=base_radius, h=base_height); translate([0, -40, 0]) cylinder(r=base_radius, h=base_height); } // Tapered pillar hull() { translate([0, -10, base_height]) cylinder(r=22, h=0.1); translate([0, 0, base_height + pillar_height - 10]) cylinder(r=15, h=10); } // Cradle Mount (tilted back) translate([0, 0, base_height + pillar_height]) rotate([stand_angle, 0, 0]) { // Position cradle so the phone sits centrally over the base translate([0, -80, 0]) cradle(); // Mounting bracket bridging the pillar and backplate translate([0, 0, -backplate_t/2 - 5]) cube([30, 50, 10], center=true); } } // --- Modules --- module cradle() { // Main backplate with track cutout difference() { translate([0, backplate_h/2, 0]) cube([backplate_w, backplate_h, backplate_t], center=true); // Cutout for the compliant spring and grip movement translate([0, 160, 0]) cube([46, 75, backplate_t + 2], center=true); } // Anchor block to fuse the top of the spring to the backplate translate([0, 197.5, 0]) cube([40, 5, backplate_t], center=true); // Fixed Bottom Support // Bottom shelf translate([0, 5, backplate_t/2 + phone_thickness/2]) cube([backplate_w, 10, phone_thickness], center=true); // Bottom front retaining lip translate([0, 5, backplate_t/2 + phone_thickness + 2]) cube([backplate_w, 10, 4], center=true); // Compliant Print-in-Place Spring zigzag_spring(spring_start_y); // Moving Top Grip (Spring-loaded) // Base of grip (slides within the cutout) translate([0, grip_y, 0]) cube([40, 10, backplate_t], center=true); // Shelf of grip translate([0, grip_y, backplate_t/2 + phone_thickness/2]) cube([40, 10, phone_thickness], center=true); // Front retaining lip of grip translate([0, grip_y, backplate_t/2 + phone_thickness + 2]) cube([40, 10, 4], center=true); // Quick-release thumb tab (angled wedge for easy pressing) hull() { translate([0, grip_y, backplate_t/2 + phone_thickness + 2]) cube([20, 10, 4], center=true); translate([0, grip_y + 10, backplate_t/2 + phone_thickness + 12]) cube([20, 2, 4], center=true); } } module zigzag_spring(start_y) { zig_w = 40; zig_h = 2; gap = 4; zig_t = backplate_t; num_ribs = 8; // Horizontal flexing ribs for(i=[0:num_ribs-1]) { translate([0, start_y - i*(zig_h+gap), 0]) cube([zig_w, zig_h, zig_t], center=true); } // Alternating side connectors to form the continuous zigzag for(i=[0:num_ribs-2]) { side = (i%2 == 0) ? 1 : -1; translate([side * (zig_w/2 - zig_h/2), start_y - i*(zig_h+gap) - (gap+zig_h)/2, 0]) cube([zig_h, gap + zig_h, zig_t], center=true); } }