Both chassis files corrected. Previous dimensions were wrong: prototype_baseplate.scad: was 680x130mm → now 270x240mm chassis_frame.scad: was 640x220mm → now 270x240mm Geometry recalculated for 270x240mm envelope: PLATE_W = 270mm (axle direction) PLATE_D = 240mm (front-to-rear) PLATE_X_HALF = 135mm (plate edge / axle entry) FORK_SLOT_D = 50mm → AXLE_X = 85mm from plate centre Axle-to-axle = 170mm (2 × 85mm) Wheels extend beyond plate edges as expected: Tire at X = ±(85 ± 27) = ±58–112mm, plate edge at ±135mm ✓ Mount positions recalculated for smaller plate: Dropout clamp bolt holes: X = ±(85±22) = ±63 and ±107mm ✓ (all within ±135mm) Stem flange bolts: r=33mm BC, at (±33,0) and (0,±33) ✓ FC mount: X = -40mm offset, holes at ±15mm ✓ Wiring slots: Y = ±55mm (clear of stem flange bolts at ±33mm) Lightening ovals: Y = ±80mm in open front/rear corridors Bumper length: 300mm (was 660mm, now PLATE_D + 60) Longitudinal ribs: 270mm long (was 600mm) chassis_frame.scad also updated: AXLE_HEIGHT corrected: 310mm → 127mm (TIRE_OD/2) Axle dimensions: 14mm → 16.11mm, flat 10mm → 13.00mm AXLE_X for fork bracket positioning Motor fork bracket logic cleaned up (no more negative cube dimensions) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
340 lines
14 KiB
OpenSCAD
340 lines
14 KiB
OpenSCAD
// =============================================================================
|
||
// SaltyBot — Full Chassis Frame (Rev B — correct 270 × 240 mm envelope)
|
||
// Agent: sl-mechanical | 2026-02-28 | Fixes issue #18
|
||
//
|
||
// Parametric OpenSCAD model. Plate geometry corrected per issue #18:
|
||
// Width (axle direction, X): 270 mm ← was wrong 640 mm
|
||
// Depth (front-to-rear, Y): 240 mm ← was wrong 220 mm
|
||
// Wheels extend beyond plate edges — expected.
|
||
//
|
||
// Motor axle dimensions updated to caliper-verified values (see PR #7 / #11).
|
||
//
|
||
// NOTE: For the prototype, use prototype_baseplate.scad + stem_battery_clamp.scad.
|
||
// This file models the full machined chassis for production reference.
|
||
// =============================================================================
|
||
|
||
$fn = 64;
|
||
|
||
// =============================================================================
|
||
// PLATE DIMENSIONS ← primary parameters fixed for issue #18
|
||
// =============================================================================
|
||
|
||
PLATE_W = 270.0; // mm width (axle / left-right direction)
|
||
PLATE_D = 240.0; // mm depth (front-to-rear)
|
||
DECK_THICK = 6.0; // mm deck plate thickness
|
||
WALL_T = 4.0; // mm general wall / rib thickness
|
||
|
||
// Fork slot geometry — slot opens at plate edge, axle seats at bottom
|
||
FORK_SLOT_D = 50.0; // mm fork slot depth (inward from plate edge)
|
||
PLATE_X_HALF = PLATE_W / 2; // 135 mm — plate half-width / edge
|
||
AXLE_X = PLATE_X_HALF - FORK_SLOT_D; // 85 mm — axle C/L from plate centre
|
||
|
||
// =============================================================================
|
||
// HUB MOTOR — VERIFIED AXLE DIMENSIONS (caliper)
|
||
// =============================================================================
|
||
|
||
AXLE_BASE_DIA = 16.11; // mm round section near hub
|
||
AXLE_BASE_LEN = 15.00;
|
||
AXLE_DCUT_DIA = 15.95; // mm D-cut round OD
|
||
AXLE_DCUT_FLAT = 13.00; // mm flat chord
|
||
AXLE_DCUT_LEN = 43.35;
|
||
AXLE_TOTAL = 65.50; // mm protrusion from hub face
|
||
BEARING_SEAT_OD = 37.80; // mm hub centre collar OD
|
||
TIRE_OD = 254.0; // mm 10 × 2.125" pneumatic
|
||
TIRE_WIDTH = 54.0; // mm
|
||
|
||
AXLE_HEIGHT = TIRE_OD / 2; // 127 mm — axle C/L above ground
|
||
|
||
// Fork slot width (base section + clearance)
|
||
FORK_SLOT_W = AXLE_BASE_DIA + 0.4; // 16.51 mm
|
||
|
||
// Vertical motor fork bracket
|
||
FORK_BKT_H = 100.0; // mm bracket height below deck to axle level
|
||
FORK_BKT_T = 8.0; // mm bracket plate thickness
|
||
FORK_BKT_W = 28.0; // mm bracket width (Y)
|
||
|
||
// =============================================================================
|
||
// FC MOUNT — MAMBA F722S 30.5 × 30.5 mm M3
|
||
// =============================================================================
|
||
|
||
FC_PITCH = 30.5;
|
||
FC_HOLE_D = 3.2;
|
||
FC_STANDOFF = 6.0;
|
||
FC_X = -40.0; // mm from plate centre (front of plate)
|
||
|
||
// =============================================================================
|
||
// BATTERY TRAY (legacy flat — superseded by stem carousel architecture)
|
||
// =============================================================================
|
||
|
||
BATT_L = 185.0;
|
||
BATT_W = 72.0;
|
||
BATT_H = 52.0;
|
||
BATT_WALL = 3.0;
|
||
BATT_FLOOR = 4.0;
|
||
|
||
// =============================================================================
|
||
// JETSON NANO B01 MOUNT
|
||
// =============================================================================
|
||
|
||
JETSON_PITCH = 58.0;
|
||
JETSON_HOLE_D = 3.2;
|
||
JETSON_PL = 100.0;
|
||
JETSON_PW = 86.0;
|
||
JETSON_PT = 4.0;
|
||
JETSON_STOFF = 8.0;
|
||
JETSON_X = 50.0; // mm from plate centre (rear)
|
||
|
||
// =============================================================================
|
||
// BUMPER BRACKETS
|
||
// =============================================================================
|
||
|
||
BUMPER_L = PLATE_D + 60; // 300 mm — spans plate depth + 30 mm each end
|
||
BUMPER_H = 40.0;
|
||
BUMPER_T = 5.0;
|
||
BUMPER_TUBE_OD = 22.0; // 3/4" EMT
|
||
|
||
// =============================================================================
|
||
// LONGITUDINAL RIBS
|
||
// =============================================================================
|
||
|
||
RIB_T = 4.0;
|
||
RIB_H = 40.0;
|
||
|
||
// =============================================================================
|
||
// FASTENERS
|
||
// =============================================================================
|
||
|
||
M3 = 3.2; M4 = 4.3; M5 = 5.3;
|
||
|
||
// =============================================================================
|
||
// ASSEMBLY
|
||
// =============================================================================
|
||
|
||
color("Silver", 0.90) main_deck();
|
||
color("DimGray", 1.00) motor_fork_bracket(side= 1);
|
||
color("DimGray", 1.00) motor_fork_bracket(side=-1);
|
||
color("SteelBlue", 1.00) battery_tray();
|
||
color("OliveDrab", 1.00) fc_mount_plate();
|
||
color("DarkOrange", 1.00) jetson_mount_plate();
|
||
color("Tomato", 1.00) bumper_bracket(front= 1);
|
||
color("Tomato", 1.00) bumper_bracket(front=-1);
|
||
color("WhiteSmoke", 1.00) longitudinal_ribs();
|
||
|
||
// =============================================================================
|
||
// MAIN DECK (270 × 240 mm)
|
||
// =============================================================================
|
||
|
||
module main_deck() {
|
||
R = 10;
|
||
difference() {
|
||
linear_extrude(DECK_THICK)
|
||
minkowski() {
|
||
square([PLATE_W - 2*R, PLATE_D - 2*R], center=true);
|
||
circle(r=R);
|
||
}
|
||
|
||
// Fork slots (open at ±X plate edges)
|
||
for (side = [-1, 1]) {
|
||
translate([side*(PLATE_X_HALF - FORK_SLOT_D), -FORK_SLOT_W/2, -1])
|
||
cube([FORK_SLOT_D + 1, FORK_SLOT_W, DECK_THICK + 2]);
|
||
translate([side*(PLATE_X_HALF - FORK_SLOT_D), 0, -1])
|
||
cylinder(d=FORK_SLOT_W, h=DECK_THICK + 2);
|
||
}
|
||
|
||
// Bearing seat relief
|
||
for (side = [-1, 1])
|
||
translate([side*(PLATE_X_HALF - BEARING_SEAT_OD/2 - 1),
|
||
-BEARING_SEAT_OD/2, -1])
|
||
cube([BEARING_SEAT_OD/2 + 2, BEARING_SEAT_OD, DECK_THICK + 2]);
|
||
|
||
// Fork bracket bolt holes (M5 × 4 per side)
|
||
for (side = [-1, 1])
|
||
for (dx = [-15, 15])
|
||
for (dy = [-12, 12])
|
||
translate([side * AXLE_X + dx, dy, -1])
|
||
cylinder(d=M5, h=DECK_THICK + 2);
|
||
|
||
// FC mount holes
|
||
fc_holes(z=-1, h=DECK_THICK+2);
|
||
|
||
// Battery tray anchor holes
|
||
for (x = [-BATT_L/2 + 12, BATT_L/2 - 12])
|
||
for (y = [-BATT_W/2 + 10, BATT_W/2 - 10])
|
||
translate([x, y, -1]) cylinder(d=M4, h=DECK_THICK+2);
|
||
|
||
// Lightening ovals (front/rear open zones)
|
||
for (dy = [-80, 80])
|
||
hull() {
|
||
translate([ 25, dy, -1]) cylinder(d=22, h=DECK_THICK+2);
|
||
translate([-25, dy, -1]) cylinder(d=22, h=DECK_THICK+2);
|
||
}
|
||
|
||
// Cable routing slots
|
||
for (dy = [-55, 55])
|
||
hull() {
|
||
translate([ 12, dy, -1]) cylinder(d=12, h=DECK_THICK+2);
|
||
translate([-12, dy, -1]) cylinder(d=12, h=DECK_THICK+2);
|
||
}
|
||
}
|
||
}
|
||
|
||
// =============================================================================
|
||
// LONGITUDINAL RIBS (×2)
|
||
// =============================================================================
|
||
|
||
module longitudinal_ribs() {
|
||
rib_y = PLATE_D/2 - WALL_T - RIB_T/2;
|
||
for (y = [-rib_y, rib_y])
|
||
translate([-PLATE_W/2, y - RIB_T/2, -RIB_H])
|
||
cube([PLATE_W, RIB_T, RIB_H]);
|
||
}
|
||
|
||
// =============================================================================
|
||
// MOTOR FORK BRACKET (vertical, bolts to deck edge at ±PLATE_X_HALF)
|
||
// =============================================================================
|
||
|
||
module motor_fork_bracket(side = 1) {
|
||
translate([side * PLATE_X_HALF, 0, 0]) {
|
||
s = side;
|
||
difference() {
|
||
union() {
|
||
// Main bracket plate (extends below deck)
|
||
translate([s > 0 ? 0 : -FORK_BKT_T,
|
||
-FORK_BKT_W/2, -FORK_BKT_H])
|
||
cube([FORK_BKT_T, FORK_BKT_W, FORK_BKT_H + DECK_THICK]);
|
||
|
||
// Diagonal gussets
|
||
for (gy = [-1, 1])
|
||
translate([s > 0 ? 0 : -FORK_BKT_T,
|
||
gy * FORK_BKT_W/2, -FORK_BKT_H/2])
|
||
linear_extrude(FORK_BKT_T)
|
||
polygon([[0,0],[0, gy*20],[s * -25, 0]]);
|
||
}
|
||
|
||
// Axle dropout slot (open at bracket bottom)
|
||
translate([s > 0 ? -1 : -FORK_BKT_T - 1,
|
||
-AXLE_BASE_DIA/2 - 0.2, -FORK_BKT_H])
|
||
cube([FORK_BKT_T + 2, AXLE_BASE_DIA + 0.4, FORK_SLOT_D + 1]);
|
||
translate([s > 0 ? -1 : -FORK_BKT_T - 1,
|
||
0, -FORK_BKT_H + FORK_SLOT_D])
|
||
rotate([-90, 0, 0])
|
||
cylinder(d=AXLE_BASE_DIA + 0.4,
|
||
h=FORK_BKT_T + 2, center=true);
|
||
|
||
// Deck attachment bolts (M5 × 4)
|
||
for (dy = [-12, 12])
|
||
for (dz = [DECK_THICK * 0.3, DECK_THICK * 0.7])
|
||
translate([s > 0 ? -1 : -FORK_BKT_T - 1, dy, dz])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=M5, h=FORK_BKT_T + 2);
|
||
}
|
||
}
|
||
}
|
||
|
||
// =============================================================================
|
||
// FC MOUNT HELPERS
|
||
// =============================================================================
|
||
|
||
module fc_holes(z=0, h=10) {
|
||
for (x = [FC_X - FC_PITCH/2, FC_X + FC_PITCH/2])
|
||
for (y = [-FC_PITCH/2, FC_PITCH/2])
|
||
translate([x, y, z]) cylinder(d=FC_HOLE_D, h=h);
|
||
}
|
||
|
||
module fc_mount_plate() {
|
||
translate([FC_X, 0, 0]) {
|
||
difference() {
|
||
union() {
|
||
for (x = [-FC_PITCH/2, FC_PITCH/2])
|
||
for (y = [-FC_PITCH/2, FC_PITCH/2])
|
||
translate([x, y, DECK_THICK]) cylinder(d=8, h=FC_STANDOFF);
|
||
translate([-(FC_PITCH/2+8), -(FC_PITCH/2+8), DECK_THICK])
|
||
cube([FC_PITCH+16, FC_PITCH+16, 3]);
|
||
}
|
||
fc_holes(z=DECK_THICK-1, h=FC_STANDOFF+4);
|
||
fc_holes(z=-1, h=DECK_THICK+2);
|
||
}
|
||
}
|
||
}
|
||
|
||
// =============================================================================
|
||
// BATTERY TRAY
|
||
// =============================================================================
|
||
|
||
module battery_tray() {
|
||
z_base = -BATT_FLOOR - BATT_H - 5;
|
||
translate([-BATT_L/2 - BATT_WALL, -BATT_W/2 - BATT_WALL, z_base]) {
|
||
difference() {
|
||
cube([BATT_L+2*BATT_WALL, BATT_W+2*BATT_WALL, BATT_H+BATT_FLOOR]);
|
||
translate([BATT_WALL, BATT_WALL, BATT_FLOOR])
|
||
cube([BATT_L, BATT_W, BATT_H+1]);
|
||
for (x = [BATT_L/2-30, BATT_L/2+8])
|
||
translate([x, -1, BATT_FLOOR+BATT_H/2-10])
|
||
cube([20, BATT_W+2*BATT_WALL+2, 20]);
|
||
for (i = [0:1])
|
||
translate([BATT_WALL+12+i*68, BATT_WALL+8, -1])
|
||
cube([38, BATT_W-16, BATT_FLOOR+2]);
|
||
for (x=[10,BATT_L+BATT_WALL-2]) for (y=[10,BATT_W+BATT_WALL-2])
|
||
translate([x,y,BATT_H+BATT_FLOOR-1]) cylinder(d=M4,h=BATT_FLOOR+2);
|
||
}
|
||
}
|
||
}
|
||
|
||
// =============================================================================
|
||
// JETSON NANO B01 MOUNT PLATE
|
||
// =============================================================================
|
||
|
||
module jetson_mount_plate() {
|
||
translate([JETSON_X, 0, 0]) {
|
||
difference() {
|
||
union() {
|
||
translate([-JETSON_PL/2, -JETSON_PW/2, DECK_THICK+JETSON_STOFF])
|
||
cube([JETSON_PL, JETSON_PW, JETSON_PT]);
|
||
for (x=[-JETSON_PITCH/2, JETSON_PITCH/2])
|
||
for (y=[-JETSON_PITCH/2, JETSON_PITCH/2])
|
||
translate([x,y,DECK_THICK]) cylinder(d=6, h=JETSON_STOFF);
|
||
}
|
||
for (x=[-JETSON_PITCH/2, JETSON_PITCH/2])
|
||
for (y=[-JETSON_PITCH/2, JETSON_PITCH/2])
|
||
translate([x,y,DECK_THICK-1])
|
||
cylinder(d=JETSON_HOLE_D, h=JETSON_STOFF+JETSON_PT+2);
|
||
for (i=[-1,0,1])
|
||
translate([i*22-8,-JETSON_PW/2+8,DECK_THICK+JETSON_STOFF-1])
|
||
cube([16, JETSON_PW-16, JETSON_PT+2]);
|
||
for (x=[-JETSON_PL/2+8, JETSON_PL/2-8])
|
||
for (y=[-JETSON_PW/2+8, JETSON_PW/2-8])
|
||
translate([x,y,-1]) cylinder(d=M3, h=DECK_THICK+2);
|
||
}
|
||
}
|
||
}
|
||
|
||
// =============================================================================
|
||
// BUMPER BRACKETS (front / rear)
|
||
// =============================================================================
|
||
|
||
module bumper_bracket(front = 1) {
|
||
yp = front * PLATE_D/2;
|
||
translate([0, yp, 0]) {
|
||
difference() {
|
||
union() {
|
||
translate([-BUMPER_L/2, front*(BUMPER_T/2), 0])
|
||
cube([BUMPER_L, BUMPER_T, BUMPER_H]);
|
||
for (x=[-BUMPER_L/2+4, BUMPER_L/2-BUMPER_T-4])
|
||
translate([x, front*BUMPER_T, 0]) cube([BUMPER_T, 16, BUMPER_H]);
|
||
for (x=[-BUMPER_L/3, 0, BUMPER_L/3])
|
||
translate([x-BUMPER_TUBE_OD/2-2,
|
||
front*(BUMPER_T+10),
|
||
BUMPER_H-BUMPER_TUBE_OD/2-4])
|
||
difference() {
|
||
cube([BUMPER_TUBE_OD+4, BUMPER_TUBE_OD/2+4, BUMPER_TUBE_OD+4]);
|
||
translate([BUMPER_TUBE_OD/2+2,-1,BUMPER_TUBE_OD/2+2])
|
||
rotate([-90,0,0])
|
||
cylinder(d=BUMPER_TUBE_OD, h=BUMPER_TUBE_OD/2+6);
|
||
}
|
||
}
|
||
for (x=[-BUMPER_L/2+16, -BUMPER_L/6, BUMPER_L/6, BUMPER_L/2-16])
|
||
translate([x, yp*0.001, -1]) cylinder(d=M5, h=BUMPER_H+2);
|
||
}
|
||
}
|
||
}
|