Arduino(ATmega328p)でV-USBキーボードテスト
注意:この記事の内容を鵜呑みにし、事故や損失を招いた場合でも当方は一切の責任は負いかねます。自己責任でお願いします。
ATmega328p等のUSBコントローラが内蔵していないマイコンでUSBデバイスを作りたい場合には、通常、外付けのUSBコントローラICを使用します。
ですが、V-USBという、ソフトウェアでUSB1.1ロースピードモードデバイスを実現できるものがあります。
V-USB
無料で使用する場合は、GPL2.0ライセンスの下で利用できます。
今回はArduinoでV-USBを利用できるvusb-for-arduinoを使用します。
vusb-for-arduino
まず、上記vusb-for-arduinoで「Code」→「Download ZIP」でファイル一式をダウンロードします。
ZIPを解凍し、「vusb-for-arduino-master」→「libraries」内にある「UsbKeyboard」フォルダを
「C:\Users\???\Documents\Arduino\libraries」(※???は現在使用しているユーザー名)
へコピーします。
次にArdino IDE (Ardino IDE 1.8.9で確認済み)を起動し、「スケッチ例」→「カスタムライブラリのスケッチ例:UsbKeyboard」→「UsbKeyboardDemo1」を開きます。
使用ボードは、「Arduino/Genuino Uno」にセットします。
※水晶振動子は16MHzです。
マイコンボードを接続し書き込みボタンを押すとプログラムが書き込まれますが、Arduino IDEのバージョンや、vusb-for-arduinoのバージョンの違いによって、コンパイルが通らない場合があります。その時はエラー文にそって各自ヘッダファイル等を修正してください。
特に、古いバージョンのvusb-for-arduinoはPROGMEMにconst属性の付け忘れによるエラーがあります。
・回路
マイコンボードへの書き込みが成功したら、次は周辺回路を作成します。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
・USB1.1について
USB1.1は4本の端子があり、それぞれGND,D+,D-,5Vと割り当てられています。
GND,と5Vは電源、D+,D-はデータバスとなります。
USB1.1のデータバスD+,D-のHレベルは3.3Vなので注意が必要です。
ホスト側のデータバスD+,D-には15kΩのプルダウン抵抗が挿入されています。
USB1.1はフルスピードモード(12Mbps)とロースピードモード(1.5Mbps)があります。これらはホストに接続した端末側で設定します。
フルスピードモードの場合、端末側のD+を1.5kΩの抵抗で3.3Vへプルアップします。
ロースピードモードの場合、端末側のD-を1.5kΩの抵抗で3.3Vへプルアップします。
フルスピードモードで使用する場合はデータバスをツイストペアにし、シールドします。
ロースピードモードの場合はツイストペアやシールドは不要です。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Arduino(ATmega328p)のポートのHレベル出力電圧は5Vなので、3.3Vへ変換する回路が必要です。
https://www.obdev.at/vusb/では、ダイオード2個分の電圧降下(約1.4V)で電源レベルを3.6Vにしているようです。V-USBはロースピードモードのみ対応しているため、データバスD-を1.5kΩでプルアップしています。
また、5V電源で使用する場合は、データバスは3.6Vのツェナーダイオードでクリップするようです。
これらを踏まえ、今回は次のような回路で実験しました。
データバスD-のプルアップ抵抗の先がArduinoのD5ピンへ接続されていますが、これは、Arduinoをリセットした時にUSBの接続を切るためのようです。
詳しくは「libraries」→「UsbKeyboard」内のArduinoNotes.txtを見てください。
上記回路を組み立て、PCのUSBポートへ接続すると、「HIDキーボードデバイス」として認識します。また、ArduinoのD12ピンへ接続したスイッチを押している間は「hello world」という文字列がキー入力されます。
安定性は悪く、ちょくちょくデバイスが認識されなくなります。
プログラム中の「UsbKeyboard.update()」または「usbPoll()」を50ms以内ごとに実行しないと、接続がタイムアウトしてしまうことが関係しているかもしれません。
「libraries」→「UsbKeyboard」内のヘッダファイル「UsbKeyboard.h」のメンバ関数「sendKeyStroke」内のwhile (!usbInterruptIsReady()){}で、50ms以上空いてしまい、接続断となってしまうのでしょうか?