Windowsで動く音量調整や再生/一時停止デバイスを前から作りたいなと考えていたがdrdnar / Arduino-HID-Remote をふと見つけArduinoでも簡単に実現できると知ったので試してみました. しかしこれはATMEGA32U4が搭載されているArduino限定で手元になかったのでATMEGA328Pで動くように工夫し動かしてみました.
ATMEGA328Pでキーボードデバイス
結構前にAVRデバイスで限定的ではあるがUSBデバイスを実現できるV-USBが話題になっていたのですがArduinoでも簡単に適用できるライブラリがあったのでありがたく使用します. サンプルにはキーボードがありました.
gloob / vusb-for-arduino
回路図はProject Log : Arduino USB, Arduino(ATmega328p)でV-USBキーボードテストを参考にしました. 手元に68Ωの抵抗がなかったため47Ωないしは100Ωで代替することができました. 面倒なのでユニバーサル基板に起こしました.
サンプルファイルであるUsbKeyboardDemo1.pdeを使用しテストしました. PlatformIOでビルドしましたが, そのままではエラーが吐かれてしまったので以下の行の宣言をcharからunsigned charに変更しました.
libraries/UsbKeyboard/utility/usbdrv.h#L492
libraries/UsbKeyboard/UsbKeyboard.h#L43
USBケーブルが悪いのか基板が悪いのかわかりませんがちゃんと動くまでに数時間かかってしまいました.
12ピンをGNDに落とすことで「hello world」が入力されるデバイスが実現できました.
ATMEGA328PでHID(Consumer)デバイス
音量の調整や再生/一時停止を可能にするデバイスはConsumer Pageを設定します.
https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
キーボードもHIDデバイス一種であり最低限の設定は既に出来上がっているのでキーボードを実現しているGeneric DesktopからCosumerに切り替えて必要なディスクリプタを記述します. 基本的にArduino-HID-RemoteのHIDRemote.cpp#L3をコピペします. 配列のサイズが変更されるのでlibraries/UsbKeyboard/usbconfig.h#L276を配列サイズに変更します.
今回はHID_REMOTE_PLAYからHID_REMOTE_MUTEを16bitで記述するのでuint16_tに変更しました. また, このディスクリプタではレポートIDを使用していることから対応したプログラムに変更する必要があります. 転送するデータの先頭にレポートIDを追加するだけで問題ありませんでした. バッファのサイズは必要に応じて変更しました.
1 | void sendKeyStroke(uint16_t key) { |
HID_REMOTE_PLAYやHID_REMOTE_PAUSEはアクティブなウィンドウのプレイヤー(Windows Media PlayerやiTunes)でのみ有効, HID_REMOTE_PLAY_PAUSEはバックグラウンドで再生していた場合でも有効でした.
HIDレポートディスクリプタのメモ
ディスクリプタを構築するツールが公式から提供されています.
HID Descriptor Tool
色々探せば解説されていますが, REPORT_SIZE, REPORT_COUNTの理解に時間がかかりました. REPORT_SIZEはUSAGEで使用するデータのフィールドをビットごとに指定しており, REPORT_COUNTはUSAGEの数を指定しています. データは記述した順に配置されていき今回は1ビットごとなのでこれだけであれば12ビットとなっています.
1 | //0か1の設定 |