第15回 キーボード試作

今までの習得した知識を使って、キーボードを何種類か試作してみます。この試作を通してキーボード製作の基本を確認しましょう!

目次

キーボード試作する際の注意点

今回の記事では、Arduino Microを、USBキーボードとして機能するようなスケッチをいくつか試作して、キーボード製作の要素技術を確認していきます。

ところで、プログラミングには失敗がつきものです

例えば、プログラミングに失敗してしまい、どのスイッチも押していないのに「a」という文字をずっとPCに送り続けるようになってしまう場合もあるかもしれません。

このようになってしまった場合、新しいスケッチを書き込もうとしても、これから書き込むスケッチのウィンドウにどんどん「a」が入力されてしまい、結果として正しいスケッチが書き込めなくなってしまいます。


このようになってしまうと、そのArduino Microは永遠に「a」という文字をひたすら入力する専用のキーボードになってしまいます。

Ardunio Microがこのようになった場合、なんとか復活させる必要が出てきてしまいます。

こんなことになってしまうと、キーボード試作どころではありませんので、今回から第17回の記事までは次のように進めることにします。

  • 第15回(今回の記事)
    キーボードを何種類か試作します。
    掲載したスケッチは正常に動作することを確認済みですので、なるべくスケッチをそのままコピペして動作確認するようにしてください。
    もしご自身でスケッチを変更する場合は、十分に確認してからArduino Microに書き込むようにしてください。
  • 第16回
    スケッチに問題があり、Arduino Microが正常に反応しなくなってしまった場合の対処方法を説明します。
  • 第17回
    今までの知識を活用してチャレンジ課題に取り組んでみます。
    自分でスケッチを作成しますので、失敗するとArduino Microが正常に反応しなくなる可能性もあります。その場合は、第16回で説明した方法でArduino Microをリセットして、正しくスケッチが書き込めるようにしてください。

試作するキーボードの仕様

前回までの記事で、次のスケッチ作成方法を習得しました。

  • Aruino MicroをPCに接続したときにキーボードとして認識してもらう処理
  • Arduino MicroからPCに文字データを送る処理
  • スイッチを押したことを検知する処理

これらが実現できれば、キーボードの試作ができます。

そこで、言い訳キーボードを作る前に、次の4種類のキーボードを試作してみます。これらのスケッチを通して、キーボードライブラリとスイッチライブラリの使い方に慣れましょう!

  • 「a」と「b」の2種類の文字が入力できるキーボード
  • の機能に追加して、それぞれ大文字を大文字の「A」と「B」にするためのShift機能がついたキーボード
  • カット、コピー、ペーストの3種類の機能のキーボード
  • スイッチを1回押すと小文字の「a」、ダブルクリックすると大文字の「A」になるキーボード

それぞれのスケッチについて、記事内では細かい説明はしていませんが、スケッチにコメントを入れてありますので参考にしていただければと思います。

試作キーボードのスケッチ

❶「a」と「b」の2種類の文字が入力できるキーボード

左側のスイッチを押すと「a」、中央のスイッチを押すと「b」を入力できるキーボードを製作します。

スイッチ検知は、スイッチライブラリを使用します。

最初にpollメソッドでスイッチ状態の調査をして、次にpushedメソッドで押されたかどうかを判定します。

押されたことがわかったら、キーボードライブラリを使用してKeyboard.print("a");というようにスイッチに対応する文字をPCに送ります。

スケッチは以下のように作成してみました。

/*
 * 「a」と「b」の2種類の文字が入力できるキーボード
 *     左スイッチ: 「a」の入力
 *     中央スイッチ:「b」の入力
 */

// ライブラリヘッダファイル
#include <Keyboard.h>
#include <avdweb_Switch.h>

// スイッチの接続端子
#define SWITCH_HIDARI A5 // 左側スイッチ
#define SWITCH_CHUO   A4 // 中央スイッチ

