코코아팹은 누구나 창의적 아이디어를 현실로 만들어 낼 수 있도록
만들고, 공유하고, 배울 수 있는 터전이
되고자 합니다.
아이디와 비밀번호를 잊으셨나요?아이디 / 비밀번호 찾기
코코아팹 회원이 아니신가요? 회원가입
2016-03-16 17:11:36
만두입니다.
벌써 2016년도에도 봄이 오고 있습니다. 봄바람 휘날리며~ 흩날리는 벚꽃 잎이~
봄은 참 설레는 계절인 것 같아요.
3월 14일 화이트데이도 지나가고, 이제 남은 데이는 빼빼로데이 뿐!
그래서 이번에 처음 만들어 본 프로젝트는 빼빼로데이를 겨냥한 '빼빼로 금고'입니다.
아두이노를 처음 접해보았는데 코코아팹 덕분에 쉽게 프로젝트를 마무리할 수 있었습니다.
코코아팹의 모든 메이커분들께 감사 인사 올립니다^ㅇ^
제가 예전에 어느 게시판에서 본 빼빼로 금고입니다.
궁금하신 분은 여기에서 원글을 확인하실 수 있습니다. -> http://pann.nate.com/talk/317134264
신기하기만 했는데, 이번에 제가 직접 만들어보고 싶다는 생각을 가지게 되었습니다.
기존 코코아팹 프로젝트에 올라와있는 금고 프로젝트와 매우 흡사합니다! 코코아팹.. 더럽.. (The Love..♥️)
선물용으로 만들 금고는 진짜 빼빼로를 사용해야 하지만...
저는.. 가난한공대생이므로.. 사진으로 대체했습니다...하.. 여러분들은 빼빼로 박스로 만들어보시길 바랍니다...
그럼 본격적으로 빼빼로 금고에 대해 소개를 해드리겠습니다!
<금고 여는 순서>
1. 사전 등록한 네자리의 비밀 번호를 입력합니다. 일치하지 않을 경우 맞는 비밀 번호를 입력할 때까지 다음 단계로 넘어가지 않습니다.
2. 비밀번호 일치시 금고의 문이 열립니다.
3. 문을 닫고, 키패드의 '*'을 누르면, 금고가 잠깁니다.
<관리자 모드>
1. 금고 문이 열렸을 때 미리 지정해둔 관리자 번호를 누르면 관리자 모드로 진입하게 됩니다.
2. 변경하고 싶은 비밀번호를 입력합니다. 확인을 위해 다시 한 번 입력합니다.
3. 둘의 입력값이 같다면 성공적으로 비밀 번호가 변경됩니다.
4. 비밀번호 확인이 가능합니다.
NO | 부품명 | 수량 | 상세설명 |
1 | 오렌지 보드 | 1 | |
2 | 서보모터 | 1 | SG-90 |
3 | 16x2 LCD | 1 | |
4 | 피에조 부저 | 1 | |
5 | 가변저항 | 1 | 1K |
6 | 키패드 | 1 | |
7 | 스프링 | 1 | 용수철 누름(40mm) |
8 | 잠금 고리 | 1 |
부품명 | 오렌지 보드 | 서보모터 | 16x2 LCD | 피에조 부저 | 키패드 |
파트 |
브레드보드 레이아웃
회로도(스케메틱)
1. 케이스 만들기
저는 빼빼로가 프린팅 된 A4용지를 붙일 예정이었기 때문에 편리하게 A4용지 사이즈로 제작하였습니다.
빼빼로 상자로 만드시는 분들은 연인을 사랑하는만큼 많은 빼빼로를 이용하여 만들어보시면 어마어마하게 큰 금고가 완성되겠죠!
저는 금고 상단에 부품들을 넣었습니다.
아구가 안맞아보이는건 기분탓이겠죠..?
괜찮아요. 저는 A4용지로 다 가릴 예정이니까요^^!
조금 더 가까이에서 다시 한 번 보실까요?
2. 금고 잠금장치 배치
금고 기능은 서보모터와 다*소에서 파는 생활용품을 이용하여 구현해보았습니다.
ㄷ자 고리를 붙이셔도 좋을 것 같습니다.
잠금시에는 고정되있다가 잠금을 해제하면 서보모터가 돌아가고, 스프링으로 인해 상자가 앞으로 밀려나오게 됩니다.
이쑤시개는.. 저 부분이 실리콘 소재라서
서랍을 강제로 당길 때 서보모터의 캡(하얀색) 부분이 부러질 것을 대비하여 붙여놓았습니다.
'ㅡ' 모양으로 눕혀져있는 서보모터의 캡이
서랍에 붙어있는 잠금장치의 가운데 공간으로 들어가고
'*' 버튼을 이용하여 잠그면
이쑤시개가 붙은 방향으로 90도 틀어지게 됩니다.
서랍을 밀어주는 스프링, 금고를 잠가주는 서보모터를 조금 더 자세히 보실까요?
'
하드웨어는 이것이 끝입니다! 넘나 간단한 것..
이제 프린트한 종이만 겉에 붙여주면 완성입니다.
✮☆✮☆✮☆짜란✮☆✮☆✮☆
원래 붙어있던 하트모양 장식은 어디갔냐구요? 바로.. 여러분 마음 속에 들어가있을겁니다..(*ㅡ_ㅡ*)
/*
제목: DIY 빼빼로 금고
내용: 빼빼로 금고를 만들어보자
*/
#include "SoftwareSerial.h"
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Servo.h>
Servo locker;
// LCD 초기화
LiquidCrystal lcd(13, 12, 11, 9, A1, A0);
// 비밀번호 세팅
char secretCode[4] = {'1', '2', '3', '4'};
char input[4];
char newInput[4];
char key;
// 관리자 비밀번호 세팅
char adminCode[3] = {'#', '#', '#'};
char adminInput[3];
int position = 0;
int wrong = 0;
int i = 0;
int j = 0;
int pos = 0;
int a = 0;
int n = 0;
const byte rows = 4;
const byte cols = 4;
boolean c = false;
char keys[rows][cols] =
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[rows] = {8, 7, 6, 5};
byte colPins[cols] = {4, 3, 2, 1};
// 키패드 오브젝트 생성
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
// 음계 표준 주파수(4옥타브) : 도, 레, 미, 파, 솔, 라, 시, 도
int tones[] = {261, 294, 330, 349, 392, 440, 494, 523};
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
// 서보모터를 오렌지보드 10번핀에 부착
locker.attach(10);
// 서보모터의 디폴트 각도 지정
locker.write(0);
// 서보모터 핀모드
pinMode(10,INPUT);
// 피에조부저 핀모드
pinMode(A5, OUTPUT);
}
void loop() {
while (a == 0) {
// 비밀번호 입력 모드
inputKey();
// 비밀번호 확인
password();
// 현재 상태 LCD에 보여줌
passwordCheck();
}
// 만약 비밀번호가 맞다면
if (a == 1) {
lcd.clear();
lcd.setCursor(0, 0);
pinMode(10,OUTPUT);
// 서보모터 90도로 회전하며 금고 열림
locker.write(90);
lcd.print(" ONLY FOR YOU");
delay(2000);
pinMode(10,INPUT);
key = keypad.waitForKey();
if (key == '*') {
lockOn();
}
else if (key == '#') {
// admin mode를 위한 input 가능해짐.
Serial.println("Admin Mode Available ");
inputAdmin();
}
}
}
// 금고 잠금
void lockOn() {
// flag 다시 0으로 초기화
a = 0;
lcd.clear();
lcd.setCursor(0,0);
pinMode(10,OUTPUT);
lcd.print(" Lock ON");
// 서보모터 0도로 회전하며 금고 잠금
locker.write(0);
ringPiezo(99);
delay(2000);
pinMode(10,INPUT);
}
void inputAdmin() {
lcd.clear();
lcd.setCursor(0, 0);
pinMode(10,OUTPUT);
lcd.print("Admin mode");
delay(1000);
pinMode(10,INPUT);
for (i = 0; i < 3; i++) {
key = keypad.waitForKey();
if (key == '#') {
Serial.print(i);
input[i] = key;
}
else if (key == '*') {
// 중간에 * 누를 시 lock되고 admin mode 빠져나옴
lockOn();
break;
}
if (i == 2) {
Serial.println("");
Serial.println("Go to Admin Mode");
adminMode();
}
}
}
void adminMode()
{
Serial.println("---- Admin Mode On ----");
lcd.clear();
pinMode(10,OUTPUT);
lcd.setCursor(0, 0);
lcd.print("1. P/W Change");
lcd.setCursor(0, 1);
lcd.print("2. P/W Check");
delay(2000);
pinMode(10,INPUT);
key = keypad.waitForKey();
if (key == '1') {
while (n == 0) {
// 새 비밀번호 입력
inputNewPassword();
// 새 비밀번호 다시 입력
inputNewPasswordAgain();
// 위 두 번의 새 비밀번호 입력을 대조해봄
newPassword();
// 그 결과를 LCD로 띄움, wrong값 초기화
newPasswordCheck();
}
if (a == 1) {
// 두 값이 같을 때 비밀번호 변경
setNewPassword();
}
}
else if(key == '2') {
// password check
Serial.println("Password check");
lcd.clear();
pinMode(10,OUTPUT);
lcd.setCursor(0, 0);
lcd.print("Current Password");
for(int i = 0; i<4; i++) {
lcd.setCursor(i + 6, 1);
lcd.print(secretCode[i]);
Serial.print(secretCode[i]);
}
delay(3000);
}
}
void ringPiezo(int situation) {
// 비밀번호 일치
if (situation == 0) {
for (int i = 0; i < 3; i++) {
tone(A5, tones[2*i]);
// 0.2초 동안 대기
delay(200);
}
tone(A5, tones[7]);
delay(200);
// 피에조 부저가 연결된 핀으로부터 square-ware를 생성을 중단하도록 설정합니다.
noTone(A5);
}
// *버튼으로 금고 lock
else if(situation == 99) {
tone(A5, tones[7]);
delay(200);
for (int i = 0; i < 3; i++) {
tone(A5, tones[4 - 2*i]);
delay(200);
}
noTone(A5);
}
// 비밀번호 불일치
else {
for (int i = 0; i < 3; i++) {
tone(A5, tones[2]);
delay(200);
}
noTone(A5);
}
}
void inputKey() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Password");
for (i = 0; i < 4; i++) {
key = keypad.waitForKey();
input[i] = key;
if (input[0] == '#') {
lcd.clear();
lcd.setCursor(0, 0);
// 첫 입력부터 # 버튼 누를 시
lcd.print(" '#' is");
lcd.setCursor(0, 1);
// 삭제키라는 사실 알려줌
lcd.print(" Delete Key");
delay(2000);
// 다시 비밀번호 첫자리 입력하도록
i = i - 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Password");
}
else if (input[0] == '*') {
lcd.clear();
lcd.setCursor(0, 0);
// 첫 입력부터 * 버튼 누를 시
lcd.print(" '*' is");
lcd.setCursor(0, 1);
// 잠금키라는 사실 알려줌
lcd.print(" Lock Key");
delay(2000);
// 다시 비밀번호 첫자리 입력하도록
i = i - 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Password");
}
else if (i > 0 && input[i] == '#') {
i = i - 1;
lcd.setCursor(i + 6, 1);
// 직전에 입력했던 key 삭제
lcd.print(" ");
// 컴퓨터 모니터에도 보여줌
Serial.println("");
Serial.print("D");
// 직전 key 다시 입력하도록
i = i - 1;
}
// * key는 패스워드에 포함되지 않도록
else if (input[i] == '*') {
i = i - 1;
}
else {
lcd.setCursor(i + 6, 1);
lcd.print("*");
Serial.print(input[i]);
Serial.print(",");
}
if (i == 3) {
Serial.println("");
}
}
}
void password() {
wrong = 0;
for (j = 0; j < 4; j++) {
if (secretCode[j] == input[j]) {
}
else if (secretCode[j] != input[j]) {
wrong += 1;
}
}
}
void passwordCheck() {
ringPiezo(wrong);
if (wrong == 0) {
Serial.println("correct");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" CORRECT");
delay(2000);
a = 1;
lcd.clear();
}
else if (wrong != 0) {
Serial.println("wrong");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" WRONG");
delay(2000);
a = 0;
lcd.clear();
wrong = 0;
}
}
void inputNewPassword() {
// 비밀번호 변경
Serial.println("Password change");
lcd.clear();
pinMode(10,OUTPUT);
lcd.setCursor(0, 0);
lcd.print("Input New P/W");
for (i = 0; i < 4; i++) {
key = keypad.waitForKey();
input[i] = key;
if (input[0] == '#') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" '#' is");
lcd.setCursor(0, 1);
lcd.print(" Delete Key");
delay(2000);
i = i - 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Input New P/W");
}
else if (input[0] == '*') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" '*' is");
lcd.setCursor(0, 1);
lcd.print(" Lock Key");
delay(2000);
i = i - 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Password");
}
else if (i > 0 && input[i] == '#') {
i = i - 1;
lcd.setCursor(i + 6, 1);
lcd.print(" ");
Serial.println("");
Serial.print("D");
i = i - 1;
}
else if(input[i] == '*') {
i = i - 1;
}
else {
lcd.setCursor(i + 6, 1);
lcd.print("*");
Serial.print(input[i]);
Serial.print(",");
}
if (i == 3) {
Serial.println("");
}
}
}
void inputNewPasswordAgain() {
Serial.println("New password Check Again.");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Please Again");
for (i = 0; i < 4; i++) {
key = keypad.waitForKey();
newInput[i] = key;
if (newInput[0] == '#') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" '#' is");
lcd.setCursor(0, 1);
lcd.print(" Delete Key");
delay(2000);
i = i - 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Input New P/W");
}
else if (newInput[0] == '*') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" '*' is");
lcd.setCursor(0, 1);
lcd.print(" Lock Key");
delay(2000);
i = i - 1;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Password");
}
else if (i > 0 && newInput[i] == '#') {
i = i - 1;
lcd.setCursor(i + 6, 1);
lcd.print(" "); // 직전에 입력했던 key 삭제
Serial.println(""); // 모니터에도 보여줌
Serial.print("D");
i = i - 1; // 직전 key 다시 입력하도록
}
else if (newInput[i] == '*') {
i = i - 1;
}
else {
lcd.setCursor(i + 6, 1);
lcd.print("*");
Serial.print(newInput[i]);
Serial.print(",");
}
if (i == 3) {
Serial.println("");
}
}
}
void newPassword() {
Serial.println("new Password matching...");
wrong = 0;
for (j = 0; j < 4; j++) {
if (input[j] == newInput[j]) {
}
else if (input[j] != newInput[j]) {
wrong += 1;
}
}
}
void newPasswordCheck() {
// 새 비밀번호가 일치하면
if (wrong == 0) {
Serial.println("setting new Password...");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Setting Password...");
delay(2000);
n = 1;
}
else if (wrong != 0) {
Serial.println("New password is NOT correct");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" NOT CORRECT!");
delay(2000);
n = 0;
wrong = 0;
}
}
void setNewPassword() {
Serial.println("SET NEW PASSWORD");
for (j = 0; j < 4; j++) {
secretCode[j] = newInput[j];
Serial.print(newInput[j]);
}
Serial.println("");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET NEW PASSWORD");
delay(2000);
// 다시 n값 초기화
n = 0;
}
만두