I/Oピン一つで読み取れるキーパッドの製作

このページをスマホなどでご覧になる場合は、画面を横長にする方が読みやすくなります。
2014年01月08日 公開。
2014年05月27日 一部追記(キット化しました)。
2014年10月04日 一部追記(表面実装版も作りました)。
2015年11月17日 キーマトリックス方式の原理図を追加。
関連製品のページへのリンクを整理。
製作したキーパッドの外観
製作したキーパッドの外観

目次

1. はじめに … 1ページ
2. 動作原理と回路図 … 1ページ
3. キーパッドの製作 … 1ページ
4. Arduinoでキーパッドを読み取ってみる … 1ページ
5. 関連製品 … 1ページ
6. まとめ … 1ページ

1.はじめに

マイコンで組み込み機器を作っている時に、キーパッドを付けて、数値の入力などをしたい事があります。キーパッドの読み取りは、キーマトリックス方式を用いることが一般的です。例えば、4×4のキーパッドを読み取るなら、図1の様に行方向に4本、列方向に4本のGPIO線を割当て、それらの交点にスイッチ(場合によってはダイオードも)を配置するのが一般的です。16個のGPIOピンを使う単純な回路よりはましではありますが、それでも8本ものGPIOピンを使ってしまいます。マイコンは、ピン数が増えると、価格が急激に上がる物が多いので、できればもう少しピン数を減らせる方法があれば便利です。

図1、キーマトリックス方のキーパッドの原理
図1、キーマトリックス方のキーパッドの原理

そこで、4×4のキーパッドを、一つのアナログ入力ピンで読み取れる回路構成を考えました。A/D変換器が付いているマイコンでしか使えませんが、I/Oピンを大幅に節約できます。また、マイコンとキーパッドの間の配線が減りますから、線の引き回しが楽になります。

一方で、キーマトリクス方式の場合、ダイオードを使えば複数のキーを同時に押した場合でも、全てのキーの情報を取得できるメリットがありますが、今回紹介する回路では各キーに優先順位が付いており、複数のキーを同時に押した場合は、最も優先順位の高いキーだけが取得されます。

2.動作原理と回路図

図2の様な抵抗分圧器を作り、押したキーで分圧比を変化させることで、出力電圧を変化させます。詳しい話は抵抗分圧器を使った、多くのスイッチのセンシングという記事に書いていますので、そちらを参照してください。

図2、4X4キーパッドの回路図
図2、4X4キーパッドの回路図
広告

3.キーパッドの製作

今回は手元にあったユニバーサル基板に回路を組んでみました。E24系列抵抗は、ほとんどストックしていますので、キーパッドを製作するのに必要な抵抗は全て手持ちの部品の中にありました。ただし1/4W抵抗と1/8W抵抗が混在していますが…。今回製作した分圧器には、それほど大電流は流れませんので(最大で0.5mA)、全て1/8W抵抗で作っても、定格電力の範囲内に収まります。

今回作ったキーパッドの写真を次に示します。

写真1、表面の写真
↑ 画像をクリックすると拡大
写真1、表面の写真
写真2、裏面の写真
↑ 画像をクリックすると拡大
写真2、裏面の写真

基本的に図2の回路をそのまま組んでいますが、Arduinoに5V、出力、GNDの3本の線をつなぐために、3ピンのピンソケットを使っています。それから、電圧計で出力電圧を計れるように、テストピン(金メッキのピン)を3本(5V、出力、GND)立てています。単にキーパッドとして基板を使いたいだけなら、テストピンは不要です。

4.Arduinoでキーパッドを読み取ってみる

16進キーパッドをArduinoにつないで、読み取ってみます。読み取ったキーの状態は、GLCD学習シールドに表示することにします。

GLCD学習シールドキット 商品名 GLCD学習シールドキット
税抜き小売価格 1410円
販売店 スイッチサイエンス
サポートページ

次に示すスケッチでキーを読み取ることができます。このスケッチは、Arduino Uno、Arduino Leonardo、Arduino Mega2560、Arduono Pro 328 5V 16MHz、Seeeduino V3.0(Atmega 328P)などで使うことができます。また、MGLCDライブラリのVer.0.34がインストールされている必要があります。具体的なインストール方法はArduinoでグラフィックLCDを動かす(S12232ZA編)(2)の記事をご覧ください。

#include <mglcd.h> // MGLCDライブラリを使う

