Add parametric OpenSCAD designs for the SaltyRover stable 4-wheel variant. Reuses existing 25mm stem, sensor head, and all SaltyLab sensor mounts without modification. Files: - saltyrover_chassis.scad 480×500mm deck, stem collar, FC+Orin standoffs, motor attachment holes, battery tray opening; RENDER deck_2d for waterjet/CNC DXF - rover_motor_mount.scad L-bracket + axle clamp plate per motor; uses caliper-verified axle dims from BOM.md; dropout slot for tool-free motor swap; RENDER bracket_2d for CNC DXF - rover_battery_tray.scad Slide-out tray for 2-4 × 420×88×56mm packs laid flat (low CG); T-slot rails, spring latch - rover_stem_adapter.scad Flange + split clamp locks 25mm stem to deck collar; 550mm stem option for rover height - rover_BOM.md Assembly sequence, fastener table, mass estimate (~13.4kg), height stack diagram Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
241 lines
9.8 KiB
OpenSCAD
241 lines
9.8 KiB
OpenSCAD
// ============================================================
|
||
// rover_motor_mount.scad — SaltyRover Drive Motor Brackets
|
||
// Rev A 2026-03-01 sl-mechanical
|
||
// ============================================================
|
||
// L-bracket that bolts to the deck edge and positions the drive
|
||
// motor axle at the correct height. Print or CNC 4×.
|
||
//
|
||
// Default values from BOM.md (caliper-verified hoverboard motor):
|
||
// Axle base OD: 16.11 mm
|
||
// D-cut OD: 15.95 mm (flat chord 13.00 mm)
|
||
// Bearing seat OD: 37.80 mm
|
||
// Axle CL above gnd: 127 mm
|
||
// Tire OD: 254 mm (10×2.125")
|
||
//
|
||
// Bracket geometry (all dims in mm):
|
||
// Vertical flange — bolts to deck edge (2× M5 SHCS)
|
||
// Horizontal arm — extends BRKT_REACH beyond deck edge
|
||
// to position axle CL at TRACK_W/2
|
||
// Axle channel — open-bottom dropout slot for easy
|
||
// motor install/removal; retained by
|
||
// a separate clamping plate (×1 per bracket)
|
||
// Bearing recess — 37.8 mm recess on inboard face
|
||
//
|
||
// ⚠ VERIFY before printing / CNC:
|
||
// AXLE_D, AXLE_FLAT, BEARING_OD from caliper measurement.
|
||
// DECK_BOT_H = GND_CLR + BATT_FLOOR_T + BATT_PACK_H.
|
||
// Adjust BRKT_REACH so TRACK_W matches chassis layout.
|
||
//
|
||
// Print orientation: flange face flat on bed.
|
||
// Material: PETG or PC, 5 perims, 60% infill.
|
||
// Alternative: CNC-routed 10mm 6061-T6 aluminium plate.
|
||
//
|
||
// RENDER options:
|
||
// "assembly" bracket + clamp plate + phantom motor axle
|
||
// "bracket" main L-bracket for printing/CNC
|
||
// "clamp_plate" axle retention clamp plate (print 4×)
|
||
// "bracket_2d" bracket floor projection → DXF
|
||
// ============================================================
|
||
|
||
RENDER = "assembly";
|
||
|
||
// ── Axle / motor (BOM.md caliper-verified) ────────────────
|
||
AXLE_D = 16.11; // axle base section OD (round)
|
||
AXLE_FLAT = 13.00; // D-cut flat chord width
|
||
AXLE_D_DCUT = 15.95; // D-cut section OD
|
||
BEARING_OD = 37.80; // bearing seat collar OD
|
||
BEARING_D = BEARING_OD + 1.0; // bore clearance for bearing seat
|
||
BEARING_H = 8.0; // bearing recess depth on inboard face
|
||
|
||
AXLE_H = 127.0; // axle CL above ground
|
||
TIRE_OD = 254.0; // 10×2.125" tire outer diameter
|
||
|
||
// Dropout slot dims
|
||
DROP_W = AXLE_D + 2.0; // slot width (axle + 1 mm each side)
|
||
DROP_D = AXLE_H; // slot depth from bracket bottom (full height)
|
||
|
||
// ── Bracket geometry ─────────────────────────────────────
|
||
// Deck geometry (must match saltyrover_chassis.scad)
|
||
GND_CLR = 50.0;
|
||
BATT_FLOOR_T = 3.0;
|
||
BATT_PACK_H = 56.0;
|
||
DECK_T = 8.0;
|
||
DECK_BOT_H = GND_CLR + BATT_FLOOR_T + BATT_PACK_H; // 109 mm
|
||
DECK_TOP_H = DECK_BOT_H + DECK_T; // 117 mm
|
||
|
||
// Axle height relative to deck top:
|
||
AXLE_ABOVE_DECK = AXLE_H - DECK_TOP_H; // ~10 mm
|
||
|
||
// Bracket reach beyond deck edge to motor axle CL
|
||
BRKT_REACH = 40.0; // motor CL is BRKT_REACH mm outside deck edge
|
||
// (TRACK_W/2 - ROVER_W/2 = 270 - 240 = 30 mm +
|
||
// bearing housing clearance margin = 40 mm)
|
||
|
||
// Bracket plate dimensions
|
||
BRKT_T = 10.0; // bracket plate thickness
|
||
BRKT_H_ABOVE = AXLE_ABOVE_DECK + BEARING_OD/2 + 8.0; // above deck top
|
||
BRKT_H_BELOW = DECK_T + 12.0; // below deck bottom
|
||
BRKT_TOTAL_H = BRKT_H_ABOVE + BRKT_H_BELOW; // full height
|
||
|
||
// Width of bracket arm (fore-aft direction)
|
||
BRKT_W = 60.0; // covers motor fore-aft attachment bolts
|
||
|
||
// Flange for deck attachment
|
||
FLANGE_T = 8.0; // flange plate thickness
|
||
FLANGE_DEPTH = 20.0; // how deep flange sits on deck face (Y direction)
|
||
|
||
// M5 bolt holes: 2× through flange (deck attachment)
|
||
M5_D = 5.3;
|
||
MOT_BOLT_SPC = 30.0; // matches saltyrover_chassis.scad MOT_BOLT_SPC
|
||
|
||
// Clamping plate (retains axle in dropout slot)
|
||
CLAMP_T = 6.0; // clamp plate thickness
|
||
CLAMP_W = DROP_W + 12.0;
|
||
CLAMP_H = BEARING_D + 12.0;
|
||
CLAMP_BOLT_D= 4.3; // M4 clearance
|
||
CLAMP_BOLT_SPC = CLAMP_W - 10.0;
|
||
|
||
// Gusset (triangular fillet between flange and arm)
|
||
GUSSET_T = 8.0;
|
||
|
||
$fn = 64;
|
||
e = 0.01;
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// motor_bracket()
|
||
// Main L-bracket. Coordinate: Z=0 at deck top.
|
||
// Bracket outboard face at X=0 (deck edge).
|
||
// Bracket arm extends +X toward motor.
|
||
// ─────────────────────────────────────────────────────────
|
||
module motor_bracket() {
|
||
axle_z = AXLE_ABOVE_DECK; // axle CL in bracket coords
|
||
|
||
difference() {
|
||
union() {
|
||
// ── Vertical arm (extends +X from deck edge) ──
|
||
translate([0, -BRKT_W/2, -BRKT_H_BELOW])
|
||
cube([BRKT_REACH + BRKT_T, BRKT_W, BRKT_TOTAL_H]);
|
||
|
||
// ── Vertical flange (sits against deck edge, -X side) ──
|
||
translate([-FLANGE_DEPTH, -BRKT_W/2, -BRKT_H_BELOW])
|
||
cube([FLANGE_DEPTH, BRKT_W, BRKT_TOTAL_H]);
|
||
|
||
// ── Gusset (arm to flange transition) ──
|
||
translate([0, -BRKT_W/2, axle_z - GUSSET_T/2])
|
||
linear_extrude(GUSSET_T)
|
||
polygon([
|
||
[0, 0],
|
||
[BRKT_REACH/2, 0],
|
||
[0, BRKT_W]
|
||
]);
|
||
}
|
||
|
||
// ── Axle dropout slot (open at bottom, centered on arm tip) ──
|
||
translate([BRKT_REACH, -DROP_W/2, -BRKT_H_BELOW - e])
|
||
cube([BRKT_T + e, DROP_W, AXLE_H + 2*e]);
|
||
|
||
// ── Axle round bore at slot top ──
|
||
translate([BRKT_REACH, 0, axle_z])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=AXLE_D + 1.0, h=BRKT_T + 2*e);
|
||
|
||
// ── D-cut anti-rotation flat (matches axle flat chord) ──
|
||
translate([BRKT_REACH - e, -AXLE_FLAT/2, axle_z - AXLE_D/2 - e])
|
||
cube([BRKT_T + 2*e, AXLE_FLAT, AXLE_D/2 + e]);
|
||
|
||
// ── Bearing seat recess (inboard face, X=BRKT_T) ──
|
||
translate([BRKT_REACH + BRKT_T - BEARING_H, 0, axle_z])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=BEARING_D, h=BEARING_H + e);
|
||
|
||
// ── Clamping plate bolt holes (×2, retain axle) ──
|
||
for (dz=[-CLAMP_BOLT_SPC/2, CLAMP_BOLT_SPC/2])
|
||
translate([BRKT_REACH - e, 0, axle_z + dz])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=CLAMP_BOLT_D, h=BRKT_T + 2*e);
|
||
|
||
// ── Deck attachment holes through flange (M5 × 2) ──
|
||
for (bz=[-MOT_BOLT_SPC/2, MOT_BOLT_SPC/2])
|
||
translate([-FLANGE_DEPTH - e, 0, bz])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=M5_D, h=FLANGE_DEPTH + 2*e);
|
||
|
||
// ── Lightening pocket on arm (inboard face) ──
|
||
translate([BRKT_T, -BRKT_W/2 + 8, -BRKT_H_BELOW/2])
|
||
cube([BRKT_REACH - BRKT_T - 8,
|
||
BRKT_W - 16,
|
||
BRKT_H_BELOW/2 - 4]);
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// axle_clamp_plate()
|
||
// Bolts to bracket outboard face to close dropout slot.
|
||
// Print flat face down. 1× per bracket.
|
||
// ─────────────────────────────────────────────────────────
|
||
module axle_clamp_plate() {
|
||
axle_z = AXLE_ABOVE_DECK;
|
||
|
||
difference() {
|
||
translate([-CLAMP_W/2, 0, axle_z - CLAMP_H/2])
|
||
cube([CLAMP_W, CLAMP_T, CLAMP_H]);
|
||
|
||
// Axle bore
|
||
translate([0, -e, axle_z])
|
||
rotate([-90, 0, 0])
|
||
cylinder(d=AXLE_D + 0.5, h=CLAMP_T + 2*e);
|
||
|
||
// Bearing seat relief
|
||
translate([0, CLAMP_T - BEARING_H + e, axle_z])
|
||
rotate([-90, 0, 0])
|
||
cylinder(d=BEARING_D, h=BEARING_H + e);
|
||
|
||
// M4 bolt holes (×2)
|
||
for (dz=[-CLAMP_BOLT_SPC/2, CLAMP_BOLT_SPC/2])
|
||
translate([0, -e, axle_z + dz])
|
||
rotate([-90, 0, 0])
|
||
cylinder(d=CLAMP_BOLT_D, h=CLAMP_T + 2*e);
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// Render selector
|
||
// ─────────────────────────────────────────────────────────
|
||
if (RENDER == "assembly") {
|
||
color("DimGray", 0.90) motor_bracket();
|
||
color("SteelBlue", 0.85)
|
||
translate([BRKT_REACH + BRKT_T, 0, 0])
|
||
axle_clamp_plate();
|
||
|
||
// Phantom axle stub
|
||
color("Silver", 0.4)
|
||
translate([BRKT_REACH, 0, AXLE_ABOVE_DECK])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=AXLE_D, h=80);
|
||
|
||
// Phantom tire (semi-transparent outline)
|
||
color("Black", 0.12)
|
||
translate([BRKT_REACH + 40, 0, AXLE_ABOVE_DECK])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=TIRE_OD, h=54);
|
||
|
||
// Reference deck edge
|
||
color("Gold", 0.25)
|
||
translate([-FLANGE_DEPTH - 20, -BRKT_W/2, -BRKT_H_BELOW])
|
||
cube([20, BRKT_W, BRKT_TOTAL_H]);
|
||
|
||
} else if (RENDER == "bracket") {
|
||
motor_bracket();
|
||
|
||
} else if (RENDER == "clamp_plate") {
|
||
// Orient for printing: lay flat, rotate upright
|
||
translate([0, CLAMP_T, -AXLE_ABOVE_DECK])
|
||
rotate([90, 0, 0])
|
||
axle_clamp_plate();
|
||
|
||
} else if (RENDER == "bracket_2d") {
|
||
projection(cut=true)
|
||
translate([0, 0, -BRKT_H_BELOW - BRKT_T/2])
|
||
motor_bracket();
|
||
}
|