⌨️

オリジナルDIYキーボードキットでUSBキーボードを作るためのヒント - USBキーボードの超基本構成

2023/10/13に公開

これは何?

ボクが作ったDIYキーボードキット DIY kit 01 - Keyboardを使用してArduinoでUSBキーボードを作るためのヒントをまとめているよ。DIYキーボードキットを持っていなくても、RP2040を使用したUSBキーボードの作り方について知ることができるよ。

DIYキーボードキットはBOOTHで発売中なので、よかったら、お手元に用意して自分だけのキーボードを作ってみてね。

BOOTHの商品ページ
DIY kit 01 - Keyboard XIAO RP2040

対象読者

  • DIYキーボードキットをお買い上げ頂いたみんな
  • DIYキーボードのプログラムをどうやって作るのか知りたいみんな

環境

  • RP2040を搭載したワンボードマイコン
  • DIY kit 01 - Keyboard
  • Arduino IDE
  • Arduino IDEが動作するPC

RP2040を搭載したワンボードマイコン
このページではSeeed StudioさんのXIAO RP2040を使用していると想定して説明しているよ。

DIY kit 01 - Keyboard
ボクが作ったDIYキーボードキットを使用していると想定して説明しているよ。DIYキーボードキットを持っていなくても、RP2040のGPIOに適当なスイッチやメカニカルスイッチを接続することで、このページで説明している内容に対応できるよ。

作りたいもの

このページで作るものを説明するよ。DIYキーボードキットの基板上にあるKey1のキースイッチを押したときに、Hello world!という文字列をPCに入力するコードを作成するよ。

DIYキーボードキットのKey1はXIAO RP2040のD0ピンに接続されているよ。DIYキットを持っていない場合は、RP2040のD0ピンにキースイッチを接続するか、別のGPIOに接続した場合はこの後のプログラムのピンを適宜読み替えてね。


Key1接続箇所 DIY kit 01 - Keyboard 回路図

作ってみよう

実はArduinoのライブラリには最初からUSBキーボードを作るためのライブラリが用意されていて、これはRP2040にも対応しているよ(正確に言うと、RP2040のライブラリにKeyboardライブラリと同じように振る舞うライブラリが入っているみたい。これをArduinoライブラリと言って良いのか分からないので、補足しておくね←認識が間違ってたら教えて欲しいよ)。このライブラリを使うことで、すごく簡単にUSBキーボードを作れるようになっているよ。

USBキーボード用のライブラリ

ArduinoのUSBキーボードのサンプルコードを少し見てみるよ。Arduino IDEのExamplesから09.USB>Keyboard>KeyboardSerialを選択してみてね。以下のようなサンプルコードが表示されるはずだよ。

#include "Keyboard.h"

void setup() {
  // open the serial port:
  Serial.begin(9600);
  // initialize control over the keyboard:
  Keyboard.begin();
}

void loop() {
  // check for incoming serial data:
  if (Serial.available() > 0) {
    // read incoming serial data:
    char inChar = Serial.read();
    // Type the next ASCII value from what you received:
    Keyboard.write(inChar + 1);
  }
}

このコードでは、シリアルコンソールで入力された文字を受信して、受信した文字のASCIIコード上の次の文字(例えばシリアルでaと入力するとキーボードからbと入力されるよ)をPC側に入力するサンプルになっているよ。スケッチをコンパイルしてRP2040に書き込んでみてね。

Arduinoのサンプルコードのポイントを説明しておくよ。

#include "Keyboard.h"

キーボードのライブラリをインクルードしているよ。ライブラリを使用するために必要だよ。

Keyboard.begin();

キーボードのライブラリを初期化しているよ。setup()関数内で1回だけ実行してね。

Keyboard.write(inChar + 1);

キーボードから指定された文字をPC側へ入力するよ。この関数で入力できる文字は1文字だけだよ。文字列をPCへ入力したい場合は、print関数を使用するよ。print関数は1文字でも文字列でもOKだよ。

Keyboard.print("Hello");

Arduinoさんの公式ドキュメントは以下を参照してね。
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/

必要な機能を実装してみよう

Arduinoのキーボードライブラリについて分かったと思うから、実際にDIYキーボードキット上のKey1を押したときにHello World!と入力するコードを作成するよ。最後にサンプルコードを示しているけど、まずは自分で作成してみてね。

キーボードを制御するために必要な機能は以下の通りだよ。それぞれの機能の実装方法についてポイントを説明していくよ。

  • Key1が押されたことを検出する
  • Key1が押されたときにHello World!とPCへ入力する

Key1が押されたことを検出する
ArduinoでGPIOの状態を知るためには、setup関数内でピンのモードを設定する必要があるよ。下記の例のように、setup関数内でpinMode関数を呼び出して、指定したピンのモードを設定するよ。Key1はRP2040のD0ピンに繋がっているから、defineを使用してPIN_KEY_1を定義しているよ。

pinMode関数の2番目の引数でピンのモードを指定するよ。INPUT_PULLUPはピンのモードを入力にして、RP2040内部でD0を電源電圧にプルアップするよ。

