Arduinoの中でもArduino LeonardoはパソコンのUSB外付けキーボードやUSB外付けマウスとして動かすことができるようなので,やってみました.
ハードウェア
以下の部品を購入しました.
- Arduino Leonardo
- GROVE - ベースシールド
- M5Stack用カード型キーボードユニット
- USB Type-A - micro-Bケーブル
今回使用したM5Stack用のカード型キーボードユニットは,元々M5Stack用なのですが,Grove Aポート(I2Cインターフェース)で接続できるため,Arduinoでも使用できるようなので,使ってみました.
I2Cのアドレスは0x5Fに固定されています.
以下のように接続します.キーボードユニットはGROVEシールドのI2Cのコネクタに接続しました.
プログラミング
第一段階:キーボードから入力したコードをシリアルコンソールに表示
まず,入力されたキーコードを確認するために,シリアルコンソールに表示しました.ソースコードは以下のとおりです.
/* * I2Ckbd1 * 2022/1/13 * M5Stack用のI2CキーボードからArduinoでキー読み込み * コードが来るのでシリアルコンソールに表示する */ #include <Wire.h> // I2C kbd #define AclSenAdrs 0x5F unsigned char AclSen; void setup() { Wire.begin(); Serial.begin(9600); } void loop() { int byteAvailable; // ArduinoがI2Cのマスター側になる Wire.beginTransmission(AclSenAdrs); // レジスタアドレスを定義する Wire.write(0x00); Wire.endTransmission(); // レジスタアドレスから1アドレス分のデータを読む Wire.requestFrom(AclSenAdrs, 1); // 読み込めるバイト数(常に1が返る) byteAvailable = Wire.available(); if ( byteAvailable > 0) { AclSen = Wire.read(); // 0が返って来た時はキーが押されていない // キーが押されていたらコードが来る if (AclSen > 0) { Serial.println(AclSen); } } delay(50); }
プログラムを書き込んだ後でシリアルコンソールを表示すると,押したキーのコードが表示されます.
第二段階:パソコンに対してキーボードとしての動作を確認
次に,USBキーボードとしての動作を確認しました.ソースコードは以下のとおりです.
/* * I2Ckbd2 * 2022/1/15 * Arduino Leonardoを,USB接続したパソコンのkbd, mouseにする * 書き込んだ後は常にキー入力があるので,最後のコメント内にカーソル * を置いてArduinoをUSBに接続し,コンパイル・書き込みする */ #include <Keyboard.h> void setup() { Keyboard.begin(); } void loop() { Keyboard.print("Hello World"); delay(1000); } /* */
一度このソースコードを書き込むと,USBでパソコンに繋いでいる間,ずっとキー入力があるので,次の書き込みがなかなかできません.なので,2回目以降はArduinoソフトウェアで,コメント欄を作成しておいて,ここにカーソルを置いてからArduinoを USBでパソコンと接続すると,入力されてくる文字列が全てコメントとなるので,次のプログラムが書き込み可能になります.
第三段階:特定のキーが入力されたらまとめて文字列をパソコンに入力
ソースコードは以下のとおりです.
/* * I2Ckbd3 * 2022/1/15 * Arduino Leonardoを,USB接続したパソコンのkbd, mouseにする * 'h'を押したら'Hello World'をキーボードとして入力する */ #include <Wire.h> #include <Keyboard.h> // I2C kbd #define AclSenAdrs 0x5F int AclSen; void setup() { Wire.begin(); Keyboard.begin(); } void loop() { int byteAvailable; Wire.beginTransmission(AclSenAdrs); Wire.write(0x00); Wire.endTransmission(); Wire.requestFrom(AclSenAdrs, 1); byteAvailable = Wire.available(); if (byteAvailable > 0) { AclSen = Wire.read(); if (AclSen > 0) { if (AclSen == 'h') { Keyboard.print("Hello World"); } } } delay(50); }
自作キーボードとして便利なのが,特定のキーでまとまった文字列を入力できる機能を組み込めることです.ここでは,キーボードで'h'キーを押すと,パソコンに'Hello World'という文字が入力されます.
第四段階:通常のキーボードとして使用
最後に,通常のキーボードとして使えるようにする作業です.普通の表示可能文字はASCIIコードが送信されるのですが,制御コードなどはキーコードとASCIIコードが異なるので,調整する必要があります.最初に処理したのがEnterキーで,そのままキーを押すと0x0dが来ます.Macでやっているので,ターミナルなどでは0x0aを入力しないと改行コードとして認識されません.その他に上下左右の矢印キーを対応してみました.キーボードとして送信できるコードの一覧はここにあります.一方で,入力されるコードの一覧は製品のページにあります.これらを比較して,違うコードを置き換えます.とりあえず上下左右とEnter,ESCを対応しました.ソースコードは以下のとおりです.
/* * I2Ckbd3 * 2022/1/15 * Arduino Leonardoを,USB接続したパソコンのkbd, mouseにする * 押されたキーコードを送信 * scanするキーコードはI2Ckbd1で確認する.以下のコードが来ている. * https://docs.m5stack.com/en/unit/cardkb * 送信できるキーコードは以下 * https://www.arduino.cc/reference/en/language/functions/usb/keyboard/keyboardmodifiers/ */ #include <Wire.h> #include <Keyboard.h> // I2C kbd #define AclSenAdrs 0x5F #define KEY_ESC 0xb1 #define KEY_UP_ARROW 0xda #define KEY_DOWN_ARROW 0xd9 #define KEY_LEFT_ARROW 0xd8 #define KEY_RIGHT_ARROW 0xd7 void setup() { Wire.begin(AclSenAdrs); Keyboard.begin(); } void loop() { Wire.beginTransmission(AclSenAdrs); Wire.write(0x00); Wire.endTransmission(); Wire.requestFrom(AclSenAdrs, 1); while (Wire.available()) { unsigned char c = Wire.read(); switch (c) { case 0x0d: // 13 Enter Keyboard.write(0x0a); break; case 0x1b: // 27 ESC Keyboard.write(KEY_ESC); break; case 0xb4: // 180 Left Keyboard.write(KEY_LEFT_ARROW); break; case 0xb5: // 181 Up Keyboard.write(KEY_UP_ARROW); break; case 0xb6: // 182 Down Keyboard.write(KEY_DOWN_ARROW); break; case 0xb7: // 183 Right Keyboard.write(KEY_RIGHT_ARROW); break; default: Keyboard.write(c); } } delay(50); }