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);
}