技術レビュー

ジェスチャーコントローラーを無線化 -Bluetooth LE- してみた

 UnrealEngine上でキャラクターのちょっとした身振り手振りの動作させるためのトリガーコントローラーを以前製作しましたが今回はそれを無線化してワイヤレスで使えるようにしてみました。無線にはBluetoothを選択しましたがBluetoothを使ったデバイスを作るのは久々だったので試行錯誤しながらの開発でした。完成した商品の紹介とともに開発顛末もブログに書いていきます。

 最初からジェスチャーコントローラーを無線化しよう!なんてことはなく、作ったきっかけは別にあります。デバイスを開発するときに外装ケースをどうするか考えるわけですがそのケース製造で有名なタカチ電機工業という会社があります。普段私もここのケースを使って穴あけ加工や塗装を頼んだりしています。なのでたまに製品サンプル配布のメールが来ていてちょっといいなというものがあればいただくこともあります。

 今回GETしたのはIP67ポータブル防水ケースというモデルです。選んだ理由は防水が必要だったというわけではなく単にカッコ良さげだっただけのことです。ボタン電池タイプが主のようですが単4電池x2が入るモデルにしてみました。ケース眺めて何に使おうかと考えた挙句、以前作ったジェスチャーコントローラーの機能をこの中に詰め込もうという考えに至りました。

関連Blog
【UE5】プアマンズジェスチャーコントローラーを作る

Link

 ブレッドボードに組んだ回路のままだったしケーブル配線が複数あって邪魔なので使い勝手が悪く、無線化&電池駆動にさせてすっきりさせることにします。

 次にどんな機能を持たせるか考えます。既に元ネタはあるので足したい機能を妄想するだけです。
 ・UnrealEngineで使えるワイヤレスジェスチャーコントローラー
 ・M-Design Virtual Studioに搭載してあるシリアル通信機能をそのまま使う
 ・ステータス表示のディスプレイは欲しい
 ・握力に対するセンサーの感度調整機能はつけたい
 ・単4電池x2 で駆動する(アルカリ、ニッケル水素充電池、リチウムイオン充電池のどれでも動作可能にする)
 ・接続に必要な煩わしいオペレーションはしない

という感じになりました。
センサーの感度調整は人によって握力が違うので合わせるために付けることにしました。電池の種類を選ばないようにしたのは入手性を考慮してのことです。放送業務用システムの設計をしているので現場使用で急な買い出しに走って簡単に入手できるようにすることが染み付いてしまっています。

 まず無線化させるモジュールの選定ですがWi-Fiで電池駆動は消費電力の面で厳しいだろうということでBluetooth対応のものということになります。前回使用したRaspberryPi Pico Wや手持ちのESP32の開発ボードを使おうとしましたが他の部品の搭載を考えるとケースに収まらないので専用基板を作ってそれに載せられるモジュールを選ぶ必要がありました。ということで選んだモジュールがEspressif社のESP32-C3-WROOM-02-N4という製品です。

 このモジュールを選んだわけは、
 ・Wi-Fi、Bluetooth 5.0に対応
 ・制御用に別のマイコンが要らない(このモジュールで完結できる)
 ・MCUコアがRISC-Vベース
 ・他のESP32ベースのモジュールより消費電力が低い(らしい)
 ・十分小さいが手ハンダできる大きさ
 ・技適(技術基準適合証明)取得済み(シールが付いてくる)
 ・安い(秋月電子で¥310)
 ・ESP32の資産が活用できる(以前別のESP32モジュールを使ったことがある)
 です。RISC-Vは特に意識してコードを書いたわけではありませんが今流行りらしいので乗っかってみただけです。

