YouDuck.ai

Pair a gamepad

Last updated

Once per pad. After that padd.service drives whatever pad connects, from boot — nothing to start, and nothing that dies with your ssh session.

Put the pad in pairing mode

On an Xbox controller this is two presses, and the second is the one that goes wrong:

  1. Switch it on with a short press of the Xbox button. Held, that button switches the controller off.
  2. Press the small Sync button on the top edge until the light flashes quickly. Slow blinking means it is on but not pairing.

On a DualSense: hold Create and PS together until the light bar flashes.

Pair it

sudo robotctl pad pair
sudo robotctl pad pair 78:86:2E:BB:13:28
sudo robotctl pad pair --timeout 5

No MAC address needed — the robot looks for a pad in pairing mode and takes the one it finds. The pad is trusted as well as paired, which is what makes it reconnect by itself after a reboot with nobody logged in.

If two are in pairing mode it refuses rather than guessing, and prints both addresses. Naming one is also how to pair hardware the robot does not recognise as a gamepad.

A second pad needs no forgetting

A pad already bonded is in range and in every sweep, so the robot prefers one in pairing mode. Both stay paired afterwards and padd drives whichever connects.

The cost is that re-running with nothing new in pairing mode waits out the whole search window before reporting the pad you already have. --timeout 5 if you are only repairing trust.

Check it

robotctl pad status
pad     Xbox Wireless Controller 78:86:2E:BB:13:28  connected
padd    active — driving whatever pad connects

Two lines, because they fail separately. A connected pad with a dead driver looks exactly like a working robot ignoring you.

paired but NOT trusted is the state worth knowing: it works now and does not reconnect after a reboot, because approving a reconnection needs an agent and at boot there is none. Re-run pad pair to fix it.

Forget one

sudo robotctl pad forget 78:86:2E:BB:13:28

This removes the robot’s half of the bond, which is all a robot can remove. The pad keeps its own half, so pairing it again needs it back in pairing mode — otherwise it arrives with a key this robot no longer has and the bond is refused.

An Xbox pad holds one host bond, and a half-completed attempt leaves it holding a key this board no longer has — which fails in exactly the way a broken board does.

If pairing keeps failing, pair the pad to a laptop once and remove it there. That consumes and releases its bond slot; putting it in pairing mode alone does not reliably do so.

When a pad will not bond at all

On the aic8800 radio a pad cannot form a new bond while btd is advertising. Re-provision such a board with --pause-btd-on-pair:

./scripts/provision-board.sh --pause-btd-on-pair [email protected]

That leaves a marker at /var/lib/robot/weird-ble and changes nothing else. On a board with that marker, sudo robotctl pad pair handles the rest itself — it stops btd, power-cycles the adapter, pairs, and starts btd again. An existing bond is unaffected.

Some units also need the Privacy setting

Some boards cannot bond under BlueZ’s default Privacy = off even with btd paused. Those want --weird-ble, which implies the pause and also sets Privacy = device.

Try the pause first. Privacy = device on a board that only needed the pause produces a worse failure than no flag at all: the pad bonds and then flaps with Encryption Change: PIN or Key Missing (0x06), never creating an input device.

Seeing that error means dropping --weird-ble and keeping the pause.

Pairing by hand on such a board

sudo systemctl stop btd
sudo bluetoothctl power off && sudo bluetoothctl power on

Pair, then sudo systemctl start btd.

The power cycle is not optional. Stopping btd leaves its advertisement and the IO capability its pairing agent gave the controller behind, and a pad still refuses to bond.

When it drops while you are driving

Watch the link live: run robotctl monitor, then press p for the pad’s raw input stream — every evdev report, with the gaps between them.

That is the only place a stalled radio is visible. There is a failure padd cannot see, where the link stays up and the robot walks on a stale command; only the gaps between input reports reveal it.

This view works with no robot too: on a board whose servos are unpowered, the monitor opens on the pad block instead of refusing.

For a verdict over a window instead:

scp scripts/pad-link-test.sh radxa@<board>:/tmp/
sudo sh /tmp/pad-link-test.sh --history   # drops already in padd's journal
sudo sh /tmp/pad-link-test.sh             # measure now, keep the sticks moving

When two boards behave differently

scp scripts/pad-stack-report.sh radxa@<board>:/tmp/
sudo sh /tmp/pad-stack-report.sh

Kernel, BlueZ, controller firmware, LE or BR/EDR, and the pad’s own firmware revision. --fingerprint prints only the values that must match between two boards, for diff.

Related