diff --git a/chassis/vesc_mount.scad b/chassis/vesc_mount.scad new file mode 100644 index 0000000..676277c --- /dev/null +++ b/chassis/vesc_mount.scad @@ -0,0 +1,296 @@ +// ============================================================ +// vesc_mount.scad — FSESC 6.7 Pro Mini Dual ESC Mount Cradle +// Issue #699 / sl-mechanical 2026-03-17 +// ============================================================ +// Open-top tray for Flipsky FSESC 6.7 Pro Mini Dual (~100 × 68 × 28 mm). +// Attaches to 2020 aluminium T-slot rail via 4× M5 T-nuts +// (2× per rail, two parallel rails, 60 mm bolt spacing in X, +// 20 mm bolt spacing in Y matching 2020 slot pitch). +// +// Connector access: +// XT60 battery inputs — X− end wall cutouts (2 connectors, side-by-side) +// XT30 motor outputs — Y+ and Y− side wall cutouts (2 per side wall) +// CAN/UART terminal — X+ end wall cutout (screw terminal, wire exit) +// +// Ventilation: +// Open top face — heatsink fins fully exposed +// Floor grille slots — under-board airflow +// Side vent louvres — 4 slots on each Y± wall at heatsink height +// +// Retention: 4× M3 heat-set insert boss in floor — board screws down through +// ESC mounting holes via M3×8 FHCS. Board sits on 4 mm raised posts for +// under-board airflow. +// +// ⚠ VERIFY WITH CALIPERS BEFORE PRINTING: +// PCB_L, PCB_W board outline +// XT60_W, XT60_H XT60 shell at X− edge +// XT30_W, XT30_H XT30 shells at Y± edges +// TERM_W, TERM_H CAN screw terminal at X+ edge +// MOUNT_X1/X2, MOUNT_Y1/Y2 ESC board mounting hole pattern +// +// Print settings (PETG): +// 3 perimeters, 40 % gyroid infill, no supports, 0.2 mm layer +// Print orientation: open face UP (as modelled) +// +// BOM: +// 4 × M5×10 BHCS + 4 × M5 slide-in T-nut (2020 rail) +// 4 × M3 heat-set insert (Voron-style, OD 4.5 mm × 4 mm deep) +// 4 × M3×8 FHCS (board retention) +// +// Export commands: +// openscad -D 'RENDER="mount"' -o vesc_mount.stl vesc_mount.scad +// openscad -D 'RENDER="assembly"' -o vesc_assembly.png vesc_mount.scad +// ============================================================ + +RENDER = "assembly"; // mount | assembly + +$fn = 48; +EPS = 0.01; + +// ── ⚠ Verify before printing ───────────────────────────────── +// FSESC 6.7 Pro Mini Dual PCB +PCB_L = 100.0; // board length (X: XT60 end → CAN terminal end) +PCB_W = 68.0; // board width (Y) +PCB_T = 2.0; // board thickness (incl. bottom-side components) +COMP_H = 26.0; // tallest component above board top face (heatsink ~26 mm) + +// XT60 battery connectors at X− end (2 connectors, side-by-side) +XT60_W = 16.0; // each XT60 shell width (Y) +XT60_H = 16.0; // each XT60 shell height (Z) above board surface +XT60_Z0 = 0.0; // connector bottom offset above board surface +// Y centres of each XT60 measured from PCB Y− edge +XT60_Y1 = 16.0; +XT60_Y2 = 52.0; + +// XT30 motor output connectors at Y± sides (2 per side) +XT30_W = 10.5; // each XT30 shell width (X span) +XT30_H = 12.0; // each XT30 shell height (Z) above board surface +XT30_Z0 = 0.5; // connector bottom offset above board surface +// X centres measured from PCB X− edge (same layout both Y− and Y+ sides) +XT30_X1 = 22.0; +XT30_X2 = 78.0; + +// CAN / UART screw terminal block at X+ end (3-pos 3.5 mm pitch) +TERM_W = 14.0; // terminal block Y span +TERM_H = 10.0; // terminal block height above board surface +TERM_Z0 = 0.5; // terminal bottom offset above board surface +TERM_Y_CTR = PCB_W / 2; + +// ── ESC board mounting hole pattern ────────────────────────── +// 4 corner holes, 4 mm inset from each PCB edge +MOUNT_INSET = 4.0; +MOUNT_X1 = MOUNT_INSET; +MOUNT_X2 = PCB_L - MOUNT_INSET; +MOUNT_Y1 = MOUNT_INSET; +MOUNT_Y2 = PCB_W - MOUNT_INSET; + +M3_INSERT_OD = 4.6; // Voron M3 heat-set insert press-fit OD +M3_INSERT_H = 4.0; // insert depth +M3_CLEAR_D = 3.4; // M3 clearance bore below insert + +// ── Cradle geometry ────────────────────────────────────────── +WALL_T = 2.8; // side / end wall thickness +FLOOR_T = 4.5; // floor plate thickness (fits M5 BHCS head pocket) +POST_H = 4.0; // standoff post height (board lifts off floor for airflow) +CL_SIDE = 0.35; // Y clearance per side +CL_END = 0.40; // X clearance per end + +INN_W = PCB_W + 2*CL_SIDE; +INN_L = PCB_L + 2*CL_END; +INN_H = POST_H + PCB_T + COMP_H + 1.5; + +OTR_W = INN_W + 2*WALL_T; +OTR_L = INN_L + 2*WALL_T; +OTR_H = FLOOR_T + INN_H; + +PCB_X0 = WALL_T + CL_END; +PCB_Y0 = WALL_T + CL_SIDE; +PCB_Z0 = FLOOR_T + POST_H; + +// ── M5 T-nut mount (2020 rail) ──────────────────────────────── +// 4 bolts: 2 columns (X) × 2 rows (Y), centred on body +M5_D = 5.3; +M5_HEAD_D = 9.5; +M5_HEAD_H = 3.0; +M5_SPAC_X = 60.0; // X bolt spacing +M5_SPAC_Y = 20.0; // Y bolt spacing (2020 T-slot pitch) + +// ── Floor ventilation grille ────────────────────────────────── +GRILLE_SLOT_W = 4.0; +GRILLE_SLOT_T = FLOOR_T - 1.5; +GRILLE_PITCH = 10.0; +GRILLE_X0 = WALL_T + 14; +GRILLE_X_LEN = OTR_L - 2*WALL_T - 28; +GRILLE_N = floor((INN_W - 10) / GRILLE_PITCH); + +// ── Side vent louvres on Y± walls ──────────────────────────── +LOUV_H = 5.0; +LOUV_W = 12.0; +LOUV_Z = FLOOR_T + POST_H + PCB_T + 4.0; // mid-heatsink height +LOUV_N = 4; +LOUV_PITCH = (OTR_L - 2*WALL_T - 20) / max(LOUV_N - 1, 1); + +// ── CAN wire strain relief bosses (X+ end) ─────────────────── +SR_BOSS_OD = 7.0; +SR_BOSS_H = 6.0; +SR_SLOT_W = 3.5; +SR_SLOT_T = 2.2; +SR_Y1 = WALL_T + INN_W * 0.25; +SR_Y2 = WALL_T + INN_W * 0.75; +SR_X = OTR_L - WALL_T - SR_BOSS_OD/2 - 2.5; + +// ───────────────────────────────────────────────────────────── +module m3_insert_boss() { + // Solid post with heat-set insert bore from top + post_h = FLOOR_T + POST_H; + difference() { + cylinder(d = M3_INSERT_OD + 3.2, h = post_h); + // Insert bore from top + translate([0, 0, post_h - M3_INSERT_H]) + cylinder(d = M3_INSERT_OD, h = M3_INSERT_H + EPS); + // Clearance bore from bottom + translate([0, 0, -EPS]) + cylinder(d = M3_CLEAR_D, h = post_h - M3_INSERT_H + EPS); + } +} + +module vesc_mount() { + difference() { + union() { + // Main body + cube([OTR_L, OTR_W, OTR_H]); + + // M3 insert bosses at board mounting corners + for (mx = [MOUNT_X1, MOUNT_X2]) + for (my = [MOUNT_Y1, MOUNT_Y2]) + translate([PCB_X0 + mx, PCB_Y0 + my, 0]) + m3_insert_boss(); + + // CAN strain relief bosses on X+ end + for (sy = [SR_Y1, SR_Y2]) + translate([SR_X, sy, 0]) + cylinder(d = SR_BOSS_OD, h = SR_BOSS_H); + } + + // ── Interior cavity (open top) ───────────────────────── + translate([WALL_T, WALL_T, FLOOR_T]) + cube([INN_L, INN_W, INN_H + EPS]); + + // ── XT60 cutouts at X− end (2 connectors) ────────────── + for (yc = [XT60_Y1, XT60_Y2]) + translate([-EPS, + PCB_Y0 + yc - (XT60_W + 2.0)/2, + PCB_Z0 + XT60_Z0 - 0.5]) + cube([WALL_T + 2*EPS, XT60_W + 2.0, XT60_H + 3.0]); + + // ── XT30 cutouts at Y− side (2 connectors) ───────────── + for (xc = [XT30_X1, XT30_X2]) + translate([PCB_X0 + xc - (XT30_W + 2.0)/2, + -EPS, + PCB_Z0 + XT30_Z0 - 0.5]) + cube([XT30_W + 2.0, WALL_T + 2*EPS, XT30_H + 3.0]); + + // ── XT30 cutouts at Y+ side (2 connectors) ───────────── + for (xc = [XT30_X1, XT30_X2]) + translate([PCB_X0 + xc - (XT30_W + 2.0)/2, + OTR_W - WALL_T - EPS, + PCB_Z0 + XT30_Z0 - 0.5]) + cube([XT30_W + 2.0, WALL_T + 2*EPS, XT30_H + 3.0]); + + // ── CAN terminal cutout at X+ end ────────────────────── + translate([OTR_L - WALL_T - EPS, + PCB_Y0 + TERM_Y_CTR - (TERM_W + 3.0)/2, + PCB_Z0 + TERM_Z0 - 0.5]) + cube([WALL_T + 2*EPS, TERM_W + 3.0, TERM_H + 5.0]); + + // ── Floor ventilation grille ─────────────────────────── + for (i = [0 : GRILLE_N - 1]) { + sy = WALL_T + 5 + i * GRILLE_PITCH; + translate([GRILLE_X0, sy, -EPS]) + cube([GRILLE_X_LEN, GRILLE_SLOT_W, GRILLE_SLOT_T + EPS]); + } + + // ── Side vent louvres — Y− wall ──────────────────────── + for (i = [0 : LOUV_N - 1]) { + lx = WALL_T + 10 + i * LOUV_PITCH; + translate([lx, -EPS, LOUV_Z]) + cube([LOUV_W, WALL_T + 2*EPS, LOUV_H]); + } + + // ── Side vent louvres — Y+ wall ──────────────────────── + for (i = [0 : LOUV_N - 1]) { + lx = WALL_T + 10 + i * LOUV_PITCH; + translate([lx, OTR_W - WALL_T - EPS, LOUV_Z]) + cube([LOUV_W, WALL_T + 2*EPS, LOUV_H]); + } + + // ── M5 BHCS head pockets (4 bolts, bottom face) ──────── + for (mx = [OTR_L/2 - M5_SPAC_X/2, OTR_L/2 + M5_SPAC_X/2]) + for (my = [OTR_W/2 - M5_SPAC_Y/2, OTR_W/2 + M5_SPAC_Y/2]) + translate([mx, my, -EPS]) { + cylinder(d = M5_D, h = FLOOR_T + 2*EPS); + cylinder(d = M5_HEAD_D, h = M5_HEAD_H + EPS); + } + + // ── Zip-tie slots through CAN strain relief bosses ───── + for (sy = [SR_Y1, SR_Y2]) + translate([SR_X, sy, SR_BOSS_H/2 - SR_SLOT_T/2]) + rotate([0, 90, 0]) + cube([SR_SLOT_T, SR_SLOT_W, SR_BOSS_OD + 2*EPS], + center = true); + + // ── Weight-relief pocket in floor underside ───────────── + translate([WALL_T + 16, WALL_T + 6, -EPS]) + cube([OTR_L - 2*WALL_T - 32, OTR_W - 2*WALL_T - 12, + FLOOR_T - 2.0 + EPS]); + } +} + +// ── Assembly preview ───────────────────────────────────────── +if (RENDER == "assembly") { + color("DimGray", 0.93) vesc_mount(); + + // Phantom PCB + color("ForestGreen", 0.30) + translate([PCB_X0, PCB_Y0, PCB_Z0]) + cube([PCB_L, PCB_W, PCB_T]); + + // Phantom heatsink / component block + color("SlateGray", 0.22) + translate([PCB_X0, PCB_Y0, PCB_Z0 + PCB_T]) + cube([PCB_L, PCB_W, COMP_H]); + + // XT60 connector highlights (X− end) + for (yc = [XT60_Y1, XT60_Y2]) + color("Gold", 0.85) + translate([-2, + PCB_Y0 + yc - XT60_W/2, + PCB_Z0 + XT60_Z0]) + cube([WALL_T + 3, XT60_W, XT60_H]); + + // XT30 connector highlights — Y− side + for (xc = [XT30_X1, XT30_X2]) + color("OrangeRed", 0.80) + translate([PCB_X0 + xc - XT30_W/2, + -2, + PCB_Z0 + XT30_Z0]) + cube([XT30_W, WALL_T + 3, XT30_H]); + + // XT30 connector highlights — Y+ side + for (xc = [XT30_X1, XT30_X2]) + color("OrangeRed", 0.80) + translate([PCB_X0 + xc - XT30_W/2, + OTR_W - WALL_T - 1, + PCB_Z0 + XT30_Z0]) + cube([XT30_W, WALL_T + 3, XT30_H]); + + // CAN terminal highlight + color("Tomato", 0.75) + translate([OTR_L - WALL_T - 1, + PCB_Y0 + TERM_Y_CTR - TERM_W/2, + PCB_Z0 + TERM_Z0]) + cube([WALL_T + 3, TERM_W, TERM_H]); + +} else { + vesc_mount(); +}