I/Oピン一つで読める4X5キーパッドキットサポートページ(4)

このページをスマホなどでご覧になる場合は、画面を横長にする方が読みやすくなります。
目次へ  前のページへ (1) (2) (3) (4) 次のページへ
I/Oピン一つで読める4X5キーパッドキット 商品名 I/Oピン一つで読める4X5キーパッドキット
税抜き小売価格 2400円
販売店 スイッチサイエンス
2015年09月08日 暫定公開。
2015年09月12日 正式公開。

9.キーパッドを利用するスケッチの作り方

キーパッドを利用するスケッチを、ResKeypadライブラリを使って作る方法を説明します。

9-1.ResKeypadライブラリを使うための準備

ResKeypadライブラリを利用するためには、スケッチの先頭部分で、ResKeypad.hをインクルードする必要があります。

#include <ResKeypad.h>

また、グローバル変数を宣言する部分で、ResKeypadクラスのオブジェクト変数を宣言する必要があります。オブジェクト変数の名前は何でもいいのですが、ここではkeypadにすることにします。

ResKeypadクラスのオブジェクト変数の宣言の際に、キーパッドのキーアサイン(どのキーにどの文字を割り当てるか)を指定します。4X5キーパッドキットの場合、キーアサインは、キートップと樹脂キャップにはさむ紙片により、自由に設定できます。ご自分のキーアサインに応じた宣言をする必要があります。

