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

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

9-9.複数のキーパッドを使う方法

Arduinoには、複数のアナログ入力ピンがあります。例えば、Arduino Unoには、A0~A5の6本のアナログ入力ピンがあります。複数のアナログ入力ピンにそれぞれキーパッドを接続する事で、複数のキーパッドを使い、使用できるキーの数を拡張できます。

例として、図28の様な配線で、Arduino Unoに2つのキーパッドを接続して使う場合について、プログラムの作り方を説明します。

図28、2つのキーパッドとArduino Unoの配線
↑ 画像をクリックすると拡大
図28、2つのキーパッドとArduino Unoの配線

複数のキーパッドの値を読む場合は、WaitForChar関数WaitForKey関数は使わずにスケッチを作ります。これらの関数は、キーパッドからキー入力を待ち、キーが押された時点で関数から呼び出し元に処理が戻ります。よって、WaitForChar関数やWaitForKey関数を使うと、1つのキーパッドの入力待ちをしてしまい、その間、他のキーパッドのキーが押されても無視してしまいます。

例えば、リスト11の様にWaitForKey関数で2つのキーパッドからキーを読み取るスケッチを考えます。

リスト11、WaitForKey関数で2つのキーパッドからキーを読み取る例(うまくいかない例)COPY
#include <ResKeypad.h>

