7주차 금고 만들기

From Arduwiki

1. 키패드

프레임없음|400x400픽셀

4 x 4 크기의 키패드 모듈을 사용해 봅시다. 금고에 비밀번호를 설정해두고 키패드를 이용해 비밀번호를 누르는 기능을 만들 예정입니다.

1-1. 회로

프레임없음|859x859픽셀

1-2. 라이브러리 추가

먼저 아두이노 IDE 에서 키패드를 사용하기 위해 라이브러리를 설치합니다.

[스케치] - [라이브러리 포함] - [라이브러리 관리] 에서 "keypad"을 검색합니다. [Keypad by Mark Stanley, Alexander Brevig]을 찾아 설치해주세요.

프레임없음|571x571픽셀

1-3. 키패드를 눌러 시리얼 모니터에 출력하기

키패드가 눌릴 때마다 시리얼 모니터에 눌린 버튼에 해당하는 문자를 출력해 봅시다.

#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
  
void setup(){  
  Serial.begin(9600);  
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    Serial.println(keyPressed);  
  }  
}

1-4. [실습] 특정 버튼이 눌렸을 때 LED 켜기

버튼 '*'이 눌리면 LED를 켜고, 버튼 '#'이 눌리면 LED를 끄는 코드를 작성해 봅시다.

#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
  
void setup(){  
  Serial.begin(9600);  
  pinMode(13,  OUTPUT);
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    Serial.println(keyPressed);  
    if(keyPressed=='*') {
      // code ..
    }
    if(keyPressed=='#'){
      // code ..
    }
  }  
}

1-5. String 자료형의 이해

String 자료형은 문자열을 쉽게 사용하고 저장, 관리할 수 있습니다.

금고의 비밀번호를 저장하고 비교하기 위해 사용할 것입니다.

문자열은 더하기(+) 연산이 가능합니다. 문자열 더하기 연산은 두 문자열을 연결해서 새로운 문자열을 만들어낼 수 있습니다.

String a = "hello";
String b = "coders";
String c = a + b;
// c에는 "hellocoders"가 저장된다.

1-6. 문자열 비교

String 변수 2개가 같은 문자인지 확인하기 위해서는 앞서 배운 비교연산자 "=="을 사용하면 됩니다.

String a = "hello"
String b = "coders"
if (a==b) {
    //같은 문자열이라면
}
if (a!=b) {
    //다른 문자열이라면
}

1-7. [실습] 누른 문자열을 모두 합쳐 출력하기

키패드에서 누르는 문자를 모두 String 변수에 합쳐 저장해 봅시다.

키패드의 '#'이 눌렀을 때 이전까지 누른 문자열이 "1234"라면 LED를 1번 깜빡이고 아니라면 LED를 3번 깜빡이게 코드를 작성해 봅시다.

#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "1234";

void setup(){  
  Serial.begin(9600);  
  pinMode(13,  OUTPUT);
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed=='#') {
      if(s == pw) {

      }
      if(s != pw) {

      }
      s = "";
    }
    else{
      s += keyPressed;
    }
  }  
}

2. LCD

키패드로 누른 문자를 LCD를 이용해 출력해 봅시다.

2-1. LCD 회로도[편집 | 원본 편집]

I2C LCD 모듈 핀 아두이노 우노 핀
VCC 5V
GND GND
SDA A4
SCL A5

프레임없음|672x672픽셀

2-2. 키패드를 눌러 LCD에 문자 출력하기

키패드가 눌리면 LCD에 문자열을 출력하도록 코드를 작성해 봅시다.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";

void setup(){  
  lcd.init();
  lcd.backlight();
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    s += keyPressed;
    lcd.clear();
    lcd.print(s);
  }  
}

2-3. [실습] 비밀번호 확인하기

금고 프로젝트를 위해 비밀번호를 확인하는 기능을 구현해 봅시다.

비밀번호는 "2025"라는 문자열로 지정합니다.

키패드에 눌리는 문자열을 LCD에 출력합니다.

만약 키패드의 '#'을 눌렀다면 비밀번호를 확인합니다.

비밀번호가 맞다면 LCD에 "OK!!"를 출력하고 아니라면 "NOoooo!!"를 3초 동안 출력합니다.


★ 비밀번호를 확인 후 문자열 초기화를 해야 다시 문자열을 입력해 비밀번호를 확인할 수 있습니다.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "2025";

void setup(){  
  lcd.init();
  lcd.backlight();
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed == '#') {
      if (s == pw) {
        // code ..
      }
      else {
        // code ..
      }
      // code ..
    }
    else {
      s += keyPressed;
      lcd.clear();
      lcd.print("PW : ");
      lcd.print(s);
    }
  }  
}

3. 서보모터 움직이기

3-1. 서보모터 회로

프레임없음|780x780픽셀

서보모터를 아두이노에 연결해봅시다.

