아두이노 MKR 번들로 만드는 보안 IoT 퍼즐 박스: 단계별 가이드
부품 및 소모품
| 아두이노 MKR IoT 번들 |
MKR1000 보드 + 센서/액추에이터 키트 포함 |
1 |
소프트웨어 및 서비스
- Blynk: IoT 모바일 앱 플랫폼 (iOS/안드로이드)
프로젝트 소개
※ 본 튜토리얼은 구버전일 수 있습니다. 최신 버전은 여기 참조하세요.
귀중품을 숨기기엔 큰 금고는 부담스럽죠. MKR IoT 번들 구성품과 골판지로 나만의 퍼즐 박스를 만들어 보세요. 도난 방지는 장담 못 하지만, 재미있는 방해물로는 충분합니다. (진짜 귀중품 대신 사탕 넣어두기 추천!)
핵심 아이디어
- 서보 모터로 박스 잠금/해제
- 포텐셔미터 3개를 돌려 비밀 조합(0-9 각 자리) 맞추기
- 비밀 조합은 Blynk 앱에서 원격 설정 가능
- RGB LED로 근접도 피드백: 파랑(멀음) → 청록 → 노랑 → 빨강(정답 근접)
- 정답 맞추면 부저로 스타워즈 테마곡 연주하며 서보가 90° 회전해 박스 개방
학습 목표
- Blynk IoT 플랫폼 입문
- LCD 화면(16x2) 배선 및 사용법
- 부저로 멜로디(스타워즈 테마) 연주
Blynk 시작하기
Blynk는 킥스타터로 시작해 가장 널리 쓰이는 IoT 앱입니다. 훌륭한 문서와 단순함이 강점.
- 앱 설치 → 새 프로젝트 생성 → 보드: Arduino MKR1000 선택
- 인증 토큰(Auth Token) 이메일로 수신 → 코드에 입력
- 위젯: Slider 3개 (V1, V2, V3) 추가 → 각 0~9 범위 설정
- Blynk 라이브러리 설치 (아두이노 웹 에디터면 자동, IDE면 라이브러리 매니저에서 설치)
LCD 화면 연결 및 사용
16x2 문자 LCD는 배선이 많으니 인내심 필요. 5V 전원 + 220Ω 저항으로 백라이트 제어. analogWrite(A3, 0)로 최대 밝기.
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 2, d5 = 3, d6 = 4, d7 = 5;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
analogWrite(A3, 0);
lcd.begin(16, 2);
lcd.print("hello, world!");
}
void loop() {
lcd.setCursor(0, 1);
lcd.print(millis() / 1000);
}
포텐셔미터 3개 추가
A0, A1, A2에 연결. 0~1023 아날로그 값을 map(analogRead(Ax), 0, 1023, 0, 9)로 0~9 숫자로 매핑해 조합 입력용으로 사용.
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 2, d5 = 3, d6 = 4, d7 = 5;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
analogWrite(A3, 0);
Serial.begin(9600);
lcd.begin(16, 2);
}
void loop() {
int PotOne = map(analogRead(A0), 0, 1023, 0, 9);
int PotTwo = map(analogRead(A1), 0, 1023, 0, 9);
int PotThree = map(analogRead(A2), 0, 1023, 0, 9);
lcd.setCursor(0, 0); lcd.print(PotOne);
lcd.setCursor(2, 0); lcd.print(PotTwo);
lcd.setCursor(4, 0); lcd.print(PotThree);
}
RGB LED 피드백 추가
조합 근접도에 따라 색상 변화: 파랑(기본) → 청록(±4) → 노랑(±3) → 빨강(±1).
// RGB 핀
int redPin = 6, greenPin = 8, bluePin = 7;
void setColor(int r, int g, int b) {
analogWrite(redPin, r);
analogWrite(greenPin, g);
analogWrite(bluePin, b);
}
void loop() {
setColor(0, 0, 255); delay(1000); // 파랑
setColor(0, 255, 255); delay(1000); // 청록
setColor(255, 255, 0); delay(1000); // 노랑
setColor(255, 0, 0); delay(1000); // 빨강
}
Blynk 연동 통합
앱에서 설정한 슬라이더 값(V1~V3)을 비밀 조합으로 사용. giveColorFeedback()로 LED 색상 피드백. bool start = true로 정답 맞춘 후 중복 오픈 방지. 모든 포텐셔미터를 0으로 돌리면 리셋돼 다시 잠금.
#include <LiquidCrystal.h>
#include <SPI.h>
#include <WiFi101.h>
#include <BlynkSimpleWiFiShield101.h>
// ... (핀 정의, 인증 토큰, 와이파이 설정 생략)
int SliderValueOne = 1, SliderValueTwo = 1, SliderValueThree = 1;
bool start = true;
BLYNK_WRITE(V1) { SliderValueOne = param.asInt(); }
BLYNK_WRITE(V2) { SliderValueTwo = param.asInt(); }
BLYNK_WRITE(V3) { SliderValueThree = param.asInt(); }
void giveColorFeedback(int p1, int p2, int p3) {
if (abs(p1-SliderValueOne)<=1 && abs(p2-SliderValueTwo)<=1 && abs(p3-SliderValueThree)<=1)
setColor(255,0,0); // 빨강: 매우 가까움
else if (abs(p1-SliderValueOne)<=3 && abs(p2-SliderValueTwo)<=3 && abs(p3-SliderValueThree)<=3)
setColor(255,255,0); // 노랑
else if (abs(p1-SliderValueOne)<=4 && abs(p2-SliderValueTwo)<=4 && abs(p3-SliderValueThree)<=4)
setColor(0,255,255); // 청록
else
setColor(0,0,255); // 파랑
}
void blinkGreenLed() {
for(int a=0;a<2;a++) {
for(int b=0;b<=255;b+=5){ setColor(0,b,0); delay(5); }
for(int b=255;b>=0;b-=5){ setColor(0,b,0); delay(5); }
}
for(int b=0;b<=255;b+=5){ setColor(0,b,0); delay(5); }
}
void loop() {
Blynk.run();
int PotOne = map(analogRead(A0),0,1023,0,9);
int PotTwo = map(analogRead(A1),0,1023,0,9);
int PotThree = map(analogRead(A2),0,1023,0,9);
lcd.setCursor(0,0); lcd.print(PotOne);
lcd.setCursor(2,0); lcd.print(PotTwo);
lcd.setCursor(4,0); lcd.print(PotThree);
if (start) {
giveColorFeedback(PotOne, PotTwo, PotThree);
if (PotOne==SliderValueOne && PotTwo==SliderValueTwo && PotThree==SliderValueThree) {
blinkGreenLed();
start = false;
}
}
if(!start && PotOne==0 && PotTwo==0 && PotThree==0) start = true; // 리셋
}
부저로 스타워즈 테마 연주
const int c=261, d=294, e=329, f=349, g=391, gS=415, a=440, aS=455, b=466;
const int cH=523, cSH=554, dH=587, dSH=622, eH=659, fH=698, fSH=740, gH=784, gSH=830, aH=880;
#define buzzerPin 1
void beep(int note, int duration) {
tone(buzzerPin, note, duration);
noTone(buzzerPin);
delay(50);
}
void play_jingle() {
beep(a,500); beep(a,500); beep(a,500);
beep(f,350); beep(cH,150); beep(a,500);
beep(f,350); beep(cH,150); beep(a,650); delay(500);
beep(eH,500); beep(eH,500); beep(eH,500);
beep(fH,350); beep(cH,150); beep(gS,500);
beep(f,350); beep(cH,150); beep(a,650); delay(500);
}
서보 모터로 잠금 장치 제어
#include <Servo.h>
Servo myservo;
int pos = 0;
void setup() {
myservo.attach(9);
myservo.write(0); // 잠금 위치
}
void open_the_box() {
for(pos=0; pos<=90; pos+=1) { myservo.write(pos); delay(15); }
}
void close_the_box() {
for(pos=90; pos>=0; pos-=1) { myservo.write(pos); delay(15); }
}
정답 맞추면 open_the_box() 호출. 모든 포텐셔미터를 0으로 돌리면 close_the_box()로 재잠금.
퍼즐 박스 조립
2mm 골판지로 케이스 제작. 아래 DXF 파일 다운로드해 레이저 커팅하거나 칼로 재단.
소스 코드
완성된 통합 스케치는 위 단계별 코드를 합친 형태입니다. GitHub 또는 프로젝트 페이지에서 전체 코드 다운로드 가능.
커스텀 파트 및 인클로저
2mm 골판지용 DXF 파일: box_E5j7tnFdNC.dxf
회로도