// A0につながっているキーパッドをkeypad1とする
ResKeypad keypad1(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad1(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

// A1につながっているキーパッドをkeypad2とする
ResKeypad keypad2(A1,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad3(A1,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

void loop()
{
  Serial.println(keypad1.WaitForKey()   ); // keypad1からキー番号を読み取りシリアル出力
  Serial.println(keypad2.WaitForKey()+16); // keypad2からキー番号を読み取り16を足してシリアル出力
} // loop

このスケッチの4行目では、ArduinoのA0ピンにつながっているキーパッド(図28のキーパッド1)をkeypad1という変数で宣言しています。

また8行目では、ArduinoのA1ピンにつながっているキーパッド(図28のキーパッド2)をkeypad2という変数で宣言しています。

loop関数内の18行目では、キーパッド1で押されたキーの番号を読み取り、その番号をSerial.println関数でシリアルポートに出力しています。この行では、押されたキーに応じて、0~15の範囲の数字がシリアルポートに出力されます。

また19行目では、キーパッド2で押されたキーの番号を読み取り、それに16を足して、シリアルポートに出力しています。この行では、押されたキーに応じて、16~31の範囲の数字がシリアルポートに出力されます。

このスケッチは、一見、両方のキーパッドをうまく扱える様に思えますが、思った通りには動作しません。というのは、先程も説明した通り、WaitForKey関数は、呼び出すと、指定のキーパッドでキーが押されるまでは処理を返さない(関数から戻ってこない)からです。

例えば今、8行目を実行していて、キーパッド1の入力を待っているとします。この時、keypad1.WaitForKey()は、キーパッド2の状態に関わらず、キーパッド1のキーが何か押されるまで処理を返しません。つまり、keypad1.WaitForKey()の実行中は、キーパッド2のキーを押しても、Arduinoが反応できないのです。

同様に、9行目を実行している時は、keypad2.WaitForKey()は、キーパッド2のキーが何か押されるまで処理を返しません。keypad2.WaitForKey()の実行中にキーパッド1のキーを押しても、Arduinoは反応できないのです。

この問題に対処するために、リスト11のWaitForKey関数の呼び出しをGetKey関数に置き換えて、リスト12の様に作り変えれば、期待通りの動作をする様になります。

リスト12、GetKey関数で2つのキーパッドからキーを読み取る例(うまくいく例)COPY
#include <ResKeypad.h>

// A0につながっているキーパッドをkeypad1とする
ResKeypad keypad1(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad1(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

// A1につながっているキーパッドをkeypad2とする
ResKeypad keypad2(A1,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad3(A1,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

void loop()
{
  signed char key; // キーパッドから読み取ったキー番号(キーパッド1とキーパッド2で共用)

  key=keypad1.GetKey(); // keypad1からキー番号を読み取る。キーが押されていないならkey=-1
  if(key>=0) Serial.println(key); // もしkeypad1のキーが押されていたら、キー番号をシリアル出力

  key=keypad2.GetKey(); // keypad2からキー番号を読み取る。キーが押されていなかったらkey=-1
  if(key>=0) Serial.println(key+16); // もしkeypad2のキーが押されていたら、キー番号に16を足してシリアル出力
} // loop

リスト11とリスト12は、loop関数だけが異なっています。

リスト12の18行目では、GetKey関数で読み取ったキー番号を記憶しておくための変数keyを宣言しています。この変数は、キーパッド1のキーを読み取る場合とキーパッド2のキーを読み取る場合で共用します。

20行目では、押されたキーのキー番号をkeypad1.GetKey()でキーパッド1から読み取り、変数keyに代入しています。もしキーパッド1のキーが押されていない場合でもkeypad1.GetKey()の呼び出しは瞬時に終わり、-1が返されます。

21行目では、変数keyが0以上であるかを確認し、0以上なら(キーパッド1のキーが押されていたなら)、Serial.println関数で、押されたキーのキー番号をシリアルポートに出力します。

22行目では、押されたキーのキー番号をkeypad2.GetKey()でキーパッド2から読み取り、変数keyに代入しています。もしキーパッド2のキーが押されていない場合でもkeypad2.GetKey()の呼び出しは瞬時に終わり、-1が返されます。

23行目では、変数keyが0以上であるかを確認し、0以上なら(キーパッド2のキーが押されていたなら)、Serial.println関数で、押されたキーのキー番号に16を足した数をシリアルポートに出力します。

この様にGetKey関数を使えば、キーパッドに押されたキーを取得に行って、もしキーが押されていなくても、何かキーが押されるまで待つことがないので、もう一方のキーパッドをすぐに読みに行くことができる様になり、スケッチが期待通り動作する様になります。

ただし、リスト11のスケッチでは、読み取ったキーを処理する部分(この場合ではSerial.print関数でシリアルポートに出力している部分)が2カ所に分散しています。(21行目と24行目) この程度の短いスケッチならこれでもあまり問題がないのですが、読み取ったキーを処理する部分が複雑な場合は、2カ所に分散していると、スケッチが読みにくくなってしまいます。

読み取ったキーを処理する部分を1カ所にまとめるには、リスト13の様にします。

リスト13、読み取ったキーを処理する部分を1カ所にまとめたスケッチの例COPY
#include <ResKeypad.h>

// A0につながっているキーパッドをkeypad1とする
ResKeypad keypad1(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad1(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

// A1につながっているキーパッドをkeypad2とする
ResKeypad keypad2(A1,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_A); // SIDE Aに部品を実装した場合はこの行を有効にする
//ResKeypad keypad3(A1,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B); // SIDE Bに部品を実装した場合はこの行を有効にする

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

void loop()
{
  signed char key; // キーパッドから読み取ったキー番号(キーパッド1とキーパッド2で共用)

  key=keypad1.GetKey(); // keypad1からキー番号を読み取る。キーが押されていないならkey=-1
  if(key<0) { // keypad1のキーが押されていなかった場合
    key=keypad2.GetKey(); // keypad2からキー番号を読み取る。キーが押されていないならkey=-1
    if(key>=0) key+=16; // keypad2のキーが押されていたら、keyに16を足す
  } // if

  // この時点で、keypad1のキーが押されていた場合は、keyの値は0~15になっており、
  // keypad1のキーが押されておらず、keypad2のキーが押されていた場合は、keyの値は16~31になっており、
  // キーが全く押されていない場合はkeyの値は-1になっている。

  if(key>=0) Serial.println(key); // もし何かキーが押されていたら、keyの値をシリアル出力
} // loop

10.Arduino Uno等でI2Cインターフェースを使う場合の注意点

Arduino Uno、Arduino Pro、Arduino Nanoなど、ATmega328PやATmega168を使ったArduinoで、I2Cインターフェース(TWIインターフェース)を使って通信する場合は、キーパッドで使用するアナログ入力ピンの選択に注意が必要です。

ATmega328PやATmega168を搭載したArduinoは、I2Cの通信にA4ピン(SDA)とA5ピン(SCL)を使用します。よって、I2C通信を行うシールドとキーパッドを併用するためには、キーパッド側をA0~A3のいずれかのピンに割り当てる必要があります。

このサポートページのサンプルスケッチは、A4ピンにキーパッドを割り当てていますので、I2C機器との併用には、スケッチの書き換えが必要です。

例えば、キーパッドをA0に割り当てる場合は、動かしたいサンプルスケッチに

ResKeypad keypad(A4,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B);

と書いてあれば、

ResKeypad keypad(A0,16,RESKEYPAD_4X4,RESKEYPAD_4X4_SIDE_B);

と打ち直し、キーパッドのOUTPUTピンをArduinoのA0ピンに接続して使ってください。

自分の使っているシールドがI2Cインターフェースを使っているかどうか分からない場合は、スケッチのはじめの方で、

#include <Wire.h>

と、Wire.hをインクルードしているかどうかで判断できます。Wire.hをインクルードしていれば、そのスケッチはI2Cインターフェースを利用しています。(つまり、A4とA5のピンを利用しています) 逆にWire.hをインクルードしていない場合は、断言はできないものの、ほとんどの場合、I2Cインターフェースを利用していません。

11.問い合わせ先

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

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

目次へ  前のページへ (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の書籍購入ページに移動します。