// LCDのピン割当ての宣言
static const TLcdPinAssignTable PinAssignTable={
    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;

static mglcd_S12232ZA MGLCD(PinAssignTable); // MGLCDライブラリを使うためのクラスインスタンス
const int KeyNum = 16; // キーの数
const int threshold[KeyNum]={17,57,110,170,236,306,384,465,549,633,713,787,855,914,964,1006}; // AD変換値の閾値
const char KeyName[KeyNum]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; // キーの名称

// キーデコード関数
// 引数をA/D変換結果(0~1023)にして呼ぶと、押したキーの番号(0~15)を返す。
// 何もキーを押していない時は、-1を返す。
int KeyDecode(int n)
{
  int i=0;
  while(i<KeyNum && n>threshold[i]) i++;
  if(i>=KeyNum) return -1;
  return i;
} // KeyDecode

void setup()
{
  // LCDに与える負電圧を作るため、チャージポンプ回路にクロックを供給する
  pinMode(3,OUTPUT);
  analogWrite(3,128);

  // LCDを初期化する
  while(MGLCD.Reset());

  // 半角カナ出力を有効にする
  MGLCD.SetCodeMode(MGLCD_CODE_UTF8);
} // setup

void loop()
{
  int LastResult=-2; // 前回のキーデコード結果
  int result; // 今回のキーデコード結果
  int cnt=0; // デコード結果が一致した回数
  static int LastDisplayed=-2; // 前回loop関数が呼ばれたと時に表示したキー
                               // 複数回のloop関数の呼び出しにわたって値を保持するために、static変数にしている

  // キーを読み取る
  // チャタリングの除去などのため、A/D変換の値が落ち着くまで待つ
  // 1ms間隔でキーを読み取り、5回連続で同じキーが押されていたら、落ち着いたと判断する
  do {
    result=KeyDecode(analogRead(A4));
    if(result==LastResult) {
      cnt++;
    } else {
      LastResult=result;
      cnt=0;
    } // if
    delay(1);
  } while(cnt<5);

  // 読んだキーをLCDに表示する
  if(result!=LastDisplayed){ // このチェックがないと、LCDの表示が少しちらつく
    MGLCD.ClearScreen(); // 画面を消去
    if(result<0) { // キーが押されていなかった場合
      MGLCD.print("キー ハ オサレテ イマセン。");
    } else { // キーが押されていた場合
      MGLCD.print(KeyName[result]);
      MGLCD.print(" ガ オサレマシタ。"); 
    } // if
  } // if
  LastDisplayed=result;
} // loop

上のスケッチではA4端子にキーパッドの出力をつなぐ事を前提にしていますが、もしA5端子につなぎたいなら、result=KeyDecode(analogRead(A4));result=KeyDecode(analogRead(A5));に書き直してください。

Arduino Mega 2560を使って動作させた場合の写真を次に示します。

写真3、キーを押していない場合の写真
↑ 画像をクリックすると拡大
写真3、キーを押していない場合の写真
写真4、5のキーを押した場合の写真
↑ 画像をクリックすると拡大
写真4、5のキーを押した場合の写真
写真5、Dのキーを押した場合の写真
↑ 画像をクリックすると拡大
写真5、Dのキーを押した場合の写真
写真6、1と3と6のキーを同時に押した場合の写真
↑ 画像をクリックすると拡大
写真6、1と3と6のキーを同時に押した場合の写真

最後の写真を見ると、1と3と6のキーを同時に押した場合、1が押されたと判定されていることが分かります。今回作った16進キーパッドは、若い数字のキーほど優先順位が高く設定されています。そこで、1と3と6の中で、一番優先順位の高い1が認識されたわけです。

なお、上の例では、キーのデコードの関数を作りましたが、キーのデコードやチャタリング処理などを専用のライブラリに任せてしまう方法もあります。詳しくは、ResKeypadライブラリのページをご覧ください。

5.関連製品

今回製作したキーパッドは実用価値が高そうなので、キットや完成品を用意しました。

I/Oピン一つで読める4X4キーパッドキット 商品名 I/Oピン一つで読める4X4キーパッドキット
税抜き小売価格 900円
販売店 スイッチサイエンス
サポートページ
写真7、I/Oピン一つで読める4X4キーパッドキットの組み立て完成後の写真
写真7、I/Oピン一つで読める4X4キーパッドキットの組み立て完成後の写真
写真8、I/Oピン一つで読める4X4キーパッドキットの全部品
↑ 画像をクリックすると拡大
写真8、I/Oピン一つで読める4X4キーパッドキットの全部品
I/Oピン一つで読める4X4キーパッド(完成品) 商品名 I/Oピン一つで読める4X4キーパッド(完成品)
税抜き小売価格 1380円
販売店 スイッチサイエンス
サポートページ
写真9、I/Oピン一つで読める4X4キーパッド(完成品)
↑ 画像をクリックすると拡大
写真9、I/Oピン一つで読める4X4キーパッド(完成品)
I/Oピン一つで読める4X5キーパッドキット 商品名 I/Oピン一つで読める4X5キーパッドキット
税抜き小売価格 2400円
販売店 スイッチサイエンス
サポートページ
写真10、I/Oピン一つで読める4X5キーパッドキットの組み立て後の写真
↑ 画像をクリックすると拡大
写真10、I/Oピン一つで読める4X5キーパッドキットの組み立て後の写真
写真11、キートップと透明キャップの間に文字を書いた紙片を入れた様子
↑ 画像をクリックすると拡大
写真11、キートップと透明キャップの間に文字を書いた紙片を入れた様子

6.まとめ

今回16進キーパッドを作ってみて、マイコンのアナログ入力端子1つで、たくさんのキーを読めることが確認できました。

さらに、コンピュータシミュレーションしたところ、5%精度の抵抗を使う場合、ノイズやA/D変換の誤差が無視できるという仮定においては、キャリブレーション(抵抗値のばらつきに応じた閾値の調整)がなくとも最大32個のキーを読めることが分かりました。

この技術を応用すれば、ATtiny85などのピン数が少ないマイコンでも、本格的なキー入力を行うアプリケーションの開発に利用できることが期待されます。

今後は、更にキーを増やした場合のノイズ耐性の評価や、8ピンマイコンへの接続実験などを行っていく予定です。

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

関連ページ

関連製品

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