Files
ps4-lego-onebrain/docs/CONTROLS.md
T

3.6 KiB
Raw Blame History

Controls and hardware map

Model: Johnny 5 (Short Circuit) MOC. Seven motors across two Technic hubs.

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 AD can be ignored.

Controls

Input Function
Left stick Y Drive forward / back
Left stick X Turn
Right stick X Head turn
Right stick Y Head tilt
R2 Body lift up (proportional)
L2 Body lift down (proportional)
D-pad up / down Left arm up / down
Triangle / Cross Right arm up / down
L1 (held) Precision mode, 40% drive
R1 (held) Full speed, 100% drive
Circle All stop

Default drive scale is 75%.

Bluepad32 names buttons Xbox-style, so in the code y() is Triangle, a() is Cross and b() is Circle. throttle() is R2 and brake() is L2, both analog 01023.

Why this layout: arcade drive on one stick keeps the other free for the head, which is the expressive part of this model. The analog triggers go to body lift because it is the heavy slow axis that benefits most from proportional feel. Arms are digital because they are pose-and-hold, not modulate.

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

static const int TRACK_MAX = 100;
static const int HEAD_MAX  = 50;
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.


Created by: Jess Rogerson (yelling commands at Claude.AI)