Files
hexapod-robot/2026-current/remote/README.md
T

120 lines
5.6 KiB
Markdown
Raw Normal View History

# Hexapod remote firmware (Teensy 4.1)
Handheld transmitter for the hexapod. It reads two 3-axis twist-grip
joysticks and an MPU6050, takes operator commands from a Nextion
touchscreen, and sends a `CmdPacket` (defined in
`../shared/HexapodProtocol/HexapodProtocol.h`) to the robot over nRF24L01
at 100 Hz.
## Building
From the repo root: `pio run -e remote`, flash with
`pio run -e remote -t upload`, monitor with `pio device monitor -e remote`.
## Wiring (placeholders; edit `Config.h` to match)
| Part | Signal | Teensy 4.1 pin |
|------|--------|----------------|
| nRF24L01 | MOSI / MISO / SCK | 11 / 12 / 13 (SPI0) |
| nRF24L01 | CE / CSN | 9 / 10 |
| nRF24L01 | VCC | 3.3 V, with a 10–100 µF cap right at the module |
| MPU6050 | SDA / SCL | 18 / 19 (Wire) |
| Nextion | TX → RX2, RX ← TX2 | 7 / 8 (Serial2), 5 V supply |
| Left stick | X / Y / twist | A0 / A1 / A2 |
| Right stick | X / Y / twist | A3 / A6 / A7 |
Stick pots are wired 3.3 V – wiper – GND. **Never feed 5 V into a Teensy
4.x analog pin.**
## Control scheme
| Input | Packet field | Meaning on the robot |
|-------|--------------|----------------------|
| Left stick forward/back | `vx` | walk forward/back |
| Left stick left/right | `vy` | strafe (mode A); heading target direction (mode B) |
| Left stick twist | `yaw_rate` | turn rate (mode A only; ignored in mode B) |
| Right stick, **ROTATE** (default) | `rx/ry/rz` | body roll / pitch / yaw |
| Right stick, **MOVE** (`FLAG_RSTICK_XLATE`) | `rx/ry/rz` | body X / Y / Z (height, via twist) offset |
| Handset tilt | `remote_roll/pitch` | extra body roll/pitch while REMOTE GYRO is on |
| Height slider | `body_height` | standing height, default ± `STANCE_HEIGHT_RANGE_MM` (robot rate-limits the change) |
In **HEADING** mode the left stick steers, relative to where the robot
faces at that moment. Forward/back walks forward/back, and sideways
steers: forward+left or back+left walk while turning left, and left alone
turns on the spot for as long as you hold it. Let go and the robot holds
its heading.
Touchscreen: ARM / DISARM, SIT/STAND, TRIPOD/WAVE, DIRECT/HEADING,
R: ROTATE/MOVE, REMOTE GYRO, ROBOT GYRO, speed slider, LEVEL (re-zero the
handset tilt), CAL / CANCEL CAL. `NEXTION.md` has the HMI build guide.
### Safety interlocks (in `RemoteState`)
- **Arming** is refused unless every stick axis is centered, and never
allowed during calibration.
- **Disarming** always clears the stand request. The robot arms into SIT,
so re-arming never stands it up by itself.
- **Link loss:** if no ack arrives for `LINK_LOST_MS` (300 ms, matching the
robot's failsafe), the remote disarms itself. When the link comes back
the robot stays down until you re-arm deliberately.
- **Sit/stand** requests are only accepted while armed. `FLAG_WALK` is only
sent while standing is requested.
- While disarmed or calibrating, all motion fields are sent as zero.
### Smoothing
- **Speed scale** ramps toward the slider at `SPEED_SCALE_RATE_PER_SEC`.
The robot uses speed scale directly on the walking twist, so a slider
jump would otherwise be a velocity step.
- **Remote tilt** fades in/out over ~0.5 s when REMOTE GYRO is toggled, and
the handset re-zeroes its "level" at the moment you enable it.
- **FLAG_WALK** lingers 250 ms after the left stick centers, so hovering at
the deadzone edge doesn't make the robot chatter between STAND and
WALKING.
- Body pose smoothing is left to the robot's `BodyPose` rate limiters.
## Stick calibration
1. Power on with both sticks released and the remote held still. Each
axis's resting center is captured automatically.
2. For full calibration, disarm, then tap **CAL** (or press `c` on the
serial console). Move every axis of both sticks to both limits, release
them, and tap **SAVE CAL** (`c`). The result is saved to EEPROM.
3. If any axis moved less than `CAL_MIN_HALF_SPAN` either side of center,
the save is refused and you stay in calibration mode. **CANCEL CAL**
(`x`) aborts.
4. `p` prints the calibration in a form you can paste into `Config.h`
defaults. `R` wipes EEPROM back to the `Config.h` defaults.
## Serial console (USB, 115200, single keystrokes)
Every touchscreen control is available here, so you can bench-test with no
display attached.
| Key | Action | Key | Action |
|-----|--------|-----|--------|
| `a` | toggle arm | `k` | disarm |
| `s` | toggle sit/stand | `g` | tripod ↔ wave |
| `m` | direct ↔ heading-hold | `t` | right stick rotate ↔ translate |
| `r` | remote gyro on/off | `b` | robot gyro on/off |
| `+` / `-` | speed ±25 | `z` | zero handset level |
| `]` / `[` | height up / down 10% | | |
| `c` | start / save calibration | `x` | cancel calibration |
| `p` | print status (raw + mapped sticks, IMU, link, state, cal) | `d` | toggle 10 Hz packet dump |
| `R` | reset stick cal to Config defaults | | |
## Bench-check checklist
1. **Stick directions:** with `p`, confirm each logical axis reads
positive for right / forward / counterclockwise twist. Flip it in
`STICK_INVERT[]` if not.
2. **IMU mounting:** with `p`, dip the right edge down to get +roll, and
tip the far edge down to get +pitch. If not, fix `IMU_AXIS_FROM_CHIP` /
`IMU_AXIS_SIGN`.
3. **Nextion baud:** `bauds=115200` must be in Program.s, or the display
shows nothing useful.
4. **Radio:** with the robot powered, `tLink` / `p` should show ~100%. If
it reads NO LINK, check that both boards were built from the same
`HexapodProtocol.h`. The static payload size is part of the handshake.
5. **End to end with the robot on a stand:** use `d` to dump packets and
confirm each field changes the way the table above says.