【Arduino】LCDキーパッドシールドのボタン入力を使う!

前回はLCDの表示を行いましたが(→Arduino LCD KeyPad Shieldを使う(LCD編))、今回はKeyPad部分を動作させてみたいと思います。

IMG_6072

このキーパッド部を使うときのキーポイントを下記に記します。

  • キーパッド入力はアナログピンを使用(AnalogRead関数を使ってキーを判別)
  • 分圧回路を使って1つのピンで複数のボタン入力に対応
  • 同時押しには未対応

回路図の確認

(前回)→Arduino LCD KeyPad Shieldを使う(LCD編)

今回はボタン部分だけ確認します。

spread_lcd

キーパッドはデジタルピンに繋がっているものと予想していたのですが、どうやらアナログピンで電圧の変化を読み込んで判別する方式のようです。

 

 

分圧回路によるスイッチ判別

アナログ入力でスイッチ判別を行えば一つのアナログピンで多数のスイッチ判別が行えるようになります。今回使うキーバッドには5つのスイッチが付いていますが、入力にアナログピンを使うことで1つのピンを使うだけで済んでいます。

まず、スケッチを書き始める前に分圧回路によるスイッチの判別の仕組みについて説明します。

 

分圧回路とは?

分圧回路は目的の電圧を作りたいときに使用する回路です。抵抗を数本使うだけで目的の電圧を得られるため様々なところで使われます。

一番簡単なものは抵抗を2本使った分圧回路です。この回路では抵抗の分圧則を使うことで必要な抵抗値を計算することができます。

formula

 

VCCに5V・R1とR2に同じ抵抗を使うと、VCCの丁度半分の2.5Vを得ることができます。

spread

簡単な分圧回路。この回路ではV OUT端子から2.5Vを得られる。

KeyPadシールドの分圧回路の動作を確認してみる

RIGHTボタンが押されたとき

RIGHTボタンが押されると回路の状態は以下のように変化します。

この状態では分圧回路は機能せず、GNDとV OUTは短絡状態となるため0Vとなります。

spread_right3

RIGHTボタンが押されるとGNDと短絡してV OUTが得られる電圧は0Vとなる。

 

UPボタンが押されたとき

次にUPボタンが押された場合には以下のような回路状態となります。

この場合ではR3の330Ωとの分圧回路が成立します。R4からR6についてはUPボタンがGNDと短絡したために電気は流れていません。

spread_up2

UPボタンが押されるとR2とR3で分圧回路が成立しV OUTには約0.71Vが現れる

あとの3つも同じような流れで電圧値を求めることができます、長いので次にまとめます。

 

KeyPad部の電圧値まとめ

まとめると以下の表のようになります。

押されたボタンによってAD0に入力される電圧値が変わるので、これを判別できるようなスケッチを書くことによって1つのアナログピンで複数のボタンを制御できるようになります。

押されたボタン ボタンが押された時の等価回路 計算上のAD0電圧値
何も押さない spread_none 5V
RIGTH spread_rihgt_2 0V
UP spread_up 0.71V
DOWN spread_down 1.61V
LEFT spread_left 2.47V
SELECT spread_select 3.62V

 

スケッチを書く。

analogRead関数

アナログピンからアナログ電圧を読み取るにはanalogRead関数を使います。

arduinoの分解能は10bitなのでanalogRead関数を使うと0~1023の値として状態を取得することができます。arduinoのアナログ入力には5Vの内臓電圧を使っているので0V~5Vの電圧はそれぞれ0~1023の値として取り込めます。

このキーパッドシールドはAD0ピン使っているので、analogRead関数で電圧値を読み込む場合は下記のように呼び出します。

analogRead(0)

 

ifと条件分岐でスイッチを判定

analogRead関数で読み込んだ値を使って、押されたボタンの判定を行う関数を作ります。

内容はanalogRead関数から渡された引数を元に、if分で条件分岐を行い対応した戻り値で返す関数です。この関数にanalogRead(0)を直接入れてやればボタンに対応した戻り値が出力されます

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
#define ERRORR    6

