feat: prototype base plate with real hub motor measurements

Adds prototype_baseplate.scad — a laser-cuttable / CNC-routable flat
base plate for the self-balancing robot using caliper-verified axle
dimensions from the wiki (replaces placeholder values in PR #7):

  Axle base dia:     16.11 mm (was 14 mm)
  D-cut OD:          15.95 mm (new)
  D-cut flat chord:  13.00 mm (new)
  Total protrusion:  65.50 mm
  Bearing seat OD:   37.80 mm
  Tire OD:          254 mm (10x2.125")
  Axle CL height:   127 mm (was wrong 310 mm)

Design:
- Single flat plate (6 mm Al / 8 mm acrylic), 680x220 mm blank
- Open fork slots (16.51 mm, semicircular tip) at each axle end
- Bearing seat relief cutout prevents Ø37.8 mm collar binding on edge
- Two-piece dropout clamp: lower (round bore) + upper (D-cut bore)
- D-cut profile computed from chord geometry with 0.3 mm all-round clearance
- MAMBA F722S FC holes (30.5x30.5 mm M3), battery mount holes (M4)
- Lightening slots, corner radii via minkowski
- RENDER param switches between 3-D assembly and 2-D DXF projections
  for each of the three laser-cut parts

Updates BOM.md to Rev B: measurement delta table, prototype BOM section,
updated motor entry with verified axle spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sl-mechanical 2026-02-28 14:43:26 -05:00
parent 909763494f
commit 22d7b546f3
2 changed files with 420 additions and 14 deletions

View File

@ -1,24 +1,58 @@
# SaltyBot Chassis — Bill of Materials # SaltyBot Chassis — Bill of Materials
**Task:** bd-1iy5 **Task:** bd-1iy5 / prototype-baseplate
**Rev:** A — 2026-02-28 **Rev:** B — 2026-02-28 (updated with caliper-verified axle measurements)
**Agent:** sl-mechanical **Agent:** sl-mechanical
--- ---
## ⚠ Axle Measurement Update (Rev B)
PR #7 (`chassis_frame.scad`) used placeholder values. The table below records the
**caliper-verified** hub motor axle dimensions. All new designs must use these.
| Feature | Measured | PR #7 placeholder | Delta |
|---------|----------|-------------------|-------|
| Axle base diameter (round, near hub) | **16.11 mm** | 14 mm | +2.11 mm |
| D-cut shaft OD | **15.95 mm** | — (not modelled) | new |
| D-cut flat chord | **13.00 mm** | — | new |
| Total axle protrusion | **65.5 mm** | ~60 mm est. | +5.5 mm |
| Base section length | **15.0 mm** | — | new |
| D-cut section length | **43.35 mm** | — | new |
| Tip / shoulder | **3.0 mm** | — | new |
| Bearing seat collar OD | **37.8 mm** | — | new |
| Tire OD | **254 mm** (10×2.125") | 170 mm motor OD only | — |
| Axle CL height above ground | **127 mm** | 310 mm (wrong) | 183 mm |
`chassis_frame.scad` should be updated in a follow-on task to match Rev B values.
---
## Structural / Fabricated Parts ## Structural / Fabricated Parts
### Prototype Base Plate (`prototype_baseplate.scad`) — Rev B
| # | Part | Qty | Material | Cut size | Notes |
|---|------|-----|----------|----------|-------|
| 1 | Prototype base plate | 1 | 6mm 5052-H32 aluminium **or** 8mm clear acrylic | 680×220mm blank | Laser or CNC; export DXF from `RENDER="plate_2d"` |
| 2 | Dropout clamp — lower (L+R) | 2 | 8mm 6061-T6 aluminium | 90×70mm blank each | Round bore Ø16.51mm; `RENDER="clamp_lower_2d"` |
| 3 | Dropout clamp — upper (L+R) | 2 | 8mm 6061-T6 aluminium | 90×70mm blank each | D-cut bore (Ø16.25mm, 13.6mm flat chord); `RENDER="clamp_upper_2d"` |
| 4 | FC standoff M3×6mm nylon | 4 | Nylon | — | MAMBA F722S vibration isolation |
| 5 | Ø4mm alignment pin | 8 | Steel dowel | 16mm length | Clamp-to-plate alignment (2 per clamp stack) |
### Full Chassis (`chassis_frame.scad`) — Rev A (placeholder values — pending Rev B update)
| # | Part | Qty | Material | Notes | | # | Part | Qty | Material | Notes |
|---|------|-----|----------|-------| |---|------|-----|----------|-------|
| 1 | Main deck plate | 1 | 6mm 5052 aluminium plate, 640×220mm | CNC router or waterjet; all holes per `chassis_frame.scad` | | 6 | Main deck plate | 1 | 6mm 5052 aluminium plate, 640×220mm | CNC router or waterjet; all holes per `chassis_frame.scad` |
| 2 | Longitudinal rib (front) | 1 | 4mm 5052 aluminium, 600×40mm | Laser-cut; press-fit into deck slots | | 7 | Longitudinal rib (front) | 1 | 4mm 5052 aluminium, 600×40mm | Laser-cut; press-fit into deck slots |
| 3 | Longitudinal rib (rear) | 1 | 4mm 5052 aluminium, 600×40mm | Same file, symmetric | | 8 | Longitudinal rib (rear) | 1 | 4mm 5052 aluminium, 600×40mm | Same file, symmetric |
| 4 | Motor fork bracket (L) | 1 | 8mm 6061 aluminium | CNC mill or FDM PETG @100% infill for prototyping | | 9 | Motor fork bracket (L) | 1 | 8mm 6061 aluminium | **Update fork slot to Ø16.51mm before cutting** |
| 5 | Motor fork bracket (R) | 1 | 8mm 6061 aluminium | Mirror of item 4 | | 10 | Motor fork bracket (R) | 1 | 8mm 6061 aluminium | Mirror of item 9 |
| 6 | Battery tray | 1 | 3mm PETG FDM or 3mm aluminium fold | `chassis_frame.scad``battery_tray()` module | | 11 | Battery tray | 1 | 3mm PETG FDM or 3mm aluminium fold | `chassis_frame.scad``battery_tray()` module |
| 7 | FC mount plate / standoffs | 1 set | PETG or nylon FDM | Includes 4× M3 nylon standoffs, 6mm height | | 12 | FC mount plate / standoffs | 1 set | PETG or nylon FDM | Includes 4× M3 nylon standoffs, 6mm height |
| 8 | Jetson Nano mount plate | 1 | 4mm 5052 aluminium or 4mm PETG FDM | B01 58×58mm hole pattern | | 13 | Jetson Nano mount plate | 1 | 4mm 5052 aluminium or 4mm PETG FDM | B01 58×58mm hole pattern |
| 9 | Front bumper bracket | 1 | 5mm PETG FDM | Saddle clamps for 22mm EMT conduit | | 14 | Front bumper bracket | 1 | 5mm PETG FDM | Saddle clamps for 22mm EMT conduit |
| 10 | Rear bumper bracket | 1 | 5mm PETG FDM | Mirror of item 9 | | 15 | Rear bumper bracket | 1 | 5mm PETG FDM | Mirror of item 14 |
--- ---
@ -26,8 +60,9 @@
| # | Part | Qty | Source / Spec | Notes | | # | Part | Qty | Source / Spec | Notes |
|---|------|-----|---------------|-------| |---|------|-----|---------------|-------|
| 11 | Hoverboard hub motor | 2 | Generic 6.5" / 170mm OD, 36V nominal | ~350W each; 14mm flat axle; confirm exact OD before cutting fork slots | | 16 | Hoverboard hub motor | 2 | 10×2.125" pneumatic tire, 36V nominal, ~350W | Axle: Ø16.11mm base / Ø15.95mm D-cut / 13mm flat; bearing seat Ø37.8mm — **all caliper-verified** |
| 12 | Motor hall-sensor cable extension | 2 | 6-pin JST-PH 300mm | Route through deck cable slot | | 17 | Motor hall-sensor cable extension | 2 | 6-pin JST-PH 300mm | Route through deck cable slot |
| 18 | Axle lock nut | 4 | M16×1.5 or thread-matched to actual axle tip | Confirm thread at tip before ordering; calipers show Ø≈10mm at tip |
--- ---

View File

@ -0,0 +1,371 @@
// =============================================================================
// SaltyBot Prototype Base Plate
// Agent: sl-mechanical | 2026-02-28
//
// Laser-cut or CNC-routed flat plate (6mm aluminium or 8mm acrylic).
// Uses CALIPER-VERIFIED hub motor axle measurements replaces placeholder
// values from chassis_frame.scad (PR #7).
//
// VERIFIED AXLE PROFILE (stepped D-cut)
// Zone Feature Diameter / Width Length
//
// Base Round (near hub) Ø 16.11 mm 15.00 mm
// D-cut Round OD Ø 15.95 mm 43.35 mm
// Flat chord 13.00 mm across
// Tip Shoulder/end 3.00 mm (tip lock nut seat)
// Total Hub face tip 65.50 mm
//
// Bearing seat collar OD: Ø 37.8 mm (hub centre)
// Tire: 10 × 2.125" pneumatic (254 mm OD, 54 mm wide, 35 PSI)
// =============================================================================
$fn = 128;
// =============================================================================
// AXLE PARAMETERS caliper-verified (edit only when re-measured)
// =============================================================================
AXLE_BASE_DIA = 16.11; // mm round section near hub face
AXLE_BASE_LEN = 15.00; // mm length of base section
AXLE_DCUT_DIA = 15.95; // mm round OD of D-cut zone
AXLE_DCUT_FLAT = 13.00; // mm flat chord width (caliper across flat)
AXLE_DCUT_LEN = 43.35; // mm D-cut section length
AXLE_TIP_LEN = 3.00; // mm tip / shoulder
AXLE_TOTAL = 65.50; // mm total protrusion from hub face
BEARING_SEAT_OD = 37.80; // mm hub centre collar OD
TIRE_OD = 254.0; // mm 10" × 25.4
TIRE_WIDTH = 54.0; // mm 2.125" × 25.4
AXLE_CL_HEIGHT = TIRE_OD / 2; // 127 mm axle centre above ground
// =============================================================================
// PLATE PARAMETERS
// =============================================================================
WHEELBASE = 600.0; // mm axle C/L to axle C/L
PLATE_DEPTH = 220.0; // mm front-to-rear
PLATE_OVERHANG = 40.0; // mm plate extends past axle C/L on each side
PLATE_THICK = 6.0; // mm stock thickness (6 mm Al / 8 mm acrylic)
// Fork (open-ended slot in plate edge)
// Width matched to base-section diameter + 0.4 mm running clearance
FORK_W = AXLE_BASE_DIA + 0.4; // 16.51 mm
FORK_DEPTH = 50.0; // mm slot depth inward from plate edge
// Clamp block (two-piece sandwich, bolts through plate)
CLAMP_L = 80.0; // mm along axle axis
CLAMP_H = 60.0; // mm across axle (front-to-back of plate)
CLAMP_THICK = 8.0; // mm each clamp layer 8 mm Al or 10 mm acrylic
CLAMP_BOLT_D = 5.3; // M5 clearance
CLAMP_BOLT_DX = 22.0; // mm bolt ±X from axle C/L
CLAMP_BOLT_DY = 22.0; // mm bolt ±Y from axle C/L (across plate)
CLAMP_ALIGN_D = 4.1; // Ø4 alignment pin clearance
// D-cut bore clearance (applied to both diameter and flat chord)
DCUT_CL = 0.3; // mm all-round clearance on D-cut profile
// FC mount MAMBA F722S 30.5 × 30.5 mm M3 stack
FC_PITCH = 30.5;
FC_HOLE_D = 3.2;
// Battery area 24 V pack footprint (mount holes)
BATT_L = 185.0;
BATT_W = 72.0;
// Utility
M3 = 3.2; M4 = 4.3; M5 = 5.3;
// =============================================================================
// COMPUTED GEOMETRY (do not edit directly)
// =============================================================================
// D-cut bore geometry (with clearance):
// r = (AXLE_DCUT_DIA + 2·DCUT_CL) / 2
// fc = AXLE_DCUT_FLAT + 2·DCUT_CL (chord with clearance on each side)
// d = distance from centre to flat = sqrt(r² (fc/2)²)
DCUT_R = (AXLE_DCUT_DIA + 2*DCUT_CL) / 2; // 8.275 mm
DCUT_FC = AXLE_DCUT_FLAT + 2*DCUT_CL; // 13.60 mm
// DCUT_D computed inside module (OpenSCAD has no sqrt at module-level constant)
// Plate outer bounds
PLATE_X_HALF = WHEELBASE/2 + PLATE_OVERHANG; // ± 340 mm
// =============================================================================
// RENDER CONTROL
// =============================================================================
// Set RENDER to one of:
// "assembly" full 3-D preview (default)
// "plate_2d" 2-D projection of base plate ( DXF)
// "clamp_lower_2d" 2-D projection of lower clamp ( DXF)
// "clamp_upper_2d" 2-D projection of upper clamp ( DXF)
RENDER = "assembly";
if (RENDER == "assembly") {
assembly();
} else if (RENDER == "plate_2d") {
projection(cut=true) translate([0,0,-PLATE_THICK/2]) base_plate();
} else if (RENDER == "clamp_lower_2d") {
projection(cut=true) translate([0,0,-CLAMP_THICK/2]) clamp_lower();
} else if (RENDER == "clamp_upper_2d") {
projection(cut=true) translate([0,0,-CLAMP_THICK/2]) clamp_upper();
}
// =============================================================================
// ASSEMBLY
// =============================================================================
module assembly() {
color("Silver", 0.85) base_plate();
for (side = [-1, 1]) {
// Lower clamp sits on top of base plate, below fork slot level
color("SteelBlue", 0.8)
translate([side * WHEELBASE/2, 0, PLATE_THICK])
clamp_lower();
// Upper clamp stacks on top of lower clamp
color("CornflowerBlue", 0.8)
translate([side * WHEELBASE/2, 0, PLATE_THICK + CLAMP_THICK])
clamp_upper();
}
// Reference ghosts (not for export)
%for (side = [-1, 1])
color("Orange", 0.25)
translate([side * WHEELBASE/2, 0, 0])
rotate([0, side * 90, 0])
axle_ghost();
}
// =============================================================================
// BASE PLATE
// =============================================================================
module base_plate() {
difference() {
// Outer profile (rounded corners via minkowski)
R = 12; // corner radius
linear_extrude(PLATE_THICK)
minkowski() {
square([2*(PLATE_X_HALF - R), PLATE_DEPTH - 2*R], center=true);
circle(r=R);
}
// Fork slots (open at ±X edges)
// Slot is FORK_W wide, FORK_DEPTH deep, open at plate edge
for (side = [-1, 1]) {
// Round the slot tip (half-circle end)
union() {
translate([side*(PLATE_X_HALF - FORK_DEPTH),
-FORK_W/2, -1])
cube([FORK_DEPTH + 1, FORK_W, PLATE_THICK + 2]);
// Semicircular slot bottom
translate([side*(PLATE_X_HALF - FORK_DEPTH), 0, -1])
cylinder(d=FORK_W, h=PLATE_THICK + 2);
}
}
// Clamp bolt through-holes (4 per side × 2 sides)
for (side = [-1, 1])
for (dx = [-CLAMP_BOLT_DX, CLAMP_BOLT_DX])
for (dy = [-CLAMP_BOLT_DY, CLAMP_BOLT_DY])
translate([side * WHEELBASE/2 + dx, dy, -1])
cylinder(d=CLAMP_BOLT_D, h=PLATE_THICK + 2);
// Alignment pin holes (Ø4, 2 per clamp side)
for (side = [-1, 1])
for (dy = [-CLAMP_BOLT_DY + 8, CLAMP_BOLT_DY - 8])
translate([side * WHEELBASE/2, dy, -1])
cylinder(d=CLAMP_ALIGN_D, h=PLATE_THICK + 2);
// FC mount holes (MAMBA F722S 30.5 × 30.5 M3)
for (x = [-FC_PITCH/2, FC_PITCH/2])
for (y = [-FC_PITCH/2, FC_PITCH/2])
translate([x, y, -1])
cylinder(d=FC_HOLE_D, h=PLATE_THICK + 2);
// Battery tray mount holes (M4 × 4 corners)
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=PLATE_THICK + 2);
// Lightening / cable routing slots (3 centre panels)
slot_w = 28;
slot_h = PLATE_DEPTH - 80;
for (x = [-130, 0, 130])
translate([x - slot_w/2, -slot_h/2, -1])
// Rounded slot via hull
hull() {
translate([slot_w/2, slot_w/2, 0]) cylinder(d=slot_w, h=PLATE_THICK+2);
translate([slot_w/2, slot_h - slot_w/2, 0]) cylinder(d=slot_w, h=PLATE_THICK+2);
}
// Bearing seat relief (36mm slot lets hub collar clear plate edge)
// Prevents Ø37.8mm bearing seat from binding against plate edge.
for (side = [-1, 1])
translate([side*PLATE_X_HALF - side*(BEARING_SEAT_OD/2 + 2),
-BEARING_SEAT_OD/2, -1])
cube([BEARING_SEAT_OD/2 + 3, BEARING_SEAT_OD, PLATE_THICK + 2]);
}
}
// =============================================================================
// DROPOUT CLAMP LOWER (round bore, base-section diameter)
// =============================================================================
// Sits directly on top of the base plate.
// The 16.11 mm round bore captures the base axle section.
// The fork slot in the base plate is reproduced here to allow the axle to
// slide in from the side.
module clamp_lower() {
difference() {
// Body
hull() {
translate([-CLAMP_L/2 + CLAMP_H/2, 0, 0]) cylinder(d=CLAMP_H, h=CLAMP_THICK);
translate([ CLAMP_L/2 - CLAMP_H/2, 0, 0]) cylinder(d=CLAMP_H, h=CLAMP_THICK);
}
// Round bore base axle diameter + clearance
translate([0, 0, -1])
cylinder(d = AXLE_BASE_DIA + 0.4, h = CLAMP_THICK + 2);
// Open entry slot (matches base plate fork slot allows slide-in assembly)
translate([-CLAMP_L/2 - 1, -FORK_W/2, -1])
cube([CLAMP_L/2 + 1, FORK_W, CLAMP_THICK + 2]);
// Clamp bolt holes
for (dx = [-CLAMP_BOLT_DX, CLAMP_BOLT_DX])
for (dy = [-CLAMP_BOLT_DY, CLAMP_BOLT_DY])
translate([dx, dy, -1])
cylinder(d=CLAMP_BOLT_D, h=CLAMP_THICK + 2);
// Alignment pin holes
for (dy = [-CLAMP_BOLT_DY + 8, CLAMP_BOLT_DY - 8])
translate([0, dy, -1])
cylinder(d=CLAMP_ALIGN_D, h=CLAMP_THICK + 2);
}
}
// =============================================================================
// DROPOUT CLAMP UPPER (D-cut bore, anti-rotation)
// =============================================================================
// Stacks on top of lower clamp.
// D-cut bore matches the caliper-verified profile:
// Ø 15.95 mm round OD, 13.00 mm flat chord
// Clearance DCUT_CL applied all-round.
// The flat is oriented toward +Y (front of robot) rotate clamp at assembly
// to match actual flat position on your axles.
module clamp_upper() {
dcut_r = DCUT_R;
dcut_fc = DCUT_FC;
// Distance from bore CL to flat (chord geometry)
dcut_d = sqrt(pow(dcut_r, 2) - pow(dcut_fc/2, 2));
difference() {
// Body (same footprint as lower clamp)
hull() {
translate([-CLAMP_L/2 + CLAMP_H/2, 0, 0]) cylinder(d=CLAMP_H, h=CLAMP_THICK);
translate([ CLAMP_L/2 - CLAMP_H/2, 0, 0]) cylinder(d=CLAMP_H, h=CLAMP_THICK);
}
// D-cut bore:
// 1. Full round circle of radius dcut_r
// 2. Intersect with a box that removes the top (y > dcut_d)
// Net result: D-shape with flat at +Y = dcut_d
translate([0, 0, -1])
linear_extrude(CLAMP_THICK + 2)
dcut_profile_2d(dcut_r, dcut_d);
// Open entry slot (same as lower clamp)
translate([-CLAMP_L/2 - 1, -FORK_W/2, -1])
cube([CLAMP_L/2 + 1, FORK_W, CLAMP_THICK + 2]);
// Clamp bolt holes
for (dx = [-CLAMP_BOLT_DX, CLAMP_BOLT_DX])
for (dy = [-CLAMP_BOLT_DY, CLAMP_BOLT_DY])
translate([dx, dy, -1])
cylinder(d=CLAMP_BOLT_D, h=CLAMP_THICK + 2);
// Alignment pin holes
for (dy = [-CLAMP_BOLT_DY + 8, CLAMP_BOLT_DY - 8])
translate([0, dy, -1])
cylinder(d=CLAMP_ALIGN_D, h=CLAMP_THICK + 2);
// Label emboss (orientation marker "D-CUT" + flat side arrow)
translate([-12, dcut_d + 1, CLAMP_THICK - 0.8])
linear_extrude(1)
text("D", size=6, font="Liberation Sans:style=Bold", halign="center");
// Arrow indicating flat direction
translate([8, dcut_d - 1, CLAMP_THICK - 0.8])
linear_extrude(1)
polygon([[0,0],[4,-3],[4,3]]);
}
}
// 2-D D-cut profile helper
// r = bore radius (with clearance already applied)
// flat_d = distance from bore CL to flat (computed from chord geometry)
module dcut_profile_2d(r, flat_d) {
intersection() {
circle(r=r);
// Keep everything from y = -(r+1) up to y = flat_d
translate([-r - 1, -r - 1])
square([2*(r + 1), r + 1 + flat_d]);
}
}
// =============================================================================
// AXLE GHOST (for assembly visualisation)
// =============================================================================
module axle_ghost() {
// Bearing seat collar
cylinder(d=BEARING_SEAT_OD, h=12);
// Base zone round
translate([0, 0, 12])
cylinder(d=AXLE_BASE_DIA, h=AXLE_BASE_LEN);
// D-cut zone (approximate cylinder for ghost)
translate([0, 0, 12 + AXLE_BASE_LEN])
cylinder(d=AXLE_DCUT_DIA, h=AXLE_DCUT_LEN);
// Tip
translate([0, 0, 12 + AXLE_BASE_LEN + AXLE_DCUT_LEN])
cylinder(d=10, h=AXLE_TIP_LEN);
}
// =============================================================================
// DXF / FLAT-PATTERN EXPORT GUIDE
// =============================================================================
//
// PART 1 Base plate
// openscad prototype_baseplate.scad \
// -D 'RENDER="plate_2d"' \
// -o baseplate_plate.dxf
//
// PART 2 Lower clamp (× 2, one per side)
// openscad prototype_baseplate.scad \
// -D 'RENDER="clamp_lower_2d"' \
// -o baseplate_clamp_lower.dxf
//
// PART 3 Upper clamp (× 2, one per side)
// openscad prototype_baseplate.scad \
// -D 'RENDER="clamp_upper_2d"' \
// -o baseplate_clamp_upper.dxf
//
// MATERIAL NOTES
// Base plate: 6 mm 5052-H32 aluminium (preferred)
// 8 mm clear acrylic (quick prototype)
// Clamp blocks: 8 mm 6061-T6 aluminium (preferred tighter bore tolerance)
// 10 mm PETG FDM (proto only pre-drill bolt holes)
//
// LASER PARAMETERS (6 mm Al, fibre laser)
// Power: 3 kW | Speed: 1800 mm/min | Assist: N2
// Min bore dia: 6 mm (M5 holes OK)
//
// DIMENSIONAL NOTES
// Fork slot width (FORK_W): 16.51 mm verify on actual axle before cut
// D-cut flat clearance (DCUT_CL): 0.3 mm adjust if axle spins in clamp
// Bearing seat relief: check collar actually clears plate edge before tightening
// =============================================================================