// スイッチクラスのインスタンスを生成
Switch hidariSwitch(SWITCH_HIDARI); // 左側スイッチのインスタンス
Switch chuoSwitch(SWITCH_CHUO);     // 中央スイッチのインスタンス


void setup() {
  // キーボード接続時の処理
  Keyboard.begin();

  // スイッチ接続ピンの設定
  pinMode(SWITCH_HIDARI, INPUT_PULLUP);
  pinMode(SWITCH_CHUO,   INPUT_PULLUP);
}

void loop() {

  // スイッチライブラリに左側スイッチ状態の調査を指示
  hidariSwitch.poll();
  
  // 左側スイッチが押されたら「a」をPCに送信
  if( hidariSwitch.pushed() ){
    Keyboard.print("a");
  }


  // スイッチライブラリに中央スイッチ状態の調査を指示
  chuoSwitch.poll();

  // 中央スイッチが押されたら「b」をPCに送信
  if( chuoSwitch.pushed() ){
    Keyboard.print("b");
  }

}

❷ Shift機能がついたキーボード

❶のスケッチでは「a」と「b」の文字しか入力できません。

右側のスイッチが空いていますので、右側スイッチにShiftキーの機能を持たせることにします。

右側のスイッチ状態に応じて、左側スイッチが押された時と中央スイッチが押された時、次のような文字入力ができるようにしてみます。

右側スイッチの状態左側スイッチ押下時中央スイッチ押下時
OFFaを送信bを送信
ONAを送信Bを送信

アルゴリズムは次のように考えてみました。

❶のスケッチでは、スイッチが押されたとき、すぐに「a」や「b」を送っています。

❷のスケッチでは、文字データを送る前に右側スイッチ(Shiftキーの状態)をdigitalReadで確認することにしました。例えば右側スイッチがOFF(ShiftキーOFF)のときは「a」を、右側スイッチがON(ShiftキーON)のときは「A」を送るようにします。

スケッチは以下のように作成してみました。

/*
 * 「a」と「b」の2種類の文字入力と、Shift機能がついたキーボード
 *     左スイッチ: 「a」の入力
 *     中央スイッチ:「b」の入力
 *     右スイッチ:  Shiftキー機能
 */

// ライブラリヘッダファイル
#include <Keyboard.h>
#include <avdweb_Switch.h>

// スイッチの接続端子
#define SWITCH_HIDARI A5 // 左側スイッチ
#define SWITCH_CHUO   A4 // 中央スイッチ
#define SWITCH_MIGI   A3 // 右側スイッチ

// スイッチクラスのインスタンスを生成
Switch hidariSwitch(SWITCH_HIDARI); // 左側スイッチのインスタンス
Switch chuoSwitch(SWITCH_CHUO);     // 中央スイッチのインスタンス
Switch migiSwitch(SWITCH_MIGI);     // 右側スイッチのインスタンス


void setup() {
  // キーボード接続時の処理
  Keyboard.begin();

  // スイッチ接続ピンの設定
  pinMode(SWITCH_HIDARI, INPUT_PULLUP);
  pinMode(SWITCH_CHUO,   INPUT_PULLUP);
  pinMode(SWITCH_MIGI,   INPUT_PULLUP);

}

void loop() {

  // スイッチライブラリに左側スイッチ状態の調査を指示
  hidariSwitch.poll();
  
  // 左側スイッチが押されたら、Shiftキーの状態により「a」か「A」をPCに送信
  if( hidariSwitch.pushed() ){
    if( digitalRead(SWITCH_MIGI) ) {
      Keyboard.print("a");  // ShiftキーがOFFのとき
    } else {
      Keyboard.print("A");  // ShiftキーがONのとき
    }

  }


  // スイッチライブラリに中央スイッチ状態の調査を指示
  chuoSwitch.poll();

  // 中央スイッチが押されたら、Shiftキーの状態により「b」か「B」をPCに送信
    if( digitalRead(SWITCH_MIGI) ) {
      Keyboard.print("b");  // ShiftキーがOFFのとき
    } else {
      Keyboard.print("B");  // ShiftキーがONのとき
    }

}