/**************************************************************/
/*関数名:read_LCD_buttons*/
/*動作;A0ポートの電圧値から押されたボタンを判別*/
/**************************************************************/
int read_LCD_buttons(int adc_key_in)
{
 if (adc_key_in > 1000) return btnNONE;   //1023, 戻り値5, 5.0V
 if (adc_key_in < 50)   return btnRIGHT;  //0   , 戻り値0, 0V
 if (adc_key_in < 250)  return btnUP;     //144 , 戻り値1, 0.70V
 if (adc_key_in < 450)  return btnDOWN;   //329 , 戻り値2, 1.61V
 if (adc_key_in < 650)  return btnLEFT;   //504 , 戻り値3, 2.47V
 if (adc_key_in < 850)  return btnSELECT; //741 , 戻り値4, 3.62V
 
 /* 全てのifが失敗(通常はこれを返さない)*/
 return ERRORR;                          
}

 

サンプルスケッチ

下記にKeyPad部分を動作させるスケッチを記載します。

押されたボタンをLCDに表示させて、分圧した電圧も表示するようにスケッチしました。

#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
#define ERRORR    6

/**************************************************************/
/*関数名:read_LCD_buttons*/
/*動作;A0ポートの電圧値から押されたボタンを判別*/
/**************************************************************/
int read_LCD_buttons(int adc_key_in)
{
 if (adc_key_in > 1000) return btnNONE;   //1023, 戻り値5, 5.00V
 if (adc_key_in < 50)   return btnRIGHT;  //0   , 戻り値0, 0V
 if (adc_key_in < 250)  return btnUP;     //144 , 戻り値1, 0.70V
 if (adc_key_in < 450)  return btnDOWN;   //329 , 戻り値2, 1.61V
 if (adc_key_in < 650)  return btnLEFT;   //504 , 戻り値3, 2.47V
 if (adc_key_in < 850)  return btnSELECT; //741 , 戻り値4, 3.62V
 
 /* 全てのifが失敗(通常はこれを返さない)*/
 return ERRORR;                          
}

/**************************************************************/
/*関数名:out_analog_volt*/
/*動作;A0ピンの電圧値を表示*/
/**************************************************************/
void out_analog_volt(int adc_key_in)
{
 lcd.setCursor(11,1);
 lcd.print((float)adc_key_in*5/1024);
}

/**************************************************************/
/*関数名:out_analog_state*/
/*動作;押されたボタンをLCDに表示*/
/**************************************************************/
void out_analog_state(int lcd_key)
{
   lcd.setCursor(0,1); 
   switch (lcd_key) 
 {
   case btnRIGHT:
     {
     lcd.print("RIGHT ");
     break;
     }
   case btnLEFT:
     {
     lcd.print("LEFT   ");
     break;
     }
   case btnUP:
     {
     lcd.print("UP    ");
     break;
     }
   case btnDOWN:
     {
     lcd.print("DOWN  ");
     break;
     }
   case btnSELECT:
     {
     lcd.print("SELECT");
     break;
     }
     case btnNONE:
     {
     lcd.print("NONE  ");
     break;
     }
     case ERRORR:
     {
     lcd.print("ERROR ");
     break;
     }
 }
}

/**************************************************************/
/*関数名:setup*/
/*動作;LCDの初期化*/
/**************************************************************/
void setup()
{
 lcd.begin(16, 2);              
 lcd.setCursor(0,0);
 lcd.print("Push the buttons"); 
 lcd.setCursor(8,1);            
 lcd.print("A0     V");     
}

/**************************************************************/
/*関数名:loop*/
/*動作;メイン処理*/
/**************************************************************/
void loop()
{
 int lcd_key     = 0;
 
 lcd_key = read_LCD_buttons(analogRead(0));
 out_analog_state(lcd_key);
  
 out_analog_volt(analogRead(0));
}

スケッチの動作

IMG_6126

RIGHTボタンを押した場合の動作。RIGHTと0Vが表示される

まとめ

アナログピンを使うことで複数のボタンであっても1つのピンで制御することができるようになります。arduinoのアナログ入力の分解能は10bitなので理論上1023個のボタンを付けることができますが、ノイズや抵抗の選別などを考えた場合、10個ほどに収めておいた方がよさそうです。また、今回の分圧回路ではどうやっても同時入力には対応できません。

ボタン入力ができるようになったのでArduinoでできることが大幅に増えました。パソコンから書き込んで動かしっぱなしなことが多いArduinoですがスタンドアロンで操作できるようになればちょっとした組み込みシステムのような使い方もできるかもしれません。

今回の作業環境

  • ハードウェア
    • Arduino UNO R3
    • LCD KeyPad Shield (SainSmart製)
    • USBケーブル A-Bコネクタ
  • ソフトウェア
    • Arduno 1.6.7