ATtiny404 + AQM1602 + 4×4キーパッドで簡単入力装置を作る

ATtiny404と4×4マトリックスキーパッドを使った電子工作のアイキャッチ画像。薄い緑色の背景に、16キーの4×4キーパッドとAQM1602液晶モジュールが配置されている。液晶には「KEY = A」と表示され、ATtiny404によるキーパッド入力のイメージをシンプルに表現している。ATtiny404 + AQM1602 + 4×4キーパッドで簡単入力装置を作る
スポンサーリンク

今回は、ATtiny404と16キー4×4マトリックスキーパッドを使って、押したキーをAQM1602へ表示する簡単なプログラムを作ってみました。

使用したキーパッドは8ピン構成の4×4タイプで、行と列をスキャンすることでどのキーが押されたかを判定します。
キーが押されると、その文字をAQM1602へ表示するだけのシンプルな内容ですが、キーパッド入力の基本的な考え方がよく分かる内容になっています。

またATtiny404は14ピンで扱いやすく、秋月電子で100円程度と非常に安価です。
さらに4KBのプログラムメモリーを搭載しているため、標準I2CライブラリやAQM1602ライブラリも比較的余裕を持って使用できます。

今回のようなキーパッド入力は、

  • 初期設定画面
  • メニュー操作
  • パスコード入力
  • 周波数設定
  • タイマー設定

などにも応用できるので、電子工作ではかなり便利な入力方法になります。

スポンサーリンク

今回使用したもの

  • ATtiny404
  • AQM1602 LCD
  • 16キー 4×4 マトリックスキーパッド
  • ジャンパーワイヤー
  • ブレッドボード

キーパッドについて

今回使用した4×4キーパッドは、内部的には「行」と「列」が接続された構造になっています。
例えば「1」キーを押すと、

  • 1行目
  • 1列目

が導通する仕組みです。
そのためマイコン側では、

  1. 行を順番にLOWにする
  2. 列入力を確認する
  3. LOWになった場所を調べる

ことで、どのキーが押されたかを判定できます。

4×4キーパッドは8ピン必要

4×4キーパッドは、

  • 行4本
  • 列4本

合計8本のGPIOが必要になります。
そのため小ピン数マイコンでは少し厳しくなりますが、ATtiny404は14ピン版なのでちょうど扱いやすいサイズです。
さらにATtiny404は価格も安く、性能も十分あるため、キーパッド制御にはかなり向いているマイコンだと思います。

また、4×3タイプに変更すれば、

  • 行4本
  • 列3本

となるため、7ピン構成に減らすことも可能で、残りPA6 PA7 をUARTなどに使うこともでき、いろいろ面白いことができるかもしれません。
数字入力だけなら4×3タイプでも十分実用的です。

回路図

Attint404、キーパッド AQM1602、接続図

I2CとAQM1602ライブラリについて

今回使用しているSoftI2C_VPORTとAQM1602_SoftI2Cについては、以前の記事で詳しく紹介しています。

#include <SoftI2C_VPORT.h>
#include <AQM1602_SoftI2C.h>

SoftI2C_VPORT i2c(1, 2);

こちらでは、

  • ソフトウェアI2C
  • 軽量AQM1602制御
  • Wireを使わない構成

について説明していますので、先に見ると理解しやすいと思います。
使いかたはこちらから確認してください

配列でキーマップを定義する

キーの対応表は配列で作っています。

char keyMap[4][4] = {
  { '1', '2', '3','A'},
  { '4', '5', '6','B'},
  { '7', '8', '9','C'},
  { '*', '0', '#','D'}
};

例えば、

  • 1行目 + 1列目 → ‘1’
  • 2行目 + 3列目 → ‘6’

というように、押された場所と文字を対応させています。
この方法は非常に分かりやすく、初心者にもおすすめです。

行と列をスキャンしてキーを判定する

キー判定は scanKey() 関数で行っています。
処理の流れ

1. 全ての行をHIGHにする

for (uint8_t i = 0; i < 4; i++) {
  digitalWrite(rowPins[i], HIGH);
}

