saltylab-firmware/docs/SALTYLAB-DETAILED.md
sl-firmware 291dd689f8 feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only
Archive STM32 firmware to legacy/stm32/:
- src/, include/, lib/USB_CDC/, platformio.ini, test stubs, flash_firmware.py
- test/test_battery_adc.c, test_hw_button.c, test_pid_schedule.c, test_vesc_can.c, test_can_watchdog.c
- USB_CDC_BUG.md

Rename: stm32_protocol → esp32_protocol, mamba_protocol → balance_protocol,
  stm32_cmd_node → esp32_cmd_node, stm32_cmd_params → esp32_cmd_params,
  stm32_cmd.launch.py → esp32_cmd.launch.py,
  test_stm32_protocol → test_esp32_protocol, test_stm32_cmd_node → test_esp32_cmd_node

Content cleanup across all files:
- Mamba F722S → ESP32-S3 BALANCE
- BlackPill → ESP32-S3 IO
- STM32F722/F7xx → ESP32-S3
- stm32Mode/Version/Port → esp32Mode/Version/Port
- STM32 State/Mode labels → ESP32 State/Mode
- Jetson Nano → Jetson Orin Nano Super
- /dev/stm32 → /dev/esp32
- stm32_bridge → esp32_bridge
- STM32 HAL → ESP-IDF

docs/SALTYLAB.md:
- Update "Drone FC Details" to describe ESP32-S3 BALANCE board (Waveshare ESP32-S3 Touch LCD 1.28)
- Replace verbose "Self-Balancing Control" STM32 section with brief note pointing to SAUL-TEE-SYSTEM-REFERENCE.md

TEAM.md: Update Embedded Firmware Engineer role to ESP32-S3 / ESP-IDF

No new functionality — cleanup only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 08:41:26 -04:00

