// ============================================================ // imx219_mount.scad — IMX219 Camera Radial Arm Rev A // Agent: sl-mechanical 2026-02-28 // ============================================================ // Radial arm bracket for 32×32 mm IMX219 camera PCB. // 4× arms at 0/90/180/270° around the sensor_head platform. // Camera face tilted 10° nose-down. CSI ribbon slot along arm. // // Print: one arm at a time, flat-side-down — no supports. // // RENDER options: // "arm" single arm for slicing (default) // "assembly" all 4 arms positioned around origin // ============================================================ RENDER = "arm"; // ── Camera PCB (IMX219, 32×32 mm) ──────────────────────────── PCB_SIZE = 32.0; // PCB square side // M2 hole pattern: 24×24 mm square (±12 mm from centre) M2_SPACING = 24.0; M2_D = 2.4; // M2 clearance hole // ── Arm geometry ───────────────────────────────────────────── // Arm is centred on Y=0, extends in +X direction from origin. // Base attachment holes near X=0; camera face plate at X=REACH_LEN. ARM_W = 26.0; // arm width (Y direction, centred) ARM_H = 5.0; // arm thickness (Z direction) // Must match sensor_head.scad ARM_R and ARM_DY_CAM ARM_R = 50.0; // platform attachment radius (used in assembly view) ARM_DY = 9.0; // half-spacing of M4 base attachment holes (Y axis) ARM_BOLT_X = 8.0; // base bolt CL from arm base (X) REACH_LEN = 52.0; // arm extension (X) FACE_SZ = PCB_SIZE + 6.0; // camera face plate side (38 mm) FACE_THICK = 4.0; // face plate thickness (X) TILT = 10.0; // nose-down tilt angle (degrees) // CSI ribbon slot — runs along bottom face of arm CSI_W = 16.0; // ribbon clearance width CSI_H = 2.0; // slot depth // ── Fasteners ───────────────────────────────────────────────── M4_D = 4.5; // M4 clearance hole $fn = 64; e = 0.01; // ───────────────────────────────────────────────────────────── // imx219_arm() // Arm centred on Y=0. Base at X=0, tip at X=REACH_LEN. // ───────────────────────────────────────────────────────────── module imx219_arm() { difference() { union() { // Arm body — centred on Y axis translate([0, -ARM_W/2, 0]) cube([REACH_LEN, ARM_W, ARM_H]); // Camera face plate at tip, tilted TILT° nose-down translate([REACH_LEN, 0, ARM_H/2]) rotate([0, TILT, 0]) translate([0, -FACE_SZ/2, -FACE_SZ/2]) cube([FACE_THICK, FACE_SZ, FACE_SZ]); } // ── 2× M4 base attachment holes ─────────────────────── for (s = [-1, 1]) translate([ARM_BOLT_X, s * ARM_DY, -e]) cylinder(d = M4_D, h = ARM_H + 2*e); // ── CSI ribbon slot — bottom face of arm ────────────── translate([REACH_LEN * 0.2, -CSI_W/2, -e]) cube([REACH_LEN * 0.6, CSI_W, CSI_H + e]); // ── 4× M2 camera PCB holes on face plate ───────────── translate([REACH_LEN, 0, ARM_H/2]) rotate([0, TILT, 0]) for (dy = [-M2_SPACING/2, M2_SPACING/2]) for (dz = [-M2_SPACING/2, M2_SPACING/2]) translate([-e, dy, dz]) rotate([0, 90, 0]) cylinder(d = M2_D, h = FACE_THICK + 2*e); } } // ───────────────────────────────────────────────────────────── // Render selector // ───────────────────────────────────────────────────────────── if (RENDER == "arm") { imx219_arm(); } else if (RENDER == "assembly") { // 4 arms at 90° intervals, base at ARM_R from stem CL for (a = [0, 90, 180, 270]) rotate([0, 0, a]) translate([ARM_R, 0, 0]) color("SkyBlue", 0.9) imx219_arm(); }