写真1(再掲)、紙片をキートップと透明キャップではさみ込む様子
↑ 画像をクリックすると拡大
写真1(再掲)、紙片をキートップと透明キャップではさみ込む様子
PROGMEM const char RESKEYPAD_4X5_CHAR[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'};
ResKeypad keypad(A4,20,RESKEYPAD_4X5,RESKEYPAD_4X5_CHAR);

上のコードでは、RESKEYPAD_4X5_CHARという配列が、キーアサインを宣言しています。この例では、SW1に'a'、SW2に'b'、SW3に'c'、…、SW20に't'という文字を割り当てています。この部分を、ご自分のキーパッドのキーアサインにしたがって、書き換えてください。なお、キーに割り当てられる文字は、1バイト文字1文字です。文字列を割り当てたり、全角文字や半角カタカナなどマルチバイト文字を割り当てる事はできません。

ただし、キーアサインに関係のない関数(GetKey、GetKeyState、およびWaitForKey)のみを利用する場合は、RESKEYPAD_4X5_CHARの宣言と、keypadオブジェクトの第4引数を省略して次のようにすることもできます。

ResKeypad keypad(A4,20,RESKEYPAD_4X5);

ResKeypadクラスのオブジェクト変数の宣言時の各引数の意味は、次のとおりです。ResKeypadライブラリは、4X5キーパッドだけではなく、同様の原理で動作する色々なキーパッドに対応したライブラリなので、引数が少し多くなっています。

図10、ResKeypadクラスのオブジェクト変数の宣言時の各引数
図10、ResKeypadクラスのオブジェクト変数の宣言時の各引数

第1引数は、キーパッドの出力信号をつなぐ、Arduinoのアナログ入力ピンを指定します。上の例ではA4を指定していますが、例えばA5端子にキーパッドをつなぐときは、第1引数をA5にします

第2引数は、キーパッドについているキーの数を指定します。4X5キーパッドの場合は、キーが20個付いていますから、第2引数には必ず20を指定します。

第3引数は、キーパッドの出力電圧の閾値を指定します。閾値の話は抵抗分圧器を使った、多くのスイッチのセンシングという記事に解説がありますが、必ずしも理解する必要はありません。4X5キーパッドの場合は、第3引数には必ずRESKEYPAD_4X5を指定します。

第4引数は、キーアサインを宣言したPROGMEM const char型の配列を指定します。キーアサインに関係ない関数のみを使う場合は、第4引数を省略することが可能です。

9-2.ResKeypadライブラリの関数群

ResKeypadライブラリには、キーパッドから情報を読み出すための関数が、ResKeypadクラスのメンバ関数として6種類用意されています。全ての関数には引数はありません。

6種類の関数の名称、返り値の型、および関数の働きを、次の表に示します。

表3、ResKeypadライブラリの関数群
関数の名称 返り値の型 関数の働き
WaitForChar char 何かキーが押されるまで待ち、キーに割り当てられた文字を返す。
WaitForKey signed char 何かキーが押されるまで待ち、キーの番号を返す。
GetChar char 押されたキーに割り当てられた文字を返す。キーが押されない場合は、'\0'を返す。
GetKey signed char 押されたキーの番号を返す。キーが押されない場合は、-1を返す。
GetCharState char キーパッドの状態を返す。現在押されているキーがある場合は、そのキーに割り当てられた文字を返し、現在何もキーが押されていない場合は'\0'を返す。
GetKeyState signed char キーパッドの状態を返す。現在押されているキーがある場合は、そのキーの番号を返し、現在何もキーが押されていない場合は-1を返す。

9-3.WaitForChar関数の使い方

WaitForChar関数は、キーパッドで入力された文字を取得するのに、一番使いやすい関数です。この関数を呼び出すと、何かキーを押すまで関数から帰ってきません。何かキーを押すと、そのキーに割り当てられた文字を返します。

例えば次のスケッチでは、押したキーの文字をシリアルポートに9600bpsで送信します。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

PROGMEM const char RESKEYPAD_4X5_CHAR[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'}; // キーアサインの宣言。実際のキーアサインに合わせて書き換えが必要。
ResKeypad keypad(A4,20,RESKEYPAD_4X5,RESKEYPAD_4X5_CHAR); // 4X5キーパッドをA4端子に接続する事を宣言。

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  Serial.print(keypad.WaitForChar());
} // loop

WaitForChar関数は、ResKeypadクラスのメンバ関数なので、呼び出し時にkeypad.WaitForChar()と、keypad.を付けている点に注意してください。

実行結果は、シリアルモニタ(ツール→シリアルモニタメニューで起動)で観察できます。下の図は、シリアルモニタを起動後に、キーパッド上でSW1、SW2、SW3、SW4、SW5の順に押した場合の結果です。(SW1~SW5のキーはa~eのアルファベットに割り当てられている)

図11、SW1~SW5を順に押した結果
図11、SW1~SW5を順に押した結果

WaitForChar関数に限らず、ResKeypadライブラリの関数は、その関数が呼び出される間しか、キーパッドの状態を監視しません。よって、人間がキーを押す間隔よりも短い間隔で関数を繰り返し呼ぶ必要があります。

試しに次のスケッチのようにdelay(1000);により、1秒の間隔をおいてWaitForChar関数を呼び出すようにすると、キーを短い間隔で押した場合に文字を取りこぼします。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

PROGMEM const char RESKEYPAD_4X5_CHAR[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'}; // キーアサインの宣言。実際のキーアサインに合わせて書き換えが必要。
ResKeypad keypad(A4,20,RESKEYPAD_4X5,RESKEYPAD_4X5_CHAR); // 4X5キーパッドをA4端子に接続する事を宣言。

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  Serial.print(keypad.WaitForChar());
  delay(1000); // 意図的に1秒間動作を止める
} // loop

このスケッチの実行し、すばやくSW1~SW5を順に押した結果は、例えば次のようになります。キーを取りこぼしている様子がわかります。

図12、delay(1000)によりキーを取りこぼした例
図12、delay(1000)によりキーを取りこぼした例

9-4.WaitForKey関数の使い方

WaitForKey関数の働きは、WaitForChar関数とほぼ同じです。唯一違う点は、返り値がキーに割り当てられた文字ではなく、キーの番号だという点です。

4X5キーパッドには、SW1~SW20の20個のキーがありますが、それぞれ順に0~19の番号が付いています。つまり、SW1を押した場合は0が返 り、SW2を押した場合は1が返り、…(中略)…、SW20を押した場合は19が返るという具合に、SW番号より1だけ小さい番号が返り値として戻ってきます。

次のスケッチは、押したキーの番号をシリアルポートに9600bpsで送信します。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

ResKeypad keypad(A4,20,RESKEYPAD_4X5); // 第4引数は省略できる

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  Serial.println(keypad.WaitForKey());
} // loop

SW1、SW2、SW3、SW4、SW5の順にキーを押した結果は、次のようになります。

図13、SW1~SW5を順に押した結果
図13、SW1~SW5を順に押した結果

9-5.GetChar関数の使い方

WaitForChar関数は、何かキーが押されるまで待ち、キーが押された瞬間に、そのキーに割り当てられる文字を返しますが、キーが押されるまでArduinoが停止してしまうという問題があります。そこで、キーが押されていない場合は、押されるまで待たずに、'\0'を返すことで、処理を続行できるようにしたのがGetChar関数です。