455 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SaltyLab — Detailed Build Plan 🔬⚖️
Self-balancing two-wheeled indoor robot with AI brain.
---
## 1. Battery Analysis
### Pack Specs (Begode Master V1 packs)
- **Configuration per pack:** 10S (35V nominal, 42V full, 30V cutoff)
- **Chemistry:** Li-ion 18650 or 21700
- **Estimated capacity per pack:** ~450-500Wh (based on Master V1 total ~1800Wh ÷ 4 packs)
- If 10S4P with 21700 5000mAh cells: 36V × 20Ah = **720Wh**
- If 10S3P with 21700 5000mAh cells: 36V × 15Ah = **540Wh**
- If 10S4P with 18650 3500mAh cells: 36V × 14Ah = **504Wh**
- **Need to verify:** check cell count visible on pack, or weigh it
### SaltyLab Battery Config: Single Pack
- **Voltage:** 35V nominal (fits hoverboard ESC: designed for 36V/10S)
- **Capacity:** ~500Wh (conservative estimate)
- **Weight:** ~2-3kg per pack
### Why Single Pack is Enough
- SaltyLab is indoor-only, short missions
- One pack gives 2-4 hours runtime (see estimates below)
- Keep other 3 packs for SaltyRider and SaltyTank
---
## 2. Power Budget & Range Estimation
### Component Power Draw
| Component | Voltage | Current | Power (W) | Notes |
|-----------|---------|---------|-----------|-------|
| Jetson Orin Nano Super | 5V | 2-4A | 10-20W | AI inference mode: ~15W avg |
| RealSense D435i | 5V (USB) | 0.7A | 3.5W | Depth + RGB streaming |
| RPLIDAR A1M8 | 5V | 0.5A | 2.5W | Spinning at 5.5Hz |
| BNO055 IMU | 3.3V | 0.01A | 0.04W | Negligible |
| ESC (idle/balance) | 36V | 0.3A | 10W | Maintaining balance, no movement |
| LEDs + misc | 12V | 0.5A | 6W | Status LEDs, speaker |
| DC-DC losses | — | — | ~5W | ~85% efficiency on converters |
| **Subtotal (idle/balancing)** | | | **~47W** | |
### Motor Power (Moving)
| Activity | Per Motor | Total (2 motors) | Notes |
|----------|-----------|-------------------|-------|
| Balancing in place | 5-15W | 10-30W | Continuous micro-corrections |
| Slow indoor movement (2 km/h) | 15-25W | 30-50W | Walking pace |
| Normal indoor (5 km/h) | 30-50W | 60-100W | Brisk walk |
| Fast / acceleration | 80-150W | 160-300W | Bursts, turning |
| Climbing threshold/ramp | 100-200W | 200-400W | Short duration |
### Total Power by Use Case
| Mode | Electronics | Motors | Total | Notes |
|------|-------------|--------|-------|-------|
| **Idle (balancing)** | 47W | 20W | **~67W** | Standing still |
| **Slow patrol** | 47W | 40W | **~87W** | Gentle movement |
| **Normal follow** | 47W | 80W | **~127W** | Following person around house |
| **Active (turning, accel)** | 47W | 200W | **~247W** | Bursts |
### Range Estimates (Single 500Wh Pack)
| Mode | Avg Power | Runtime | Distance |
|------|-----------|---------|----------|
| Idle (balancing) | 67W | **7.5 hours** | 0 km (stationary) |
| Slow patrol (2 km/h) | 87W | **5.7 hours** | ~11 km |
| Normal follow (5 km/h) | 127W | **3.9 hours** | ~20 km |
| Mixed indoor use | ~100W avg | **5 hours** | ~15 km |
| Aggressive (lots of turning) | 180W avg | **2.8 hours** | ~8 km |
**Bottom line: 3-5 hours of indoor use on a single pack.** More than enough.
### Weight Budget
| Component | Weight (g) | Notes |
|-----------|-----------|-------|
| Battery pack (1x) | 2500 | Estimated, weigh to verify |
| 2x 8" hub motors | 2400 | ~1200g each with tire |
| ESC board | 150 | Single board |
| Jetson Orin Nano Super + heatsink | 280 | With Noctua fan |
| RealSense D435i | 72 | Very light |
| RPLIDAR A1M8 | 170 | With motor |
| BNO055 breakout | 5 | Tiny |
| DC-DC converters (2x) | 300 | 150g each |
| Frame + brackets | 1200 | Aluminum + 3D printed |
| Wiring + connectors | 200 | |
| Bumpers (TPU) | 150 | |
| **TOTAL** | **~7.4 kg** | Target: under 8 kg |
---
## 3. Detailed 2D Schematics
### 3.1 Base Plate — Top View
```
350mm
←─────────────────────────────────────→
┌─────────────────────────────────────┐ ─┬─
│ ○ ○ │ │
│ ┌───────────────────────────┐ │ │
│ │ MOTOR MOUNT PLATE │ │ │
│ │ │ │ │
│ │ ┌─────┐ ┌─────┐ │ │ │
│ │ │AXLE │ │AXLE │ │ │ │ 200mm
│ │ │ L │ │ R │ │ │ │
│ │ └─────┘ └─────┘ │ │ │
│ │ ↑ 250mm ↑ │ │ │
│ │ └─────────────┘ │ │ │
│ │ track width │ │ │
│ └───────────────────────────┘ │ │
│ ○ ○ │ │
└─────────────────────────────────────┘ ─┴─
○ = M5 mounting holes for vertical spine (4 corners)
Axle holes: Ø14mm (standard hoverboard axle)
Plate thickness: 6mm PETG
Motor mount detail:
┌──────────────┐
│ ┌────────┐ │
│ │ Ø14mm │ │ Two-piece clamp:
│ │ axle │ │ Bottom: part of base plate
│ │ hole │ │ Top: clamp plate with 2x M6 bolts
│ └────────┘ │
│ ○ ○ │ ○ = M6 clamp bolt holes
└──────────────┘
80mm
```
### 3.2 Side View — Full Assembly
```
FRONT →
550mm ┬ ┌─────────┐
│ │ RPLIDAR │ Ø80mm, 360° clear
│ │ A1M8 │
500mm │ ├─────────┤
│ │ │ ← LIDAR standoff tube (80mm tall)
│ │ │
420mm │ ├─────────┤
│ │RealSense│ ← Tilted down 10°, front-facing
│ │ D435i │ Adjustable bracket
380mm │ ├─────────┤
│ │ │
│ │ JETSON │ ← Noctua fan, ventilation slots
│ │ NANO │
300mm │ ├─────────┤
│ │ BNO055 │ ← IMU, vibration-isolated mount
280mm │ ├─────────┤
│ │ │
│ │ ESC + │ ← ESC board + DC-DC converters
│ │ DC-DCs │
200mm │ ├─────────┤
│ │ │
│ │ BATTERY │ ← Heaviest component, lowest position
│ │ PACK │ Strapped to spine with velcro
│ │ │
80mm │ ├─────────┤
│ │ BASE │ ← Motor mount plate (6mm)
│ │ PLATE │
40mm │ ├────┬────┤
│ │ │ │
┴ └────┘ └── 8" wheel (Ø203mm)
═════════════
GROUND (0mm)
Ground clearance: ~40mm (bottom of plate to ground)
Wheel contact to axle center: ~100mm (8" diameter / 2)
Axle height from ground: ~100mm
```
### 3.3 Front View
```
←── 350mm ──→
┌─────────┐ ─┬─ 550mm
│ RPLIDAR │ │
├─────────┤ │
│ ┃ │ ← spine │
│ ┃ │ (2020 │
│ ┃ │ extrusion│
│ ┃ │ or │
│ ┃ │ aluminum │
│ ┃ │ tube) │
│ ┃ │ │
├───┃─────┤ │
┌─────┐ │ ┃ │ ┌─────┐│
│ │ │ ┃ │ │ ││
│ 8" │ │ ┃ │ │ 8" ││ 100mm
│ L │───┤ ┃ ├───│ R ││ (axle)
│ │ │ ┃ │ │ ││
│ │ └───┃─────┘ │ │┴─ 0mm
└─────┘ ┃ └─────┘
═══════════════════════════════════
←65→←──── 250mm ────→←65→
mm (track width) mm
Total width with tires: ~380mm
Fits through standard doorway (760mm) ✓
```
### 3.4 Spine Detail — Side View
```
┌──┐ ← 20×20mm aluminum extrusion (2020 V-slot)
│ │ or 25×25mm square aluminum tube
│ │
│ │──── Shelf bracket (3D printed, bolts to T-slot)
│ │ Each shelf: 120mm wide × 100-150mm deep
│ │
│ │──── Shelf bracket
│ │
│ │──── Shelf bracket
│ │
│ │──── Shelf bracket
│ │
├──┤
│ │──── Base plate connection (L-brackets, 4x M5)
└──┘
Spine length: 470mm (from base plate to LIDAR mount)
Shelf positions (from base plate):
0mm — Base plate
30mm — Battery shelf (holds pack on its side)
150mm — ESC + DC-DC shelf
250mm — Jetson Orin Nano Super shelf
300mm — BNO055 (attached to spine directly)
370mm — RealSense bracket (front-facing arm)
420mm — LIDAR standoff begins
500mm — LIDAR mount plate
```
### 3.5 Wiring Diagram
```
BATTERY PACK (35V nominal, 10S Li-ion)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
│(+) ()│
│ │
├──[E-STOP (NC)]───────────┤
│ │
XT60 ├────────┬────────┬────────┤ XT60
│ │ │ │
│ ┌───┴───┐ │ │
│ │DC-DC │ │ │
│ │36V→5V │ │ │
│ │ 4A │ │ │
│ └───┬───┘ │ │
│ 5V │ │ │
│ ┌───┴────┐ │ │
│ │USB Hub │ │ │
│ │Jetson │ │ │
│ │RealSns │ │ │
│ │RPLIDAR │ │ │
│ └────────┘ │ │
│ │ │
│ ┌────┴───┐ │ │
│ │DC-DC │ │ │
│ │36V→12V │ │ │
│ │ 2A │ │ │
│ └───┬────┘ │ │
│ 12V │ │ │
│ ┌───┴────┐ │ │
│ │LEDs │ │ │
│ │Speaker │ │ │
│ └────────┘ │ │
│ │ │
┌────┴─────────────────┴────────┴────┐
│ HOVERBOARD ESC │
│ (FOC firmware) │
│ │
│ I2C: SDA──BNO055──SCL │
│ UART: TX──Jetson──RX │
│ │
│ PHASE L: ─── 8" LEFT MOTOR │
│ HALL L: ─── (5 wire: hall A/B/C │
│ + 5V + GND) │
│ │
│ PHASE R: ─── 8" RIGHT MOTOR │
│ HALL R: ─── (5 wire) │
└────────────────────────────────────┘
```
---
## 4. Phased Build Plan
### Phase 1: Rolling Skeleton (Days 1-3)
**Goal:** Prove balance works.
**Tasks:**
- [ ] Measure 8" motor axle diameter with calipers
- [ ] Design motor mount plate in CAD (FreeCAD or TinkerCAD)
- [ ] Print motor mount plate on Bambu X1C (PETG, 80% infill, ~4h print)
- [ ] Print axle clamp tops (x2)
- [ ] Mount both 8" motors to plate
- [ ] Mount ESC to plate with standoffs
- [ ] Wire BNO055 to ESC I2C (4 wires: VCC, GND, SDA, SCL)
- [ ] Wire battery to ESC (XT60)
- [ ] Modify FOC firmware: add BNO055 I2C read, replace gyro board input
- [ ] Flash ESC with updated firmware
- [ ] **SAFETY:** Tie rope from ceiling to plate as fall catch
- [ ] Power on, tune PID (start with Kp=20, Ki=0, Kd=0, increase gradually)
- [ ] Achieve stable free-standing balance (no rope)
**Parts needed:** motor mount plate, 2x clamp tops, M6 bolts, M3 standoffs
**Risk:** PID tuning can take hours of iteration. Be patient.
### Phase 2: Spine + Brain (Days 4-7)
**Goal:** Add Jetson, achieve remote-controlled movement while balancing.
**Tasks:**
- [ ] Cut aluminum extrusion/tube to 470mm for spine
- [ ] Print shelf brackets (4x) and L-brackets for base connection
- [ ] Assemble spine onto base plate
- [ ] Mount battery to lowest shelf (velcro straps)
- [ ] Mount ESC + DC-DC converters
- [ ] Mount Jetson Orin Nano Super on shelf, connect 5V power
- [ ] Wire Jetson UART → ESC UART
- [ ] Install JetPack 4.6 on Jetson (if not already)
- [ ] Write serial bridge: Jetson Python → ESC UART commands
- [ ] Test: keyboard control (WASD) → speed/steer commands → balanced movement
- [ ] Tune speed response (acceleration limits, max speed for indoor)
- [ ] Add E-stop button (inline with battery positive)
**Software deliverable:** `saltylab_teleop.py` — keyboard-controlled balancing bot
### Phase 3: Eyes + Ears (Days 8-12)
**Goal:** See the world. Map a room. Detect people.
**Tasks:**
- [ ] Print RealSense bracket (adjustable tilt)
- [ ] Print LIDAR standoff tube + mount plate
- [ ] Mount RealSense D435i (front-facing, ~10° down tilt)
- [ ] Mount RPLIDAR A1M8 (top of spine, 360° clear)
- [ ] Install ROS2 on Jetson
- [ ] Install and test `realsense-ros` (verify depth stream)
- [ ] Install and test `rplidar_ros` (verify laser scan)
- [ ] Run `slam_toolbox` — drive around room, build 2D map
- [ ] Test person detection with SSD-MobileNet-v2 (TensorRT)
- [ ] Implement follow mode:
- Detect person in RGB frame
- Get distance from depth frame
- PID to maintain 1.5m following distance
- LIDAR for obstacle avoidance
**Software deliverable:** `saltylab_follow.py` — person-following balanced bot
### Phase 4: Polish + Personality (Days 13-17)
**Goal:** Make it feel alive. Make it SaltyLab.
**Tasks:**
- [ ] Print proper enclosures for all electronics
- [ ] Print TPU bumpers (front + rear)
- [ ] Print carry handle
- [ ] Add NeoPixel LED ring around LIDAR mount (status indication)
- Blue breathing: idle/balancing
- Green: following
- Yellow: exploring/mapping
- Red: error/low battery
- [ ] Add small speaker (USB or I2S to amp)
- Boot sound
- Acknowledge commands with beeps/chirps
- Optional: TTS via Jetson ("I see you", "battery low")
- [ ] WiFi dashboard: live camera feed + map + battery status
- [ ] Battery voltage monitoring (ADC on ESC → Jetson via UART)
- [ ] Low battery return behavior (stop and beep)
- [ ] Integrate with Home Assistant (MQTT: location, battery, status)
### Phase 5: House Mapping + Autonomy (Days 18-24)
**Goal:** SaltyLab knows your house.
**Tasks:**
- [ ] Map every room (drive around manually, SLAM builds full floor plan)
- [ ] Save map, set up `nav2` for autonomous navigation
- [ ] Define waypoints: lab, living room, kitchen, hallway
- [ ] Patrol mode: visit waypoints on schedule
- [ ] Person detection + greeting ("hey Tee", "hi Inka")
- [ ] Integration with Bermuda BLE: know where people are, go to them
- [ ] Charging dock design (future: auto-dock when low)
---
## 5. Speed & Performance Specs
### Target Performance
| Parameter | Value | Notes |
|-----------|-------|-------|
| Max speed (indoor) | 5 km/h | Software limited for safety |
| Normal follow speed | 2-3 km/h | Walking pace |
| Turning radius | 0 (pivot) | Differential drive, spins in place |
| Ground clearance | 40mm | Clears door thresholds (~15mm) |
| Max incline | ~10° | Limited by motor torque + balance |
| Operating time | 3-5 hours | Single 500Wh pack |
| Charge time | ~2-3 hours | Using one of the existing chargers |
| Weight | ~7.5 kg | Easy to pick up with handle |
| Width | 380mm | Fits all doorways |
| Height | 550mm | Below table height |
### Motor Specs (8" hub motor, estimated)
| Parameter | Value |
|-----------|-------|
| Nominal voltage | 36V |
| Rated power | 250-350W per motor |
| No-load RPM | ~250 RPM |
| Wheel circumference | ~0.64m (Ø203mm) |
| Max wheel speed | 160 m/min = 9.6 km/h |
| Continuous torque | ~2-3 Nm |
| Stall torque | ~8-10 Nm |
---
## 6. Safety Considerations
| Hazard | Mitigation |
|--------|-----------|
| Falls over | TPU bumpers, max tilt cutoff (30°), low CoG |
| Runs away | Software speed limit (5 km/h), E-stop button |
| Pinches/crushes | No exposed gears, motor covers |
| Battery fire | BMS on pack, fused main power, no charging unattended |
| Hits furniture | LIDAR obstacle avoidance, bumper sensors (future) |
| Scares the cat | Slow acceleration, no sudden movements |
---
## 7. Shopping List (Items NOT in Inventory)
| Item | Price (CAD) | Source | Notes |
|------|------------|--------|-------|
| 2020 aluminum extrusion 500mm | ~$8 | Amazon/AliExpress | Spine |
| T-slot nuts + M5 bolts (pack) | ~$12 | Amazon | For shelf mounting |
| M6 bolts + nuts (axle clamps) | ~$5 | Hardware store | 4x sets |
| NeoPixel ring (24 LED) | ~$8 | Amazon | Status indication |
| Small speaker + amp (MAX98357A) | ~$10 | Amazon/Adafruit | I2S audio |
| E-stop mushroom button | ~$5 | Amazon | Safety |
| XT60 splitter/distribution | ~$8 | Amazon | Power wiring |
| Misc: heat shrink, zip ties, wire | ~$10 | — | Always need more |
| **TOTAL** | **~$66** | | Everything else: already owned |
---
*Last updated: 2026-02-27*
*Project: SaltyRover / SaltyLab*