プルアップ?

上の方にある回路図を見て欲しいんだけど、Key1には2つのピンがあって、1つはRP2040のD0、もう1つはGNDに接続されているよね。この場合、Key1の状態変化を知るためには、Key1を押していない(スイッチが閉じていない)ときはD0がHIGHになっていて欲しいよね。そのためには、大体10kΩぐらいのプルアップ抵抗というものを電源とD0の間に入れる必要があるんだけど、最近のマイコンは内部にこのプルアップ抵抗を持っていて、プログラムからOn/Offできるようになっているよ。pinMode関数の2番目の引数でINPUT_PULLUPを指定することで、マイコン内部でD0がプルアップされた(D0がHIGHの電圧まで引っ張り上げられた)状態になるよ。Key1を押し下げる(スイッチが閉じる)とD0はGNDと繋がるので、D0はLOWになるよ。D0がGNDと同じ電圧=0Vになっても、プルアップ抵抗のおかげで電源とGNDはショートせずに済むよ。

ピンの設定ができたら、後はピンの状態を確認するだけだね。ピンの状態はdigitalRead関数を呼び出すことで知ることができるよ。digitalRead関数の引数に状態を知りたいピンの番号を指定するよ。ピンの状態がLOWならLOW, HIGHならHIGHが返ってくるよ。

DIYキーボードキットのキースイッチはキーを押し下げたときにスイッチが閉じてD0はLOWになるから、digitalReadがLOWになっているときがスイッチが押されている状態だよ。これを active low というよ。逆にスイッチが押されたときにHIGHになるパターンは active high というよ。

#define PIN_KEY_1 D0

void setup() {
  // ・・省略・・
  pinMode(PIN_KEY_1, INPUT_PULLUP);
}

void loop() {
  int key1 = digitalRead(PIN_KEY_1);
  // ・・省略・・
}

Key1が押されたときにHello World!とPCへ入力する
これは、先ほどのKeyboardライブラリで説明した通りだね。文字列をPCへ入力するための関数はprint関数だよ。Key1が押されたときにprint関数を呼び出すことで、文字列をPCへ入力できそうだね。

サンプルコード

うまく実装できたかな?ボクが作成したサンプルコードを書いておくよ。このサンプルコードは、Key1を押したときにHello World!という文字列をPCに入力するよ。ArduinoにUSBキーボードのライブラリが用意されていることで、すごく簡単にUSBキーボードが作れるってこと、分かってもらえたかな?

#include "Keyboard.h"

#define PIN_KEY_1 D0

void setup() {
  Serial.begin(9600);
  Serial.println("XIAO Keyboard");
  pinMode(PIN_KEY_1, INPUT_PULLUP);
  Keyboard.begin();
}

void loop() {
  int key1 = digitalRead(PIN_KEY_1);
  if(key1 == LOW){
    Keyboard.print("Hello World!");
  }
  delay(50);
}

応用 - 複数のキーを同時に送る

キーボードを作るなら色々なショートカットキーを入力できるようにしたいよね。そのために、複数のキーの組み合わせを同時にPCへ送信する必要があるけど、そのための方法について説明するよ。

複数のキーを同時に送る手順は以下の通りだよ。

  1. 1つめのキーを押し下げた状態にする
  2. 2つめのキーを押し下げた状態にする
  3. 全てのキーを離した状態にする

キーを押し下げた状態にするには、Keyboardライブラリのpress関数を使用するよ。以下のようにすると、Nキーがずっと押しぱなしになるよ。

Keyboard.press('n');

押しっぱなしになったキーを離すにはreleaseAll関数を使用するよ。以下のようにすると、押されたキーが全て離された状態になるよ。

Keyboard.releaseAll();

複数のキーを同時に入力する方法は見えてきたかな?例えば、Ctrlキーを押しながらNキーを押すサンプルは以下の通りだよ。キーとキーの間にdelayを入れているのは、delayが無いとうまく動作しなかったから、キーとキーの間は10ms待つようにしているよ。これは環境に依存するかもしれないので、色々と調整してみてね。

char ctrlKey = KEY_LEFT_CTRL;

//・・省略・・

void sendKey(){
    //・・省略・・
    Keyboard.press(cmdKey);
    delay(10);
    Keyboard.press('n');
    delay(10);
    Keyboard.releaseAll();
}

Ctrlキーのような特殊なキーの割り当てはArduinoの公式ドキュメントを参照してね。
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/keyboardmodifiers/

まとめ

このページでは、RP2040を使用してUSBキーボードを作る方法について説明したよ。USBキーボードのライブラリがArduinoに用意されているから、とっても簡単に作成できたよね。このページでは1つのキースイッチが押されたときの処理だけだったから、もっとキーを増やしたときの処理とか、ロータリーエンコーダからの入力をどうやって処理するのかなど、色々考えてみてね。

分からないことがあったらXで気軽に質問してね!
じゃあ、またね!

Discussion