GetChar関数は、キーが押されている間に複数回呼ばれると、最初の1回のみキーに対応した文字を返し、残りの呼び出しでは'\0'を返します。(下図参照)

図14、GetChar関数の呼び出しタイミングと返り値
図14、GetChar関数の呼び出しタイミングと返り値

次のスケッチは、WaitForChar関数の使い方の項の最初のスケッチと同様、押したキーの文字をシリアルポートに9600bpsで送信します。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

PROGMEM const char RESKEYPAD_4X5_CHAR[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'}; // キーアサインの宣言。実際のキーアサインに合わせて書き換えが必要。
ResKeypad keypad(A4,20,RESKEYPAD_4X5,RESKEYPAD_4X5_CHAR);

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  char c=keypad.GetChar();
  if(c!='\0') Serial.print(c);
} // loop

GetChar関数の返り値を'\0'と比較している点に注意してください。

このスケッチを動作させ、abcde(SW1~SW5)と順にキーを押した結果を次に示します。

図15、abcdeと順に押した結果
図15、abcdeと順に押した結果

次のスケッチは、GLCD学習シールドキットを用いて、millis関数で取得した時刻(スケッチ起動後の経過時間。単位はミリ秒)を画面上部に表示しながら、押したキーを画面下部に表示するものです。このように、キーを受け付けている状態で、何かほかの事(この場合は時刻の表示)を行うには、WaitForChar関数ではなくGetChar関数を使います。(キーパッドはA4端子に接続してください)

//#include <mglcd.h> // MGLCDライブラリ Ver. 0.40より前の場合
#include <MGLCD.h> // MGLCDライブラリ Ver. 0.40以降の場合

#include <ResKeypad.h>

const TLcdPinAssignTable PinAssignTable={ // LCDのピンアサイン
    A0_DI  : A3, // A0
    CS1_E1 : A0, // E1
    CS2_E2 : A1, // E2
    E      : MGLCD_UNUSED_PIN,
    RW     : A2,
    DB0    : 8 ,
    DB1    : 9 ,
    DB2    : 10,
    DB3    : 11,
    DB4    : 4 ,
    DB5    : 5 ,
    DB6    : 6 ,
    DB7    : 7
}; // PinAssignTable;

mglcd_S12232ZA MGLCD(PinAssignTable);

PROGMEM const char RESKEYPAD_4X5_CHAR[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'}; // キーアサインの宣言。実際のキーアサインに合わせて書き換えが必要。
ResKeypad keypad(A4,20,RESKEYPAD_4X5,RESKEYPAD_4X5_CHAR);

void setup()
{
  // LCDに負電圧を供給するチャージポンプ回路を動作させる
  pinMode(3,OUTPUT);
  analogWrite(3,127);

  // LCDの初期化
  while(MGLCD.Reset());
  MGLCD.SetCodeMode(MGLCD_CODE_UTF8); // カナ表示を許可
  MGLCD.print("ジコク");
  MGLCD.SetTextWindow(0,1,19,3); // キーを押した結果を表示するウィンドウ
} // setup

void loop() {
  unsigned char x,y;
  char c=keypad.GetChar(); // 押したキーを取得
  if(c!='\0') MGLCD.print(c); // 押したキーを表示
  x=MGLCD.GetX(); // x座標を退避
  y=MGLCD.GetY(); // y座標を退避
  MGLCD.SetTextWindow(0,0,19,0); // 時刻表示のウィンドウ
  MGLCD.Locate(6,0);
  MGLCD.print(millis()); // 時刻表示
  MGLCD.SetTextWindow(0,1,19,3); // キーを押した結果を表示するウィンドウ
  MGLCD.Locate(x,y); // 座標を復帰
} // loop
写真32、スケッチ実行の様子
↑ 画像をクリックすると拡大
写真32、スケッチ実行の様子

9-6.GetKey関数の使い方

GetKey関数の働きは、GetChar関数とほぼ同じです。唯一違う点は、返り値がキーに割り当てられた文字ではなく、キーの番号だという点です。

4X5キーパッドには、SW1~SW20の20個のキーがありますが、それぞれ順に0~19の番号が付いています。つまり、SW1を押した場合は0が返 り、SW2を押した場合は1が返り、…(中略)…、SW20を押した場合は19が返るという具合に、SW番号より1だけ小さい番号が返り値として戻ってきます。

何もキーが押されていない場合は、-1が返り値になります。

次のスケッチは、押したキーの番号をシリアルポートに9600bpsで送信します。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

ResKeypad keypad(A4,20,RESKEYPAD_4X5); // 第4引数は省略できる

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  signed char key=keypad.GetKey();
  if(key>=0) Serial.println(key);
} // loop