서보모터의 검정색 선을 GND, 빨간색 선을 5V, 주황색 선을 디지털 핀(10번)에 연결해주세요.

3-2. 서보모터 회전하기

먼저 서보모터를 움직여 봅시다. 서보모터를 움직여 각도를 제어해 봅시다.

#include <Servo.h>
Servo servo;

void setup() {
  servo.attach(10);
}

void loop() {
  servo.write(0);
  delay(2000);
  servo.write(90);
  delay(2000);
  servo.write(180);
  delay(2000);
}

3-3. [실습] 비밀번호가 맞으면 금고 열기

위의 실습에서 비밀번호를 확인하는 코드를 작성해 보았습니다.

비밀번호가 맞다면 서보모터를 회전하여 금고를 열어봅시다.

서보모터가 "90"도로 회전하면 금고가 열리고 "0"도로 회전하면 금고가 잠깁니다.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "2025";

#include <Servo.h>
Servo servo;

void setup(){  
  lcd.init();
  lcd.backlight();
  servo.attach(10);
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed == '#') {
      if (s == pw) {
        // code ..
      }
      else {
        // code ..
      }
      // code ..
    }
    else {
      s += keyPressed;
      lcd.clear();
      lcd.print("PW : ");
      lcd.print(s);
    }
  }  
}

[참고사항] 서보모터가 움직이지 않는다면?

서보모터가 움직이지 않을 때는 아두이노에 전력이 부족해서 그럴 수도 있어요!

이런 경우 서보모터를 움직일 때만 attach() 함수를 이용해 서보모터를 연결한 후 회전합니다. 회전 후 서보모터 연결을 detach() 함수를 이용해 해제합니다.

#include <Servo.h>
Servo servo;

void setup() {
}

void loop() {
  servo.attach(10);
  servo.write(0);
  delay(300);
  servo.detach();

  delay(2000);

  servo.attach(10);
  servo.write(90);
  delay(300);
  servo.detach();

  delay(2000);

  servo.attach(10);
  servo.write(0);
  delay(300);
  servo.detach();

  delay(2000);
}

3-4. [실습] 금고 완성하기

비밀번호를 확인하여 서보모터를 이용해 금고를 열었습니다. 나머지 동작을 코딩해 금고 프로젝트를 완성해 봅시다. 아래 순서에 따라 코드를 작성해보세요.

  1. 금고가 열리고 1초 후 LCD에 모든 문자열을 지우고 "Press 'A'"라는 문자열을 출력합니다.
  2. "Press 'A'"라는 문자열이 출력된 후 키패드의 'A'를 누르면 서보모터를 회전시켜 금고를 다시 잠궈주세요.
  3. 다시 비밀번호를 치고 '#' 버튼을 눌렀을 때 금고가 열리는지 확인하세요.

4. 실습 코드 참고하기

1-4. [실습] 특정 버튼이 눌렸을 때 LED 켜기

#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
  
void setup(){  
  Serial.begin(9600);  
  pinMode(13,  OUTPUT);
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    Serial.println(keyPressed);  
    if(keyPressed=='*') {
      digitalWrite(13, HIGH);
    }
    if(keyPressed=='#'){
      digitalWrite(13, LOW);
    }
  }  
}

1-7. [실습] 누른 문자열을 모두 합쳐 출력하기

#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "1234";

void setup(){  
  Serial.begin(9600);  
  pinMode(13,  OUTPUT);
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed=='#') {
      Serial.println(s);
      if(s == pw) {
        digitalWrite(13, HIGH);
        delay(500);
        digitalWrite(13, LOW);
        delay(500);
      }
      if(s != pw) {
        for(int i=0; i<3; i++) {
          digitalWrite(13, HIGH);
          delay(500);
          digitalWrite(13, LOW);
          delay(500);
        }
      }
      s = "";
    }
    else{
      s += keyPressed;
    }
  }  
}

2-3. [실습] 비밀번호 확인하기

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "2025";

void setup(){  
  lcd.init();
  lcd.backlight();
  lcd.print("PW : ");
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed == '#') {
      if (s == pw) {
        lcd.clear();
        lcd.print("OK!!");
        delay(3000);
      }
      else {
        lcd.clear();
        lcd.print("NOoooo!!");
        delay(3000);
      }
      s="";
      lcd.clear();
      lcd.print("PW : ");
    }
    else {
      s += keyPressed;
      lcd.clear();
      lcd.print("PW : ");
      lcd.print(s);
    }
  }  
}

3-3. [실습] 비밀번호가 맞으면 금고 열기

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "2025";

#include <Servo.h>
Servo servo;

void setup(){  
  lcd.init();
  lcd.backlight();
  lcd.print("PW : ");
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed == '#') {
      if (s == pw) {
        servo.attach(10);
        delay(200);
        servo.write(90);
        lcd.clear();
        lcd.print("OPEN!!");
        delay(1000);
        servo.write(0);
        delay(200);
        servo.detach();
      }
      else {
        lcd.clear();
        lcd.print("WRONG PW! -_-");
      }
      delay(2000);
      lcd.clear();
      lcd.print("PW : ");
      s = "";
    }
    else {
      s += keyPressed;
      lcd.clear();
      lcd.print("PW : ");
      lcd.print(s);
    }
  }  
}

