プロポからパッド
自作ドローンのコントローラーを市販のプロポにしていたが、受信側での信号変換が面倒なので、ゲームパッドから無線モジュール経由に変更したいと思っていた。ELECOMのJC-U4013Sをアキバで買った(価格は忘れた)が、はじめはなんとも手が出せなかった。
その間、別のUSBデバイスを使う機会があって、そのやり方がそのまま使えることが分かったので、試してみた。
libusbjava を使う
JAVAで操作する。そのため、まず、Windowsでlibusbjavaを使えるようにする。
https://libusb-java.ch/
の指示通りのインストールを行う。少し面倒だが、丁寧に指示をたどって実行する。そして、LibusbJava.jarを自分のプロジェクトに組み込む。
ベンダーIDとプロダクトIDを調べる
Windowsのコントロールパネル→ハードウェアとサウンド→デバイスとプリンターなどを探って、デバイスを表示させ、JC-U4013Sのプロパティを見ていくと「詳細」のところに、
「デバイス HID\VID_056E&PID_200F\7&b070207&0&0000 が構成されました」
などと記述されている。これで、ベンダーIDが0x056E、プロダクトIDが0x200Fであることがわかる。それ以外の記述の意味は知らない。IDは、多分どの環境でも同じような気がするが、確かめてはいない。
デバイス開閉のJAVAのコード
まず、コンテキストオブジェクトを作成し、デバイスオブジェクトを作成する。その際、先に取得した二つのIDを使う。
// デバイスを開くとき
Context useCtx = new Context();
Device usbDev = Device.search(useCtx, 0x056E, 0x200F);
usbDev.open();
// デバイスを閉じるとき
usbDev.releaseInterface(0);
usbDev.close();
エラーなどの細かい処理はここには記載しないが、基本的にtry-catch (LibusbException ex)で成功/失敗がわかる。
ゲームパッド出力の読み取り
こんな感じだが、細かい引数の意味については、先のサイトにあるAPIのページを参考にしていただきたい。
int ret = usbDev.readBulk(0x01, rdata, rdata.length, 2000, true);
ゲームパッドからのデータは、28バイトで、スティック、ボタンの状況がわかるようになっている。ただし、注意しなければならないのは、56バイト、すなわち、2つ分を一度に送ってくるので、それを切り分ける作業が必要である。
データは、すべて0から255の整数値として送られてくる。スティックは連続量だが、ボタン類は、おさないと0、押すと255になる。
また、データは、そのままとると符号付の値となっているので、私の場合は、
int rd = Byte.toUnsignedInt(rdata[i]);
として、符号なしの少数に変換している。そうしないと、スティック一の値が跳んでうまく連続量が処理できなかった。
私の場合は、こんな感じで出力を処理している。jdataというオブジェクトにデータを放り込んでいる。送られたデータのバイト列の何番目が、どのデータであるかも、わかるようにしている。
/*
データ出力フォーマット
スティック
(0から255の値)中央値127でスティックニュートラル
4列:左スティック左右、5列:左スティック上下、6列:右スティック左右、7列:右スティック上下
4つボタン左
8列:左、9列:右、10列:上、11列:下
4つボタン右
12列:右、13列:左、14列:下、15列:上
フロントボタン
16列:左上、17列:右上、18列:左下、19列:右下
*/
switch (count) {
case 4 -> jdata.rtdrive = (double) rd;
case 5 -> jdata.uddrive = (double) rd;
case 6 -> jdata.lrdrive = (double) rd;
case 7 -> jdata.fbdrive = (double) rd;
case 8 -> jdata.left4r = rd > 100;
case 9 -> jdata.left4l = rd > 100;
case 10 -> jdata.left4u = rd > 100;
case 11 -> jdata.left4d = rd > 100;
case 12 -> jdata.right4r = rd > 100;
case 13 -> jdata.right4l = rd > 100;
case 14 -> jdata.right4d = rd > 100;
case 15 -> jdata.right4u = rd > 100;
case 16 -> jdata.fleftu = rd > 100;
case 17 -> jdata.frightu = rd > 100;
case 18 -> jdata.fleftd = rd > 100;
case 19 -> jdata.frightd = rd > 100;
}
パッドの読み取り動画
実際、GUIをJAVAで作って、ゲームパッドの出力データを表示させた動画は、以下でご覧ください。
https://youtu.be/XUuMUdgNt7c
以上です。