Files

206 lines
8.1 KiB
OpenSCAD
Raw Permalink Normal View History

// 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
// ── ESP32 D1 Mini ──
esp_width = 34.2;
esp_height = 25.6;
esp_thick = 5; // board + components
usb_cutout_w = 10;
usb_cutout_h = 5;
// ── 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 = max(esp_thick, lipo_thick) + 3; // internal compartment height
// ── 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 ESP32 + routes cables
// ══════════════════════════════════════════════════════════════
module electronics_compartment() {
comp_w = max(esp_width, esp_height) + wall*2 + 10;
comp_h = compartment_height + wall*2;
comp_d = gopro_depth + wall*2;
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);
// ESP32 board recess
translate([0, 5, wall + 1])
cube([esp_width + tolerance, esp_height + tolerance, esp_thick + 1], center=true);
// USB cable entry (side hole)
translate([comp_w/2, 15, comp_h/2])
rotate([0, 90, 0])
cylinder(d=usb_cutout_w, 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 window (thin wall for ESP32 LED visibility)
translate([0, 0, wall])
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);
}
}
}