配对手柄
最后更新
一台手柄只需要配对一次。配好之后 padd.service 从开机起就会驱动任何连上来的手柄——不需要手动启动任何东西,也不会随着你的 SSH 会话断开而失效。
先把手柄切到配对模式
Xbox 手柄是两次按键,而出错的总是第二次:
- 短按 Xbox 键开机。不要长按——长按是关机。
- 按顶部靠近 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 [email protected]
它会在 /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。