作成日:2016年4月12日
最終更新日:
2020年11月25日
Arduino Leonardoでポインタの絶対位置を指定してみる その2
旧「Arduino Leonardoでポインタの絶対位置を指定してみる」では、ArduinoのIDEの中に含まれるソースを書き換える事により、Leonardoでデジタイザとしての振る舞い、つまり画面の絶対位置を指定してポインタを動かす、クリックするという事を実現してました。しかしArduino L.L.C からリリースされているIDE Ver1.6.6からはUSBデバイスがプラガブルとなり、配布されているソースを書き換えることなくライブラリの形でUSBデバイスを自由に追加できるようになりました。そこで、以前に作成したDigitizerクラスもライブラリの形に書き換え、簡単に機能を使用できるようにしてみました。
本コンテンツはArduino L.L.C. からリリースされている IDE Ver1.6.8にて動作を確認しています。少なくともVer1.6.6より前では動作しません。また、Arduino SRL(http://www.arduino.org)がリリースしているIDEでは検証していません。
どうやるか
前述のとおり、Arduino Ver1.6.6からはUSBデバイスがプラガブルになりました。それより前のバージョンではUSBのHID(Human Interface Device)としてマウスとキーボードとしての機能があるという情報、つまりマウスとキーボードのHIDレポートディスクリプタが静的にインプリメントされていました。1.6.6からは実行時にレポートディスクリプタが作成され、それがホストであるPCに伝えられるようになりました。
ということで、追加したいHIDレポートディスクリプタをライブラリ上に用意し、追加するクラスのコンストラクタでディスクリプタを追加するメソッドを呼べばOKです。
レポートディスクリプタの追加
レポートディスクリプタそのものは旧版と全く変わりません。異なるのはコンストラクタ内でそのディスクリプタを追加する部分です。以前はソースそのものに追加していましたが、新版ではAppendDescriptorメソッドにデジタイザ部分のレポートディスプリプタのポインタとサイズを渡すことで動的に追加しています。
…前略 Digitizer_::Digitizer_(void) { static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); HID().AppendDescriptor(&node); (略) } …以下略
ライブラリ
ライブラリをダウンロードし、解凍後、スケッチ保存ディレクトリの下の libraries フォルダの中に解凍後のフォルダを保存してください。libraries フォルダが無いようであれば作成してください。
2020/11/25 Ver1.1.0
これまでデバイスを「スタイラス」として登録していましたが、Windows10以降、挙動が変わり、マウスポインタの動作がスタイラスに連動しなくなったようです。そこでデバイスを「マウス」として登録するようにしました。
API
旧版と全く変わりませんが同じ事をコピーしておきます。
APIとして以下を用意しました。
Digitizer.setLogicalResolution(int x0, int y0, int x1, int y1)
setDisplayResolutionでは、スケッチで指定するディスプレイ上での端(左および上)から端(右および下)までの値を指定します。例えば1280×1024ドットのディスプレイを使用し、スケッチでも横方向を0〜1279、縦方向を0〜1023で指定したい場合には、
Digitizer.setDisplayResolution(0, 0, 1279, 1023);
と指定します。
他の例として、例えばディスプレイのドット数に関係なく、
Digitizer.setDisplayResolution(0, 0, 100, 100);
と指定すれば、縦横とも画面全体を0〜100の範囲で指定するようになります。例えばこの設定の場合に
Digitizer.move(50, 50);
と指定すればポインタは画面中央に移動します。
setLogicalResolutuinは、Arduinoから送信するデータの最小・最大値を指定します。これはよくわかりませんが、環境によって画面上のピクセル数と一致する場合や0〜32767になる場合があるようです(同じ機器でも表示するモニタによって異なったりするようです)。いろいろ試してみて意図する位置にポインタを移動できる値に設定してください。以下、経験上の値です。
Windowsの場合は、
Digitizer.setLogicalResolution(0, 0, <画面の横方向ドット数-1>, <画面の縦方向ドット数-1>);
または、
Digitizer.setLogicalResolution(0, 0, 32767, 32767);
のいずれかを指定してみてください。
Macの場合は実際の画面よりも広い大きさの仮想的なサイズを持っているようで、私の環境では、
Digitizer.setLogicalResolution(2460, 2460, 30306, 30306);
と指定し、あとはsetDisplayResolutionで実際の画面のドット数を指定することで、move(x,y)で指定したピクセル位置にポインタを移動させることができました。
Windowsの場合、ポインタを移動させるとポインタの形状がデジタイザ用のものに変わってしまうようです。通常の矢印のポインタに戻したいようであれば、移動等の後に、
Mouse.move(1,0);
Mouse.move(-1,0);
等を追加して、マウスを微妙に動かした事にすれば戻るようです。
ライブラリの中にexampleとして「Circle」というスケッチを入れておきました。実行すると画面上をポインタが円を描くように動きます。そのままではLeonardoを外さないとPCを操作できなくなってしまいますので、Digital pin2をGNDに接続するとポインタの動きが停止するようにしてあります。または、一周すると5秒停止するので、その間に何か操作してください。