125 lines
4.7 KiB
Markdown
125 lines
4.7 KiB
Markdown
# Controls and hardware map
|
||
|
||
Model: Johnny 5 (Short Circuit) MOC. Seven motors across two Technic hubs.
|
||
|
||
Control scheme is **tank drive**: every input drives exactly one motor. Nothing
|
||
is mixed, so a single stick can never command two motors at once.
|
||
|
||
## Port map
|
||
|
||
| Hub | Address | Port | Function | Desired field |
|
||
| --- | --- | --- | --- | --- |
|
||
| 0 | `90:84:2b:61:e6:8c` | A | Right track | `rightTrack` |
|
||
| 0 | | B | Left track | `leftTrack` |
|
||
| 0 | | D | Body lift | `bodyLift` |
|
||
| 1 | `90:84:2b:61:f2:d7` | A | Head tilt | `headTilt` |
|
||
| 1 | | B | Head turn | `headTurn` |
|
||
| 1 | | C | Left arm | `leftArm` |
|
||
| 1 | | D | Right arm | `rightArm` |
|
||
|
||
The sketch does not rely on this table — it is here for humans. At connect the
|
||
hubs report their own inventory over notifications, so the serial log tells you
|
||
what is actually plugged in:
|
||
|
||
```
|
||
hub0 port A : Technic Control+ LARGE motor (0x002E)
|
||
hub0 port B : Technic Control+ LARGE motor (0x002E)
|
||
hub0 port D : Technic Control+ XL motor (0x002F)
|
||
hub0 port 0x32 : hub RGB LED (0x0017)
|
||
...
|
||
```
|
||
|
||
Internal devices (LED on `0x32`, battery voltage, current, IMU) report as
|
||
attached too. Anything not on A–D can be ignored.
|
||
|
||
## Controls
|
||
|
||
| Input | Function |
|
||
| --- | --- |
|
||
| Left stick Y | Left track |
|
||
| Right stick Y | Right track |
|
||
| D-pad up / down | Head tilt |
|
||
| D-pad left / right | Head turn |
|
||
| R2 | Body lift up (proportional) |
|
||
| L2 | Body lift down (proportional) |
|
||
| Square / Circle | Left arm up / down |
|
||
| Triangle / Cross | Right arm up / down |
|
||
| L1 (held) | Precision mode, 40% track speed |
|
||
| R1 (held) | Full speed, 100% track speed |
|
||
| L1 + R1 together | All stop |
|
||
|
||
Default track scale is 75%. The stick X axes are unused.
|
||
|
||
Bluepad32 names buttons Xbox-style, so in the code `x()` is Square, `b()` is
|
||
Circle, `y()` is Triangle and `a()` is Cross. `throttle()` is R2 and `brake()`
|
||
is L2, both analog 0–1023.
|
||
|
||
Trade-offs in this layout:
|
||
|
||
* **Tracks are independent.** Turning means pushing one stick further than the
|
||
other, like a skid-steer. Takes a minute to get used to, but you always know
|
||
which motor you are commanding.
|
||
* **The head is digital now**, not proportional — d-pad has no analog travel, so
|
||
it runs at a fixed `HEAD_MAX`. Drop that constant if it moves too fast to aim.
|
||
* **Body lift kept the triggers** because they are the only remaining analog
|
||
inputs, and it is the axis that benefits most from proportional control.
|
||
* **D-pad diagonals** will tilt and turn the head simultaneously. That is two
|
||
motors from one thumb, but only when you deliberately press a diagonal.
|
||
|
||
To remap, set `DEBUG_BUTTONS` to 1 at the top of the sketch and press each
|
||
button — it prints the mask so you can match your pad's firmware exactly.
|
||
|
||
## Power caps
|
||
|
||
```cpp
|
||
static const int TRACK_MAX = 100;
|
||
static const int HEAD_MAX = 45;
|
||
static const int LIFT_MAX = 60;
|
||
static const int ARM_MAX = 45;
|
||
```
|
||
|
||
**Everything except the tracks runs into a mechanical end stop.** There is no
|
||
position feedback in this code, so holding a direction against a stop stalls the
|
||
motor — that means stripped gears or a browned-out hub, and the hub will not
|
||
complain until it drops the BLE connection entirely. That is why the non-track
|
||
caps are well below 100. Lower them further if an axis feels forceful, and do
|
||
not hold a direction once the axis has stopped moving.
|
||
|
||
The real fix, worth doing once the travel of each axis is known: Control+ motors
|
||
have absolute encoders. Subscribe to position with Port Input Format Setup
|
||
(`0x41`), learn each axis's limits, and refuse to drive past them. That turns a
|
||
mechanical hazard into a software one.
|
||
|
||
## Rate limiting
|
||
|
||
Two limits, both in `driveMotor`:
|
||
|
||
* `MOTOR_MIN_GAP_MS` (100ms) per port
|
||
* `HUB_MIN_GAP_MS` (25ms) per hub, roughly 40 commands/sec
|
||
|
||
The second one exists because hub 1 has four motors on it. The per-port limit
|
||
alone would let through up to 66 commands/sec to a single hub, which is more
|
||
than these will absorb — you get stutter, then a dropped link. Stops are exempt
|
||
from both and always go out immediately.
|
||
|
||
If motors feel laggy, lower `MOTOR_MIN_GAP_MS` before touching the hub limit.
|
||
If a hub drops out under heavy stick movement, raise `HUB_MIN_GAP_MS`.
|
||
|
||
## Clearing stale pairings
|
||
|
||
Bluepad32 stores Bluetooth pairing keys in NVS, and **reflashing the sketch does
|
||
not clear them**. If you end up with a pad paired into more than one slot, or an
|
||
old device from a previous build still remembered, uncomment this in `setup()`:
|
||
|
||
```cpp
|
||
BP32.forgetBluetoothKeys();
|
||
```
|
||
|
||
Flash once, re-pair, then comment it out again — leaving it in means re-pairing
|
||
on every boot. For a full wipe, Tools → Erase All Flash Before Sketch Upload →
|
||
Enabled, upload once, then set it back to Disabled.
|
||
|
||
---
|
||
|
||
Created by: Jess Rogerson (yelling commands at Claude.AI)
|