他にも必要な部品をリスト化して秋月、千石、Amazon、ダイソーで調達します。ちなみにパーツで一番高いのはケースです。(今回買ってませんが、、)

 買ってきた部品をブレッドボード上に組み込んでテストすることにします。モジュールのESP32-C3-WROOM-02-N4はそのままブレッドボードに挿せないので変換基板を作りました。基板製作にはJLCPCBというプリント基板製造メーカーに依頼しました。ネット上で激安との評判でそれに釣られてのことです。確かに基板5枚、送料込みで$3.46、中国から航空便+ヤマトネコポス便で来ていてガーバーデータ提出から1週間で届きました。どういう仕組みなのかよくわかりません。

 Bluetoothを使ってデータをシリアル転送扱いでPCに送信するにはSPP(Serial Port Profile)というプロファイルを使うのがラクです。PC側とペアリングするとデバイスマネージャーに仮想シリアルポートが現れて有線接続と全く同じに使えるようになります。PCが最初からBluetooth使える機種であれば別途ハードウェアを用意する必要もありません。今回の用途にはまさにうってつけです。

 早速コード書いてコンパイルし半田付けしたESP32-C3からテスト転送してみます。
   あれれ?何も反応しない、、!?

 試しにESP32-DevkitCという市販の開発ボードがあるのでこちらでやってみると、、普通に動く、、

何が違うのか?ってモデルが違うだろ!

 

 現在Bluetoothの最新バージョンは5.4です(2024年6月)バージョン4.0からBluetooth Low Energy(通称 BLE)というそれまでとは互換性の無い規格を追加するようになりました。それまでの規格はBluetooth Classicと呼ぶようになり(通称 BR/EDR)、使おうとしたSPPプロファイルはこちらの規格に属するものです。
 今回使うESP32-C3-WROOM-02-N4の仕様を見るとBluetooth 5.0とあるので動きそうなもんですが(だから買った)よくよくドキュメントをみてみるとBLEのみ対応でClassicには対応しないとのこと、、

Bluetoothはバージョン4以降はBLEしかないというのは間違いではあるがメーカーの考えや差配によってClassic (BR/EDR) が省かれることがある(主にコスト面で)

 ここへ来て仕様変更です。その前に仕様書をよく読めって感じですが、

 盛り上がってまいりました

 仕事をやっていれば途中で急な仕様変更に対応することなんてザラにあることです。問題はどのように仕様変更したら被害が少ないというかスムーズに解決できるかです。BLE使っての仕様変更の案を考えると、
 1、UnrealEngineで代替えできる機能がないものか
 2、Nordic UART Service を使う
 3、普通にESP32どうしでBLE通信→USBシリアル変換してUnrealEngineへ送る
というのが頭に浮かびました。

1はEpicのマーケットプレイスでBLE Utilities V2というプラグインがあるのですがAndroid OS / iOS 用のものでデスクトップOSでは動作しないようです。
2はBLEでUART通信するには業界標準のやり方のようで(ただしBluetooth規格の標準サービスではない)ESP32でも扱えるのですが本来ならNordic社のチップを使うのがスジで消費電力も小さく済むようです。一応送信側をESP32でNordic UART Serviceを使えるようにはしてみました。(受けはスマホでチェック)
結局のところ普通に3を選択しました。最終的なデバイスの基板を2つ製作して内部のコード違いで送受信ができるようにします。ESP32-C3-WROOM-02-N4はUSBシリアル変換機能が内蔵されているので別途チップを用意しなくても線を引っ張り出せばそれ経由でPCからはシリアルポートとして認識されます。

 BLE通信の基本としてデバイスはCentral(親機)、Peripheral(子機)の区別があり今回はジェスチャーコントローラー側がPeripheral、UnrealEnginePC側の受けデバイスがCentralとなります。双方の電源が入るとPeripheral側はアドバタイズという自身の存在を周りに知らせる機能が働き、Central側は周辺をスキャンしてつながるデバイスを探しに行きます。双方のデバイスには固有のID(Servive UUID、Characteristic UUID)が設定されていてこれが合えば自動的に繋がるようにしています。(UUIDは独自に設定)もちろんBluetooth接続時でお馴染みのパスキー(暗証番号)を使ったりMACアドレス指定して特定のデバイスのみ繋がるようにしセキュリティを高める方法もあります。

 双方が繋がるとGATTという通信モードに入りデータのやり取りをすることができます。途中で接続が切れたら自動的に再試行するようにしています。送ってるデータはまぁ平文ですがセキュリティを高めるのにBluetooth規格にある方法では大した対策にならないっぽいので、独自の暗号化や使用場所がせいぜいスタジオ内想定なので電波強度を調整した方がいいかなと思います。それでも悪意のある人って、、むしろ見てみたいもんです。

 デバイスを電池2本で動かすわけですが種類は問わないと言ってもアルカリ電池、ニッケル水素充電池、リチウムイオン充電池(あの横っ面にUSB挿して充電できるタイプ)それぞれ電圧も特性も違います。今回使用するメインのモジュールは、
 Espressif ESP32-C3-WROOM-02-N4
 最低電源電圧 3.0V
 最大電源電圧 3.6V
