YouDuck.ai

配对手柄

最后更新

一台手柄只需要配对一次。配好之后 padd.service 从开机起就会驱动任何连上来的手柄——不需要手动启动任何东西,也不会随着你的 SSH 会话断开而失效。

先把手柄切到配对模式

Xbox 手柄是两次按键,而出错的总是第二次:

  1. 短按 Xbox 键开机。不要长按——长按是关机。
  2. 按顶部靠近 USB-C 口的小 Sync 键,直到 Xbox 灯快闪。慢闪表示只是开着机,没进配对模式。

DualSense:同时按住 Create 和 PS 键,直到灯带闪烁。

配对

sudo robotctl pad pair

不需要 MAC 地址。机器人会扫描处于配对模式的手柄并接管找到的那一个。手柄会被同时标记为 paired 和 trusted——后者才是它能在重启后(且无人登录时)自动重连的原因。

如果同时有两个手柄处于配对模式,它会拒绝而不是随便猜,并打印出两个地址。指定地址也是配对“机器人不认为它是手柄”的硬件的方法:

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

配第二个手柄不需要先删掉第一个

已经绑定的手柄在范围内、每次扫描都能看到,所以机器人优先选择处于配对模式的那个。配完之后两个手柄都保持配对状态,padd 驱动先连上的那个。

代价是:如果没有新手柄处于配对模式时重跑这条命令,它会把整个搜索窗口等完才报告你已有的手柄。只是想重新建立信任关系的话,加 --timeout 5

确认

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

两行,因为它们是分开失败的。

有一个状态特别值得认识:paired but NOT trusted。这种状态下手柄现在能用,但重启后不会自动重连——因为批准重连需要一个 agent,而开机时没有。重新跑一次 pad pair 就能修好。

解除配对

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

这只删除机器人这一侧的绑定关系,也是机器人唯一能删的那一半。手柄保留自己那一半,所以要重新配对必须把它重新切到配对模式——否则它会带着一个机器人已经不认识的密钥连过来,绑定被拒绝。

这里有个 Xbox 手柄的硬限制:一个 Xbox 手柄只能保存一个主机绑定。一次失败的配对尝试会让它保存着一个本板子已经没有的密钥——失败表现和板子坏了一模一样。

如果配对反复失败,把手柄配到一台笔记本上再在笔记本上删除。这个过程会消耗并释放它的绑定槽位。只把它切到配对模式并不能可靠地做到这一点。

完全配不上:aic8800 无线芯片

在 aic8800 无线芯片上,btd 正在广播时手柄无法建立新的绑定

这类板子需要用 --pause-btd-on-pair 重新 provision:

./scripts/provision-board.sh --pause-btd-on-pair pierre@192.168.1.42

它会在 /var/lib/robot/weird-ble 留一个标记文件,除此之外不改任何东西。有这个标记的板子上,sudo robotctl pad pair 会自己处理剩下的事——停掉 btd、给蓝牙适配器断电重启、配对、再启动 btd,并且过程中会打印它在做什么。已有的绑定不受这些影响,所以配好的手柄在一切正常运行时照样能连能用。

少数机器还需要改 Privacy 设置

有些板子即使暂停了 btd,在 BlueZ 默认的 Privacy = off 下依然无法绑定。这些需要 --weird-ble,它包含暂停行为,并额外设置 Privacy = device

先试暂停这一个。 这一点很重要——官方文档明确警告:

在只需要暂停的板子上设 Privacy = device 会产生比不加任何参数更糟的失败:手柄能绑定上,然后不断掉线并报 Encryption Change: PIN or Key Missing (0x06),永远创建不出输入设备。

看到这个报错,就把 --weird-ble 去掉、保留暂停。

手动配对时的两步

在这类板子上手动配对需要同样的两步:

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

配对,然后:

sudo systemctl start btd

断电重启这一步不是可选的。 只停掉 btd 会留下它的广播和它的配对 agent 给控制器设置的 IO capability,手柄依然拒绝绑定。

驱动时掉线

怀疑链路本身有问题时,实时观察它:跑 robotctl monitor,然后按 p 打开手柄原始输入流——每一份来自手柄的 evdev 报告,以及它们之间的时间间隔。

这是唯一能看见“无线电卡住”的地方。这一点值得展开:还有一种 padd 自己看不到的故障——链路保持连接、机器人拿着一条过期的指令继续行走。只有看输入报告之间的间隔才能发现它。

这个界面没有机器人也能用:舵机没上电、或者 robotd 停着的板子上,monitor 会直接打开在手柄面板上,而不是拒绝启动。

想要一段时间窗口的统计结论而不是实时画面,从仓库克隆里把测量脚本拷过去:

scp scripts/pad-link-test.sh radxa@<board>:/tmp/

已经记录在 padd 日志里的掉线可以立刻查,不需要接手柄:

sudo sh /tmp/pad-link-test.sh --history

或者现场测两分钟——期间要持续拨动摇杆

sudo sh /tmp/pad-link-test.sh

它会统计掉线次数并对应到内核给出的每一次原因,同时记录手柄输入报告之间的间隔。

两块板子表现不一样

同一个手柄在两块板子上行为不同时,差异在底下的协议栈里:

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

它会打印内核版本、BlueZ 版本、蓝牙控制器固件、走的是 LE 还是 BR/EDR,以及手柄自身的固件版本,同时保存到 /tmp/pad-stack-<host>-<when>.log

--fingerprint 只打印两块板子之间必须一致的那些值,方便直接 diff

相关内容