// ============================================ // Presence Sensor Wall-Mount Enclosure // ESP32-S3 + OV5640 + LD2410C + AM312 + SHT41 + BH1750 // Board: 45 x 35 mm // ============================================ // Dimensions (mm) pcb_w = 45; // PCB width pcb_h = 35; // PCB height pcb_t = 1.6; // PCB thickness wall = 1.8; // Wall thickness tolerance = 0.3; // Fit tolerance bottom_gap = 3; // Space below PCB for solder joints top_gap = 12; // Space above PCB for components + modules lid_lip = 1.5; // Lid overlap lip // Derived inner_w = pcb_w + tolerance * 2; inner_h = pcb_h + tolerance * 2; inner_d = bottom_gap + pcb_t + top_gap; outer_w = inner_w + wall * 2; outer_h = inner_h + wall * 2; outer_d = inner_d + wall; // Open top (lid covers) // Screw post dimensions post_d = 4.5; // Post outer diameter screw_d = 2.2; // M2 screw hole post_h = bottom_gap; // Height to PCB level // Component positions (from bottom-left of PCB) cam_x = pcb_w / 2; // Camera centered horizontally cam_y = pcb_h - 5; // Camera near top cam_hole_w = 10; // Camera lens window cam_hole_h = 10; pir_x = 12; // PIR left of center pir_y = pcb_h - 20; pir_hole_d = 10; // AM312 dome diameter light_x = 30; // BH1750 right of center light_y = pcb_h - 20; light_hole_d = 4; // Small window for light sensor mmwave_x = pcb_w / 2; // LD2410C centered mmwave_y = 8; // Near bottom mmwave_slot_w = 8; // Slot for radar signal mmwave_slot_h = 36; usbc_x = pcb_w / 2; // USB-C centered bottom usbc_w = 10; usbc_h = 4; vent_slot_w = 1.5; vent_slot_h = 8; // ============================================ // Main body // ============================================ module body() { difference() { // Outer shell rounded_box(outer_w, outer_h, outer_d, 3); // Inner cavity translate([wall, wall, wall]) rounded_box(inner_w, inner_h, inner_d + 1, 2); // Camera window (front face - top) translate([wall + tolerance + cam_x - cam_hole_w/2, wall + tolerance + cam_y - cam_hole_h/2, -1]) rounded_box(cam_hole_w, cam_hole_h, wall + 2, 2); // PIR window (front face) translate([wall + tolerance + pir_x, wall + tolerance + pir_y, -1]) cylinder(h=wall+2, d=pir_hole_d, $fn=32); // Light sensor window (front face) translate([wall + tolerance + light_x, wall + tolerance + light_y, -1]) cylinder(h=wall+2, d=light_hole_d, $fn=32); // USB-C cutout (bottom edge) translate([wall + tolerance + usbc_x - usbc_w/2, -1, wall + bottom_gap - 1]) cube([usbc_w, wall + 2, usbc_h + 2]); // Ventilation slots (sides - for SHT41 airflow) for (i = [0:3]) { // Left side translate([-1, wall + 5 + i * (vent_slot_h + 2), wall + bottom_gap + pcb_t + 2]) cube([wall + 2, vent_slot_h, vent_slot_w]); // Right side translate([outer_w - wall - 1, wall + 5 + i * (vent_slot_h + 2), wall + bottom_gap + pcb_t + 2]) cube([wall + 2, vent_slot_h, vent_slot_w]); } // mmWave radar slot (through back wall for better signal) translate([wall + tolerance + mmwave_x - mmwave_slot_w/2, wall + tolerance + mmwave_y - mmwave_slot_h/2, outer_d - wall - 0.5]) rounded_box(mmwave_slot_w, mmwave_slot_h, wall + 1, 1); // Wall mount screw slots (keyhole on back) translate([outer_w/2, outer_h * 0.3, outer_d - wall - 1]) wall_mount_keyhole(); translate([outer_w/2, outer_h * 0.7, outer_d - wall - 1]) wall_mount_keyhole(); } // PCB support posts for (pos = [[wall + tolerance + 2.5, wall + tolerance + 2.5], [wall + tolerance + pcb_w - 2.5, wall + tolerance + 2.5], [wall + tolerance + 2.5, wall + tolerance + pcb_h - 2.5], [wall + tolerance + pcb_w - 2.5, wall + tolerance + pcb_h - 2.5]]) { translate([pos[0], pos[1], wall]) difference() { cylinder(h=post_h, d=post_d, $fn=20); cylinder(h=post_h + 1, d=screw_d, $fn=20); } } } // ============================================ // Lid (snap-fit) // ============================================ module lid() { difference() { union() { // Lid plate rounded_box(outer_w, outer_h, wall, 3); // Inner lip for alignment translate([wall - lid_lip/2, wall - lid_lip/2, wall]) rounded_box(inner_w + lid_lip, inner_h + lid_lip, 2, 2); } // Status LED window (small hole) translate([wall + tolerance + 40, wall + tolerance + 25, -1]) cylinder(h=wall+2, d=2, $fn=16); } } // ============================================ // Helper modules // ============================================ module rounded_box(w, h, d, r) { hull() { translate([r, r, 0]) cylinder(h=d, r=r, $fn=20); translate([w-r, r, 0]) cylinder(h=d, r=r, $fn=20); translate([r, h-r, 0]) cylinder(h=d, r=r, $fn=20); translate([w-r, h-r, 0]) cylinder(h=d, r=r, $fn=20); } } module wall_mount_keyhole() { // Large hole (screw head) cylinder(h=wall+2, d=7, $fn=24); // Slot (slide down to lock) translate([0, -5, 0]) hull() { cylinder(h=wall+2, d=4, $fn=24); translate([0, 5, 0]) cylinder(h=wall+2, d=4, $fn=24); } } // ============================================ // Render // ============================================ // Body body(); // Lid (offset for viewing - move to origin for printing) translate([outer_w + 10, 0, 0]) lid();