Project 22.2 暗証番号で開くドア/Keypad Door

前回はマトリックスキーパッドの使い方を学びました。

あわせて読みたい
Project 22.1 マトリックスキーパッド/Matrix Keypad 前回は超音波測距モジュールを温度補正して距離を測定してみました。 https://kaneshige.org/?p=626 今回はマトリックスキーパッドを使用してみましょう。 【4x4マト...

今回はキーパッドとサーボを使って『暗証番号で開くドア』風のものを作ってみましょう。

目次

回路

前回の回路にサーボとアクティブブザーを追加しましょう。アクティブブザーは裏がレジンでシールされているものです。

接続図

コード

/**********************************************************************
  Filename    : Combination Lock
  Description : Make a simple combination lock.
  Auther      : www.freenove.com
  Modification: 2022/10/26
**********************************************************************/
#include <Keypad.h>

#define SERVO_PIN 21  //define the pwm pin
#define SERVO_CHN 0   //define the pwm channel
#define SERVO_FRQ 50  //define the pwm frequency
#define SERVO_BIT 12  //define the pwm precision
#define BUZZER_PIN 17 // Define the buzzer pin

void servo_set_pin(int pin);
void servo_set_angle(int angle);

byte rowPins[4] = {14, 13, 12, 11}; // connect to the row pinouts of the keypad
byte colPins[4] = {10,  9,  8, 18}; // connect to the column pinouts of the keypad

// define the symbols on the buttons of the keypad
char keys[4][4] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

// initialize an instance of class NewKeypad
Keypad myKeypad = Keypad(makeKeymap(keys), rowPins, colPins, 4, 4);

char passWord[] = {"1234"}; // Save the correct password

void setup() {
  servo_set_pin(SERVO_PIN);
  pinMode(BUZZER_PIN, OUTPUT);
  Serial.begin(115200);
}

void loop() {
  static char keyIn[4];     // Save the input character
  static byte keyInNum = 0; // Save the the number of input characters
  char keyPressed = myKeypad.getKey();  // Get the character input
  // Handle the input characters
  if (keyPressed) {
    // Make a prompt tone each time press the key
    digitalWrite(BUZZER_PIN, HIGH);
    delay(100);
    digitalWrite(BUZZER_PIN, LOW);
    // Save the input characters
    keyIn[keyInNum++] = keyPressed;
    // Judge the correctness after input
    if (keyInNum == 4) {
      bool isRight = true;            // Save password is correct or not
      for (int i = 0; i < 4; i++) {   // Judge each character of the password is correct or not
        if (keyIn[i] != passWord[i])
          isRight = false;            // Mark wrong passageword if there is any wrong character.
      }
      if (isRight) {                  // If the input password is right
        servo_set_angle(90);           // Open the switch
        delay(2000);                  // Delay a period of time
        servo_set_angle(0);            // Close the switch
        Serial.println("passWord right!");
      }
      else {                          // If the input password is wrong
        digitalWrite(BUZZER_PIN, HIGH);// Make a wrong password prompt tone
        delay(1000);
        digitalWrite(BUZZER_PIN, LOW);
        Serial.println("passWord error!");
      }
      keyInNum = 0; // Reset the number of the input characters to 0
    }
  }
}

void servo_set_pin(int pin) {
  ledcSetup(SERVO_CHN, SERVO_FRQ, SERVO_BIT);
  ledcAttachPin(pin, SERVO_CHN);
}

void servo_set_angle(int angle) {
  if (angle > 180 || angle < 0)
    return;
  long pwm_value = map(angle, 0, 180, 103, 512);
  ledcWrite(SERVO_CHN, pwm_value);
}

ネストが深いので読むのが大変でしょうか??
以下の部分は私としてはしっくり来ません。

    if (keyInNum == 4) {
      bool isRight = true;            // Save password is correct or not
      for (int i = 0; i < 4; i++) {   // Judge each character of the password is correct or not
        if (keyIn[i] != passWord[i])
          isRight = false;            // Mark wrong passageword if there is any wrong character.
      }
      if (isRight) {                  // If the input password is right
        servo_set_angle(90);           // Open the switch
        delay(2000);                  // Delay a period of time
        servo_set_angle(0);            // Close the switch
        Serial.println("passWord right!");
      }

しっくりこないポイントは、判定する前にtrueを入れているところです。性善説と性悪説なわけですが、暗証番号の性質を考えると性悪説でプログラムを作るべきではないかと思います。プログラマーも完璧ではないので、考慮不足ということはままあります。なので54行目でfalseを入れてそれに合うようにプログラムを書くべき、という考え方をします。
ただ、文字列の比較はstrcmp()関数を使用するのが一般的なので、54行目から58行目までを削除して、59行目を以下のように書き換えたほうがスマートだと思います。

      if (!strcmp(keyIn,passWord)) {

strcmp()関数は文字列が一致していたら0(=false)が返ってきますので、『!』で反転させています。
結局は好みの問題ですので、『こうじゃなきゃダメ』ということはないです。
ですが、極力コードを短くシンプルに書くという癖はつけたほうが良いです。

次回はリモコンを使用して赤外線通信をしてみましょう!

非営利団体 金重総合研究所 - 知...
Project 23.1 赤外線リモコン/Infrared Remote Control - 非営利団体 金重総合研究所 前回はキーパッドとサーボの連携と、コードのスリム化について学びました。 今回は赤外線リモコンの使い方を学びまし
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

金重総合研究所の主席研究員。
子供の頃から研究者を目指し、ライフワークとして日々様々な研究をしています。
経営・マネジメント・金融・DXあたりが本職です。
私を採用したい人、私と一緒に働きたい人、一緒に知識を肥やしていきたい人はぜひお声がけ下さい。

コメント

コメントする

目次