❸ カット、コピー、ペーストの3種類の機能のキーボード

次に、カット、コピー、ペースト機能のキーボードを試作してみます。

ドキュメントを作成するとき、コピぺってよく使いますよね。

普通のキーボードでは、Windowsの場合は「Ctrl+C」、macOSの場合は「command+C」というように、2つのキーを組み合わせて使用します。

よく使う機能ですので、使うたびに2つのキーを押すのはちょっと面倒です。

そこで、スイッチ1個押すだけで、カット、コピー、ペーストの機能が使えるようにしてみます。

キーボードライブラリはこのようなキー操作にも対応していますので、その機能を使用して以下のように押されたスイッチに応じてカット、コピー、ペーストができるキーボードを製作します。

OSWindowsmacOS
左側スイッチ
カット
Ctrl + Xcommand + X
中央スイッチ
コピー
Ctrl + Ccommand + C
右スイッチ
ペースト
Ctrl + Vcommand + V

カット、コピー、ペーストは、Ctrlキーやcommandキーを押しながら、XやCやVキーを押す必要があります。

つまり、Arduino Microのキーボードの動きとしては、最初に「Ctrlキー・commandキーを押す」、次に「XやCやVの文字データを送る」、最後に「Ctrlキー・commandキーを離す」という動作を再現する必要があります。

キーボードライブラリでは、キーを押したり離したりする操作を行う次のメソッドが用意されています。

これらのメソッドを使用して、キー操作を再現することにします。

メソッド意味使い方
press(文字またはキー名)引数で指定したキーを押した状態にするKeyboard.press('x');
「x」キーを押した状態にする
release(文字またはキー名)引数で指定したキーを離した状態にするKeyboard.release('x');
「x」キーを離した状態にする
releaseAll()
※引数なし
全ての押しているキーをまとめて離した状態にするKeyboard.releaseAll();
全てキーを離した状態にする

注意点としては、文字キーの場合はキーに書かれている文字を'で囲みます。

「x」キーの場合は'x'で、"x"ではない点に注意します。

またCtrlキー、Commandキー、Deleteキーなどの特殊キーについては、キーボードライブラリのヘッダファイルの中で、#defineで定義されています。

例えばWindowsキーボードの場合、左側のCtrlキーを押す場合は次のようなスケッチになります。

Keyboard.press(KEY_LEFT_CTRL);  // 左側のCTRLキーを押した状態にする

このスケッチを実行すると、左側CTRLキーが押された状態のままになります。

押した状態のキーを離した状態にするには次のようなスケッチになります。

Keyboard.release(KEY_LEFT_CTRL);  // 左側のCTRLキーを離した状態にする

CTRLキーなどの特殊キーは他にもたくさんありますが、キーボードライブラリでは次のように定義されています。

キー名対応OS定義名
左側 SHIFTキー共通KEY_LEFT_SHIFT
右側 SHIFTキー共通KEY_RIGHT_SHIFT
左側 CTRLキーWindowsKEY_LEFT_CTRL
右側 CTRLキーWindowsKEY_RIGHT_CTRL
左側 ALTキーWindowsKEY_LEFT_CTRL
右側 ALTキーWindowsKEY_RIGHT_CTRL
左側 CommandキーmacOSKEY_LEFT_GUI
右側 CommandキーmacOSKEY_RIGHT_GUI
上矢印キー共通KEY_UP_ARROW
下矢印キー共通KEY_DOWN_ARROW
左矢印キー共通KEY_LEFT_ARROW
右矢印キー共通KEY_RIGHT_ARROW
バックスペースキー共通KEY_BACKSPACE
Deleteキー共通KEY_DELETE
TABキー共通KEY_TAB
リターンキー共通KEY_RETURN
ESBキー共通KEY_ESC
Page Upキー共通KEY_UP
Page Downキー共通KEY_DOWN
Homeキー共通KEY_HOME
Endキー共通KEY_END
Caps Lockキー共通KEY_CAPS_LOCK
ファンクションキー共通KEY_F1など
(F1 〜 F24で指定)

