Simulation - sim/: the unchanged robot firmware compiled into hexapod_sim.dll against PC stand-ins (Arduino, Servo, Wire + register-level MPU6050, RF24 with matching-config radio), a kinematic body model (support plane + planted-foot odometry) that also drives the simulated IMU, and a headless smoke test (sim_smoke). build.ps1 builds and tests. - Hexapod_Simulation_Unity/ folded in (history kept in a bundle outside the repo). Assets/HexapodSim loads the DLL, drives the existing leg rig, and offers joystick / keyboard / robot-serial input plus a test panel. Robot (all found or confirmed in the simulation) - Config.h geometry taken from the Unity model. - IK femur elevation sign, gait stance direction, body pose rotation direction, yaw lever arm. - Stance feet integrated from the current command; gait restarts at mid-stance; heading integrates the applied turn rate, only while walking. - Leg clearance and reach checks (Limits::feetFeasible); walk command and body pose scaled as a whole, pose scale rate-limited, planted feet guarded so the body never snaps or legs collide. - Robot-gyro self-leveling as an integrator. - Heading mode: steering relative to the body; S walks backward. - Standing height from the remote (STANCE_HEIGHT_RANGE_MM). Protocol v3 (reflash both boards) - CmdPacket gains body_height (22 bytes). Remote - Height slider (Nextion hHeight/nHeight, serial [ ]). - Fixed unspecified I2C read order in RemoteIMU. LEGACY/: owner's old Nextion HMI and remote hardware assets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
121 lines
5.6 KiB
Markdown
121 lines
5.6 KiB
Markdown
# 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.
|