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

このページをスマホなどでご覧になる場合は、画面を横長にする方が読みやすくなります。
目次へ  前のページへ (1) (2) (3) (4) 次のページへ
I/Oピン一つで読める4X4キーパッドキット 商品名 I/Oピン一つで読める4X4キーパッドキット
税抜き小売価格 900円
販売店 スイッチサイエンス
2016年03月23日 「Arduino Uno等でI2Cインターフェースを使う場合の注意点」と「問い合わせ先」を追加。
2022年06月23日 「Arduino Uno等でI2Cインターフェースを使う場合の注意点」と「問い合わせ先」を、4ページに移動。

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

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

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

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

リスト1、ResKeyPad.hのインクルードCOPY
#include <ResKeypad.h>

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

ResKeypadクラスのオブジェクト変数の宣言の際に、キーパッドのキーアサイン(どのキーにどの文字を割り当てるか)を指定します。SIDE Aに部品を実装した場合と、SIDE Bに部品を実装した場合とでは、キーアサインが異なるため、オブジェクト変数の宣言も変わってきます。

SIDE Aに部品を実装した場合の宣言はリスト2の様になります。

リスト2、SIDE Aに部品を実装した場合のオブジェクト変数の宣言(ArduinoのA4端子にキーパッドをつなげた場合)COPY
ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A);

SIDE Bに部品を実装した場合の宣言は次のようになります。

リスト3、SIDE Bに部品を実装した場合のオブジェクト変数の宣言(ArduinoのA4端子にキーパッドをつなげた場合)COPY
ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B);

ただし、キーアサインに関係のない関数(GetKey関数GetKeyState関数、およびWaitForKey関数)のみを利用する場合は、第4引数を省略してリスト4の様にすることもできます。(ただし、第4引数を省略しないでもいいです)

リスト4、第4引数を省略したオブジェクト変数の宣言(ArduinoのA4端子にキーパッドをつなげた場合)COPY
ResKeypad keypad(A4,16,RESKEYPAD_4X4);

各引数の意味は、次の通りです。ResKeypadライブラリは、4X4キーパッドだけではなく、同様の原理で動作する色々なキーパッドに対応したライブラリなので、引数が少し多くなっています。(図21参照)

図21、ResKeypad型のオブジェクト変数の宣言
図21、ResKeypad型のオブジェクト変数の宣言

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

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

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

第4引数は、キーアサインを指定します。SIDE Aに部品を実装した場合はRESKEYPAD_4X4_SIDE_Aを、SIDE Bに部品を実装した場合はRESKEYPAD_4X4_SIDE_Bを指定します。先ほど述べたように、キーアサインに関係ない関数のみを使う場合は、第4引数を省略することが可能です。

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

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

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

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

9-3.WaitForChar関数の使い方

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

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

リスト5、WaitForChar関数の使用例(入力したキーの文字をシリアルポートに出力するスケッチ)COPY
#include <ResKeypad.h>

ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

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

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

実行結果は、シリアルモニタ(ツール→シリアルモニタメニューで起動)で観察できます。下の図は、シリアルモニタを起動後に、キーパッド上のキーを0123456789の順に押した場合の結果です。

図22、キーの読み取り結果をシリアルモニタで確認する
図22、キーの読み取り結果をシリアルモニタで確認する

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

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

リスト6、WaitForChar関数の呼び出し頻度が少ないためにキーを取りこぼすスケッチCOPY
#include <ResKeypad.h>

ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

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

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

図23、関数の呼び出し頻度が低いとキーを取りこぼす
図23、関数の呼び出し頻度が低いとキーを取りこぼす

9-4.WaitForKey関数の使い方

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

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

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

リスト7、WaitForKey関数の使用例(入力したキーの番号をシリアルポートに出力するスケッチ)COPY
#include <ResKeypad.h>

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

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

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

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

図24、SW1~5を順に押した結果
図24、SW1~5を順に押した結果

9-5.GetChar関数の使い方

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

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

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

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

リスト8、GetChar関数の使用例(入力したキーの文字をシリアルポートに出力するスケッチ)COPY
#include <ResKeypad.h>

ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

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

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

このスケッチを動作させ、0123456789と順にキーを押した結果を次に示します。

図22(再掲)、GetChar関数でキーの押下を取得した結果
図22(再掲)、GetChar関数でキーの押下を取得した結果

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

リスト9、LCDに時刻を表示しながら押したキーの文字も表示するスケッチCOPY
#include <mglcd.h>
#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);
ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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
写真41、GetChar関数で、キーの押下の判定と別の作業を、平行して行っている様子
↑ 画像をクリックすると拡大
写真41、GetChar関数で、キーの押下の判定と別の作業を、平行して行っている様子

9-6.GetKey関数の使い方

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

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

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

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

リスト10、GetKey関数の使用例(押したキーの番号をシリアルポートに出力するスケッチ)COPY
#include <ResKeypad.h>

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

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

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

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

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

図24(再掲)、Getkey関数の動作の例
図24(再掲)、Getkey関数の動作の例

9-7.GetCharState関数の使い方

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

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

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

#include #include <ResKeypad.h>

ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

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

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

図27、GetCharState関数の動作例
図27、GetCharState関数の動作例

9-8.GetKeyState関数の使い方

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

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

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

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

#include <ResKeypad.h>

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

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

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

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

図27(再掲)、GetKeyState関数の動作例
図27(再掲)、GetKeyState関数の動作例

次のページでは、1つのArduinoで複数のキーパッドを使う方法等を説明します。

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

このページで使われている用語の解説

関連ページ

関連製品

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