概要
愛用している分割キーボードのsoshoが、突然Windows PCとBluetooth接続できなくなってしまいました。
症状としては、Bluetooth設定画面で「接続」と「ペアリング」の表示が1秒間に何度もカチカチ切り替わる謎のループが発生。一度Windows側からデバイスを削除して再ペアリングを試みたものの、今度はリストには出るのに「接続しています」のあとに接続失敗のエラーが出る始末……。
ログを追いかけながらファームウェア(ZMK)側の接続管理と再試行ロジックを修正したところ、無事に常用できるレベルまで復旧できたので、調査の過程と分かったことを残しておきます。
先に結論
- 再ペアリング不能: Windows側とキーボード側でペアリング情報の食い違いが起きていた(キーボード側の該当プロファイルを個別にクリアして解決)。
- マルチデバイスの干渉: 選択していない端末との接続が維持されっぱなしになる問題があったため、切替時に旧端末との接続を切る処理を追加。
- 接続ループの回避: 接続失敗が続く場合、5秒ごとに接続待ち(アドバタイズ)をやり直す処理を入れて自動復帰できるようにした。
なお、そもそも最初の1回目で接続確立に失敗する根本原因までは特定できていません。ただ、現在は5秒以内に自動で再試行されてつながるため、体感としては「復帰に少し時間がかかるかな?」程度で、実用上のストレスはかなり解消されました。
症状と環境
今回の検証環境です。
| 項目 | 環境 |
|---|---|
| キーボード | sosho(左:トラックパッド / 右:トラックボール) |
| 主マイコン(右側) | Seeed XIAO nRF52840 Plus |
| ファームウェア | ZMKベースのカスタム構成(Zephyr 3.5.0) |
| 検証用PC | Windows 11(Intel AX201) |
| その他の接続先 | iPhone、iPad |
※ログ解析やコード修正の補助にはCodexを使い、実際の接続切替や入力テストは実機で行っています。
切り分けのため、以下の2点に分けて調べました。
- Windowsから登録削除後、再ペアリングできなくなった問題
- 突然発生するようになった接続・切断の無限ループ現象
1. 再ペアリングできない問題
まず「削除後に再ペアリングできない」問題ですが、これは単純にsosho側に古い接続プロファイルが残り続けていたのが原因でした。
Windows側の詳細ログを見ると登録や認証キーはきれいに削除されていましたが、soshoをUSB接続して設定を確認すると、選択中のプロファイルに古いPCの情報が残ったままでした。
このPCに対応するプロファイルだけをピンポイントでクリアしてペアリングし直したところ、無事に認識されました。他の接続先やStudioでカスタムしたキー配置は消したくなかったので、全初期化用UF2(settings_reset.uf2)は使わずに済ませています。
ZMKは新しいペアリング時に古いプロファイルを自動上書きしてくれない仕様のようです。やり直すときは「PC側とキーボード側の両方で登録を消す」という基本を徹底する必要がありました。公式のBluetooth説明
2. 接続ループをログで追跡する
次に、一番厄介だった接続ループの調査です。WindowsのBluetooth詳細ログと、診断用ファームウェアのUSBログを照合して追跡しました。
ログに大量に出ていたのは 0x3E(接続確立失敗)というエラー。接続完了の通知が出た直後、数十ミリ秒で切断される動作を繰り返しており、ひどい時には474回も失敗をカウントしていました。
ただ、このエラーコード自体は「Bluetooth接続を確立できなかった」という事実を示すだけで、ファームウェア側の問題なのか、Windowsのドライバなのか、電波やハードウェアの問題なのかまでは絞り込めません。Bluetoothのエラーコード定義
sosho側のログを見ると稼働時間は増え続けており、マイコン自体が再起動しているわけではありませんでした。さらに謎だったのは、接続を試みているPC以外の端末(iPhoneなど)とは接続を維持していた点です。
iPhoneの「接続中」が残る問題も関係していた?
ここでふと、以前から気になっていた別の不便さを思い出しました。
soshoをiPhoneやiPadにつないだあとPC用プロファイルに切り替えても、iPhone側では「接続中」の表示が残ってしまいます。文字入力自体はPCに飛ぶのですが、iPhone側は外付けキーボードがつながっていると誤認しているため、画面のソフトキーボードが出なくなっていました。
ZMKの仕様を調べてみると、プロファイルを切り替えても「裏で他端末とのBLE接続自体は維持される」ことがあるようです。入力を送る対象は選択中の端末だけですが、物理的な接続は複数残ってしまいます。
ドキュメントを確認すると、非選択端末との接続を切る BT_DISC という挙動が用意されていました。Bluetooth Behavior
たとえばプロファイル2の接続を切る場合は、キーマップの bindings に以下のように記述します。
&bt BT_DISC 2
※ BT_DISC は通信を切断する操作で、ペアリング情報を消す BT_CLR とは異なります。
単独接続に制限してみる
そこで試しに、選択中のPC以外とは接続しない(単独接続にする)テスト用ファームウェアを作ってみました。
| 試した条件 | 結果 |
|---|---|
| 通常の接続方式(リセット後) | 接続確立に474回失敗。他端末との接続は維持 |
| 選択中PCだけに制限 | 3回試してすべて8〜10秒で接続成功 |
| そのまま運用確認 | 時間が経つと、単独接続でも再発 |
一瞬「同時接続が犯人か!」と思ったのですが、追試を進めると他端末を切断した状態でも症状が再現してしまいました。接続台数を減らすと成功率は上がるものの、これが根本原因というわけではなさそうです。
3. 「プロファイル切替」で復旧することを発見
調査中、偶然ひとつのみつけものがありました。
- 接続失敗ループに陥っている状態にする
- 空いているプロファイルへ一瞬切り替える
- すぐ元のPC用プロファイルに戻す
この操作を行うと、わずか2.5秒ほどで接続が復旧し、認証まで正常に通ることが分かりました。
なぜ一発目の接続でコケるのかは依然として不明ですが、「接続待ち(アドバタイズ)を作り直してあげれば復帰できる」 という強力なヒントが得られました。
4. ファームウェアへ加えた対策
根本原因の特定は一旦諦め、運用でカバーするためにファームウェア側へ以下の2つの改修を加えました。
① プロファイル切替時に旧端末を切断する
プロファイルを切り替えた際、新しい選択先からの接続のみを受け付けるように変更。iPhone側のソフトキーボードが隠れてしまう問題も同時に解決しました(保存済みのペアリング情報は保持されるため、戻ったときの再ペアリングは不要です)。
② 未接続時は5秒ごとに接続待ちをやり直す
登録済みの端末につながっていない状態に限り、5秒周期でBLEのアドバタイズを停止→再開始する処理を追加しました。同じプロファイルキーを押した際も未接続なら再試行が走ります。
(※接続済みの状態や、新規ペアリング処理中はこのループをスキップします。)
まとめと現在の状況
改修後、実機で以下の動作を確認できました。
- 切替キーでPC・iPhone・iPad間をスムーズに再接続できるようになった。
- PC操作中にiPhone側でソフトキーボードが正常に出るようになった。
- 万が一接続に失敗しても、5秒以内に自動的にアドバタイズがやり直され、接続が維持される。
起動直後のログに一瞬だけ失敗が刻まれる挙動自体は残っていますが、勝手にリトライされて復旧するため、普段使いする上でのストレスはほぼゼロになりました。根本原因の探求はまた折を見てやってみようと思います。
おまけ:使っているファームウェアとキー配列
今回の不具合調査でZMKをいじり倒すことになりましたが、普段の運用環境も少しこだわっているのでついでに紹介しておきます。
1. DYA StudioでBluetooth越しにキーマップ変更
ファームウェアは、cormoran氏が開発されているDYA Studio(Web GUI)に対応したカスタム版をビルドして導入しています。
ZMKは通常、キーマップ変更時にUSB接続してファームウェアを書き直す必要がありますが、DYA Studioを入れるとBluetooth接続のままWebブラウザ上ですぐにキー配置やトラックボール感度を調整できるようになります。これが快適すぎて手放せません。見た目もモダンでかっこいいです。
2. キー配列は「大西配列」を採用
配列は、日本語のローマ字入力に特化して作られたモダン配列の大西配列を使っています。
QWERTY配列に比べて指の上下移動と同指連続打鍵が劇的に減り、日本語の約8割を左右交互打鍵で流れるように入力できます。分割キーボードのエルゴノミクス効果と相まって、長時間のタイピングでも指が疲れにくくなるのでかなりおすすめです。