本記事ではArduinoマイコンボードでUSBキーボードの入力を読み取る方法を解説します。
利用するのは "Suzuno32RV" というボードです。Suzuno32RVは、RISC-V CPUを搭載したWCH CH32Vシリーズのマイコンチップを実装した、UNO形状のマイコンボードです。USB Type-CコネクタとUSB Type-Aコネクタが搭載されており、USBデバイス機能とUSBホスト機能の両方を利用できます。わたし(三峰スズ)が設計し、マイ・プロダクトサービスにより株式会社ビット・トレード・ワンが製造・販売をしています。
今回は、USB Type-AコネクタにUSBキーボードを接続し、入力されたキーをArduino IDEのシリアルモニタへ表示してみます。
ビット・トレード・ワン(BitTradeOne)は神奈川県相模原に本社を置く、電子工作モジュール・キット、ユニークで便利なガジェット、同人ハードウェアの製品化サービス「BTOマイ・プロダクトサービス」、模型向けブランド「MODMAGIC」、各種受託を手掛ける、電子機器の製造・販売の会社です。
製品は各取扱店のほか、公式オンラインショップ BTOS やAmazonでも販売しています。
必要なもの
- Suzuno32RV マイコンボード
- ベーシックなUSBキーボード(Type-Aコネクタのもの)
Suzuno32RVはBTO公式オンラインショップ BTOS や、Amazon.co.jp、各取扱店にて購入できます。
Suzuno32RVのおもなスペック:
- CPU: 32bit RISC-V 144MHz RV32IMAC
- FlashROM: 224KB
- RAM: 20KB
- 通信: I2C, SPI, UART, CAN, USB x2
配線する
配線といっても、今回はケーブルを接続するだけです。
- Suzuno32RVの USB Type-Aコネクタ にUSBキーボードを接続します
- Suzuno32RVの USB Type-Cコネクタ をPCに接続します
USB Type-C側は、スケッチの書き込みとシリアル出力の確認に使います。USB Type-A側は、Suzuno32RVがUSBホストとしてキーボードを認識するために使います。
Arduino IDEの準備
Suzuno32RVはArduino環境で開発ができます。初回だけ、ボードマネージャーの設定と、デバイスドライバの設定が必要です。
ボードマネージャーURLを追加する
Arduino IDEを起動し、「基本設定」→「追加のボードマネージャーのURL」に以下を追加します。
https://raw.githubusercontent.com/verylowfreq/board_manager_ch32/main/package_ch32v_index_sz.json
その後、「ボードマネージャー」で ch32 を検索し、CH32V Boards by M.S. をインストールします。本記事では バージョン 2.1.4 を利用しました。
Windowsの場合はUSBドライバを設定する
WindowsでUSB書き込みを行う場合は、zadigでWinUSBドライバを設定します。
- BOOTスイッチを押しながらSuzuno32RVをPCに接続します
- zadigを起動します
- Options → List All Devices にチェックを入れます
- USB IDが 4348:55E0 のデバイスを選択します
- ドライバとして WinUSB を選択します
- Replace Driver を実行します
誤ったUSBデバイスを選ぶと、そのデバイスが正常に動作しなくなる場合があります。USB IDをよく確認してください。
ボードと書き込み方法を選択する
Arduino IDEの「ツール」メニューから、以下のように設定します。本記事ではUSBホスト機能も利用するので、USB Supportの設定も忘れずに。
- ボード: Suzuno32RV
- Upload method: WCH-ISP
- USB Support: Adafruit TinyUSB with USBD/USBFS Host
ライブラリの紹介
この記事では、ボードライブラリ arduino_core_ch32_sz に同梱されている KeyboardHost ライブラリを利用します。
KeyboardHost はTinyUSBを利用したUSBキーボード用のラッパーライブラリです。USB HIDキーボードから送られてくるキー入力を、Arduinoスケッチから扱いやすい形で受け取れるようにしてくれます。
USBホスト処理を低レイヤから直接書くと、USBデバイスの接続検出、HIDレポートの受信、キーコードの解釈などを自分で扱う必要があります。KeyboardHost を使うと、まずは「押されたキーを読む」ことに集中できます。
コード
以下のコードは、接続されたUSBキーボードで押されたキーを、ASCII文字としてUSBシリアルでパソコンへ送信します。また、キーボードの接続・切断時にメッセージを表示します。
#include <Adafruit_TinyUSB.h>
#include <KeyboardHost.h>
Adafruit_USBH_Host USBHost;
void onMount(uint8_t dev_addr, uint8_t instance, uint16_t vid, uint16_t pid) {
Serial.printf("Mounted. dev_addr=%u, instance=%u, VID/PID=0x%04x/0x%04x\r\n", dev_addr, instance, vid, pid);
}
void onUmount(uint8_t dev_addr, uint8_t instance) {
Serial.printf("Unmounted. dev_addr=%u, instance=%u\r\n", dev_addr, instance);
}
void onKeyDown(uint8_t keycode, uint8_t modifier) {
(void)keycode;
(void)modifier;
Serial.printf("onKeyDown: modifier=0x%02x, keycode=0x%02x\r\n", modifier, keycode);
}
void setup() {
Serial.begin(115200);
while (!Serial) { delay(100); }
Serial.println();
Serial.println("Suzuno32RV USB Keyboard Host sample");
Serial.println("Connect a USB keyboard to the Type-A port.");
KeyboardHost.onMount(onMount);
KeyboardHost.onUmount(onUmount);
KeyboardHost.onKeyDown(onKeyDown);
KeyboardHost.begin();
// レイアウトは KeyboardHost.begin() のあとで設定する
KeyboardHost.setLayout(KeyboardLayout::JP_JIS);
// USBホスト機能全体の begin()
USBHost.begin(0);
}
void loop() {
// task() を高頻度に呼び出す
USBHost.task();
if (KeyboardHost.available() > 0) {
int ch = KeyboardHost.read();
if (ch >= 0) {
Serial.printf("Key: %c\r\n", ch);
}
}
}
使用している arduino_core_ch32_sz のバージョンによって、KeyboardHost ライブラリのサンプル名やAPIが変わる可能性があります。
もし上のコードでコンパイルできない場合は、Arduino IDEの「ファイル」→「スケッチ例」から、KeyboardHost に含まれているサンプルスケッチを開き、そのAPI名に合わせてください。
書き込み方法
Arduino IDEで「検証」を実行し、コンパイルが通ることを確認します。
次に、Suzuno32RVを書き込み待機モードにします。
- RESETスイッチを押します
- BOOTスイッチを押します
- RESETスイッチを離します
- BOOTスイッチを離します
この状態でArduino IDEの「書き込み」を実行します。
書き込みが完了したら、必要に応じてRESETスイッチを押してスケッチを再実行します。
実行結果
USBキーボードをSuzuno32RVのType-Aコネクタに接続し、キーを押すと、シリアルモニタに次のように表示されます。
- 接続時にはVIDとPIDも取得できます。
- onKeyDown()では、USB-HID規格でのUsage IDが読み取れます。
- read()では、レイアウトに応じたASCII文字が読み取れます。
- Shiftキーも認識・処理されます。
Suzuno32RV USB Keyboard Host sample
Connect a USB keyboard to the Type-A port.
Mounted. dev_addr=1, instance=0, VID/PID=0x1c4f/0x0027
onKeyDown: modifier=0x00, keycode=0x1e
Key: 1
onKeyDown: modifier=0x00, keycode=0x1f
Key: 2
onKeyDown: modifier=0x00, keycode=0x20
Key: 3
onKeyDown: modifier=0x02, keycode=0x00
onKeyDown: modifier=0x02, keycode=0x04
Key: A
onKeyDown: modifier=0x02, keycode=0x05
Key: B
onKeyDown: modifier=0x02, keycode=0x06
Key: C
onKeyDown: modifier=0x02, keycode=0x00
onKeyDown: modifier=0x02, keycode=0x1e
Key: !
onKeyDown: modifier=0x02, keycode=0x1f
Key: @
onKeyDown: modifier=0x02, keycode=0x20
Key: #
まとめ
Suzuno32RVを使って、USBキーボードの入力を読み取る方法を紹介しました。
電子工作でUSBキーボードが利用できると、ボタンやロータリーエンコーダだけでは作りにくい、文字入力を含むインターフェースを実装しやすくなり、電子工作の入力方法の幅がかなり広がります。
たとえば、次のような用途に使えます。
- シリアルコンソールの代わりにキーボードで操作する
- メニュー画面の操作に使う
- ロボットや装置の手動操作に使う
- マクロパッドや専用入力デバイスの実験に使う
- USBバーコードリーダーの入力を読み取る
USBバーコードリーダーの多くは、PCから見るとUSBキーボードのように動作します。そのため、USBキーボードが扱えるようになると、バーコード入力を使った電子工作にも応用できます。
USBホスト機能は少し難しそうに見えますが、KeyboardHost ライブラリを使うことで、まずは手軽にUSBキーボード入力を試せます。Suzuno32RVのUSBホスト機能を活かした工作の入口として、手軽なわりに威力を発揮しやすいテーマだと思います。
参考資料
ビット・トレード・ワン Suzuno32RV 商品ページ
arduino_core_ch32_sz (筆者が独自管理しているArduinoコア)
Suzuno32RVサンプルコード
Suzuno32RVドキュメント