という仕様で電池を何の対策もせずに使おうとするとアルカリでは容量だいぶ残したまま途中で止まってしまいますしニッケル水素では必要電圧に届きません。ということでDC-DCコンバーターで昇圧することにします。小さい基板に載せることを考えてトレックス・セミコンダクター社の製品で3.3Vに昇圧させることにしました。
 あともう一つは電源スイッチです。こちらは電源ボタンをちょい長押しでON、少し長めの押しでOFFができるロードスイッチを使っています。またこのスイッチモジュールからの信号でOFFにさせることもできるのでシャットダウン時にMPU側の処理を終わらせてからOFFにさせるなんてことも可能です。ON時もソフトスタートしてくれるのでパチパチスイッチで動作させるよりはるかに安全です。

左がDC-DCコンバーター右がロードスイッチIC

 ただしこれらのチップ本当に小さいんですね。ロードスイッチは2mmx2mmしかないのにパッドが9つもあります。最初は何とかハンダこてでつけようとプットプリント変えて何とか下からハンダを流し込もうと思ったのですが素直にリフローすることにします。(リフロー機器を手に入れました)

 というわけでコントローラーが完成しました! 基板は必要部品だけなのでかなりスカスカです。裏面には電源スイッチ、握力調整半固定ボリューム、ステータス表示のOLEDディスプレイを取り付けてあります。さっそく動作検証です。ボールを一握りした時の最大握力値をUnrealengineに転送しています。なので少しづつ力を加えている時は値を出力せず力が抜けた直前の値を転送する仕組みにしています。UnrealEngine側のロジックは一切変えていません。

 

 本機は単四電池x2本で動作しますが試しにダイソーのアルカリ電池を使ったところ動作時間は7時間くらいでした。IoT機器のようにDeep Sleepを使った間欠動作では無く常に情報入力を待ってリアルタイム伝送させる動作なのでこんなものかと思います。とはいえ少なくとも展示会などの1日仕事くらいは持ってもらいたいものです。
 というわけで何か消費電力を下げる手立てはないものかと調べてクロック周波数を下げることにしました。MCUは通常160MHz動作なのですがBLEが動作するギリギリの80MHzに落としてみました。すると
 動作時間 9.5時間
まぁこれなら何とかなりそうです。電池切れたら変えればいいわけですしね。ちなみに東芝製ニッケル水素充電池 Impulseで試してみましたが同じような動作時間になりました。

 今回は圧力センサの値をBLE-シリアル経由でUnrealEngineに送り、キャラクターのジェスチャーコントロールをしてみたわけですが、要は何らかのセンサの値をUnrealEngineに送るデバイスなので例えばモーションセンサーを使ってトラッカー代わりに使ったりすることも出来そうです。またワイヤレスということでセンサ側の自由度が上がるためワイヤードでは難しかった情報入力方法が可能になり用途が広がりそうです。

  今後の展望
 ・コントローラ側のセンサをモジュール化して取り替えられるようにする
 圧力センサ以外に他のセンサに取り替えられるような構造にすれば他に転用できる設計となります。まだ基板の面積に余裕があります。
 ・受信側のソフトウェア化
 今回は受信側(Central)をハードウェアで行っていますが、それ無しにUnrealEngine側に機能を実装したほうが機材側の見た目がすっきりします。Blueprintプラグインでも作りましょうかね?
 ・複数台のコントローラーを同時受信する
 複数のセンサの同時使用を考えてBLE同時接続できるようにすると高度なキャラクター制御ができそうです。

 さていつやるか、、妄想は一瞬で終わるのに、、