터치프리 제스처 잠금장치: APDS-9960과 아두이노로 보안 액세스 구현
부품 및 소모품
| SparkFun APDS-9960 제스처/근접/컬러 센서 |
1개 |
| 아두이노 우노 (Arduino UNO) |
1개 |
| RGB 디퓨즈드 공통 캐소드 LED |
1개 |
| Adafruit 표준 LCD 16x2 (흰색/파란색) |
1개 |
| 저항 4.75k옴 |
2개 |
| 점퍼 와이어 (일반) |
1세트 |
| 저항 1k옴 |
1개 |
앱 및 온라인 서비스
프로젝트 소개
*테스트 결과 APDS-9960 센서는 아두이노 나노나 메가 2560에서는 작동하지 않습니다.
만들기 쉽고 사용하기 간편한 제스처 기반 잠금장치입니다. 원하는 서보나 래칭 메커니즘을 적용할 수 있습니다. 이 프로젝트는 제스처 잠금장치의 시작 플랫폼으로 활용하세요.
준비물
대부분 부품은 아마존에서, APDS-9960은 스파크펀(SparkFun)에서 구입했습니다. 아두이노 우노나 마이크로 3.3V만 사용 가능하며, 다른 보드는 알 수 없는 이유로 작동하지 않습니다.
조립
LCD를 회로도대로 연결하세요. 10k 포텐셔미터가 없다면 1k 저항을 콘트라스트 핀과 GND 사이에 연결하세요. APDS-9960은 아두이노 우노 사용 시 레벨 시프팅이 필요합니다. SCL과 SDA를 4.7k 저항에 연결한 뒤 3.3V로 풀업하고, 각각 A4, A5에 연결하세요(회로도 참조). 아두이노는 9V 배터리와 DC 배럴 잭으로 구동 가능합니다.
인클로저
골판지 상자에 부품 위치만큼 구멍을 뚫어 만들었습니다. 퍼프보드에 납땜해도 되지만, 브레드보드에 두고 점퍼 와이어로 연결했습니다. 완성 모습은 아래와 같습니다.
코드 (C/C++)
/* 하드웨어 연결: 중요! APDS-9960은 3.3V만 수용 가능!
아두이노 핀 APDS-9960 보드 기능
3.3V VCC 전원
GND GND 그라운드
A4 SDA I2C 데이터
A5 SCL I2C 클럭
2 INT 인터럽트
라이브러리: Wire.h, SparkFun_APDS-9960.h 필요
*/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <LiquidCrystal.h>
#include <Servo.h>
#define PINSIZE 6 // 비밀번호 제스처 길이
#define SERVOPIN 9 // 서보 핀
#define APDS9960_INT 2 // 인터럽트 핀 (반드시 인터럽트 가능 핀)
LiquidCrystal lcd(12,11,6,5,4,3);
Servo servo;
uint8_t proximity_data = 0;
int red_led = A1;
int green_led = A2;
int pageNum = 0; // LCD 페이지 상태
// 비밀번호: 대문자로 "UP", "DOWN", "LEFT", "RIGHT"만 사용
String secret[PINSIZE] = {"UP","DOWN","UP","UP","RIGHT","LEFT"};
String currentGesture = "";
int numRight = 0;
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;
void setup() {
pinMode(APDS9960_INT, INPUT);
lcd.begin(16,2);
servo.attach(SERVOPIN);
servo.write(0);
servo.detach();
Serial.begin(9600);
Serial.print("Your password is ");
Serial.print(PINSIZE);
Serial.println(" gestures long.");
Serial.println();
Serial.println(F("----------------"));
Serial.println(F("APDS-9960 Lock"));
Serial.println(F("----------------"));
attachInterrupt(0, interruptRoutine, FALLING);
if (apds.init()) {
Serial.println(F("APDS-9960 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9960 init!"));
}
if (!apds.setProximityGain(PGAIN_1X)) {
Serial.println(F("Something went wrong trying to set PGAIN"));
}
if (apds.enableProximitySensor(false)) {
Serial.println(F("Proximity sensor is now running"));
} else {
Serial.println(F("Something went wrong during sensor init!"));
}
if (apds.enableGestureSensor(true)) {
Serial.println(F("Gesture sensor is now running"));
} else {
Serial.println(F("Something went wrong during gesture sensor init!"));
}
}
void loop() {
// 페이지 0: 대기 모드 (근접 감지 시 진입)
if(pageNum==0){
if (!apds.readProximity(proximity_data)) {
Serial.println("Error reading proximity value");
} else {
Serial.println(proximity_data);
if((proximity_data >= 40) && (pageNum==0)){
pageNum=1;
delay(2000);
}
}
}
switch(pageNum){
case 0: // 잠금 화면
LCDClear();
lcd.print("Locked- get");
lcd.setCursor(0,1);
lcd.print("3 inches away.");
blinkRed();
LCDClear();
break;
case 1: // 비밀번호 입력
numRight = 0;
lcd.print("Enter code...");
lcd.setCursor(0,0);
for(int x=0; x0;x--){
LCDClear(); lcd.print("Closing in: "); lcd.setCursor(0,1); lcd.print(x); lcd.setCursor(1,1); lcd.print(" seconds..."); delay(1000);
}
LCDClear(); lcd.print("Closing");
}
회로도