スケッチは以下のように作成してみました。

WindowsとmacOSではショートカットキーが異なりますので、macOSの場合は11行目のコメントアウトを外し、Windowsの場合は14行目のコメントアウトを外していただければと思います。

/*
 * カット・コピー・ペーストだけのキーボード
 *  左側スイッチ: カットキー
 *  中央スイッチ: コピーキー
 *  右側スイッチ: ペーストキー
 */

// commandまたはctrlキーの定義
// 使用しているOSに応じて、次のどちらかの#defineの//を削除してください

//   macOSの場合は次の行のコメントをはずしてください (先頭の//を削除)
//#define shortcutKey KEY_LEFT_GUI

//   Windowsの場合は次行のコメントをはずしてください (先頭の//を削除)
//#define shortcutKey KEY_LEFT_CTRL 

// ライブラリをインクルード
#include <Keyboard.h>
#include <avdweb_Switch.h>

// スイッチの接続端子
#define SWITCH_HIDARI A5 // 左側スイッチ
#define SWITCH_CHUO   A4 // 中央スイッチ
#define SWITCH_MIGI   A3 // 右側スイッチ

// スイッチクラスのインスタンスを生成
Switch hidariSwitch(SWITCH_HIDARI);
Switch chuoSwitch(SWITCH_CHUO);
Switch migiSwitch(SWITCH_MIGI);


void setup() {
  Keyboard.begin();  // キーボードの接続処理

  // スイッチ接続ピンの設定
  pinMode(SWITCH_HIDARI, INPUT_PULLUP);
  pinMode(SWITCH_CHUO,   INPUT_PULLUP);
  pinMode(SWITCH_MIGI,   INPUT_PULLUP);
}

void loop() {

  // 左側スイッチ(カットキー)の処理
  hidariSwitch.poll();  // スイッチライブラリに左側スイッチ状態の調査を指示
  
  // 左側スイッチが押されたか判定して、押されていたらカットキーの組み合わせを送信する
  if( hidariSwitch.pushed() ){
    Keyboard.press(shortcutKey);  // Command/Ctrlキーを押す
    Keyboard.press('x');          // 'x'キーを押す
    delay(100);                   // ちょっと待つ
    Keyboard.releaseAll();        // 両方のキーを離す
  }

  // 中央スイッチ(コピーキー)の処理
  chuoSwitch.poll();  // スイッチライブラリに中央スイッチ状態の調査を指示
  
  // 中央スイッチが押されたか判定して、押されていたらコピーキーの組み合わせを送信する
  if( chuoSwitch.pushed() ){
  
    Keyboard.press(shortcutKey);  // Command/Ctrlキーを押す
    Keyboard.press('c');          // 'c'キーを押す
    delay(100);                   // ちょっと待つ
    Keyboard.releaseAll();        // 両方のキーを離す
  }

  // 右側スイッチ(ペーストキー)の処理
  migiSwitch.poll();  // スイッチライブラリに右側スイッチ状態の調査を指示

  // 右側スイッチが押されたか判定して、押されていたらペーストキーの組み合わせを送信する
  if( migiSwitch.pushed() ){
  
    Keyboard.press(shortcutKey);  // Command/Ctrlキーを押す
    Keyboard.press('v');          // 'v'キーを押す
    delay(100);                   // ちょっと待つ
    Keyboard.releaseAll();        // 両方のキーを離す
  }

}

❹ スイッチを1回押すと小文字の「a」、ダブルクリックすると大文字の「A」になるキーボード