列入力を確認する

if (digitalRead(colPins[col]) == LOW) {
  return keyMap[row][col];
}

キーが押されていると、LOWになった行と列が接続されるため、対応する文字を取得できます。

1文字を「文字列」に変換してLCDへ渡す

今回かなり重要なのがこの部分です。

char buf1[2];

buf1[0] = key;
buf1[1] = '\0';

C/C++では、文字列の最後に '\0' (ヌル文字)が必要になります。
例えば、

'A'

これは「1文字」です。
しかしLCDの print() は、

buf1[0] = key;
buf1[1] = '\0';

とすることで、

  • 1文字
  • 終端文字

を持った「文字列」に変換しています。
これによって、

lcd.print(buf1);

のようにAQM1602へ渡すことができます。
ここは初心者の方がかなり混乱しやすい部分なので、ぜひ覚えておきたいポイントです。

「押した瞬間だけ」を判定するのが重要

今回のプログラムでは、この部分も非常に重要です。

if (key != 0 && lastKey == 0)

これは、

  • 今は押されている
  • 前回は押されていなかった

という意味になります。
つまり「押された瞬間だけ」を検出しています。
もし単純に、

if (key != 0)

だけにしてしまうと、loop()が高速で回っているため、

111111111111

のように同じ文字が大量に表示されてしまいます。
そのため、

lastKey

を使って前回状態を記録し、「押した瞬間だけ」を判定しています。
これはスイッチ入力全般で非常によく使うテクニックです。

完成プログラム

#include <SoftI2C_VPORT.h>
#include <AQM1602_SoftI2C.h>

SoftI2C_VPORT i2c(1, 2);
AQM1602 lcd(i2c);

const uint8_t rowPins[4] = {
  PIN_PB0,
  PIN_PB1,
  PIN_PB2,
  PIN_PB3
};

const uint8_t colPins[4] = {
  PIN_PA3,
  PIN_PA4,
  PIN_PA5,
  PIN_PA6
};

char keyMap[4][4] = {
  { '1', '2', '3','A'},
  { '4', '5', '6','B'},
  { '7', '8', '9','C'},
  { '*', '0', '#','D'}
};

char scanKey() {

  for (uint8_t row = 0; row < 4; row++) {

    for (uint8_t i = 0; i < 4; i++) {
      digitalWrite(rowPins[i], HIGH);
    }

    digitalWrite(rowPins[row], LOW);

    for (uint8_t col = 0; col < 4; col++) {

      if (digitalRead(colPins[col]) == LOW) {
        return keyMap[row][col];
      }
    }
  }

  return 0;
}

void setup() {

  lcd.begin(0x73, 0x52);

  lcd.print("keypad");

  for (uint8_t i = 0; i < 4; i++) {
    pinMode(rowPins[i], OUTPUT);
    digitalWrite(rowPins[i], HIGH);
  }

  for (uint8_t i = 0; i < 4; i++) {
    pinMode(colPins[i], INPUT_PULLUP);
  }
}

char lastKey = 0;

void loop() {

  char key = scanKey();

  char buf1[2];

  buf1[0] = key;
  buf1[1] = '\0';

  if (key != 0 && lastKey == 0) {

    lcd.setCursor(8, 0);
    lcd.print("KEY = ");
    lcd.print(buf1);
  }

  lastKey = key;

  delay(40);
}

まとめ

今回ATtiny404と4×4マトリックスキーパッドを使って、押したキーをAQM1602へ表示してみまた。
キーパッド入力は一見難しそうに見えますが、

  • 行をLOWにする
  • 列を読む
  • 対応表から文字を取得する

という流れを理解すると意外とシンプルです。
また、

  • 「押した瞬間だけ」を検出する方法
  • 1文字を文字列へ変換する方法
  • マトリックススキャンの基本

など、組み込みプログラムでは重要な考え方も学べます。
この仕組みを応用すると、

  • メニュー画面
  • パスワード入力
  • 数値設定
  • 各種パラメータ変更

なども簡単に作れるようになりますので、試してみてください。

タイトルとURLをコピーしました