GetKey関数の返り値が0以上かどうかを判定している点に注意してください。

SW1、SW2、SW3、SW4、SW5の順にキーを押した結果は、次の様になります。

図13(再掲)、SW1~SW5を順に押した結果
図13(再掲)、SW1~SW5を順に押した結果

9-7.GetCharState関数の使い方

GetCharState関数は、現在押されているキーに対応した文字を返します。押されているキーがなければ'\0'を返します。キーが押されている間は、ずっとそのキーに対応した文字を返し続けるという点で、GetChar関数と異なります。

図16、GetChar関数とGetCharState関数の違い
図16、GetChar関数とGetCharState関数の違い

次のスケッチは、現在押しているキーをシリアルポートに9600bpsで送ります。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

PROGMEM const char RESKEYPAD_4X5_CHAR[20] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'}; // キーアサインの宣言。実際のキーアサインに合わせて書き換えが必要。
ResKeypad keypad(A4,20,RESKEYPAD_4X5,RESKEYPAD_4X5_CHAR);

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  char c=keypad.GetCharState();
  if(c!='\0') { // キーが押されていた
    Serial.println(c);
  } else { // キーが押されていなかった
    Serial.println("none");
  } // if
} // loop

このスケッチを起動して、fのキー(SW6)を押した場合、次のような結果になります。

図17、fのキーを押した時の結果
図17、fのキーを押した時の結果

9-8.GetKeyState関数の使い方

GetKeyState関数の働きは、GetCharState関数とほぼ同じです。唯一違う点は、返り値がキーに割り当てられた文字ではなく、キーの番号だという点です。

4X5キーパッドには、SW1~SW20の20個のキーがありますが、それぞれ順に0~19の番号が付いています。つまり、SW1を押した場合は0が返り、SW2を押した場合は1が返り、…(中略)…、SW20を押した場合は19が返るという具合に、SW番号より1だけ小さい番号が返り値として戻ってきます。

何もキーが押されていない場合は、-1が返り値になります。

次のスケッチは、現在押しているキーの番号をシリアルポートに9600bpsで送ります。(キーパッドはA4端子に接続してください)

#include <ResKeypad.h>

ResKeypad keypad(A4,20,RESKEYPAD_4X5); // 第4引数は省略できる

void setup()
{
  Serial.begin(9600);
} // setup

void loop()
{
  Serial.println(keypad.GetKeyState());
} // loop

このスケッチを起動して、SW6のキーを押した場合、次の様な結果になります。

図18、SW6を押した場合の結果
図18、SW6を押した場合の結果

10.問い合わせ先

もし、輸送上のトラブルが発生した場合は、委託販売業者にご連絡願います。

技術的な問題などが発生した場合は、こちらのフォームからメールをいただきますよう、お願いします。その際、メールのタイトルは「4X5キーパッドキットについて」としてください。

目次へ  前のページへ (1) (2) (3) (4) 次のページへ

関連ページ

関連製品

I2C接続4X4キーパッド 商品名 I2C接続4X4キーパッド
税抜き小売価格 2400円
販売店 スイッチサイエンス マルツ
サポートページ
I/Oピン一つで読める4X4キーパッドキット 商品名 I/Oピン一つで読める4X4キーパッドキット
税抜き小売価格 900円
販売店 スイッチサイエンス
サポートページ
I/Oピン一つで読める4X4キーパッド(完成品) 商品名 I/Oピン一つで読める4X4キーパッド(完成品)
税抜き小売価格 1380円
販売店 スイッチサイエンス
サポートページ
M3×6mm両側メススペーサ・M3X5mmネジ 各4本セット 商品名 M3×6mm両側メススペーサ・M3X5mmネジ 各4本セット
税抜き小売価格 120円
販売店 スイッチサイエンス
サポートページ
Arduino 電子工作
このサイトの記事が本になりました。
書名:Arduino 電子工作
ISBN:978-4-7775-1941-5
工学社の書籍の内容の紹介ページ
本のカバーの写真か書名をクリックすると、Amazonの書籍購入ページに移動します。