最後に、同じスイッチでもカチッと1回押したときと、ダブルクリックしたとき(カチッカチッと短い間隔で2回押したとき)で、入力できる文字を変えてみます。

のような入力ができるキーボードを製作してみます。

スイッチ操作左側スイッチ中央スイッチ
シングルクリック
(1回カチッと押す)
「a」を送信「b」を送信
ダブルクリック
(2回カチカチっと押す)
「A」を送信「B」を送信

スイッチライブラリの使い方ですが、pollメソッドでスイッチの状態を調査した後、次のメソッドでシングルクリックかダブルクリックか判定することができます。

メソッド意味使い方
singleClickシングルクリックを検知
した場合、戻り値は1、それ以外は0
if( hidariSwitch.singleClick() ) {
シングルクリックした場合の処理;
}
doubleClickダブルクリックを検知した場合、戻り値は1、それ以外は0if( hidariSwitch.doubleClick() ) {
ダブルクリックした場合の処理;
}

スケッチは次のように作成してみました。

/*
 * スイッチの押し方で入力できる文字が異なるキーボード
 *  シングルクリックの場合
 *    左スイッチ: 「a」を入力
 *    中央スイッチ:「b」を入力
 *  ダブルクリックの場合
 *    左スイッチ: 「A」を入力
 *    中央スイッチ:「B」を入力
 */

// ライブラリをインクルード
#include <Keyboard.h>
#include <avdweb_Switch.h>

// スイッチの接続端子
#define SWITCH_HIDARI A5 // 左側スイッチ
#define SWITCH_CHUO   A4 // 中央スイッチ

// スイッチクラスのインスタンスを生成
Switch hidariSwitch(SWITCH_HIDARI);
Switch chuoSwitch(SWITCH_CHUO);


void setup() {
  Keyboard.begin();  // キーボードの接続処理

  // スイッチ接続端子の設定
  pinMode(SWITCH_HIDARI, INPUT_PULLUP);
  pinMode(SWITCH_CHUO,   INPUT_PULLUP);
}

void loop() {

  // 左側スイッチの処理
  hidariSwitch.poll();  // スイッチライブラリに左側スイッチ状態の調査を指示
  
  // 左側スイッチがシングルクリックされたら「a」をPCに送信
  if( hidariSwitch.singleClick() ){
    Keyboard.print("a");
  }

  // 左側スイッチがダブルクリックされたら「A」をPCに送信
  if( hidariSwitch.doubleClick() ){
    Keyboard.print("A");
  }


  // 中央スイッチの処理
  chuoSwitch.poll();  // スイッチライブラリに中央スイッチ状態の調査を指示

  // 中央スイッチがシングルクリックされたら「b」をPCに送信
  if( chuoSwitch.singleClick() ){
    Keyboard.print("b");
  }

  // 中央スイッチがダブルクリックされたら「B」をPCに送信
  if( chuoSwitch.doubleClick() ){
    Keyboard.print("B");
  }

}

峠を越えた感じです!

基礎編パート2のここまでの記事では、新しい考え方などをいろいろ習得してきました。

特に大きな概念として「オブジェクト」「クラス」「インスタンス」「メソッド」という項目を習得してきました。

また、今回の記事ではいくつかキーボードを試作することにより、スケッチのイメージができたのではないかと思います。

これで峠を越えた、という感じです。

次回はArduino Microの復活方法、その次にチャレンジ課題に挑戦してみます。

そのあとはいよいよ「言い訳キーボード」に向けてスケッチを仕上げていきます。(その過程で新しい知識が出てきますが、峠は超えていますのでご安心ください!)

更新履歴

日付内容
2021.9.25新規投稿
2025.2.14Arduino IDE2対応
スケッチ動作確認
説明内容補足
通知の設定
通知タイミング
guest
0 コメント
新しい準
古い順 一番投票が多い
本文中にフィードバック
全てのコメントを見る
目次