3-4. [실습] 금고 완성하기

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
#include <Keypad.h>    
char hexaKeys[4][4] = {  
  {'1', '2', '3', 'A'},  
  {'4', '5', '6', 'B'},  
  {'7', '8', '9', 'C'},  
  {'*', '0', '#', 'D'}};  
byte rowPins[4] = {9, 8, 7, 6};   
byte colPins[4] = {5, 4, 3, 2};   
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, 4, 4);   
char keyPressed; 
String s = "";
String pw = "2025";

#include <Servo.h>
Servo servo;

void setup(){  
  lcd.init();
  lcd.backlight();
  lcd.print("PW : ");
}  
void loop(){  
  keyPressed = customKeypad.getKey();  
    
  if (keyPressed)  
  {  
    if (keyPressed == 'A') {
      servo.attach(10);
      delay(200);
      servo.write(0);
      delay(1000);
      servo.detach();
      lcd.clear();
      lcd.print("PW : ");
    }
    else if (keyPressed == '#') {
      if (s == pw) {
        servo.attach(10);
        delay(200);
        servo.write(90);
        delay(200);
        servo.detach();
        lcd.clear();
        lcd.print("OPEN!!");
        delay(2000);
        lcd.clear();
        lcd.print("Press 'A'!");
      }
      else {
        lcd.clear();
        lcd.print("WRONG PW! -_-");
        delay(2000);
        lcd.clear();
        lcd.print("PW : ");
      }
      s = "";
    }
    else {
      s += keyPressed;
      lcd.clear();
      lcd.print("PW : ");
      lcd.print(s);
    }
  }  
}

5. 금고 조립하기

프레임없음|560x560픽셀

금고 앞 면에 서보모터, LCD, 키패드 모듈을 배치합니다.

그림을 잘 보고 서보모터의 방향을 잘 배치하고 선을 금고 앞 면 뒤로 빼주세요.

프레임없음|593x593픽셀

프레임없음|592x592픽셀

서보모터를 고정시킬 부품과 고정핀을 이용해 사진처럼 조립해주세요.

프레임없음|645x645픽셀

이번에는 LCD를 고정시켜 봅시다. 위의 부품을 준비해주세요.

프레임없음|603x603픽셀

LCD를 고정할 판을 준비해서 끼웁니다.

그리고 고정 핀을 이용해 LCD를 금고 앞 면에 조립합니다.

프레임없음|567x567픽셀

센서를 가릴 면을 조립하기 위한 연결 부품을 가져옵니다.

그림을 보고 알맞은 부품을 가져와 조립해 주세요.

마지막 사진을 보고 앞에서 보았을 때 왼쪽 연결 부분에만 고정핀으로 조립, 오른쪽 연결 부분에는 고정핀으로 조립하지 않는 것을 확인하고 조립을 진행해 주세요.


프레임없음|596x596픽셀

아랫 부분도 부품을 찾아 연결합니다.

고정핀으로 고정시켜 주세요.

프레임없음|800x800픽셀

센서를 가릴 판을 가져와 조립합니다.

센서들의 손은 사진처럼 바깥으로 빠져나올 수 있게 정리해주세요.

고정핀으로 고정시켜 주세요.

프레임없음|586x586픽셀

금고의 아래, 옆 면을 찾아와 조립합니다.

고정핀을 이용해 고정합니다.

프레임없음|581x581픽셀

금고의 잠금 장치를 위한 부품을 찾아 조립합니다.

★★★ 빨간 동그라미를 잘 보고 네모 구멍이 금고의 뒷 편으로 가도록 조립해야 합니다.

프레임없음|806x806픽셀

이번에는 앞서 조립해두었던 금고의 앞 면을 가져와 봅시다.

금고 아랫 면의 홈에 금고 앞 면을 조립합니다.

프레임없음|494x494픽셀

금고의 옆, 앞 면을 조립해두었습니다.

금고의 윗 면을 가져와 금고를 조립해봅시다.


프레임없음|822x822픽셀

만약 윗 면을 조립하기 힘들다면 왼쪽 면을 빼고 윗 면을 먼저 조립해보세요.

윗 면을 먼저 조립 후 다시 왼쪽 면을 고정시켜 보세요.

면을 조립하였다면 고정핀으로 고정해 주세요.


프레임없음|831x831픽셀

마지막으로 뒷 면을 조립해 봅시다.

★★★★ 뒷 면을 닫기 전 아두이노 케이블을 아두이노에 연결한 후 닫아주세요. ★★★★ 닫고나면 연결하기 힘들어용 😂

프레임없음|513x513픽셀

완성!!