Draft: shared protocol, remote firmware, project docs

Not yet verified on hardware.

- shared/HexapodProtocol: CmdPacket (now 20 bytes, adds remote_roll /
  remote_pitch), FLAG_* bits and radio settings as the single protocol
  definition; static payload size = sizeof(CmdPacket) on both radios.
- robot: use the shared protocol; vx = forward (harness w/x <-> q/e);
  InputMapper adds remote tilt on top of the right stick when
  FLAG_REMOTE_GYRO is set, and robot.ino no longer zeroes stick
  roll/pitch when it's off.
- remote (Teensy 4.1): Sticks (calibration, EEPROM), RemoteIMU,
  RemoteState (interlocks, link-loss disarm, smoothing), PacketBuilder,
  RadioLink, NextionUI, SerialConsole.
- CLAUDE.md, README.md, remote/README.md, remote/NEXTION.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-09-28 18:14:00 +02:00
1 parent ad77b06c36
commit 91dac16fca
30 files changed
+1706 -57

No files matched your search

+39 -20
View File
@@ -1,16 +1,20 @@
# Hexapod robot firmware (Teensy 4.0)
This is the **robot-side** firmware only. It is fully functional on its own
(driven by the serial test harness below) and is already wired to receive
commands from a future remote over nRF24L01 — the packet format in
`Comms.h` is the contract the remote sketch must match.
This is the **robot-side** firmware. It is fully functional on its own
(driven by the serial test harness below) and receives commands from the
remote (`../remote/`) over nRF24L01. The packet format lives in
`../shared/HexapodProtocol/HexapodProtocol.h` — the single definition both
sketches compile against.
## Required libraries
## Building
Install via Arduino Library Manager (or Teensyduino's manager):
From the repo root (PlatformIO): `pio run -e robot`, flash with
`pio run -e robot -t upload`, monitor with `pio device monitor -e robot`.
RF24 is pulled in automatically via `lib_deps`; Servo ships with the Teensy
framework.
- **RF24** by TMRh20 — nRF24L01 radio driver
- **Servo** — bundled with Teensyduino, nothing to install
Arduino IDE also works if you copy `shared/HexapodProtocol/` into your
sketchbook `libraries/` folder and install **RF24** by TMRh20.
## Before you trust this on the floor
@@ -26,8 +30,12 @@ your own robot and edit:
- `SERVO_PINS` — must be PWM-capable pins on your Teensy 4.0 wiring
- `SERVO_US_AT_0DEG` / `SERVO_US_PER_DEG` — calibrate per servo, they vary
batch to batch
- `RADIO_ADDRESS` / channel (set in `Comms.cpp`) — must match the remote
once it exists
- `RADIO_CE_PIN` / `RADIO_CSN_PIN` — your nRF24 wiring. Address, channel,
data rate, PA level and payload size are in `shared/HexapodProtocol` so
they can't drift from the remote.
- **Pin conflict:** `SERVO_PINS` leg 3 uses pins 11 and 12, which are the
Teensy 4.0's SPI MOSI/MISO that the nRF24 needs. Move those two servos
before wiring the radio.
## Bench-check checklist (do this before the first stand-up)
@@ -50,6 +58,14 @@ for your build:
If your chassis is meant to rest its belly on the ground instead, this
needs a different, sequenced approach (fold legs up rather than just
lowering).
5. **Gait travel direction** (`GaitEngine.cpp`) — the protocol defines
`+vx` = forward, `+vy` = left, `+yaw_rate` = turn left (CCW). As written,
the stance phase sweeps each foot from `neutral - half_stride` to
`neutral + half_stride`, i.e. the foot moves *with* the commanded
direction, which pushes the body the opposite way. Verify with `w` on the
bench; if the robot backs up, swap `start`/`end` in `GaitEngine::update`
(fixes translation and yaw together). The `z`/`c` harness keys were
written against the current behavior — recheck them after that fix.
## Testing without a remote yet
@@ -61,8 +77,8 @@ keystrokes) and use:
|-----|--------|
| `a` | toggle armed |
| `s` | toggle sit / stand |
| `w` / `x` | walk forward / backward |
| `q` / `e` | strafe left / right |
| `w` / `x` | walk forward / backward (`vx` ±) |
| `q` / `e` | strafe left / right (`vy` ±) |
| `z` / `c` | yaw left / right |
| `g` | toggle gait: tripod ↔ wave |
| `m` | toggle walk mode: direct (A) ↔ heading-hold (B) |
@@ -79,17 +95,20 @@ Arm (`a`), then stand (`s`), before trying to walk — the state machine
enforces `DISARMED → SIT → STAND → WALKING` in order and will otherwise
ignore walk commands.
## What's ready for the remote
## Link with the remote
- `Comms.h`'s `CmdPacket` struct and `FLAG_*` bit constants are the exact
wire format the remote must send (as an RF24 payload to `RADIO_ADDRESS`
on the same channel/data-rate/PA-level set in `Comms::begin()`).
- `CmdPacket` and the `FLAG_*` bits in `shared/HexapodProtocol` are the
exact wire format. Both radios set a static payload size of
`sizeof(CmdPacket)`, so a robot and remote built from different protocol
versions won't receive each other at all (and the robot fails safe).
- Failsafe: if no packet arrives for `LINK_TIMEOUT_SEC`, `Comms::linkOk()`
goes false and the main loop falls back to a zeroed `CmdPacket`, which
disarms the robot.
- `FLAG_REMOTE_GYRO` / `FLAG_ROBOT_GYRO` independently gate whether the
remote's tilt feeds into body pose and whether the robot's own IMU
stabilizes it — matching the touchscreen toggles you described.
- The right stick's roll/pitch/yaw (or X/Y/Z) always apply. The remote's
handset tilt arrives in its own `remote_roll` / `remote_pitch` fields and
is added on top only while `FLAG_REMOTE_GYRO` is set, capped at
`MAX_TILT_DEG` total (`InputMapper`). `FLAG_ROBOT_GYRO` independently
enables the robot's own IMU stabilization.
- `FLAG_RSTICK_XLATE` switches the right stick between rotation-axes and
translation-axes interpretation, and `FLAG_MODE_B` switches between the
two walk modes, all inside the existing `InputMapper`.
@@ -108,6 +127,6 @@ robot/
├── StateMachine.h/.cpp - DISARMED/SIT/STAND/WALKING with smoothed sit-stand blend
├── InputMapper.h/.cpp - CmdPacket -> twist/pose/mode decoding
├── Limits.h/.cpp - workspace clamp, joint rate limit, stance polygon check
├── Comms.h/.cpp - nRF24L01 receive + packet/flags definition
├── Comms.h/.cpp - nRF24L01 receive (packet definition is in shared/HexapodProtocol)
└── ServoDriver.h/.cpp - servo attach/relax/write
```