2014年01月08日 | 公開。 |
2014年05月27日 | 一部追記(キット化しました)。 |
2014年10月04日 | 一部追記(表面実装版も作りました)。 |
2015年11月17日 | キーマトリックス方式の原理図を追加。 関連製品のページへのリンクを整理。 |
マイコンで組み込み機器を作っている時に、キーパッドを付けて、数値の入力などをしたい事があります。キーパッドの読み取りは、キーマトリックス方式を用いることが一般的です。例えば、4×4のキーパッドを読み取るなら、図1の様に行方向に4本、列方向に4本のGPIO線を割当て、それらの交点にスイッチ(場合によってはダイオードも)を配置するのが一般的です。16個のGPIOピンを使う単純な回路よりはましではありますが、それでも8本ものGPIOピンを使ってしまいます。マイコンは、ピン数が増えると、価格が急激に上がる物が多いので、できればもう少しピン数を減らせる方法があれば便利です。
そこで、4×4のキーパッドを、一つのアナログ入力ピンで読み取れる回路構成を考えました。A/D変換器が付いているマイコンでしか使えませんが、I/Oピンを大幅に節約できます。また、マイコンとキーパッドの間の配線が減りますから、線の引き回しが楽になります。
一方で、キーマトリクス方式の場合、ダイオードを使えば複数のキーを同時に押した場合でも、全てのキーの情報を取得できるメリットがありますが、今回紹介する回路では各キーに優先順位が付いており、複数のキーを同時に押した場合は、最も優先順位の高いキーだけが取得されます。
図2の様な抵抗分圧器を作り、押したキーで分圧比を変化させることで、出力電圧を変化させます。詳しい話は抵抗分圧器を使った、多くのスイッチのセンシングという記事に書いていますので、そちらを参照してください。
今回は手元にあったユニバーサル基板に回路を組んでみました。E24系列の抵抗は、ほとんどストックしていますので、キーパッドを製作するのに必要な抵抗は全て手持ちの部品の中にありました。ただし1/4W抵抗と1/8W抵抗が混在していますが…。今回製作した分圧器には、それほど大電流は流れませんので(最大で0.5mA)、全て1/8W抵抗で作っても、定格電力の範囲内に収まります。
今回作ったキーパッドの写真を次に示します。
基本的に図2の回路をそのまま組んでいますが、Arduinoに5V、出力、GNDの3本の線をつなぐために、3ピンのピンソケットを使っています。それから、電圧計で出力電圧を計れるように、テストピン(金メッキのピン)を3本(5V、出力、GND)立てています。単にキーパッドとして基板を使いたいだけなら、テストピンは不要です。
16進キーパッドをArduinoにつないで、読み取ってみます。読み取ったキーの状態は、GLCD学習シールドに表示することにします。
商品名 | GLCD学習シールドキット | |
税抜き小売価格 | 1410円 | |
販売店 | スイッチサイエンス | |
サポートページ | GLCD学習シールドキットサポートページ |
次に示すスケッチでキーを読み取ることができます。このスケッチは、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を使って動作させた場合の写真を次に示します。
最後の写真を見ると、1と3と6のキーを同時に押した場合、1が押されたと判定されていることが分かります。今回作った16進キーパッドは、若い数字のキーほど優先順位が高く設定されています。そこで、1と3と6の中で、一番優先順位の高い1が認識されたわけです。
なお、上の例では、キーのデコードの関数を作りましたが、キーのデコードやチャタリング処理などを専用のライブラリに任せてしまう方法もあります。詳しくは、ResKeypadライブラリのページをご覧ください。
今回製作したキーパッドは実用価値が高そうなので、キットや完成品を用意しました。
商品名 | I/Oピン一つで読める4X4キーパッドキット | |
税抜き小売価格 | 900円 | |
販売店 | スイッチサイエンス | |
サポートページ | I/Oピン一つで読める4X4キーパッドキットサポートページ |
商品名 | I/Oピン一つで読める4X4キーパッド(完成品) | |
税抜き小売価格 | 1380円 | |
販売店 | スイッチサイエンス | |
サポートページ | I/Oピン一つで読める4X4キーパッド(完成品)サポートページ |
商品名 | I/Oピン一つで読める4X5キーパッドキット | |
税抜き小売価格 | 2400円 | |
販売店 | スイッチサイエンス | |
サポートページ | I/Oピン一つで読める4X5キーパッドキットサポートページ |
今回16進キーパッドを作ってみて、マイコンのアナログ入力端子1つで、たくさんのキーを読めることが確認できました。
さらに、コンピュータシミュレーションしたところ、5%精度の抵抗を使う場合、ノイズやA/D変換の誤差が無視できるという仮定においては、キャリブレーション(抵抗値のばらつきに応じた閾値の調整)がなくとも最大32個のキーを読めることが分かりました。
この技術を応用すれば、ATtiny85などのピン数が少ないマイコンでも、本格的なキー入力を行うアプリケーションの開発に利用できることが期待されます。
今後は、更にキーを増やした場合のノイズ耐性の評価や、8ピンマイコンへの接続実験などを行っていく予定です。
商品名 | I/Oピン一つで読める4X4キーパッドキット | |
税抜き小売価格 | 900円 | |
販売店 | スイッチサイエンス | |
サポートページ | I/Oピン一つで読める4X4キーパッドキットサポートページ |
商品名 | I/Oピン一つで読める4X4キーパッド(完成品) | |
税抜き小売価格 | 1380円 | |
販売店 | スイッチサイエンス | |
サポートページ | I/Oピン一つで読める4X4キーパッド(完成品)サポートページ |
商品名 | I/Oピン一つで読める4X5キーパッドキット | |
税抜き小売価格 | 2400円 | |
販売店 | スイッチサイエンス | |
サポートページ | I/Oピン一つで読める4X5キーパッドキットサポートページ |
商品名 | GLCD学習シールドキット | |
税抜き小売価格 | 1410円 | |
販売店 | スイッチサイエンス | |
サポートページ | GLCD学習シールドキットサポートページ |