// RemoteRig — GoPro Hero 3 + ESP32 Camera Case // ============================================== // Sleeve that wraps around GoPro Hero 3 body with ESP32 + LiPo compartment. // Designed for: ESP32 D1 Mini, 1000mAh LiPo, GoPro Hero 3 Black/Silver. // // Print settings: // Material: PETG (outdoor/heat) or PLA+ (indoor) // Layer: 0.2mm | Infill: 20% gyroid | Supports: yes (for cable channels) // Nozzle: 0.4mm | Bed: 60°C (PLA) / 80°C (PETG) // ── GoPro Hero 3 Body (approximate) ── gopro_width = 60; // mm — body width gopro_height = 42; // mm — body height (top to bottom) gopro_depth = 30; // mm — body depth (front to back) gopro_lens_dia = 28; // mm — lens protrusion diameter gopro_lens_offset = 18; // mm — lens center from top // ── ESP8266 D1 Mini + ESP32 Dev Board (stacked) ── esp8266_width = 34.2; esp8266_height = 25.6; esp8266_thick = 5; // board + components esp32_width = 52; // ESP32 Dev Board is larger esp32_height = 28; esp32_thick = 5; // Combined stack board_width = max(esp8266_width, esp32_width); board_height = max(esp8266_height, esp32_height); board_thick = esp8266_thick + esp32_thick + 3; // 3mm gap between boards // ── LiPo Battery (1000mAh typical) ── lipo_width = 35; lipo_height = 25; lipo_thick = 8; // ── Case parameters ── wall = 2.0; // case wall thickness tolerance = 0.3; // print tolerance for friction fit compartment_height = board_thick + 5; // internal compartment height for stacked boards // ── Cable channels ── cable_dia = 4; // USB cable diameter cable_channel_depth = 3; // ══════════════════════════════════════════════════════════════ // MAIN ASSEMBLY // ══════════════════════════════════════════════════════════════ // Uncomment the part you want to export: gopro_sleeve(); // translate([0, -20, 0]) electronics_compartment(); // translate([0, 20, 0]) battery_compartment(); // ══════════════════════════════════════════════════════════════ // GoPro Sleeve — wraps around the GoPro body // ══════════════════════════════════════════════════════════════ module gopro_sleeve() { union() { // Main sleeve body — wraps around GoPro difference() { // Outer shell rounded_cube( gopro_width + wall*2, gopro_height + wall*2, gopro_depth + wall*2, 4 // corner radius ); // Inner cavity (GoPro body) translate([0, 0, wall]) rounded_cube( gopro_width + tolerance, gopro_height + tolerance, gopro_depth + tolerance, 3 ); // Lens cutout (front face) translate([0, gopro_height/2 - gopro_lens_offset, 0]) rotate([90, 0, 0]) cylinder(d=gopro_lens_dia + 4, h=wall*3, center=true); // Front screen/viewfinder cutout translate([0, gopro_height/2 - gopro_lens_offset - 18, wall*2]) cube([gopro_width - 10, gopro_height - 20, wall*4], center=true); // Bottom cutout (for GoPro mounting fingers) translate([0, 0, gopro_depth/2 + wall]) cube([gopro_width - 10, wall*4, wall*4], center=true); // USB port access (side) translate([gopro_width/2 + wall, 0, -5]) cube([wall*4, 16, 10], center=true); // Cable channel from ESP32 compartment to GoPro USB translate([gopro_width/2 - 5, -gopro_height/2 + 10, -gopro_depth/2 + 5]) rotate([0, 90, 0]) cylinder(d=cable_dia, h=wall*3, center=true); } // Mounting ears for electronics compartment for (x = [-1, 1]) { translate([x * (gopro_width/2 - 6), -gopro_height/2 - 6, 0]) rotate([90, 0, 0]) cylinder(d=8, h=10); } } } // ══════════════════════════════════════════════════════════════ // Electronics Compartment — holds ESP8266 + ESP32 stacked // ══════════════════════════════════════════════════════════════ module electronics_compartment() { comp_w = board_width + wall*2 + 8; comp_h = compartment_height + wall*2; comp_d = board_height + wall*2 + 8; difference() { union() { // Main box rounded_cube(comp_w, comp_d, comp_h, 3); // Mounting tabs (match GoPro sleeve ears) for (x = [-1, 1]) { translate([x * (gopro_width/2 - 6), 0, comp_h/2]) rotate([0, 90, 0]) cylinder(d=6, h=4, center=true); } } // Inner cavity translate([0, 0, wall]) rounded_cube(comp_w - wall*2, comp_d - wall*2, comp_h - wall, 2); // Bottom board (ESP32 — larger) recess translate([0, 5, wall + 1]) cube([esp32_width + tolerance, esp32_height + tolerance, esp32_thick + 1], center=true); // Top board (ESP8266 — smaller) recess translate([0, 5, wall + esp32_thick + 4]) cube([esp8266_width + tolerance, esp8266_height + tolerance, esp8266_thick + 1], center=true); // UART wire channel (between boards) translate([comp_w/2, 0, wall + esp32_thick + 1]) cube([wall*3, 6, 3], center=true); // USB cable entry (power to boards) translate([comp_w/2, 15, comp_h/2]) rotate([0, 90, 0]) cylinder(d=6, h=wall*3, center=true); // USB cable exit (to GoPro) translate([comp_w/2, -15, comp_h/2]) rotate([0, 90, 0]) cylinder(d=cable_dia, h=wall*3, center=true); // Ventilation slots for (y = [-1:2:1]) { for (i = [-15:10:15]) { translate([i, y * comp_d/3, comp_h - 2]) cube([6, 1.5, wall*2], center=true); } } // LED windows (thin walls for ESP LEDs) translate([0, 0, wall]) cube([5, 5, wall], center=true); translate([0, 0, wall + esp32_thick + 4]) cube([5, 5, wall], center=true); } } // ══════════════════════════════════════════════════════════════ // Battery Compartment — holds LiPo under GoPro // ══════════════════════════════════════════════════════════════ module battery_compartment() { bat_w = lipo_width + wall*2 + tolerance; bat_d = lipo_height + wall*2 + tolerance; bat_h = lipo_thick + wall*2 + 4; difference() { // Shell rounded_cube(bat_w, bat_d, bat_h, 3); // Battery cavity translate([0, 0, wall]) rounded_cube(lipo_width + tolerance, lipo_height + tolerance, lipo_thick + tolerance, 1); // Cable exit (to ESP32 compartment) translate([0, bat_d/2, bat_h/2]) rotate([90, 0, 0]) cylinder(d=cable_dia, h=wall*3, center=true); // Cable exit (to GoPro USB) translate([bat_w/3, -bat_d/2, bat_h/2]) rotate([90, 0, 0]) cylinder(d=cable_dia, h=wall*3, center=true); // Strap slots (velcro strap to secure to GoPro) for (x = [-bat_w/3, bat_w/3]) { translate([x, -bat_d/2, bat_h/2]) cube([8, wall*4, 3], center=true); } } } // ══════════════════════════════════════════════════════════════ // Utility: Rounded cube (positive X/Y/Z = full dimensions) // ══════════════════════════════════════════════════════════════ module rounded_cube(w, d, h, r) { hull() { for (x = [-1, 1], y = [-1, 1], z = [-1, 1]) { translate([x * (w/2 - r), y * (d/2 - r), z * (h/2 - r)]) sphere(r=r, $fn=20); } } }