아두이노 도어락 코딩 - adu-ino do-eolag koding

개발 배경


기존의 안면인식 도어락은 일반적인 사용자들이 사용하기에는 가격이 부담스럽습니다. 또한 기존에 설치되어있는 도어락을 제거하고, 이를 설치하여야 하기때문에 부담이 더욱 큽니다. 

Show

그래서, 기존의 도어락은 유지한채 얼굴인식 기능을 추가하는 방법으로 현대인의 필수품인 스마트폰을 활용하여 경제적 부담을 덜어낸 안면인식 도어락을 개발하자 생각하였습니다.

서비스 구상도


아두이노 도어락 코딩 - adu-ino do-eolag koding

사용자는 Application을 통해 본 서비스를 이용할 수 있습니다. 사용자는 회원가입시 본인의 사진 5장을 올립니다. 이를 firebase가 저장하고, Server는 이를 받아 학습합니다. 사용자가 이미지를 전송하고, 서버에게 허가요청을 보냅니다. 이런 메시지와 이미지는 firebase에 저장됩니다. Server는 firebase의 Database에 사용자가 보낸 허가요청 메시지를 받으면 firebase의 Storage에 있는 사진을 받아와 학습한 이미지들과 비교하여, 허가요청결과를 firebase에 보냅니다. 허가되었다면 도어락이 열립니다.

사용한 오픈소스


아두이노 도어락 코딩 - adu-ino do-eolag koding

결과 화면


기존의 사진선택의 경우 사용자얼굴을 학습하기 위한 용도로 사용하기 위해 추가되어있습니다.

참여한 부분


앱에서 회원가입 부분과 Firebase부분, 앱과 서버를 연결하고, 서버와 아두이노를 연결하는 부분을 맡았습니다. Firebase중에서도 Realtime Database와 Storage를 사용하였습니다. Firebase를 회원가입에 사용한 이유는 Firebase Authentication과 통합되어 있어서 단순하고 직관적으로 회원가입을 이용할 수 있을 것 같아 사용하였습니다. 그리고 Firebase는 모바일 환경에 최적화 되어있으며, 사용법에 대한 자료가 많아 접근성이 높다고 생각하여 선택하였습니다.

각 사용자의 Uid를 통해 사용자별 메시지를 구분할 수 있으며, 안에 메시지의 내용을 담았습니다.
사용자가 찍은 사진과 사용자가 안면인식에 등록된 사진들과의 비교를 위해 Firebase Cloud Storage에 사용자가 등록한 사진과 찍은 사진을 저장하여 주었습니다. 이로 인해 사용자는 사용을 계속할수록 좀 더 나은 성능의 안면인식을 사용할 수 있게 됩니다. Cloud Storage는 사용자별로 폴더를 만들어 관리하였습니다.

아두이노 도어락 코딩 - adu-ino do-eolag koding
Firebase와 연결해주는 코드
아두이노 도어락 코딩 - adu-ino do-eolag koding
사진을 Upload하는 코드
아두이노 도어락 코딩 - adu-ino do-eolag koding
문열기 요청 코드

서버는 Python을 사용하였습니다. Python에서 Firebase를 사용하기위해 Pyrebase를 사용하였습니다. child를 통해 Firebase구조에 쉽게 접근할 수 있어 사용함에 큰 불편함은 없었습니다.

아두이노 도어락 코딩 - adu-ino do-eolag koding
Pyrebase 초기화
아두이노 도어락 코딩 - adu-ino do-eolag koding
Pyrebase를 이용해 Firebase에 접근
아두이노 도어락 코딩 - adu-ino do-eolag koding
사용한 도어락과 아두이노

기존의 도어락에 블루투스를 추가하여 작동하였습니다. 서버에서 사용자가 업로드한 사진과 기존의 사진들과 유사도를 검사하고 유사하면 블루투스 신호를 보내 문을 열어주게되고 일정시간이 지나면 자동으로 닫기게 하였습니다.

느낀점


이전에 TCP/IP 소켓통신 채팅앱을 제작할 때, Firebase를 공부해 본 적은 있었지만, 실질적으로 사용은 처음으로 해보았습니다. SDK 문서 역시 정리가 잘 되어있었고, 사용하면서 불편함을 느끼지 못하였습니다. 개발자가 신경 써야 할 보안이나 DB의 설계 부분을 많이 줄여주어서 좋았습니다. 회원가입과 로그인을 Authentication을 이용했는데, 이 부분이 굉장히 편했고, 구글 계정 연동까지 되는 부분은 많은 도움이 되었습니다. 그리고 관리자로서도 사용자들의 계정을 관리하기 편해서 좋았습니다.

아쉬웠던 부분은 이미지 파일의 관리였습니다. 서버 측에서 사용자별로 사진을 따로 저장해두고 존재하지 않는 파일만 Firebase에서 받았더라면 서버 측에서 문을 열어주는 반응이 좀 더 빠를 수 있었는데, 이를 해결하지 못한 부분이 아쉬웠습니다.

서버, 아두이노, 앱까지 3단계로 이루어진 프로젝트였습니다. 도어락 특성상 사용자의 요구에 앱과 아두이노가 빠르게 반응하여야했는데, 이를 해결하기 위한 방법에 대한 고민이 많이 부족하였던것 같습니다. 

Github


https://github.com/solyeah/photolock

당신은 주제를 찾고 있습니까 “아두 이노 도어락 – 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!“? 다음 카테고리의 웹사이트 https://you.giarevietnam.vn 에서 귀하의 모든 질문에 답변해 드립니다: https://you.giarevietnam.vn/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 라즈이노 IOT 이(가) 작성한 기사에는 조회수 8,156회 및 좋아요 54개 개의 좋아요가 있습니다.

  • 아두 이노 도어락 주제에 대한 동영상 보기
  • d여기에서 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기! – 아두 이노 도어락 주제에 대한 세부정보를 참조하세요
  • 아두 이노 도어락 주제에 대한 자세한 내용은 여기를 참조하세요.
    • 아두이노로 도어락 만들기 – 네이버 블로그
    • 아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 – postpop
    • [아두이노] 디지털 도어락 KIT – Capstonemall – 캡스톤몰
    • 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!
    • Top 36 아두 이노 도어락 9803 Votes This Answer
    • 아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 … – 인터파크
    • P18 아두이노 RFID 도어락 실험키트 RDM6300 리더기 – 11번가
    • 아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 1.0 & Ver 2.0
  • 주제와 관련된 이미지 아두 이노 도어락
  • 주제에 대한 기사 평가 아두 이노 도어락
  • 아두이노로 도어락 만들기
  • 아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법
  • [아두이노] 디지털 도어락 KIT
  • 라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!
  • Top 36 아두 이노 도어락 9803 Votes This Answer
  • 아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트
  • P18 아두이노 RFID 도어락 실험키트 RDM6300 리더기
  • NFC 도어락(DoorLock) Ver 1.0 & Ver 2.0
  • 키워드에 대한 정보 아두 이노 도어락
  • 사람들이 주제에 대해 자주 검색하는 키워드 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!

아두 이노 도어락 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

▶ RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 데이터를 교환하는 장치입니다.
교통카드, 학생신분증 겸용카드, 연구실 및 회사 출입문카드, 구내식당 카드, 마트 등의 상품 진열 및 관리 등등 다방면에서 이용되고 있다.
▶ 이번 영상 에서는 가정집에서 많이 사용되는 도어락을 구현해 보았습니다.
▶ 관련 학습자료 링크 : https://rasino.tistory.com/223
▶ 실습 회로도 : https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory\u0026fname=https%3A%2F%2Fk.kakaocdn.net%2Fdn%2FvisCy%2FbtquOG7fawu%2FG4bs12EcJKDvHkn3KIjmk1%2Fimg.png
▶ 아두이노 코드 다운로드 : https://k.kakaocdn.net/dn/byWU5v/btquOGTLG39/8MdtXLidRgMeIoSYKWjlW1/tfile.zip?attach=1\u0026nm=ko_arduino_code_Servo_LED.zip
[ 소요 재료 ] 1. RFID(세트) = https://smartstore.naver.com/domekit/products/299678248
2. 아두이노 우노 = https://smartstore.naver.com/domekit/products/449565624
3. 우노 아크릴 거치대 = https://smartstore.naver.com/domekit/products/583542706
4. 400홀 브레드보드 = https://smartstore.naver.com/domekit/products/328850535
5. SG90서보 모터 = https://smartstore.naver.com/domekit/products/299687413
6. RGB LED(5파이) = https://smartstore.naver.com/domekit/products/569142806
7. 220옴 막대저항 = https://smartstore.naver.com/domekit/products/618370169
▶아두이노 와 IOT에 관심있으신 분은 구독과 좋아요 부탁드려요~ ^^
【 RFID 배우기 학습 자료 】
본 영상에서는 전체적인 동작설명만 나와 있어서 참고하기 부족하실 텐데요, 아래 상세자료 링크글 참고하시면 도움이 되실 듯 합니다.
1 편 : 【 아두이노모듈#11】 RFID (RC522) 사용하기 #1\r https://rasino.tistory.com/221
2 편 : 【 아두이노모듈#12】 RFID (RC522) 사용하기 #2\r https://rasino.tistory.com/222
3 편 : 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!\r https://rasino.tistory.com/223

아두 이노 도어락 주제에 대한 자세한 내용은 여기를 참조하세요.

아두이노로 도어락 만들기 – 네이버 블로그

아두이노 키트(케이블, 버튼, 저항, LED전구, 9V 건전지 등). 7. 3D 프린터 Anet A8 Plus DIY(타오바오 1559위안). ​. 3D 프린터를 제외한 도어락 DIY …

+ 여기에 자세히 보기

Source: m.blog.naver.com

Date Published: 5/26/2021

View: 1476

아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 – postpop

아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다.

+ 여기에 더 보기

Source: postpop.tistory.com

Date Published: 10/26/2021

View: 7317

[아두이노] 디지털 도어락 KIT – Capstonemall – 캡스톤몰

상품명, [아두이노] 디지털 도어락 KIT ; 판매가, 120,000원 ; 제조사, [씨앤디아이 주식회사] ; 원산지, 국내 ; 배송비 · 3,500원 …

+ 더 읽기

Source: capstonemall.co.kr

Date Published: 10/21/2022

View: 5707

【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!

【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 …

+ 여기에 자세히 보기

Source: rasino.tistory.com

Date Published: 7/3/2022

View: 6939

Top 36 아두 이노 도어락 9803 Votes This Answer

라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! 아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트 – 인터파크; 아두이노 …

+ 여기에 자세히 보기

Source: toplist.avitour.vn

Date Published: 8/14/2022

View: 5997

아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 … – 인터파크

4%할인, 추가 회원 중복 할인 쿠폰, 기타에 대한 상품입니다.

+ 여기에 자세히 보기

Source: m.shop.interpark.com

Date Published: 6/1/2022

View: 5065

P18 아두이노 RFID 도어락 실험키트 RDM6300 리더기 – 11번가

P18 아두이노 RFID 도어락 실험키트 RDM6300 리더기. 현재 판매중인 상품이 아닙니다. 배송. 배송비 2,900원 (100,000원 이상 무료). 롯데택배 …

+ 여기에 표시

Source: m.11st.co.kr

Date Published: 11/20/2021

View: 7820

아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 1.0 & Ver 2.0

졸업전 만들고 싶었던 NFC를 이용한 도어락이다. 개인적으로 가졌던 로망으로 열쇠나 비밀번호가 아닌 핸드폰을 대는것으로 개인 사물함을 열고 …

+ 여기에 표시

Source: twinw.tistory.com

Date Published: 2/23/2022

View: 6039

주제와 관련된 이미지 아두 이노 도어락

주제와 관련된 더 많은 사진을 참조하십시오 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

아두이노 도어락 코딩 - adu-ino do-eolag koding
【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!

주제에 대한 기사 평가 아두 이노 도어락

  • Author: 라즈이노 IOT
  • Views: 조회수 8,156회
  • Likes: 좋아요 54개
  • Date Published: 2019. 4. 26.
  • Video Url link: https://www.youtube.com/watch?v=6nBu0obCx5Q

아두이노로 도어락 만들기

홍콩에 새로 이사온 집에는 도어락이 없다. 도어락이 없는 집에 사는것은 여간 불편한 것이 아니다. 일을하러 갈때나 잠시 마트를 갈때마저도 항상 열쇠를 가지고 나서야 하고 집 문을 열때 가방에서 열쇠를 뒤적거려 찾아서 여는 것은 상당히 귀찮은 일이다. 그래서 도어락을 설치해서 열쇠로부터 해방되고자 고민을 하기 시작했다.

사실 저렴한 도어락을 구매해서 설치하는게 가장 간단하다고 볼 수도 있다. 하지만 집 현관문 형태를 확인해보니 도어락을 설치하려면 문에 흠집을 내야하고 물어보진 않았지만 주인 아주머니가 허락할 것 같진 않았다. 온 아파트 전체가 다 같은 방식의 문고리를 사용하는 데다가 도어락은 편리하다는 장점은 있을지 몰라도 홍콩에서는 오히려 열쇠로 여는것 보다 보안에 취약하다고 여기는 모양이다. 사실 틀린말은 아닐지 모르지만 내 생각엔 열쇠든 도어락이든 어차피 마음막 먹으면 여는게 불가능은 아닐것이고 완벽한 보안이 아닌이상엔 편리함이 낫다고 본다.

결국 문에 흡집을 내지않고 도어락을 설치하는게 목적이 되었고 그러기 위해서는 시판되는 도어락을 구매해서 설치하는 것 보다는 직접 만들어서 설치하는게 더 가능성이 있을 것이다라는 결론에 이르렀다. 결국 이 결론으로 인해 모든것이 시작되었다.

아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법

아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다. 디지털 도어락 코드는 delay()함수의 문제점을 이해하는데 좋은 예제라 생각한다.

앞으로 구현할 디지털 도어락의 작동 개요 및 구성요소를 살펴보자.

작동개요(실생활에 사용하는 디지털 도어락의 작동 상태)

1. 초기 비밀번호가 설정되어 있다.

2. 사용자 비밀번호를 입력하여 저장할 수 있다.

3. 밧데리 교체등 전원을 껐다 켜도 입력된 사용자 비밀번호는 유지된다.

4. 비밀 번호가 맞게 입력될 경우 문이 열리는 작동과 그 작동을 작동음과 램프로 표시 한다.

5. 비밀 번호가 틀리게 입력될 경우 사용자 인지를 위해 경고음과 램프로 표시한다.

6. 입력이 잘못될 경우 입력을 지우고 처음부터 입력할 수 있다.

7. 사용자 비밀번호 변경중 변경작업을 종료할 수 있다.

8. 상기의 작업을 키패드를 통해 제어할 수 있다.

비밀번호 변경방법

1. 초기 비밀번호 또는 사용자 비밀번호를 입력하여 열림상태로 한다.

2. 열림 상태에서 #버튼을 2초간 누른다. (비밀번호 설정 코드로 진입된다)

3. 사용자 비밀번호를 입력하고 #버튼을 눌러 저장한다.

4. 입력이 잘못된 경우 *를 누르면 입력된 값이 지워진다.

5. 사용자 비밀번호 입력을 취소할 경우 *를 2초간 누른다.(비밀번호 설정 코드를 빠져나간다)

작동상태 표시

1. 열림: 빨간색 -> 노란색 -> 파란색 LED 순으로 한번씩 점멸하고, “도 -> 레 -> 미” 열림음이 출력된다.

2. 사용자 비밀번호 입력: 빨간색, 노란색, 파란색 LED가 동시 점멸하며 입력 완료시 까지 계속된다. .

3. 비밀번호 잘못 입력한 경우: 경고음 1회 발생, 빨간색, 노란색, 파란색 LED가 한번만 동시 점멸

위의 기능을 수행하기 위해서는 피에조부저와 LED(빨, 노, 파) 3개, 키패드, 서버모터 가 필요하고 LED용 저항은 필요에 따라 적용하면 된다.

디지털 도어락 구성 및 결선

키패드 R4 – > 아두이노 3번핀

키패드 R3 – > 아두이노 4번핀

키패드 R2 – > 아두이노 5번핀

키패드 R1 – > 아두이노 6번핀

키패드 C1 – > 아두이노 7번핀

키패드 C2 – > 아두이노 8번핀

키패드 C3 – > 아두이노 9번핀 // 키패드 C4 핀은 사용하지 않는다.

서보모터 제어선(노란색) -> 아두이노 10번핀

수동형 피에조 부저 ‘+’ -> 아두이노 11번핀 (수동형 피에조 부저는 밑면에 기판이 보인다)

파란색 LED -> 아두이노 2번핀

노란색 LED -> 아두이노 12번핀

빨간색 LED -> 아두이노 13번핀

아두이노에서 키패드를 쉽게 사용하기 위해 keypad.h라이브러리를 이용하기로 하자

https://github.com/Chris–A/Keypad

첨부된 Keypad.zip 파일을 다운로드 받은뒤 압축을 해제하고 keypad 폴더를 아래의 아두이노 라이브러리 폴더에 저장 시킨다.

아두이노 IDE가 실행되어 있다면 종료시키고 다시 실행하여 라이브러리가 등록되도록 한다.

새로 아두이노 IDE를 실행시키고 예제 -> 모든 보드의 예제 항목 Keypad -> EventKeypad를 불러온다.

아래 코드는 예제 EventKeypad를 단순화 시켜놓은 것이며, 2초동안 누르는 키동작을 위해 키 홀드 시간 설정 옵션을 추가하였다.

keypad.setHoldTime(2000);

참조사이트

https://playground.arduino.cc/Code/Keypad/#Functions

#include const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, // { S1, S2, S3} {‘4′,’5′,’6’}, // { S5, S6, S7} {‘7′,’8′,’9’}, // { S9, S10, S11} {‘*’,’0′,’#’} // { S13, S14, S15} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // {R4, R3, R2, R1} byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); void setup(){ Serial.begin(9600); keypad.addEventListener(keypadEvent); // Add an event listener for this keypad keypad.setHoldTime(2000); // 키 홀드 시간 설정 – 2000 = 2초 } void loop(){ char key = keypad.getKey(); if (key) { Serial.println(key); } } // Taking care of some special events. void keypadEvent(KeypadEvent key){ switch (keypad.getState()){ case PRESSED: if (key == ‘#’) Serial.println(“PRESSED”); break; case RELEASED: if (key == ‘*’) Serial.println(“RELEASED”); break; case HOLD: if (key == ‘*’) Serial.println(“HOLD”); break; } }

키패드를 아두이노에 연결할 때 C4핀을 연결하지 않았다. C4핀을 연결하지 않게되면 아래의 빨간표시 부분의 키들은 입력이 되지 않게 된다.

코드에서 핀배치 배열(colPins[COLS])의 C4에 해당하는 자리가 비어 있음을 볼 수 있다.

byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4}

상기 코드를 업로드하고 버튼을 차례대로 왼쪽에서 오른쪽으로 또 아래로 내려가면서 눌러보자

키패드 C4핀에 해당하는 부분은 입력이 안되며 *를 누르면 *가 출력되고 버튼을 떼는 순간 RELEASED가 출력되는 것을 볼수 있다. 또한 # 누르는 순간 PRESSED가 먼저 출력되고 바로 다음에 #이 출력되게 된다. *를 계속 누르고 있으면 * HOLD 가 차례로 나오고 뗄때 RELEASED가 출력되는 것을 볼 수 있다. keypadEvent() 코드중 case HOLD: 를 사용할 것이다.

키패드를 통해 숫자를 입력 받을 수 있게 되었다. 이제 입력된 숫자를 저장하고 비교하는 코드를 작성해 보자

위에서 살펴본 디지털 도어락 비밀번호 변경방법 절차중 2번과 5번을 구현하기 위해 keypadEvent() 함수를 살펴보자.

2. 열림 상태에서 #버튼을 2초간 누른다. (비밀번호 설정 코드로 진입된다)

5. 사용자 비밀번호 입력을 취소할 경우 *를 2초간 누른다.(비밀번호 설정 코드를 빠져나간다)

2번은 비밀번호 검증이 완료되어 문이 열린 상태(서보모터 열림 위치)에서만 #버튼이 작동되어야 하고 5번은 비밀번호 변경중 설정시간이 초과되어 문이 자동으로 닫혀질 수 있으므로 문이 닫힌 상태(서보모터 닫힘 위치)에서도 작동되어야 한다.

우선, 문이 열리고 닫히는 상태를 표시하기 위해 플래그 doorOpen를 선언하고 초기값은 false로 하자.

bool doorOpen = false;

2초간 눌렸다는 것을 표시하기 위해 플래그 longPress를 선언하고 초기값은 false로 하자.

#버튼을 2초간 누르면 longPress = true; 가 되어 비밀번호 설정 코드로 들어가고, *를 2초간 누르면 longPress = false;로 하여 #버튼을 2초간 누른 효과를 무효화 시켜 비밀번호 설정 코드를 빠져 나오게 된다.

bool longPress = false;

위 상황에 따라 아래와 같이 코드를 변경해 주었다.

void keypadEvent(KeypadEvent key){ // 키패드 이벤트 함수 switch (keypad.getState()){ case HOLD: switch (key){ case ‘*’: longPress = false; // 비밀번호 변경코드 빠져나감 key = ‘\0’; // 입력된 ‘*’ 삭제 – 오류방지 codeIndex = 0; break; } break; // HOLD 종료 } if(doorOpen == true) { // 문 열린 상태에서만 키패드 이벤트 진입 switch (keypad.getState()){ case HOLD: switch (key){ case ‘#’: longPress = true; // 비밀번호 변경코드 진입 key = ‘\0’; // 입력된 ‘#’ 삭제 – 오류방지 codeIndex = 0; break; } break; // HOLD 종료 } } }

비밀번호는 4자리 숫자이다. 이를 위해 아래와 같이 관련 변수를 설정해 주자.

char temp[4] = { 0, }; // 비밀번호 설정시 임시 저장 배열 char password[4] = “1234”; // 초기 비밀번호 및 사용자 비밀번호 저장 배열 char inputCode[4] = “0000”; // 검증을 위한 사용자 입력 비밀번호 저장 배열 uint8_t codeIndex = 0; // 비밀번호 배열 index 지정 변수 (uint8_t: 부호없는 8bit 0 ~ 255 까지의 숫자)

디지털 도어락의 작동 상황을 두가지 상황을 기준으로 구분할 수가 있는데, 하나는 4자리 비밀번호를 입력받고 검증 후 문을 열고 닫는것이고 다른 하나는 4자리 사용자 비밀번호를 입력받고 저장하여 비밀번호를 변경하는 것이다. 이는 위에서 설정한 longPress 플래그 변수값에 의해 구분 되어 질 수 있다.

if (longPress) { 비밀번호 변경 상황 } else { 비밀번호 검증 후 문을 열고 닫는 상황 }

비밀번호 변경 상황

if (key) { // 키패드 키가 눌려져 key 변수에 값이 있으면 if (key != ‘*’ && key != ‘#’ && codeIndex < 4) { temp[codeIndex] = key; codeIndex++; } // 만약 키값이 숫자이면, temp 배열에 인덱스 0 ~ 3까지 순서대로 저장(4자리 이상 입력은 무시) else if(key == '#') { // 만약 키값이 숫자가 아니고 #이면 for (int i = 0; i < 4; i++) password[i] = temp[i]; // temp 배열의 값을 password 배열에 저장 longPress = false; // 비밀번호 변경 코드 빠져나간다. key = '\0'; // 변수 key값 비우기, 입력된 '#' 삭제 - 오류방지 codeIndex = 0; // 비밀번호 확인 완료됐으므로 인덱스 번호 초기화 } else if (key == '*') { // 만약 키값이 숫자가 아니고 *이면 for (int i = 0; i < 4; i++) temp[i] = '0'; // temp 배열값 모두 0으로 초기화 key = '\0'; // 변수 key값 비우기, 입력된 '*' 삭제 - 오류방지 codeIndex = 0; // 처음부터 입력 받기 위해 인덱스 번호 초기화 } 비밀번호 검증 후 문을 열고 닫는 상황 if (key) { // 키패드 키가 눌려져 key 변수에 값이 있으면 if (key != '*' && key != '#' && doorOpen != true) { // 만약 키값이 숫자이면, 검증이 완료되고 열린상황에서는 입력 무시 inputCode[codeIndex] = key; // 키값을 비교배열 inputCode의 codeIndex 번호에 저장 codeIndex++; // 인덱스 번호 증가 if (codeIndex == 4) { // 비교배열 인덱스 3까지(4번째 숫자) 저장후 번호 증가하여 4가 되면 if (strncmp(password, inputCode, 4) == 0) { Serial.print("door open"); doorOpen = true; codeIndex = 0; } // 비밀번호 검증 후 참이면, 시리얼 모니터에 door open 출력, doorOpen 플래그 true로 변경, 인덱스 번호 초기화 **strcmp(문자열1, 문자열2); // 비교할 문자열을 넣어주면 결과를 정수로 반환 - 대소문자 구분 정수값 -1: ASCII 코드값 기준으로 문자열2가 클 때 // 문자열1 = "aab" < 문자열2 = "aac" // a = 97 b = 98 c = 99 정수값 0: ASCII 코드값 기준으로 두 문자열이 같을 때 // 문자열1 = "aaa" = 문자열2 = "aaa" 정수값 1: ASCII 코드값 기준으로 문자열1이 클 때 // 문자열1 = "aab" > 문자열2 = “aaa” else { Serial.print(“wrong_number”); codeIndex = 0; } // 검증후 일치하지 않으면, 시리얼 모니터에 wrong number 출력, 처음부터 입력 받기 위해 인덱스 번호 초기화 for (int i = 0; i < 4; i++) inputCode[i] = '0'; // 비교배열값도 초기화 else if (key == '*') { // 입력값 초기화, 아무때나 눌려도 상관없다. Serial.println("CLEAR"); for (int i = 0; i < 4; i++) inputCode[i] = '0'; // 비교배열값 초기화 key = '\0'; // 입력된 '*' 삭제 - 오류방지 codeIndex = 0; // 처음부터 입력 받기 위해 인덱스 번호 초기화 } 사용자 비밀번호 저장 코드와 비밀번호 검증을 통해 문을 열고 닫는 코드를 살펴보았다. 아래 코드를 아두이노에 업로드 하고 4자리 숫자를 입력하고 시리얼 모니터를 통해 작동 상황을 확인해 보자. #include const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, // { S1, S2, S3} {‘4′,’5′,’6’}, // { S5, S6, S7} {‘7′,’8′,’9’}, // { S9, S10, S11} {‘*’,’0′,’#’} // { S13, S14, S15} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // {R4, R3, R2, R1} byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // 키패드 오브젝트 생성 bool longPress = false; // 키패드 이벤트용 및 계속점멸 longPress 플래그 bool doorOpen = false; char temp[4] = { 0, }; // 비밀번호 설정시 임시 저장변수 char password[4] = “1234”; // 초기 비밀번호 및 사용자 비밀번호 저장 변수 char inputCode[4] = “0000”; // 검증을 위한 사용자 입력 비밀번호 저장 배열 uint8_t codeIndex = 0; // 비밀번호 문자열 배열 index void setup(){ Serial.begin(9600); keypad.addEventListener(keypadEvent); // 키패드 이밴트 관리자 설정 keypad.setHoldTime(2000); // 키 홀드 시간 설정 – 2000 = 2초 } void loop(){ char key = keypad.getKey(); if (longPress) { // password 설정 if (key) { if (key != ‘*’ && key != ‘#’ && codeIndex < 4) { // 숫자이면, 4자리 이상 무시 Serial.print("pass set key: "); Serial.println(key); temp[codeIndex] = key; codeIndex++; } else if(key == '#') { // password 저장 for (int i = 0; i < 4; i++) password[i] = temp[i]; longPress = false; key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; doorOpen = false; // 자동으로 잠기는 문 표시 Serial.println("set new password"); } else if (key == '*') { // 입력값 초기화 for (int i = 0; i < 4; i++) temp[i] = '0'; key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; Serial.println("CLEAR"); } } } else { if (key) { if (key != '*' && key != '#' && doorOpen == false) { // 숫자만 입력 Serial.print("key: "); Serial.println(key); inputCode[codeIndex] = key; codeIndex++; if (codeIndex == 4) { if (strncmp(password, inputCode, 4) == 0){ Serial.println("door open"); doorOpen = true; codeIndex = 0; } else { Serial.println("wrong number"); codeIndex = 0; } for (int i = 0; i < 4; i++) inputCode[i] = '0'; } } else if (key == '*') { // 입력값 초기화 Serial.println("CLEAR"); for (int i = 0; i < 4; i++) inputCode[i] = '0'; key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; } } } } void keypadEvent(KeypadEvent key){ // 키패드 이벤트 함수 switch (keypad.getState()){ case HOLD: switch (key){ case '*': longPress = false; // 비밀번호 변경코드 빠져나감 key = '\0'; // 입력된 '*' 삭제 - 오류방지 codeIndex = 0; Serial.println("set pass out"); break; } break; // HOLD 종료 } if(doorOpen == true) { // 문 열린 상태에서 키패드 이벤트 진입 switch (keypad.getState()){ case HOLD: switch (key){ case '#': longPress = true; // 비밀번호 변경코드 진입 key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; Serial.println("set pass in"); break; } break; // HOLD 종료 } } } 상기 코드에는 문이 열린 후 몇초 뒤 자동으로 잠기는 상황이 반영되어 있지 않다. 그러므로 문이 열려 doorOpen = true; 가 계속 유지되고 false로 바뀌지 않게 된다. 문제는 doorOpen == false 일때만 숫자가 입력되게 코드 되어 있기때문에 키패드를 통한 숫자 입력이 더이상 되지 않게 되어 추가 확인을 할 수가 없다. 비밀번호 변경 확인을 위해 비밀번호 변경 저장 #버튼을 눌렀을 때 doorOpen = false;로 변경하는 코드를 추가해 주었다. 키패드로 1234 입력하고 #버튼을 2초간 누른뒤 1111을 입력하고 #버튼을 눌러 비밀번호를 변경하고 다시 변경된 비밀번호 1111을 입력하면 아래와 같이 시리얼 모니터에 출력되는 것을 볼수 있다. 상기 코드 door open 상황에서는 *버튼과 #버튼만을 입력할 수 있다. 도어락의 핵심 기능인 키패드를 통해 입력된 4자리 비밀번호를 검증하고 결과를 출력하는 코드는 완성되었다. 이제 사용자 입력에 따라 반응하는 LED와 피에조부저의 작동상태 표시에 관해 살펴보자. LED를 켜고 끄는 작동을 반복하거나 외부 입력없이 내부적으로 제어하기 위해서는 보통 delay()함수를 사용하게 된다. 아두이노 기본 예제인 blink예제를 살펴보자. #define LED_BUILTIN 13 void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } 상기 코드를 업로드 하면 1초 간격으로 아두이노 기본 LED가 점멸하는 것을 볼 수있다. 이 코드와 위에서 살펴보았던 EventKeypad_modify.ino 코드와 합쳐보자. #include const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, // { S1, S2, S3} {‘4′,’5′,’6’}, // { S5, S6, S7} {‘7′,’8′,’9’}, // { S9, S10, S11} {‘*’,’0′,’#’} // { S13, S14, S15} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // {R4, R3, R2, R1} byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); #define LED_BUILTIN 13 void setup(){ Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); keypad.addEventListener(keypadEvent); // Add an event listener for this keypad keypad.setHoldTime(2000); // 키 홀드 시간 설정 – 2000 = 2초 } void loop(){ char key = keypad.getKey(); if (key) { Serial.println(key); } digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); } // Taking care of some special events. void keypadEvent(KeypadEvent key){ switch (keypad.getState()){ case PRESSED: if (key == ‘#’) Serial.println(“PRESSED”); break; case RELEASED: if (key == ‘*’) Serial.println(“RELEASED”); break; case HOLD: if (key == ‘*’) Serial.println(“HOLD”); break; } }

상기 코드를 업로드 하고 키패드의 버튼을 클릭해보면 시리얼 모니터에 출력이 안된다. 이때 키패드의 버튼을 빠르게 연타 하거나 또는 계속 누르고 있으면 그때야 비로소 숫자가 입력되고 시리얼 모니터에 출력 되는걸 확인 할 수 있다.

이는 keypad.h라이브러리 문제나 blink예제 코드의 문제는 아니다. 단지 delay()함수의 특성 때문에 발생하는 현상이며 정상적인 반응이다.

아두이노의 작동 방식은 처음 전원이 들어가면 스케치상 위에서 아래로 왼쪽에서 오른쪽으로 코드를 읽어나간다. 또한 전역변수나 기타 메크로등을 순서대로 읽고 그 다음 setup() 함수 그리고 loop()함수로 들어가서 무한 반복하도록 되어 있다.

무한 반복하는 loop()함수에서도 위에서 아래로 왼쪽에서 오른쪽으로 코드를 읽어 나가고, 코드의 명령에 따라 어떤 실행을 하게 된다. 이렇게 loop() 함수안의 전체 코드를 한번 읽는 동작을 “scan한다”라고 얘기를 한다. 그렇다면 아두이노 loop() 함수는 1초에 몇번 scan을 할까? 입력된 코드의 양과 특성에 따라 달라지게 되고 또한 MCU의 속도에 따라 달라지게 되어 정확하게는 측정하기는 어렵지만 아두이노 참조사이트를 통해 유추해 볼 수는 있다.

아두이노 사이트에 있는 참조 페이지의 analogRead() 설명을 살펴보자

지정한 아날로그 핀에서 값을 읽습니다. 아두이노 보드는 6채널(미니와 나노는 8채널, 메가는 16채널), 10비트의 아날로그-디지털 변환기를 가지고 있습니다. 이는, 0에서 5V 사이의 입력 전압을 0에서 1024 사이의 정수 값으로 대응시키는 것을 뜻합니다. 이는 해상도가 5V/1024 혹은 0.0049V (0.49mV) 단위라는 것을 뜻합니다. 입력 범위와 해상도는 analogReference() 를 사용해서 바꿀 수 있습니다.

아날로그 입력을 읽는 데는 약 100마이크로초(0.0001초)가 걸리므로, 최대 읽기 속도는 1초에 약 1만 번입니다.

위의 얘기는 아두이노 loop()함수에 analogRead()함수만 코딩되어 있을경우 1초에 1만번 읽는다는 얘기일 것이고, 그 얘기는 1초에 1만번 loop()함수가 실행되면서 scan하게 된다는 얘기이다. 따라서 아두이노 loop()함수는 보통 1초에 1만번 정도 스캔한다고 유추를 해도 큰 무리는 없을 것이다.

delay() 함수가 없는 EventKeypad_modify.ino 스케치에서는 loop()함수가 돌면서 아래 코드에 따라 key 변수에 값이 있어 조건을 만족하는지 안하는지를 1만번 정도 확인하고 그중에 조건을 만족하는 순간 시리얼 모니터에 출력하게 된다.

char key = keypad.getKey();

if (key) { 시리얼 모니터 출력 }

하지만 상기의 코드 처럼 delay() 함수가 포함 되게 되면 상기의 1초에 1만번 정도 실행되는 scan 작업을 방해하게 된다.

delay() 함수는 내부적으로 while 루프를 사용하여 시간의 delay를 만들게 되는데, while 루프는 어떤 조건이 만족되면 무한 루프하는 코드이다. 아두이노 loop() 함수 안에 delay()함수가 있게 되면 아두이노 loop()함수 안에 또다른 루프가 생성되는 것이고, 그 루프의 조건이 계속 만족된다면 아두이노 loop()는 한바퀴 조차 돌지 못하게 된다. 한바퀴조차 돌지 못한다는 것은 아두이노에 전원은 들어가 작동은 하지만 입력에 대한 반응을 전혀하지 않는 상태인 흔히 “먹통이 되었다”라고 하는 상태가 되게 된다. 물론 delay() 함수가 이런 상황을 유발하는 것은 아니다. 언젠가는 조건이 만족하지 않아 빠져나오도록 코딩되어 있다.

아래 delay() 함수 코드를 살펴보면 delay(조건), 조건(ms > 0)을 만족하면 while 루프가 작동을 하고 ms =0이 되면 빠져나가게 되어 있는것을 볼 수 있다.

void delay(unsigned long ms) { // ms: 밀리초 uint32_t start = micros(); // 시작 비교시간 저장 : 마이크로초 while (ms > 0) { // 조건(밀리초)이 0이 아니면 yield(); while (ms > 0 && (micros() – start) >= 1000) { // 밀리초가 0이 아닌 상태에서 1밀리초가 경과되면 ms–; // 조건 밀리초에서 1밀리초를 뺀다 start += 1000; // 다시 1밀리초를 측정하기 위해 기준값에 1밀리초를 더해준다. } } }

delay() 함수 코드 참조

https://forum.arduino.cc/index.php?topic=417302.0

delay() 함수가 아두이노 loop() 함수의 스캔작업을 방해하는데는 delay() 함수 내부에 while 루프를 사용함으로써 발생하는 현상이다. while 루프를 사용하여 delay()함수 본연의 목적인 코드와 코드 사이의 실행 시간의 간격을 손쉽게 조정하는 것에는 좋은 방법이지만, 이로 인해 발생하는 loop() 함수의 스캔작업을 방해하는 부작용은 loop()함수 안의 전체 코드의 실행에 안좋은 영향을 미치게 된다.

1초에 1만번 실행되는 loop() 함수에 delay(1000)을 주게 되면 loop() 함수는 1초에 1번만 돌게 되는데, 이때 정작 확인해야할 코드는 만분의 1초라는 짧은 시간 동안 1번만 읽히게 되고, 그 짧은 시간에 우연히 타이밍이 맞아 입력이 확인되면 코드에 대한 출력을 하게 되지만 타이밍이 맞지 않게 되면 출력이 안되게 되어 흔히 됐다 안됐다를 반복하게 된다.

blink 예제의 코드의도에 대해 다시 한번 살펴보자.

예제에서 delay(1000); 코드를 두번 사용함으로써 loop()함수를 대략 2초에 1번 scan하도록 코딩됐다는 것을 알수 있고, 그 2초 동안에 LED를 켜고 1초뒤 LED를 끄고 다시 1초뒤 loop()함수의 scan을 종료하고 다시 처음으로 돌아가게 된다. 이는 아두이노 기본 LED가 1초 간격으로 점멸하게 만드는 것으로 작동상 어떠한 문제도 없다. 하지만 보통 코드를 작성할 때 2초마다 한번씩 loop()함수가 scan하도록 의도하지는 않았을 것이다. 단지 LED가 켜지고 꺼지는 시간을 조절해서 1초 간격으로 점멸 시키기위한 의도로 delay() 함수를 사용했을 것이지만 delay() 함수를 사용함으로써 loop()함수의 scan 횟수가 대략 2초에 1회만 실행되는 결과가 초래된 것이다. 그렇다면 1초 간격은 유지하면서 loop()함수의 scan 횟수에도 영향을 미치지 않도록 코딩하려면 어떻게 해야 할까? millis()함수를 이용하여 해결 할 수 있다.

아두이노 사이트에 있는 참조 페이지의 millis() 설명을 살펴보자

아두이노 보드가 현재 프로그램을 돌리기 시작한 후 지난 밀리 초 숫자를 반환한다. 이 숫자는 약 50 일 후에 오버플로우(0으로 돌아감)가 된다.

반환

프로그램 시작 후 지난 시간 (unsigned long)

설명을 살펴보면 아두이노에 전원이 들어가면 밀리초가 카운트 되기 시작하여 전원을 끌 때 까지 계속 증가하다가 약 50일 후 오버플로우가 일어나면 다시 0부터 증가한다는 것을 알 수 있다. 추가로 설명하자면 밀리초는 아두이노 기동과 동시에 특정 명령없이 자동 실행되고 그 값이 증가되며, millis() 함수는 단지 현재의 밀리초 값만을 확인할 때 사용한다. 이렇게 시간의 지남에 따라 계속 증가하는 밀리초 값으로 초 시계로 시간간격을 측정하듯 시작시간과 끝시간을 지정하고 끝시간에 프로그램이 실행되게 하면 특정시간에 코드의 출력이 되게 하거나 일정 시간 간격으로 반복 작업을 수행하도록 할 수 있게 된다.

글로만 설명하면 그 구도가 딱 잡히지 않는다. 아래 코드 구성을 살펴보자.

unsigned long int start_time = 0; if (millis() – start_time >= 시간간격) { // 시간 간격: 밀리초 start_time = millis(); // 상기 조건을 만족할때의 밀리초를 다시 start_time에 저장하여 조건 초기화 실행코드 }

시간간격을 1000 밀리초(1초)로 하고 loop() 함수가 0밀리초부터 작동한다고 가정하면 아래와 같이 동작하게 된다.

0밀리초 : 0 – 0 >= 1000 : 거짓

500 밀리초: 500 – 0 >= 1000 : 거짓

999 밀리초: 999 – 0 >= 1000 : 거짓

1000 밀리초: 1000 – 0 >= 1000 : 참

start_time에 현재 밀리초 1000 저장후 코드 실행

1500 밀리초: 1500 – 1000 >= 1000: 거짓

2000 밀리초: 2000 – 1000 >= 1000: 참

start_time에 현재 밀리초 2000 저장후 코드 실행

이렇게 무한 반복하게 된다.

주의할 점은 조건에 millis() – start_time = 1000와 같이 ‘=’만을 사용하게 된다면 조건을 건너뛰어 코드를 실행하지 않는 오류를 내포하게 된다. 이는 loop() 함수 안에 코드들의 양이나 코드의 특성에 따라 발생할 수 있는 것으로 코드가 많아 loop()를 도는데 1밀리초 이상되거나 for 루프나 while 루프를 완료하는 시간, Serial 통신시 데이터 수신 및 송신에 걸리는 시간등에 따라 누적된 시간의 차가 정확하게 1000밀리초가 되지 못하고 1001 밀리초가되어 조건을 건너뛰는 상황이 언젠가는 발생할 수 있다. 그러므로 그러한 상황을 방지하기 위해 ‘>’를 추가해주어야 한다.

아래 코드를 업로드해 보자.

#define LED_BUILTIN 13 unsigned long int start_time = 0; void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { if (millis() – start_time >= 1000) { start_time = millis(); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } }

loop() 함수가 0밀리초부터 작동한다고 가정하면 loop()함수에 들어오고 1000 밀리초가 됐을때 코드가 실행되어 LED를 켜고 2000 밀리초가 됐을때 LED를 끄는 것을 반복하게 된다. 1초 간격으로 계속 점멸하면서 loop() 함수는 1초에 약 1만번 돌게 될것이다. 하지만 기본 예제 blink와는 차이가 있게되는데, blink예제는 loop()함수에 들어오자마자 바로 LED를 켜고 millis()를사용하는 상기 예제는 1000밀리초가 지난뒤에 LED를 켜는 차이점이 발생하게 된다. 이점은 millis()함수를 이용하여 시간을 조정하는 방법의 특성으로서 이해를 해야할 것이다. blink예제 처럼 loop()함수시작시 바로 LED가 켜지게 하려면 아래 코드를 추가해 주어야 한다.

bool first_loop = true; // 처음 시작시 한번만 작동하는 플래그 if (first_loop == true) { digitalWrite(LED_BUILTIN, HIGH); first_loop = false; // 한번 작동후 재작동 방지위해 플래그 변경 }

#define LED_BUILTIN 13 unsigned long int start_time = 0; bool first_loop = true; void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { if (first_loop == true) { digitalWrite(LED_BUILTIN, HIGH); first_loop = false; } if (millis() – start_time >= 1000) { start_time = millis(); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } }

상기 코드를 업로드 하면 기본 blink예제 코드와 시각적으로 같음을 알 수 있다.

millis() 함수를 사용하여 시간 조정함에 있어 추가로 고려해야 할 사항이 있다.

상기 예제에서는 loop() 함수 시작과 동시에 자동으로 millis()함수가 포함된 조건문을 확인하기 시작하여 1000밀리초 후에 코드 실행이 작동하기 시작했지만, 시간이 소요되는 작동에 의해 millis()함수가 포함된 조건문이 시작 될 때에는 millis()함수의 밀리초 값이 조건시간보다 큰상태가 되어 실행코드가 바로 실행되게 된다. 이는 시간조건의 크기와 언제 해당함수가 트리거 되는지에 따라 달라지게 되어 코드 작성시 코드의 작동 상황을 고려하여 millis()함수를 이용한 시간 조정 코드를 적용해야만 된다. 이것에 관한 사항은 앞으로 다룰 비밀번호가 맞을경우 LED 상태표시를 하는 코드에서 확인해 볼 수 있다.

아두이노 millis()함수 설명에 보면 “약 50 일 후에 오버플로우(0으로 돌아감)가 된다”라고 했다. 오버 플로우가 되면 계속 증가하던 값이 0이된다. 상기 코드에서 시간 조건을 검증하기 위해 millis() – start_time >= 1000 코드를 사용했는데 millis()함수가 오버플로우 되면 0 – 이전 millis() 값 >= 1000 이 되어 -값 때문에 오류가 발생할 것처럼 보이지만 발생하지 않는다고 한다. 아래 코드를 업로드하고 실행 해보면 음수값이 나와야 할거 같은 결과같이 양수값으로 나타나는 것을 볼 수 있다. 이러한 결과가 나오는것은 millis() 함수와 start_time 변수 값의 타입이 unsigned 이기 때문에 그렇다고 한다. 아마도 bit 연산을 통해 설명해야 그 원리를 설명하고 이해할 수 있을 듯 하지만 위의 코드 형식을 적용하면 50일이 지나 millis() 함수 값에 오버플로우가 발생해도 오류가 발생하지는 않는다고만 알아두자.

void setup() { Serial.begin(9600); unsigned long a = 4294967293; unsigned long b = 4294967000; // startTime unsigned long c = 4294967294; unsigned long d = 4294967295; // unsigned long maximum value unsigned long e = 0; // overflow unsigned long f = 1; unsigned long g = 2; Serial.println(a-b); Serial.println(b-b); Serial.println(c-b); Serial.println(d-b); Serial.print(“overflow: “); Serial.println(e-b); Serial.println(f-b); Serial.println(g-b); } void loop() { }

참조 사이트

Arduino Tutorial: Avoiding the Overflow Issue When Using millis() and micros()

앞서 언급한 디지털 도어락 작동상태 표시에 대한 살펴보자.

1. 열림: 빨간색 -> 노란색 -> 파란색 LED 순으로 한번씩 점멸하고, “도 -> 레 -> 미” 열림음이 출력된다.

LED가 순차적으로 켜졌다 꺼졌다 하게 된다. 이를 millis() 함수를 통해 구현하려면 아래처럼 타이머와 카운터가 결합된 형식을 취하는게 코드를 가장 단순하게 만든다. 우선 시간 측정에 진입하는 플래그(bool timer = false;)를 하나 설정한다. 그리고 if 조건에 “timer == true”를 걸어주고 이함수를 loop() 함수내에 위치하여 scan 할 때마다 해당 조건이 항상 확인되도록 해주면 loop() 함수내에서 timer = true; 라는 코드에 의해 시간측정에 진입하는 사용자 함수 delay_timer()가 트리거되고 실행되게 된다. 그리고 delay_timer()가 실행되고 정해진 시간을 만족하면 미리 설정해 놓은 카운터을 하나씩 올린다. 이렇게 되면 카운터는 시간값을 포함하게 된다.

bool timer = false; // 사용자 함수 진입 플래그 void delay_timer() { // 250 밀리초 타이머, 타이머 종료: timer = false, time_count = 0; if (timer == true) { if (millis() – delayTime >= 250) { // time_count == 0일때는 딜레이 없이 바로진입 delayTime = millis(); time_count++; // 1부터 250 밀리초 적용 } } }

시간값을 포함하는 카운터는 그 자체를 시간으로 계산할 수 있게 된다. 위의 경우에 만약 millis()가 0부터 시작한다면 카운터가 1일경우 250 밀리초가 되게되고 1씩 증가할 때마다 250밀리초가 증가하게 되어 카운터가 4일때는 1초가 된다. 하지만 상기 함수가 작동할 때에는 millis() 함수 값이 0이 될 수가 없다(50일 이내에는). 문이 열렸을 때 작동하는 LED의 제어를 위해 만들어진 함수안에 포함되었기 때문이다. 문이 열리려면 비밀번호를 입력하고 확인하는 시간이 필요한데, 아무리 빨리 입력한다고 해도 무조건 250 밀리초 이상 걸리게 되고 이 함수가 실행되는 순간은 항상 참이되어 250밀리초 이상인 조건을 시간 소요없이 바로 만족하여 카운터를 0에서 1로 바꾸게 된다. 즉, 시작값이 0이 아니라 1이된다. 1부터는 250 밀리초의 시간마다 카운터를 1씩 증가시키게 된다. 참고로 millis() 함수 값이 0이 되는 순간은 millis()함수가 오버플로우 되는 약 50일 이후가 될 것이다.

이 카운터를 활용하여 LED를 제어하기 위해 아래와 같이 문이 열렸을 때의 플래그 doorOpen = true; 에 의해 작동하는 door_open()라는 사용자함수 코드를 작성하였다.

int arrLed[3] = {13, 12, 2}; // 빨, 노, 파

setup() 함수

for (int i = 0 ; i < 3 ; i++) { pinMode(arrLed[i], OUTPUT); digitalWrite(arrLed[i], LOW); } 사용자 함수 void door_open() { // 빨, 노, 파 순차 점멸 if (doorOpen == true) { if (time_count == 1) { // 시작 0 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); // digitalWrite(arrLed[0], HIGH); } else if (time_count == 2) { // 250 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); digitalWrite(arrLed[1], HIGH); } else if (time_count == 3) { // 250 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); digitalWrite(arrLed[2], HIGH); } else if (time_count == 4) { // 250 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); } else if (time_count == 29) { // 문이 자동으로 잠기는 시간(7초) Serial.print("door close"); doorOpen = false; // 문이 잠겼으므로 플래그 초기화 timer = false; // 상태표시 종료 - 플래그 초기화 time_count = 0; // 상태표시 종료 - 카운터 초기화 } } } LED의 작동에 따라 부저음도 도 -> 레 -> 미 음으로 울리게 되므로 아래 코드를 추가해주자.

# define beepPin 11 // tone 핀 설정

door_open() 함수

tone(beepPin, 262); tone(beepPin, 294); tone(beepPin, 330); noTone(beepPin);

키패드를 누를때도 ‘도’ 음이 울리도록 아래코드를 키패드 입력부 코드에 추가해 주자.

tone(beepPin, 262, 50);

아두이노 참조 사이트의 tone()함수 설명

핀에 특정 주파수(50% 듀티 사이클)의 구형파를 발생시킵니다. 지속 시간을 정할 수 있으며, 따로 정하지 않는다면 noTone()을 부를 때까지 구형파가 지속됩니다. 핀을 피에조 버저 또는 스피커에 연결하여 tone을 연주할 수 있습니다.

한번에 한 tone만 발생시킬 수 있습니다. 다른 핀에서 tone이 이미 연주되고 있으면, tone()을 새로 불러도 아무 일도 일어나지 않을 것입니다. 같은 핀에서 tone이 연주되고 있으면, 주파수가 새로 설정될 것입니다. tone() 함수의 사용은 (Mega 이외의 보드에서) 3번과 11번 핀에서의 PWM 출력을 방해할 것입니다. 31HZ보다 낮은 tone을 발생시키는 것은 불가능합니다. 기술적인 세부 사항은, Brett Hagman’s notes를 보십시오. 문법 tone(pin, frequency) tone(pin, frequency, duration) 매개변수 pin : tone을 발생시킬 핀 frequency : tone의 주파수 (Hz 단위) – unsigned int duration (옵션) : tone 의 지속 시간 (밀리초 단위) – unsigned long noTone(pin) // tone함수 종료

비밀번호가 확인되면 잠금장치가 열리고 닫히므로 서보모터의 작동도 추가해 주자.

#include Servo myservo; // create servo object to control a servo int pos = 0; // variable to store the servo position # define servoPin 10 # define servo_open 50 # define servo_close 150

setup() 함수

myservo.attach(servoPin); // attaches the servo on pin 10 to the servo object myservo.write(servo_close); // 기동시 잠긴상태

door_open() 함수

myservo.write(servo_open); myservo.write(servo_close);

3. 비밀번호 잘못 입력한 경우: 경고음 1회 발생, 빨간색, 노란색, 파란색 LED가 한번만 동시 점멸

아래 사용자 함수 wrong_blink() 코드를 작성해 주었다.

bool wrongBlink = false; void wrong_blink() { if (wrongBlink == true) { if (time_count == 1) { tone(beepPin, 262, 500); for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], HIGH); } if (time_count == 3) { for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); timer = false; wrongBlink = false; time_count = 0; } } } 2. 사용자 비밀번호 입력: 빨간색, 노란색, 파란색 LED가 동시 점멸하며 입력 완료시 까지 계속된다. 이 코드의 경우 시간값이 포함된 카운터를 사용하여 코드를 작성할 수 없었다. 처음에는 카운터를 이용하여 작성하였으나 표시의 특성상 1번 표시 중에 2번 표시가 동시에 발생하게 되는데, 코드 상으로는 문제가 없어 보이지만 정작 적용하게 되면 서보모터가 닫힘 상태로 가기전에는 제대로 작동하다가 닫힘 상태로 가기 시작했을 때부터 이상작동을 보인다. 아마도 타이머 간섭 문제인듯 싶지만 확인 할 수는 없었고 millis() 함수를 하나더 사용, 독립적으로 작동하도록 하여 해결하였다. bool inputBlink = false; unsigned long int input_time = 0; void input_blink() { if (inputBlink == true) { if (millis() - input_time >= 1000) { // time_count == 0일때는 딜레이 없이 바로진입 input_time = millis(); for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], !digitalRead(arrLed[i])); } } } 디지털 도어락의 작동상태를 표시하기 위해 사용자 함수를 만들어 주었다. 각 함수는 모두 loop() 함수에 위치하여 매 scan 마다 그 작동 플래그의 확인에 의해 실행 유무를 결정하게 된다. void loop() { delay_timer(); door_open(); wrong_blink(); input_blink(); } 또한 각 함수의 작동에 있어서 필수 조건으로 시간값을 포함하는 타이머가 선행 되어져야만 한다. 따라서 코드상에 각각의 상태표시의 시작과 종료의 명령은 아래 코드로 이루어 지게 된다. door_open() 시작 timer = true; doorOpen = true; door_open() 종료 doorOpen = false; // 문이 잠겼으므로 플래그 초기화 timer = false; // 상태표시 종료 - 플래그 초기화 time_count = 0; // 상태표시 종료 - 카운터 초기화 wrong_blink() 시작 timer = true; wrongBlink = true; wrong_blink() 종료 timer = false; wrongBlink = false; time_count = 0; input_blink() 시작 inputBlink = true; input_blink() 종료 inputBlink = false; 이제 마지막으로 작동개요중 아래 사항을 충족시키기 위해 EEPROM을 이용하여 비밀번호를 저장하도록 하자. 3. 배터리 교체등 전원을 껐다 켜도 입력된 사용자 비밀번호는 유지된다. 위의 코드를 업로드 하고 테스트 해보면 사용자 비밀번호를 입력하고 저장하면 사용자 비밀번호로만 검증이 되어 작동되는 것을 볼 수 있다. 하지만 아두이노를 리부팅(꺼졌다 켜질때)하게 되면 아래처럼 초기 비번이 변수 초기값으로 설정되어 있어 초기값으로 초기화 되어 리부팅 전에 저장했던 사용자 비밀번호는 더이상 사용할 수 없게 된다. char password[4] = "1234"; // 초기 비밀번호 및 사용자 비밀번호 저장 변수 이를 해결하기 위해 비밀번호 변경시 '#' 버튼을 누를 때 EEPROM에 사용자 비밀번호를 저장시키고 아두이노가 리부팅 되어 password 배열에 저장되었던 사용자 비밀번호가 초기화(1234) 되어도 setup() 함수 실행시 EEPROM에 저장된 사용자 비밀번호를 읽어 password 배열에 다시 저장 시켜 사용자 비밀번호를 계속 사용 할 수 있게 된다. EEPROM을 사용하게 되면 초기 비밀번호도 EEPROM에 저장을 해주어야한다. 그래야만 setup() 함수 실행시 EEPROM을 읽고 초기 비밀번호를 사용할 수 있게 된다. 초기 비밀번호를 저장을 해주지 않으면 EEPROM의 빈값인 { 0xFF, 0xFF, 0xFF, 0xFF } 값을 입력해야 되는데 키패드로는 입력이 불가하여 비밀번호 검증 자체가 불가능하게 된다. 이를 위해 보통 초기 비밀번호를 한번 저장하기위해 스케치를 업로드하여 EEPROM에 초기 비밀번호를 저장하고 다음에 초기 비밀번호 저장 코드를 주석처리하여 다시업로드 하는 두번의 업로드 과정을 거치게 되는데, 초기비번 플래그를 설정하고 그 플래그를 이용하여 한번만 스케치를 업로드해도 계속 사용할 수 있도록 해보자. 상기 코드에 아래 코드를 추가해 주었다. #include # define EEPROM_SIZE 5 // 사용자 비번 + 초기비번 플래그 = 5 byte if(EEPROM.read(4) != 1) { for (int i = 0; i < 4; i++) EEPROM.write(i, password[i]); // (adress(0 ~ 4096), value(0 ~ 255)) EEPROM.write(4, 1); } else { for (int i = 0; i < 4; i++) password[i] = EEPROM.read(i); } 위 코드에서 EEPROM 크기를 정할때 초기비번 플래그 저장공간을 추가해 주었다. 작동 방식은 EEPROM의 초기값이 0xFF 이므로 아두이노 초기 기동시 EEPROM.read(4) != 1 조건을 만족하게 되어 password 배열에 저장된 초기 비밀번호를 저장하고 EEPROM 초기비번 플래그 위치에 1을 저장한다. 이렇게 저장된 1때문에 다음 리부팅시 코드 실행을 막게되어 초기기동시 한번만 실행되는 코드가 되었다. 다음 리부팅시에는 setup()함수에서 EEPROM에 저장된 비밀번호값을 읽기만 하게 된다. 하지만 이렇게 되면 스케치를 새로 변경하여 다시 업로드 해도 이미 저장된 EEPROM 초기 비번 플래그 1 때문에 앞서 저장된 비밀번호를 읽기만 하게된다. setup() 함수에서 초기 비밀번호를 EEPROM에 쓰도록 하기 위해서는 EEPROM의 초기 비번 플래그를 1이 아닌 값으로 바꿔줘야 하는데, 시리얼 모니터에서 명령어 입력을 통해 초기화 하도록 해주자. if(Serial.available()) { String temp = Serial.readStringUntil(' '); if (temp == "pass1234") EEPROM.write(4, 0); } 아래 풀 코드를 업로드 하고 디지털 도어락을 작동해 보자. 사용자 비밀번호가 저장된 후에는 리부팅 되거나 스케치를 새로 업로드 해도 EEPROM의 비밀번호 값이 남아 있게 된다. EEPROM의 비밀번호를 초기 비밀번호로 초기화 하기 위해서는 시리얼 모니터에서 pass1234를 입력하고 나서 리부팅 시키면 비밀번호가 1234로 초기화 된것을 볼 수 있다. 키패드 대신 블루투스를 연결하고 안드로이드 앱으로 디지털 도어락을 제어해 보았다. arduino bluetooth controller PWM - 아두이노 원격제어 안드로이드 앱 버전 3.5 다운로드 arduino bluetooth controller PWM 매뉴얼 키패드와 블루투스 이용 도어락 제어하기 키패드와 블루투스를 동시에 이용하기 위해서는 블루투스를 하드웨어 시리얼에 연결을 하여야 한다. 하지만 하드웨어 시리얼에 블루투스를 연결해 놓으면 아두이노 IDE를 통해 스케치 파일을 업로드 할 수 없게 되는데, 이럴 경우 스케치 파일을 업로드 할 때에는 아래 그림과 같이 아두이노 시리얼 RX 핀번호 0번에 연결된 케이블을 뽑아놓은 상태에서 스케치를 업로드하고 업로드 후에 다시 연결을하면 키패드와 블루투스를 통해 제어를 할 수 있게 된다.

[아두이노] 디지털 도어락 KIT

상품결제정보 고액결제의 경우 안전을 위해 카드사에서 확인전화를 드릴 수도 있습니다. 확인과정에서 도난 카드의 사용이나 타인 명의의 주문등 정상적인 주문이 아니라고 판단될 경우 임의로 주문을 보류 또는 취소할 수 있습니다.

무통장 입금은 상품 구매 대금은 PC뱅킹, 인터넷뱅킹, 텔레뱅킹 혹은 가까운 은행에서 직접 입금하시면 됩니다.

주문시 입력한 입금자명과 실제입금자의 성명이 반드시 일치하여야 하며, 7일 이내로 입금을 하셔야 하며 입금되지 않은 주문은 자동취소 됩니다.

배송정보 배송 방법 : 택배

배송 지역 : 전국지역

배송 비용 : 3,500원

배송 기간 : 3일 ~ 7일

배송 안내 : – 산간벽지나 도서지방은 별도의 추가금액을 지불하셔야 하는 경우가 있습니다.

고객님께서 주문하신 상품은 입금 확인후 배송해 드립니다. 다만, 상품종류에 따라서 상품의 배송이 다소 지연될 수 있습니다.

교환 및 반품정보 교환 및 반품이 가능한 경우

– 상품을 공급 받으신 날로부터 7일이내 단, 가전제품의

경우 포장을 개봉하였거나 포장이 훼손되어 상품가치가 상실된 경우에는 교환/반품이 불가능합니다.

– 공급받으신 상품 및 용역의 내용이 표시.광고 내용과

다르거나 다르게 이행된 경우에는 공급받은 날로부터 3월이내, 그사실을 알게 된 날로부터 30일이내

교환 및 반품이 불가능한 경우

– 고객님의 책임 있는 사유로 상품등이 멸실 또는 훼손된 경우. 단, 상품의 내용을 확인하기 위하여

포장 등을 훼손한 경우는 제외

– 포장을 개봉하였거나 포장이 훼손되어 상품가치가 상실된 경우

(예 : 가전제품, 식품, 음반 등, 단 액정화면이 부착된 노트북, LCD모니터, 디지털 카메라 등의 불량화소에

따른 반품/교환은 제조사 기준에 따릅니다.)

– 고객님의 사용 또는 일부 소비에 의하여 상품의 가치가 현저히 감소한 경우 단, 화장품등의 경우 시용제품을

제공한 경우에 한 합니다.

– 시간의 경과에 의하여 재판매가 곤란할 정도로 상품등의 가치가 현저히 감소한 경우

– 복제가 가능한 상품등의 포장을 훼손한 경우

(자세한 내용은 고객만족센터 1:1 E-MAIL상담을 이용해 주시기 바랍니다.)

※ 고객님의 마음이 바뀌어 교환, 반품을 하실 경우 상품반송 비용은 고객님께서 부담하셔야 합니다.

(색상 교환, 사이즈 교환 등 포함)

라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!

반응형

【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!

RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 데이터를 교환하는 장치이다.

교통카드, 학생신분증 겸용카드, 연구실 및 회사 출입문카드, 구내식당 카드, 마트 등의 상품 진열 및 관리 등등 다방면에서 이용되고 있다.

지난 실습에서 아두이노와 RFID모듈을 연결하고 특정 ID카드의 ID를 등록하여 시리얼모니터를 통해 승인 또는 거부 표시를 해보았다. 이번에는 좀더 실제적으로 응용이 가능하도록 서보모터와 LED를 이용해서 도어락 기능을 구현해보려 한다. 선수학습을 잘 따라왔다면, 크게 어렵지않고 더욱 흥미가 생길 것이다.

▶ 선수 학습 :

1. [아두이노 기초#30] 서보모터 제어하기 응용 ☜ (클릭)

2. [아두이노 센서#3] TMP36 온도센서 #1 (RGB LED 부분 참조) ☜ (클릭)

3. [아두이노 모듈#11] RFID(RC522) 사용하기 #1 ☜ (클릭)

4. [아두이노 모듈#12] RFID(RC522) 사용하기 #2 ☜ (클릭)

▶ RFID 모듈 (RC522) 세부 스팩

세부스팩은 위 선수학습 내용을 참조.

▶ 실습 목표 :

1. [ RFID 구동원리, 통신 방식에 대해 이해할 수 있다. ]

2. [ SPI통신과 회로 연결에 대해 이해 할 수 있다.]

3. [ 카드별 고유넘버(UID)를 알아 낼 수 있다.]

4. [ 특정 UID를 지정하여 승인 및 거부 처리를 할 수 있다.]

5. [ ‘서보 모터’와 , ‘RGB LED’를 적용하여 RFID모듈 제어를 할 수 있다.]

▶ 실습 회로도면 :

(이미지 클릭하면 확대 가능)

RFID Rc522모듈을 활용한 도어락 회로도

▶ 실습 절차 :

1. 부품을 준비하여 위와 같은 회로를 구성한다.

2. 아두이노IDE에서 MFRC522 라이브러리를 검색후 설치한다.

( 라이브러리 설치는 위 선수학습내용 참조)

3. 첨부된 아두이노 파일을 다운 받아 코드를 실행시킨다.

4. 문으로 사용될 미이어쳐나 모형 등을 준비한다. (RGB LED가 없으면 일반 LED를 사용)

5. 동작확인이 되면(실제 도어 등에 적용할 방법에 대해 고민해본다, 릴레이 사용 등등)

▶ 프로그램 코드 및 설명 :

/* RFID 도어락 만들어 보기 */

#include

#include

#define SS_PIN 10 // spi 통신을 위한 SS(chip select)핀 설정

#define RST_PIN 9 // 리셋 핀 설정

MFRC522 rfid(SS_PIN, RST_PIN); // ‘rfid’ 이름으로 클래스 객체 선언

#include // 서보 라이브러리를 지정

#define servoPin 8 // 서보 모터핀을 지정

Servo servo; // 서보 라이브러리 변수를 선언

int pos=0; // 현재 각도를 저장할 변수를 지정한다

int RLED=7; // 빨간색 LED단자를 아두이노 7번과 연결

int GLED=6; // 초록색 LED단자를 아두이노 6번과 연결

void setup ( ) {

pinMode(RLED, OUTPUT); // RED LED를 출력으로 지정

pinMode(GLED, OUTPUT); // GREEN LED를 출력으로 지정

servo.attach(servoPin); // 서보모터 핀을 설정한다

servo.write(0); // 서보모터 0도 위치로 초기화

Serial.begin(9600);

SPI.begin(); // SPI 통신 시작

rfid.PCD_Init(); // RFID(MFRC522) 초기화

Serial.println(“Approximate your card to the reader…”);

Serial.println();

}

void loop ( ) {

// 새카드 접촉이 있을 때만 다음 단계로 넘어감

if ( ! rfid.PICC_IsNewCardPresent())

{

return;

}

// 카드 읽힘이 제대로 되면 다음으로 넘어감

if ( ! rfid.PICC_ReadCardSerial())

{

return;

}

// 현재 접촉 되는 카드 타입을 읽어와 모니터에 표시함

Serial.print(“UID tag :”);

String content= “”;

byte letter;

for (byte i = 0; i < rfid.uid.size; i++) { Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " "); Serial.print(rfid.uid.uidByte[i], HEX); content.concat(String(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ")); content.concat(String(rfid.uid.uidByte[i], HEX)); } Serial.println(); Serial.print("Message : "); content.toUpperCase(); // UID값이 아래 값과 같으면 승인 처리 if (content.substring(1) == "85 7C FB D1") // 승인 하고자하는 UID 기록 { // 인증이 되면 Green LED와 함께 서보모터를 작동시킨다. Serial.println("Authorized access"); Serial.println(); digitalWrite(GLED,HIGH); servo.write(180); // 서보모터의 각도를 변경한다 delay(3000); // 서보 모터의 각도가 변하는 것을 기다려 준다 servo.write(0); // 시간지연 후 문을 닫는다 digitalWrite(GLED,LOW); // 시간지연 후 LED 끈다 } // 승인 목록에 없는 UID 처리는 // 서보모터의 작동 없이 Red LED만 켜고 끈다 else { Serial.println(" Access denied"); digitalWrite(RLED,HIGH); delay(3000); digitalWrite(RLED,LOW); } } ▶ 실행영상 : (전체화면 보기로 보세요) RFID 도어락 만들어 보기 (아래는 유튜브로 시청하기) https://youtu.be/6nBu0obCx5Q ▶ 아두이노 파일다운 : (다운받아서 압축을 풀어 사용하세요) ko_arduino_code_Servo_LED.zip 0.00MB ▶ 컴파일 에러 발생시 해결 방법 참고 : 아래 최신글을 참고해 보세요. rasino.tistory.com/321 반응형

Top 36 아두 이노 도어락 9803 Votes This Answer

【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!

【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!

아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 :: postpop

Article author: postpop.tistory.com

Reviews from users: 19630 Ratings

Ratings Top rated: 4.8

Lowest rated: 1

Summary of article content: Articles about 아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 :: postpop 아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다. …

Most searched keywords: Whether you are looking for 아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 :: postpop 아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다. 아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다. 디지털 도어락 코드는 delay()함수의 문제점을 이해하는데 좋은 예제라..홍성호

Table of Contents:

아두이노 – 디지털 도어락 예제 delay() 함수 대체 방법

티스토리툴바

아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 :: postpop

Read More

‘아두이노 도어락’ 태그의 글 목록

Article author: m.blog.daum.net

Reviews from users: 42312 Ratings

Ratings Top rated: 4.1

Lowest rated: 1

Summary of article content: Articles about ‘아두이노 도어락’ 태그의 글 목록 Arduino Uno 로 MFRC-522 RC522 RFID 모듈과 서보모터를 사용해 도어락 만들어 보기 … 근접 키체인 모듈을 가져다 댔을때 아두이노 IDE의 시리얼 모니터로 IC카드 … …

Most searched keywords: Whether you are looking for ‘아두이노 도어락’ 태그의 글 목록 Arduino Uno 로 MFRC-522 RC522 RFID 모듈과 서보모터를 사용해 도어락 만들어 보기 … 근접 키체인 모듈을 가져다 댔을때 아두이노 IDE의 시리얼 모니터로 IC카드 … 전자부품,전자키트,산업공구 전문 오마이엔지니어 http://www.ohmye.co.kr 아두이노 관련 자료,강좌,리뷰는 주기적으로 계속 업데이트 됩니다~^^b

Table of Contents:

공지사항

최근글

인기글

최근댓글

태그

전체 방문자

티스토리툴바

‘아두이노 도어락’ 태그의 글 목록

Read More

라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!

Article author: rasino.tistory.com

Reviews from users: 31678 Ratings

Ratings Top rated: 3.2

Lowest rated: 1

Summary of article content: Articles about 라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 … …

Most searched keywords: Whether you are looking for 라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 … 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 데이터를 교환하는 장치이다. 교통카드, 학생신분증 겸용카..

Table of Contents:

【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!

티스토리툴바

라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!

Read More

아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트 – 인터파크

Article author: m.shop.interpark.com

Reviews from users: 36612 Ratings

Ratings Top rated: 3.1

Lowest rated: 1

Summary of article content: Articles about 아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트 – 인터파크 3%할인, 추가 회원 중복 할인 쿠폰, 기타에 대한 상품입니다. …

Most searched keywords: Whether you are looking for 아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트 – 인터파크 3%할인, 추가 회원 중복 할인 쿠폰, 기타에 대한 상품입니다. PC부품/주변기기, PC부품, 메인보드, 기타, 아두이노, MFRC-RC522, RFID, 키트/Arduino, 도어락, 키트0%할인, 추가 회원 중복 할인 쿠폰, 기타에 대한 상품입니다.

Table of Contents:

구매하기

포토 건

포토 건

이 상품을 본 고객이 같이 본 상품

코디하기 좋은 상품

추천 딜

오마이엔지니어 스토어를 찜하면할인쿠폰을 드립니다

할인쿠폰이 발급되었습니다

추천순

청구할인 적용 방법

선택1 001_화이트

할인쿠폰변경

쿠폰받기

아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트 – 인터파크

Read More

아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 3.0

Article author: twinw.tistory.com

Reviews from users: 13814 Ratings

Ratings Top rated: 4.1

Lowest rated: 1

Summary of article content: Articles about 아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 3.0 Ver 1.0은 아래 그림과 아두이노로 릴레이에 연결된 도어락 모듈을 제어하는 단순한 방식이다. Ver 1.0 의 NFC 도어락은 … …

Most searched keywords: Whether you are looking for 아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 3.0 Ver 1.0은 아래 그림과 아두이노로 릴레이에 연결된 도어락 모듈을 제어하는 단순한 방식이다. Ver 1.0 의 NFC 도어락은 … 0. 목차 1. Ver 1.0 & Ver 2.0 : http://twinw.tistory.com/136 2. Ver 3.0 : http://twinw.tistory.com/168(현재 페이지) 3. Ver 4.0 : http://twinw.tistory.com/170 1. 개요(이전 버전) Ver 1.0은 아래..

Table of Contents:

아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 3.0

Read More

See more articles in the same category here: https://toplist.avitour.vn/blog/.

아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법

아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다. 디지털 도어락 코드는 delay()함수의 문제점을 이해하는데 좋은 예제라 생각한다. 앞으로 구현할 디지털 도어락의 작동 개요 및 구성요소를 살펴보자. 작동개요(실생활에 사용하는 디지털 도어락의 작동 상태) 1. 초기 비밀번호가 설정되어 있다. 2. 사용자 비밀번호를 입력하여 저장할 수 있다. 3. 밧데리 교체등 전원을 껐다 켜도 입력된 사용자 비밀번호는 유지된다. 4. 비밀 번호가 맞게 입력될 경우 문이 열리는 작동과 그 작동을 작동음과 램프로 표시 한다. 5. 비밀 번호가 틀리게 입력될 경우 사용자 인지를 위해 경고음과 램프로 표시한다. 6. 입력이 잘못될 경우 입력을 지우고 처음부터 입력할 수 있다. 7. 사용자 비밀번호 변경중 변경작업을 종료할 수 있다. 8. 상기의 작업을 키패드를 통해 제어할 수 있다. 비밀번호 변경방법 1. 초기 비밀번호 또는 사용자 비밀번호를 입력하여 열림상태로 한다. 2. 열림 상태에서 #버튼을 2초간 누른다. (비밀번호 설정 코드로 진입된다) 3. 사용자 비밀번호를 입력하고 #버튼을 눌러 저장한다. 4. 입력이 잘못된 경우 *를 누르면 입력된 값이 지워진다. 5. 사용자 비밀번호 입력을 취소할 경우 *를 2초간 누른다.(비밀번호 설정 코드를 빠져나간다) 작동상태 표시 1. 열림: 빨간색 -> 노란색 -> 파란색 LED 순으로 한번씩 점멸하고, “도 -> 레 -> 미” 열림음이 출력된다. 2. 사용자 비밀번호 입력: 빨간색, 노란색, 파란색 LED가 동시 점멸하며 입력 완료시 까지 계속된다. . 3. 비밀번호 잘못 입력한 경우: 경고음 1회 발생, 빨간색, 노란색, 파란색 LED가 한번만 동시 점멸 위의 기능을 수행하기 위해서는 피에조부저와 LED(빨, 노, 파) 3개, 키패드, 서버모터 가 필요하고 LED용 저항은 필요에 따라 적용하면 된다. 디지털 도어락 구성 및 결선 키패드 R4 – > 아두이노 3번핀 키패드 R3 – > 아두이노 4번핀 키패드 R2 – > 아두이노 5번핀 키패드 R1 – > 아두이노 6번핀 키패드 C1 – > 아두이노 7번핀 키패드 C2 – > 아두이노 8번핀 키패드 C3 – > 아두이노 9번핀 // 키패드 C4 핀은 사용하지 않는다. 서보모터 제어선(노란색) -> 아두이노 10번핀 수동형 피에조 부저 ‘+’ -> 아두이노 11번핀 (수동형 피에조 부저는 밑면에 기판이 보인다) 파란색 LED -> 아두이노 2번핀 노란색 LED -> 아두이노 12번핀 빨간색 LED -> 아두이노 13번핀 아두이노에서 키패드를 쉽게 사용하기 위해 keypad.h라이브러리를 이용하기로 하자 https://github.com/Chris–A/Keypad 첨부된 Keypad.zip 파일을 다운로드 받은뒤 압축을 해제하고 keypad 폴더를 아래의 아두이노 라이브러리 폴더에 저장 시킨다. 아두이노 IDE가 실행되어 있다면 종료시키고 다시 실행하여 라이브러리가 등록되도록 한다. 새로 아두이노 IDE를 실행시키고 예제 -> 모든 보드의 예제 항목 Keypad -> EventKeypad를 불러온다. 아래 코드는 예제 EventKeypad를 단순화 시켜놓은 것이며, 2초동안 누르는 키동작을 위해 키 홀드 시간 설정 옵션을 추가하였다. keypad.setHoldTime(2000); 참조사이트 https://playground.arduino.cc/Code/Keypad/#Functions #include const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, // { S1, S2, S3} {‘4′,’5′,’6’}, // { S5, S6, S7} {‘7′,’8′,’9’}, // { S9, S10, S11} {‘*’,’0′,’#’} // { S13, S14, S15} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // {R4, R3, R2, R1} byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); void setup(){ Serial.begin(9600); keypad.addEventListener(keypadEvent); // Add an event listener for this keypad keypad.setHoldTime(2000); // 키 홀드 시간 설정 – 2000 = 2초 } void loop(){ char key = keypad.getKey(); if (key) { Serial.println(key); } } // Taking care of some special events. void keypadEvent(KeypadEvent key){ switch (keypad.getState()){ case PRESSED: if (key == ‘#’) Serial.println(“PRESSED”); break; case RELEASED: if (key == ‘*’) Serial.println(“RELEASED”); break; case HOLD: if (key == ‘*’) Serial.println(“HOLD”); break; } } 키패드를 아두이노에 연결할 때 C4핀을 연결하지 않았다. C4핀을 연결하지 않게되면 아래의 빨간표시 부분의 키들은 입력이 되지 않게 된다. 코드에서 핀배치 배열(colPins[COLS])의 C4에 해당하는 자리가 비어 있음을 볼 수 있다. byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} 상기 코드를 업로드하고 버튼을 차례대로 왼쪽에서 오른쪽으로 또 아래로 내려가면서 눌러보자 키패드 C4핀에 해당하는 부분은 입력이 안되며 *를 누르면 *가 출력되고 버튼을 떼는 순간 RELEASED가 출력되는 것을 볼수 있다. 또한 # 누르는 순간 PRESSED가 먼저 출력되고 바로 다음에 #이 출력되게 된다. *를 계속 누르고 있으면 * HOLD 가 차례로 나오고 뗄때 RELEASED가 출력되는 것을 볼 수 있다. keypadEvent() 코드중 case HOLD: 를 사용할 것이다. 키패드를 통해 숫자를 입력 받을 수 있게 되었다. 이제 입력된 숫자를 저장하고 비교하는 코드를 작성해 보자 위에서 살펴본 디지털 도어락 비밀번호 변경방법 절차중 2번과 5번을 구현하기 위해 keypadEvent() 함수를 살펴보자. 2. 열림 상태에서 #버튼을 2초간 누른다. (비밀번호 설정 코드로 진입된다) 5. 사용자 비밀번호 입력을 취소할 경우 *를 2초간 누른다.(비밀번호 설정 코드를 빠져나간다) 2번은 비밀번호 검증이 완료되어 문이 열린 상태(서보모터 열림 위치)에서만 #버튼이 작동되어야 하고 5번은 비밀번호 변경중 설정시간이 초과되어 문이 자동으로 닫혀질 수 있으므로 문이 닫힌 상태(서보모터 닫힘 위치)에서도 작동되어야 한다. 우선, 문이 열리고 닫히는 상태를 표시하기 위해 플래그 doorOpen를 선언하고 초기값은 false로 하자. bool doorOpen = false; 2초간 눌렸다는 것을 표시하기 위해 플래그 longPress를 선언하고 초기값은 false로 하자. #버튼을 2초간 누르면 longPress = true; 가 되어 비밀번호 설정 코드로 들어가고, *를 2초간 누르면 longPress = false;로 하여 #버튼을 2초간 누른 효과를 무효화 시켜 비밀번호 설정 코드를 빠져 나오게 된다. bool longPress = false; 위 상황에 따라 아래와 같이 코드를 변경해 주었다. void keypadEvent(KeypadEvent key){ // 키패드 이벤트 함수 switch (keypad.getState()){ case HOLD: switch (key){ case ‘*’: longPress = false; // 비밀번호 변경코드 빠져나감 key = ‘\0’; // 입력된 ‘*’ 삭제 – 오류방지 codeIndex = 0; break; } break; // HOLD 종료 } if(doorOpen == true) { // 문 열린 상태에서만 키패드 이벤트 진입 switch (keypad.getState()){ case HOLD: switch (key){ case ‘#’: longPress = true; // 비밀번호 변경코드 진입 key = ‘\0’; // 입력된 ‘#’ 삭제 – 오류방지 codeIndex = 0; break; } break; // HOLD 종료 } } } 비밀번호는 4자리 숫자이다. 이를 위해 아래와 같이 관련 변수를 설정해 주자. char temp[4] = { 0, }; // 비밀번호 설정시 임시 저장 배열 char password[4] = “1234”; // 초기 비밀번호 및 사용자 비밀번호 저장 배열 char inputCode[4] = “0000”; // 검증을 위한 사용자 입력 비밀번호 저장 배열 uint8_t codeIndex = 0; // 비밀번호 배열 index 지정 변수 (uint8_t: 부호없는 8bit 0 ~ 255 까지의 숫자) 디지털 도어락의 작동 상황을 두가지 상황을 기준으로 구분할 수가 있는데, 하나는 4자리 비밀번호를 입력받고 검증 후 문을 열고 닫는것이고 다른 하나는 4자리 사용자 비밀번호를 입력받고 저장하여 비밀번호를 변경하는 것이다. 이는 위에서 설정한 longPress 플래그 변수값에 의해 구분 되어 질 수 있다. if (longPress) { 비밀번호 변경 상황 } else { 비밀번호 검증 후 문을 열고 닫는 상황 } 비밀번호 변경 상황 if (key) { // 키패드 키가 눌려져 key 변수에 값이 있으면 if (key != ‘*’ && key != ‘#’ && codeIndex < 4) { temp[codeIndex] = key; codeIndex++; } // 만약 키값이 숫자이면, temp 배열에 인덱스 0 ~ 3까지 순서대로 저장(4자리 이상 입력은 무시) else if(key == '#') { // 만약 키값이 숫자가 아니고 #이면 for (int i = 0; i < 4; i++) password[i] = temp[i]; // temp 배열의 값을 password 배열에 저장 longPress = false; // 비밀번호 변경 코드 빠져나간다. key = '\0'; // 변수 key값 비우기, 입력된 '#' 삭제 - 오류방지 codeIndex = 0; // 비밀번호 확인 완료됐으므로 인덱스 번호 초기화 } else if (key == '*') { // 만약 키값이 숫자가 아니고 *이면 for (int i = 0; i < 4; i++) temp[i] = '0'; // temp 배열값 모두 0으로 초기화 key = '\0'; // 변수 key값 비우기, 입력된 '*' 삭제 - 오류방지 codeIndex = 0; // 처음부터 입력 받기 위해 인덱스 번호 초기화 } 비밀번호 검증 후 문을 열고 닫는 상황 if (key) { // 키패드 키가 눌려져 key 변수에 값이 있으면 if (key != '*' && key != '#' && doorOpen != true) { // 만약 키값이 숫자이면, 검증이 완료되고 열린상황에서는 입력 무시 inputCode[codeIndex] = key; // 키값을 비교배열 inputCode의 codeIndex 번호에 저장 codeIndex++; // 인덱스 번호 증가 if (codeIndex == 4) { // 비교배열 인덱스 3까지(4번째 숫자) 저장후 번호 증가하여 4가 되면 if (strncmp(password, inputCode, 4) == 0) { Serial.print("door open"); doorOpen = true; codeIndex = 0; } // 비밀번호 검증 후 참이면, 시리얼 모니터에 door open 출력, doorOpen 플래그 true로 변경, 인덱스 번호 초기화 **strcmp(문자열1, 문자열2); // 비교할 문자열을 넣어주면 결과를 정수로 반환 - 대소문자 구분 정수값 -1: ASCII 코드값 기준으로 문자열2가 클 때 // 문자열1 = "aab" < 문자열2 = "aac" // a = 97 b = 98 c = 99 정수값 0: ASCII 코드값 기준으로 두 문자열이 같을 때 // 문자열1 = "aaa" = 문자열2 = "aaa" 정수값 1: ASCII 코드값 기준으로 문자열1이 클 때 // 문자열1 = "aab" > 문자열2 = “aaa” else { Serial.print(“wrong_number”); codeIndex = 0; } // 검증후 일치하지 않으면, 시리얼 모니터에 wrong number 출력, 처음부터 입력 받기 위해 인덱스 번호 초기화 for (int i = 0; i < 4; i++) inputCode[i] = '0'; // 비교배열값도 초기화 else if (key == '*') { // 입력값 초기화, 아무때나 눌려도 상관없다. Serial.println("CLEAR"); for (int i = 0; i < 4; i++) inputCode[i] = '0'; // 비교배열값 초기화 key = '\0'; // 입력된 '*' 삭제 - 오류방지 codeIndex = 0; // 처음부터 입력 받기 위해 인덱스 번호 초기화 } 사용자 비밀번호 저장 코드와 비밀번호 검증을 통해 문을 열고 닫는 코드를 살펴보았다. 아래 코드를 아두이노에 업로드 하고 4자리 숫자를 입력하고 시리얼 모니터를 통해 작동 상황을 확인해 보자. #include const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, // { S1, S2, S3} {‘4′,’5′,’6’}, // { S5, S6, S7} {‘7′,’8′,’9’}, // { S9, S10, S11} {‘*’,’0′,’#’} // { S13, S14, S15} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // {R4, R3, R2, R1} byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // 키패드 오브젝트 생성 bool longPress = false; // 키패드 이벤트용 및 계속점멸 longPress 플래그 bool doorOpen = false; char temp[4] = { 0, }; // 비밀번호 설정시 임시 저장변수 char password[4] = “1234”; // 초기 비밀번호 및 사용자 비밀번호 저장 변수 char inputCode[4] = “0000”; // 검증을 위한 사용자 입력 비밀번호 저장 배열 uint8_t codeIndex = 0; // 비밀번호 문자열 배열 index void setup(){ Serial.begin(9600); keypad.addEventListener(keypadEvent); // 키패드 이밴트 관리자 설정 keypad.setHoldTime(2000); // 키 홀드 시간 설정 – 2000 = 2초 } void loop(){ char key = keypad.getKey(); if (longPress) { // password 설정 if (key) { if (key != ‘*’ && key != ‘#’ && codeIndex < 4) { // 숫자이면, 4자리 이상 무시 Serial.print("pass set key: "); Serial.println(key); temp[codeIndex] = key; codeIndex++; } else if(key == '#') { // password 저장 for (int i = 0; i < 4; i++) password[i] = temp[i]; longPress = false; key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; doorOpen = false; // 자동으로 잠기는 문 표시 Serial.println("set new password"); } else if (key == '*') { // 입력값 초기화 for (int i = 0; i < 4; i++) temp[i] = '0'; key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; Serial.println("CLEAR"); } } } else { if (key) { if (key != '*' && key != '#' && doorOpen == false) { // 숫자만 입력 Serial.print("key: "); Serial.println(key); inputCode[codeIndex] = key; codeIndex++; if (codeIndex == 4) { if (strncmp(password, inputCode, 4) == 0){ Serial.println("door open"); doorOpen = true; codeIndex = 0; } else { Serial.println("wrong number"); codeIndex = 0; } for (int i = 0; i < 4; i++) inputCode[i] = '0'; } } else if (key == '*') { // 입력값 초기화 Serial.println("CLEAR"); for (int i = 0; i < 4; i++) inputCode[i] = '0'; key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; } } } } void keypadEvent(KeypadEvent key){ // 키패드 이벤트 함수 switch (keypad.getState()){ case HOLD: switch (key){ case '*': longPress = false; // 비밀번호 변경코드 빠져나감 key = '\0'; // 입력된 '*' 삭제 - 오류방지 codeIndex = 0; Serial.println("set pass out"); break; } break; // HOLD 종료 } if(doorOpen == true) { // 문 열린 상태에서 키패드 이벤트 진입 switch (keypad.getState()){ case HOLD: switch (key){ case '#': longPress = true; // 비밀번호 변경코드 진입 key = '\0'; // 입력된 '#' 삭제 - 오류방지 codeIndex = 0; Serial.println("set pass in"); break; } break; // HOLD 종료 } } } 상기 코드에는 문이 열린 후 몇초 뒤 자동으로 잠기는 상황이 반영되어 있지 않다. 그러므로 문이 열려 doorOpen = true; 가 계속 유지되고 false로 바뀌지 않게 된다. 문제는 doorOpen == false 일때만 숫자가 입력되게 코드 되어 있기때문에 키패드를 통한 숫자 입력이 더이상 되지 않게 되어 추가 확인을 할 수가 없다. 비밀번호 변경 확인을 위해 비밀번호 변경 저장 #버튼을 눌렀을 때 doorOpen = false;로 변경하는 코드를 추가해 주었다. 키패드로 1234 입력하고 #버튼을 2초간 누른뒤 1111을 입력하고 #버튼을 눌러 비밀번호를 변경하고 다시 변경된 비밀번호 1111을 입력하면 아래와 같이 시리얼 모니터에 출력되는 것을 볼수 있다. 상기 코드 door open 상황에서는 *버튼과 #버튼만을 입력할 수 있다. 도어락의 핵심 기능인 키패드를 통해 입력된 4자리 비밀번호를 검증하고 결과를 출력하는 코드는 완성되었다. 이제 사용자 입력에 따라 반응하는 LED와 피에조부저의 작동상태 표시에 관해 살펴보자. LED를 켜고 끄는 작동을 반복하거나 외부 입력없이 내부적으로 제어하기 위해서는 보통 delay()함수를 사용하게 된다. 아두이노 기본 예제인 blink예제를 살펴보자. #define LED_BUILTIN 13 void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } 상기 코드를 업로드 하면 1초 간격으로 아두이노 기본 LED가 점멸하는 것을 볼 수있다. 이 코드와 위에서 살펴보았던 EventKeypad_modify.ino 코드와 합쳐보자. #include const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {‘1′,’2′,’3’}, // { S1, S2, S3} {‘4′,’5′,’6’}, // { S5, S6, S7} {‘7′,’8′,’9’}, // { S9, S10, S11} {‘*’,’0′,’#’} // { S13, S14, S15} }; byte rowPins[ROWS] = {6, 5, 4, 3}; // {R4, R3, R2, R1} byte colPins[COLS] = {7, 8, 9}; // {C1, C2, C3, C4} Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); #define LED_BUILTIN 13 void setup(){ Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); keypad.addEventListener(keypadEvent); // Add an event listener for this keypad keypad.setHoldTime(2000); // 키 홀드 시간 설정 – 2000 = 2초 } void loop(){ char key = keypad.getKey(); if (key) { Serial.println(key); } digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); } // Taking care of some special events. void keypadEvent(KeypadEvent key){ switch (keypad.getState()){ case PRESSED: if (key == ‘#’) Serial.println(“PRESSED”); break; case RELEASED: if (key == ‘*’) Serial.println(“RELEASED”); break; case HOLD: if (key == ‘*’) Serial.println(“HOLD”); break; } } 상기 코드를 업로드 하고 키패드의 버튼을 클릭해보면 시리얼 모니터에 출력이 안된다. 이때 키패드의 버튼을 빠르게 연타 하거나 또는 계속 누르고 있으면 그때야 비로소 숫자가 입력되고 시리얼 모니터에 출력 되는걸 확인 할 수 있다. 이는 keypad.h라이브러리 문제나 blink예제 코드의 문제는 아니다. 단지 delay()함수의 특성 때문에 발생하는 현상이며 정상적인 반응이다. 아두이노의 작동 방식은 처음 전원이 들어가면 스케치상 위에서 아래로 왼쪽에서 오른쪽으로 코드를 읽어나간다. 또한 전역변수나 기타 메크로등을 순서대로 읽고 그 다음 setup() 함수 그리고 loop()함수로 들어가서 무한 반복하도록 되어 있다. 무한 반복하는 loop()함수에서도 위에서 아래로 왼쪽에서 오른쪽으로 코드를 읽어 나가고, 코드의 명령에 따라 어떤 실행을 하게 된다. 이렇게 loop() 함수안의 전체 코드를 한번 읽는 동작을 “scan한다”라고 얘기를 한다. 그렇다면 아두이노 loop() 함수는 1초에 몇번 scan을 할까? 입력된 코드의 양과 특성에 따라 달라지게 되고 또한 MCU의 속도에 따라 달라지게 되어 정확하게는 측정하기는 어렵지만 아두이노 참조사이트를 통해 유추해 볼 수는 있다. 아두이노 사이트에 있는 참조 페이지의 analogRead() 설명을 살펴보자 지정한 아날로그 핀에서 값을 읽습니다. 아두이노 보드는 6채널(미니와 나노는 8채널, 메가는 16채널), 10비트의 아날로그-디지털 변환기를 가지고 있습니다. 이는, 0에서 5V 사이의 입력 전압을 0에서 1024 사이의 정수 값으로 대응시키는 것을 뜻합니다. 이는 해상도가 5V/1024 혹은 0.0049V (0.49mV) 단위라는 것을 뜻합니다. 입력 범위와 해상도는 analogReference() 를 사용해서 바꿀 수 있습니다. 아날로그 입력을 읽는 데는 약 100마이크로초(0.0001초)가 걸리므로, 최대 읽기 속도는 1초에 약 1만 번입니다. 위의 얘기는 아두이노 loop()함수에 analogRead()함수만 코딩되어 있을경우 1초에 1만번 읽는다는 얘기일 것이고, 그 얘기는 1초에 1만번 loop()함수가 실행되면서 scan하게 된다는 얘기이다. 따라서 아두이노 loop()함수는 보통 1초에 1만번 정도 스캔한다고 유추를 해도 큰 무리는 없을 것이다. delay() 함수가 없는 EventKeypad_modify.ino 스케치에서는 loop()함수가 돌면서 아래 코드에 따라 key 변수에 값이 있어 조건을 만족하는지 안하는지를 1만번 정도 확인하고 그중에 조건을 만족하는 순간 시리얼 모니터에 출력하게 된다. char key = keypad.getKey(); if (key) { 시리얼 모니터 출력 } 하지만 상기의 코드 처럼 delay() 함수가 포함 되게 되면 상기의 1초에 1만번 정도 실행되는 scan 작업을 방해하게 된다. delay() 함수는 내부적으로 while 루프를 사용하여 시간의 delay를 만들게 되는데, while 루프는 어떤 조건이 만족되면 무한 루프하는 코드이다. 아두이노 loop() 함수 안에 delay()함수가 있게 되면 아두이노 loop()함수 안에 또다른 루프가 생성되는 것이고, 그 루프의 조건이 계속 만족된다면 아두이노 loop()는 한바퀴 조차 돌지 못하게 된다. 한바퀴조차 돌지 못한다는 것은 아두이노에 전원은 들어가 작동은 하지만 입력에 대한 반응을 전혀하지 않는 상태인 흔히 “먹통이 되었다”라고 하는 상태가 되게 된다. 물론 delay() 함수가 이런 상황을 유발하는 것은 아니다. 언젠가는 조건이 만족하지 않아 빠져나오도록 코딩되어 있다. 아래 delay() 함수 코드를 살펴보면 delay(조건), 조건(ms > 0)을 만족하면 while 루프가 작동을 하고 ms =0이 되면 빠져나가게 되어 있는것을 볼 수 있다. void delay(unsigned long ms) { // ms: 밀리초 uint32_t start = micros(); // 시작 비교시간 저장 : 마이크로초 while (ms > 0) { // 조건(밀리초)이 0이 아니면 yield(); while (ms > 0 && (micros() – start) >= 1000) { // 밀리초가 0이 아닌 상태에서 1밀리초가 경과되면 ms–; // 조건 밀리초에서 1밀리초를 뺀다 start += 1000; // 다시 1밀리초를 측정하기 위해 기준값에 1밀리초를 더해준다. } } } delay() 함수 코드 참조 https://forum.arduino.cc/index.php?topic=417302.0 delay() 함수가 아두이노 loop() 함수의 스캔작업을 방해하는데는 delay() 함수 내부에 while 루프를 사용함으로써 발생하는 현상이다. while 루프를 사용하여 delay()함수 본연의 목적인 코드와 코드 사이의 실행 시간의 간격을 손쉽게 조정하는 것에는 좋은 방법이지만, 이로 인해 발생하는 loop() 함수의 스캔작업을 방해하는 부작용은 loop()함수 안의 전체 코드의 실행에 안좋은 영향을 미치게 된다. 1초에 1만번 실행되는 loop() 함수에 delay(1000)을 주게 되면 loop() 함수는 1초에 1번만 돌게 되는데, 이때 정작 확인해야할 코드는 만분의 1초라는 짧은 시간 동안 1번만 읽히게 되고, 그 짧은 시간에 우연히 타이밍이 맞아 입력이 확인되면 코드에 대한 출력을 하게 되지만 타이밍이 맞지 않게 되면 출력이 안되게 되어 흔히 됐다 안됐다를 반복하게 된다. blink 예제의 코드의도에 대해 다시 한번 살펴보자. 예제에서 delay(1000); 코드를 두번 사용함으로써 loop()함수를 대략 2초에 1번 scan하도록 코딩됐다는 것을 알수 있고, 그 2초 동안에 LED를 켜고 1초뒤 LED를 끄고 다시 1초뒤 loop()함수의 scan을 종료하고 다시 처음으로 돌아가게 된다. 이는 아두이노 기본 LED가 1초 간격으로 점멸하게 만드는 것으로 작동상 어떠한 문제도 없다. 하지만 보통 코드를 작성할 때 2초마다 한번씩 loop()함수가 scan하도록 의도하지는 않았을 것이다. 단지 LED가 켜지고 꺼지는 시간을 조절해서 1초 간격으로 점멸 시키기위한 의도로 delay() 함수를 사용했을 것이지만 delay() 함수를 사용함으로써 loop()함수의 scan 횟수가 대략 2초에 1회만 실행되는 결과가 초래된 것이다. 그렇다면 1초 간격은 유지하면서 loop()함수의 scan 횟수에도 영향을 미치지 않도록 코딩하려면 어떻게 해야 할까? millis()함수를 이용하여 해결 할 수 있다. 아두이노 사이트에 있는 참조 페이지의 millis() 설명을 살펴보자 아두이노 보드가 현재 프로그램을 돌리기 시작한 후 지난 밀리 초 숫자를 반환한다. 이 숫자는 약 50 일 후에 오버플로우(0으로 돌아감)가 된다. 반환 프로그램 시작 후 지난 시간 (unsigned long) 설명을 살펴보면 아두이노에 전원이 들어가면 밀리초가 카운트 되기 시작하여 전원을 끌 때 까지 계속 증가하다가 약 50일 후 오버플로우가 일어나면 다시 0부터 증가한다는 것을 알 수 있다. 추가로 설명하자면 밀리초는 아두이노 기동과 동시에 특정 명령없이 자동 실행되고 그 값이 증가되며, millis() 함수는 단지 현재의 밀리초 값만을 확인할 때 사용한다. 이렇게 시간의 지남에 따라 계속 증가하는 밀리초 값으로 초 시계로 시간간격을 측정하듯 시작시간과 끝시간을 지정하고 끝시간에 프로그램이 실행되게 하면 특정시간에 코드의 출력이 되게 하거나 일정 시간 간격으로 반복 작업을 수행하도록 할 수 있게 된다. 글로만 설명하면 그 구도가 딱 잡히지 않는다. 아래 코드 구성을 살펴보자. unsigned long int start_time = 0; if (millis() – start_time >= 시간간격) { // 시간 간격: 밀리초 start_time = millis(); // 상기 조건을 만족할때의 밀리초를 다시 start_time에 저장하여 조건 초기화 실행코드 } 시간간격을 1000 밀리초(1초)로 하고 loop() 함수가 0밀리초부터 작동한다고 가정하면 아래와 같이 동작하게 된다. 0밀리초 : 0 – 0 >= 1000 : 거짓 500 밀리초: 500 – 0 >= 1000 : 거짓 999 밀리초: 999 – 0 >= 1000 : 거짓 1000 밀리초: 1000 – 0 >= 1000 : 참 start_time에 현재 밀리초 1000 저장후 코드 실행 1500 밀리초: 1500 – 1000 >= 1000: 거짓 2000 밀리초: 2000 – 1000 >= 1000: 참 start_time에 현재 밀리초 2000 저장후 코드 실행 이렇게 무한 반복하게 된다. 주의할 점은 조건에 millis() – start_time = 1000와 같이 ‘=’만을 사용하게 된다면 조건을 건너뛰어 코드를 실행하지 않는 오류를 내포하게 된다. 이는 loop() 함수 안에 코드들의 양이나 코드의 특성에 따라 발생할 수 있는 것으로 코드가 많아 loop()를 도는데 1밀리초 이상되거나 for 루프나 while 루프를 완료하는 시간, Serial 통신시 데이터 수신 및 송신에 걸리는 시간등에 따라 누적된 시간의 차가 정확하게 1000밀리초가 되지 못하고 1001 밀리초가되어 조건을 건너뛰는 상황이 언젠가는 발생할 수 있다. 그러므로 그러한 상황을 방지하기 위해 ‘>’를 추가해주어야 한다. 아래 코드를 업로드해 보자. #define LED_BUILTIN 13 unsigned long int start_time = 0; void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { if (millis() – start_time >= 1000) { start_time = millis(); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } } loop() 함수가 0밀리초부터 작동한다고 가정하면 loop()함수에 들어오고 1000 밀리초가 됐을때 코드가 실행되어 LED를 켜고 2000 밀리초가 됐을때 LED를 끄는 것을 반복하게 된다. 1초 간격으로 계속 점멸하면서 loop() 함수는 1초에 약 1만번 돌게 될것이다. 하지만 기본 예제 blink와는 차이가 있게되는데, blink예제는 loop()함수에 들어오자마자 바로 LED를 켜고 millis()를사용하는 상기 예제는 1000밀리초가 지난뒤에 LED를 켜는 차이점이 발생하게 된다. 이점은 millis()함수를 이용하여 시간을 조정하는 방법의 특성으로서 이해를 해야할 것이다. blink예제 처럼 loop()함수시작시 바로 LED가 켜지게 하려면 아래 코드를 추가해 주어야 한다. bool first_loop = true; // 처음 시작시 한번만 작동하는 플래그 if (first_loop == true) { digitalWrite(LED_BUILTIN, HIGH); first_loop = false; // 한번 작동후 재작동 방지위해 플래그 변경 } #define LED_BUILTIN 13 unsigned long int start_time = 0; bool first_loop = true; void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { if (first_loop == true) { digitalWrite(LED_BUILTIN, HIGH); first_loop = false; } if (millis() – start_time >= 1000) { start_time = millis(); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); } } 상기 코드를 업로드 하면 기본 blink예제 코드와 시각적으로 같음을 알 수 있다. millis() 함수를 사용하여 시간 조정함에 있어 추가로 고려해야 할 사항이 있다. 상기 예제에서는 loop() 함수 시작과 동시에 자동으로 millis()함수가 포함된 조건문을 확인하기 시작하여 1000밀리초 후에 코드 실행이 작동하기 시작했지만, 시간이 소요되는 작동에 의해 millis()함수가 포함된 조건문이 시작 될 때에는 millis()함수의 밀리초 값이 조건시간보다 큰상태가 되어 실행코드가 바로 실행되게 된다. 이는 시간조건의 크기와 언제 해당함수가 트리거 되는지에 따라 달라지게 되어 코드 작성시 코드의 작동 상황을 고려하여 millis()함수를 이용한 시간 조정 코드를 적용해야만 된다. 이것에 관한 사항은 앞으로 다룰 비밀번호가 맞을경우 LED 상태표시를 하는 코드에서 확인해 볼 수 있다. 아두이노 millis()함수 설명에 보면 “약 50 일 후에 오버플로우(0으로 돌아감)가 된다”라고 했다. 오버 플로우가 되면 계속 증가하던 값이 0이된다. 상기 코드에서 시간 조건을 검증하기 위해 millis() – start_time >= 1000 코드를 사용했는데 millis()함수가 오버플로우 되면 0 – 이전 millis() 값 >= 1000 이 되어 -값 때문에 오류가 발생할 것처럼 보이지만 발생하지 않는다고 한다. 아래 코드를 업로드하고 실행 해보면 음수값이 나와야 할거 같은 결과같이 양수값으로 나타나는 것을 볼 수 있다. 이러한 결과가 나오는것은 millis() 함수와 start_time 변수 값의 타입이 unsigned 이기 때문에 그렇다고 한다. 아마도 bit 연산을 통해 설명해야 그 원리를 설명하고 이해할 수 있을 듯 하지만 위의 코드 형식을 적용하면 50일이 지나 millis() 함수 값에 오버플로우가 발생해도 오류가 발생하지는 않는다고만 알아두자. void setup() { Serial.begin(9600); unsigned long a = 4294967293; unsigned long b = 4294967000; // startTime unsigned long c = 4294967294; unsigned long d = 4294967295; // unsigned long maximum value unsigned long e = 0; // overflow unsigned long f = 1; unsigned long g = 2; Serial.println(a-b); Serial.println(b-b); Serial.println(c-b); Serial.println(d-b); Serial.print(“overflow: “); Serial.println(e-b); Serial.println(f-b); Serial.println(g-b); } void loop() { } 참조 사이트 Arduino Tutorial: Avoiding the Overflow Issue When Using millis() and micros() 앞서 언급한 디지털 도어락 작동상태 표시에 대한 살펴보자. 1. 열림: 빨간색 -> 노란색 -> 파란색 LED 순으로 한번씩 점멸하고, “도 -> 레 -> 미” 열림음이 출력된다. LED가 순차적으로 켜졌다 꺼졌다 하게 된다. 이를 millis() 함수를 통해 구현하려면 아래처럼 타이머와 카운터가 결합된 형식을 취하는게 코드를 가장 단순하게 만든다. 우선 시간 측정에 진입하는 플래그(bool timer = false;)를 하나 설정한다. 그리고 if 조건에 “timer == true”를 걸어주고 이함수를 loop() 함수내에 위치하여 scan 할 때마다 해당 조건이 항상 확인되도록 해주면 loop() 함수내에서 timer = true; 라는 코드에 의해 시간측정에 진입하는 사용자 함수 delay_timer()가 트리거되고 실행되게 된다. 그리고 delay_timer()가 실행되고 정해진 시간을 만족하면 미리 설정해 놓은 카운터을 하나씩 올린다. 이렇게 되면 카운터는 시간값을 포함하게 된다. bool timer = false; // 사용자 함수 진입 플래그 void delay_timer() { // 250 밀리초 타이머, 타이머 종료: timer = false, time_count = 0; if (timer == true) { if (millis() – delayTime >= 250) { // time_count == 0일때는 딜레이 없이 바로진입 delayTime = millis(); time_count++; // 1부터 250 밀리초 적용 } } } 시간값을 포함하는 카운터는 그 자체를 시간으로 계산할 수 있게 된다. 위의 경우에 만약 millis()가 0부터 시작한다면 카운터가 1일경우 250 밀리초가 되게되고 1씩 증가할 때마다 250밀리초가 증가하게 되어 카운터가 4일때는 1초가 된다. 하지만 상기 함수가 작동할 때에는 millis() 함수 값이 0이 될 수가 없다(50일 이내에는). 문이 열렸을 때 작동하는 LED의 제어를 위해 만들어진 함수안에 포함되었기 때문이다. 문이 열리려면 비밀번호를 입력하고 확인하는 시간이 필요한데, 아무리 빨리 입력한다고 해도 무조건 250 밀리초 이상 걸리게 되고 이 함수가 실행되는 순간은 항상 참이되어 250밀리초 이상인 조건을 시간 소요없이 바로 만족하여 카운터를 0에서 1로 바꾸게 된다. 즉, 시작값이 0이 아니라 1이된다. 1부터는 250 밀리초의 시간마다 카운터를 1씩 증가시키게 된다. 참고로 millis() 함수 값이 0이 되는 순간은 millis()함수가 오버플로우 되는 약 50일 이후가 될 것이다. 이 카운터를 활용하여 LED를 제어하기 위해 아래와 같이 문이 열렸을 때의 플래그 doorOpen = true; 에 의해 작동하는 door_open()라는 사용자함수 코드를 작성하였다. int arrLed[3] = {13, 12, 2}; // 빨, 노, 파 setup() 함수 for (int i = 0 ; i < 3 ; i++) { pinMode(arrLed[i], OUTPUT); digitalWrite(arrLed[i], LOW); } 사용자 함수 void door_open() { // 빨, 노, 파 순차 점멸 if (doorOpen == true) { if (time_count == 1) { // 시작 0 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); // digitalWrite(arrLed[0], HIGH); } else if (time_count == 2) { // 250 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); digitalWrite(arrLed[1], HIGH); } else if (time_count == 3) { // 250 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); digitalWrite(arrLed[2], HIGH); } else if (time_count == 4) { // 250 밀리초 경과 for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); } else if (time_count == 29) { // 문이 자동으로 잠기는 시간(7초) Serial.print("door close"); doorOpen = false; // 문이 잠겼으므로 플래그 초기화 timer = false; // 상태표시 종료 - 플래그 초기화 time_count = 0; // 상태표시 종료 - 카운터 초기화 } } } LED의 작동에 따라 부저음도 도 -> 레 -> 미 음으로 울리게 되므로 아래 코드를 추가해주자. # define beepPin 11 // tone 핀 설정 door_open() 함수 tone(beepPin, 262); tone(beepPin, 294); tone(beepPin, 330); noTone(beepPin); 키패드를 누를때도 ‘도’ 음이 울리도록 아래코드를 키패드 입력부 코드에 추가해 주자. tone(beepPin, 262, 50); 아두이노 참조 사이트의 tone()함수 설명 핀에 특정 주파수(50% 듀티 사이클)의 구형파를 발생시킵니다. 지속 시간을 정할 수 있으며, 따로 정하지 않는다면 noTone()을 부를 때까지 구형파가 지속됩니다. 핀을 피에조 버저 또는 스피커에 연결하여 tone을 연주할 수 있습니다. 한번에 한 tone만 발생시킬 수 있습니다. 다른 핀에서 tone이 이미 연주되고 있으면, tone()을 새로 불러도 아무 일도 일어나지 않을 것입니다. 같은 핀에서 tone이 연주되고 있으면, 주파수가 새로 설정될 것입니다. tone() 함수의 사용은 (Mega 이외의 보드에서) 3번과 11번 핀에서의 PWM 출력을 방해할 것입니다. 31HZ보다 낮은 tone을 발생시키는 것은 불가능합니다. 기술적인 세부 사항은, Brett Hagman’s notes를 보십시오. 문법 tone(pin, frequency) tone(pin, frequency, duration) 매개변수 pin : tone을 발생시킬 핀 frequency : tone의 주파수 (Hz 단위) – unsigned int duration (옵션) : tone 의 지속 시간 (밀리초 단위) – unsigned long noTone(pin) // tone함수 종료 비밀번호가 확인되면 잠금장치가 열리고 닫히므로 서보모터의 작동도 추가해 주자. #include Servo myservo; // create servo object to control a servo int pos = 0; // variable to store the servo position # define servoPin 10 # define servo_open 50 # define servo_close 150 setup() 함수 myservo.attach(servoPin); // attaches the servo on pin 10 to the servo object myservo.write(servo_close); // 기동시 잠긴상태 door_open() 함수 myservo.write(servo_open); myservo.write(servo_close); 3. 비밀번호 잘못 입력한 경우: 경고음 1회 발생, 빨간색, 노란색, 파란색 LED가 한번만 동시 점멸 아래 사용자 함수 wrong_blink() 코드를 작성해 주었다. bool wrongBlink = false; void wrong_blink() { if (wrongBlink == true) { if (time_count == 1) { tone(beepPin, 262, 500); for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], HIGH); } if (time_count == 3) { for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], LOW); timer = false; wrongBlink = false; time_count = 0; } } } 2. 사용자 비밀번호 입력: 빨간색, 노란색, 파란색 LED가 동시 점멸하며 입력 완료시 까지 계속된다. 이 코드의 경우 시간값이 포함된 카운터를 사용하여 코드를 작성할 수 없었다. 처음에는 카운터를 이용하여 작성하였으나 표시의 특성상 1번 표시 중에 2번 표시가 동시에 발생하게 되는데, 코드 상으로는 문제가 없어 보이지만 정작 적용하게 되면 서보모터가 닫힘 상태로 가기전에는 제대로 작동하다가 닫힘 상태로 가기 시작했을 때부터 이상작동을 보인다. 아마도 타이머 간섭 문제인듯 싶지만 확인 할 수는 없었고 millis() 함수를 하나더 사용, 독립적으로 작동하도록 하여 해결하였다. bool inputBlink = false; unsigned long int input_time = 0; void input_blink() { if (inputBlink == true) { if (millis() - input_time >= 1000) { // time_count == 0일때는 딜레이 없이 바로진입 input_time = millis(); for (int i = 0; i <3 ; i++) digitalWrite(arrLed[i], !digitalRead(arrLed[i])); } } } 디지털 도어락의 작동상태를 표시하기 위해 사용자 함수를 만들어 주었다. 각 함수는 모두 loop() 함수에 위치하여 매 scan 마다 그 작동 플래그의 확인에 의해 실행 유무를 결정하게 된다. void loop() { delay_timer(); door_open(); wrong_blink(); input_blink(); } 또한 각 함수의 작동에 있어서 필수 조건으로 시간값을 포함하는 타이머가 선행 되어져야만 한다. 따라서 코드상에 각각의 상태표시의 시작과 종료의 명령은 아래 코드로 이루어 지게 된다. door_open() 시작 timer = true; doorOpen = true; door_open() 종료 doorOpen = false; // 문이 잠겼으므로 플래그 초기화 timer = false; // 상태표시 종료 - 플래그 초기화 time_count = 0; // 상태표시 종료 - 카운터 초기화 wrong_blink() 시작 timer = true; wrongBlink = true; wrong_blink() 종료 timer = false; wrongBlink = false; time_count = 0; input_blink() 시작 inputBlink = true; input_blink() 종료 inputBlink = false; 이제 마지막으로 작동개요중 아래 사항을 충족시키기 위해 EEPROM을 이용하여 비밀번호를 저장하도록 하자. 3. 배터리 교체등 전원을 껐다 켜도 입력된 사용자 비밀번호는 유지된다. 위의 코드를 업로드 하고 테스트 해보면 사용자 비밀번호를 입력하고 저장하면 사용자 비밀번호로만 검증이 되어 작동되는 것을 볼 수 있다. 하지만 아두이노를 리부팅(꺼졌다 켜질때)하게 되면 아래처럼 초기 비번이 변수 초기값으로 설정되어 있어 초기값으로 초기화 되어 리부팅 전에 저장했던 사용자 비밀번호는 더이상 사용할 수 없게 된다. char password[4] = "1234"; // 초기 비밀번호 및 사용자 비밀번호 저장 변수 이를 해결하기 위해 비밀번호 변경시 '#' 버튼을 누를 때 EEPROM에 사용자 비밀번호를 저장시키고 아두이노가 리부팅 되어 password 배열에 저장되었던 사용자 비밀번호가 초기화(1234) 되어도 setup() 함수 실행시 EEPROM에 저장된 사용자 비밀번호를 읽어 password 배열에 다시 저장 시켜 사용자 비밀번호를 계속 사용 할 수 있게 된다. EEPROM을 사용하게 되면 초기 비밀번호도 EEPROM에 저장을 해주어야한다. 그래야만 setup() 함수 실행시 EEPROM을 읽고 초기 비밀번호를 사용할 수 있게 된다. 초기 비밀번호를 저장을 해주지 않으면 EEPROM의 빈값인 { 0xFF, 0xFF, 0xFF, 0xFF } 값을 입력해야 되는데 키패드로는 입력이 불가하여 비밀번호 검증 자체가 불가능하게 된다. 이를 위해 보통 초기 비밀번호를 한번 저장하기위해 스케치를 업로드하여 EEPROM에 초기 비밀번호를 저장하고 다음에 초기 비밀번호 저장 코드를 주석처리하여 다시업로드 하는 두번의 업로드 과정을 거치게 되는데, 초기비번 플래그를 설정하고 그 플래그를 이용하여 한번만 스케치를 업로드해도 계속 사용할 수 있도록 해보자. 상기 코드에 아래 코드를 추가해 주었다. #include # define EEPROM_SIZE 5 // 사용자 비번 + 초기비번 플래그 = 5 byte if(EEPROM.read(4) != 1) { for (int i = 0; i < 4; i++) EEPROM.write(i, password[i]); // (adress(0 ~ 4096), value(0 ~ 255)) EEPROM.write(4, 1); } else { for (int i = 0; i < 4; i++) password[i] = EEPROM.read(i); } 위 코드에서 EEPROM 크기를 정할때 초기비번 플래그 저장공간을 추가해 주었다. 작동 방식은 EEPROM의 초기값이 0xFF 이므로 아두이노 초기 기동시 EEPROM.read(4) != 1 조건을 만족하게 되어 password 배열에 저장된 초기 비밀번호를 저장하고 EEPROM 초기비번 플래그 위치에 1을 저장한다. 이렇게 저장된 1때문에 다음 리부팅시 코드 실행을 막게되어 초기기동시 한번만 실행되는 코드가 되었다. 다음 리부팅시에는 setup()함수에서 EEPROM에 저장된 비밀번호값을 읽기만 하게 된다. 하지만 이렇게 되면 스케치를 새로 변경하여 다시 업로드 해도 이미 저장된 EEPROM 초기 비번 플래그 1 때문에 앞서 저장된 비밀번호를 읽기만 하게된다. setup() 함수에서 초기 비밀번호를 EEPROM에 쓰도록 하기 위해서는 EEPROM의 초기 비번 플래그를 1이 아닌 값으로 바꿔줘야 하는데, 시리얼 모니터에서 명령어 입력을 통해 초기화 하도록 해주자. if(Serial.available()) { String temp = Serial.readStringUntil(' '); if (temp == "pass1234") EEPROM.write(4, 0); } 아래 풀 코드를 업로드 하고 디지털 도어락을 작동해 보자. 사용자 비밀번호가 저장된 후에는 리부팅 되거나 스케치를 새로 업로드 해도 EEPROM의 비밀번호 값이 남아 있게 된다. EEPROM의 비밀번호를 초기 비밀번호로 초기화 하기 위해서는 시리얼 모니터에서 pass1234를 입력하고 나서 리부팅 시키면 비밀번호가 1234로 초기화 된것을 볼 수 있다. 키패드 대신 블루투스를 연결하고 안드로이드 앱으로 디지털 도어락을 제어해 보았다. arduino bluetooth controller PWM - 아두이노 원격제어 안드로이드 앱 버전 3.5 다운로드 arduino bluetooth controller PWM 매뉴얼 키패드와 블루투스 이용 도어락 제어하기 키패드와 블루투스를 동시에 이용하기 위해서는 블루투스를 하드웨어 시리얼에 연결을 하여야 한다. 하지만 하드웨어 시리얼에 블루투스를 연결해 놓으면 아두이노 IDE를 통해 스케치 파일을 업로드 할 수 없게 되는데, 이럴 경우 스케치 파일을 업로드 할 때에는 아래 그림과 같이 아두이노 시리얼 RX 핀번호 0번에 연결된 케이블을 뽑아놓은 상태에서 스케치를 업로드하고 업로드 후에 다시 연결을하면 키패드와 블루투스를 통해 제어를 할 수 있게 된다. 라즈이노 iOT :: 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! 반응형 【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 데이터를 교환하는 장치이다. 교통카드, 학생신분증 겸용카드, 연구실 및 회사 출입문카드, 구내식당 카드, 마트 등의 상품 진열 및 관리 등등 다방면에서 이용되고 있다. 지난 실습에서 아두이노와 RFID모듈을 연결하고 특정 ID카드의 ID를 등록하여 시리얼모니터를 통해 승인 또는 거부 표시를 해보았다. 이번에는 좀더 실제적으로 응용이 가능하도록 서보모터와 LED를 이용해서 도어락 기능을 구현해보려 한다. 선수학습을 잘 따라왔다면, 크게 어렵지않고 더욱 흥미가 생길 것이다. ▶ 선수 학습 : 1. [아두이노 기초#30] 서보모터 제어하기 응용 ☜ (클릭) 2. [아두이노 센서#3] TMP36 온도센서 #1 (RGB LED 부분 참조) ☜ (클릭) 3. [아두이노 모듈#11] RFID(RC522) 사용하기 #1 ☜ (클릭) 4. [아두이노 모듈#12] RFID(RC522) 사용하기 #2 ☜ (클릭) ▶ RFID 모듈 (RC522) 세부 스팩 세부스팩은 위 선수학습 내용을 참조. ▶ 실습 목표 : 1. [ RFID 구동원리, 통신 방식에 대해 이해할 수 있다. ] 2. [ SPI통신과 회로 연결에 대해 이해 할 수 있다.] 3. [ 카드별 고유넘버(UID)를 알아 낼 수 있다.] 4. [ 특정 UID를 지정하여 승인 및 거부 처리를 할 수 있다.] 5. [ ‘서보 모터’와 , ‘RGB LED’를 적용하여 RFID모듈 제어를 할 수 있다.] ▶ 실습 회로도면 : (이미지 클릭하면 확대 가능) RFID Rc522모듈을 활용한 도어락 회로도 ▶ 실습 절차 : 1. 부품을 준비하여 위와 같은 회로를 구성한다. 2. 아두이노IDE에서 MFRC522 라이브러리를 검색후 설치한다. ( 라이브러리 설치는 위 선수학습내용 참조) 3. 첨부된 아두이노 파일을 다운 받아 코드를 실행시킨다. 4. 문으로 사용될 미이어쳐나 모형 등을 준비한다. (RGB LED가 없으면 일반 LED를 사용) 5. 동작확인이 되면(실제 도어 등에 적용할 방법에 대해 고민해본다, 릴레이 사용 등등) ▶ 프로그램 코드 및 설명 : /* RFID 도어락 만들어 보기 */ #include #include #define SS_PIN 10 // spi 통신을 위한 SS(chip select)핀 설정 #define RST_PIN 9 // 리셋 핀 설정 MFRC522 rfid(SS_PIN, RST_PIN); // ‘rfid’ 이름으로 클래스 객체 선언 #include // 서보 라이브러리를 지정 #define servoPin 8 // 서보 모터핀을 지정 Servo servo; // 서보 라이브러리 변수를 선언 int pos=0; // 현재 각도를 저장할 변수를 지정한다 int RLED=7; // 빨간색 LED단자를 아두이노 7번과 연결 int GLED=6; // 초록색 LED단자를 아두이노 6번과 연결 void setup ( ) { pinMode(RLED, OUTPUT); // RED LED를 출력으로 지정 pinMode(GLED, OUTPUT); // GREEN LED를 출력으로 지정 servo.attach(servoPin); // 서보모터 핀을 설정한다 servo.write(0); // 서보모터 0도 위치로 초기화 Serial.begin(9600); SPI.begin(); // SPI 통신 시작 rfid.PCD_Init(); // RFID(MFRC522) 초기화 Serial.println(“Approximate your card to the reader…”); Serial.println(); } void loop ( ) { // 새카드 접촉이 있을 때만 다음 단계로 넘어감 if ( ! rfid.PICC_IsNewCardPresent()) { return; } // 카드 읽힘이 제대로 되면 다음으로 넘어감 if ( ! rfid.PICC_ReadCardSerial()) { return; } // 현재 접촉 되는 카드 타입을 읽어와 모니터에 표시함 Serial.print(“UID tag :”); String content= “”; byte letter; for (byte i = 0; i < rfid.uid.size; i++) { Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " "); Serial.print(rfid.uid.uidByte[i], HEX); content.concat(String(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ")); content.concat(String(rfid.uid.uidByte[i], HEX)); } Serial.println(); Serial.print("Message : "); content.toUpperCase(); // UID값이 아래 값과 같으면 승인 처리 if (content.substring(1) == "85 7C FB D1") // 승인 하고자하는 UID 기록 { // 인증이 되면 Green LED와 함께 서보모터를 작동시킨다. Serial.println("Authorized access"); Serial.println(); digitalWrite(GLED,HIGH); servo.write(180); // 서보모터의 각도를 변경한다 delay(3000); // 서보 모터의 각도가 변하는 것을 기다려 준다 servo.write(0); // 시간지연 후 문을 닫는다 digitalWrite(GLED,LOW); // 시간지연 후 LED 끈다 } // 승인 목록에 없는 UID 처리는 // 서보모터의 작동 없이 Red LED만 켜고 끈다 else { Serial.println(" Access denied"); digitalWrite(RLED,HIGH); delay(3000); digitalWrite(RLED,LOW); } } ▶ 실행영상 : (전체화면 보기로 보세요) RFID 도어락 만들어 보기 (아래는 유튜브로 시청하기) https://youtu.be/6nBu0obCx5Q ▶ 아두이노 파일다운 : (다운받아서 압축을 풀어 사용하세요) ko_arduino_code_Servo_LED.zip 0.00MB ▶ 컴파일 에러 발생시 해결 방법 참고 : 아래 최신글을 참고해 보세요. rasino.tistory.com/321 반응형 [아두이노] 디지털 도어락 KIT 상품결제정보 고액결제의 경우 안전을 위해 카드사에서 확인전화를 드릴 수도 있습니다. 확인과정에서 도난 카드의 사용이나 타인 명의의 주문등 정상적인 주문이 아니라고 판단될 경우 임의로 주문을 보류 또는 취소할 수 있습니다. 무통장 입금은 상품 구매 대금은 PC뱅킹, 인터넷뱅킹, 텔레뱅킹 혹은 가까운 은행에서 직접 입금하시면 됩니다. 주문시 입력한 입금자명과 실제입금자의 성명이 반드시 일치하여야 하며, 7일 이내로 입금을 하셔야 하며 입금되지 않은 주문은 자동취소 됩니다. 배송정보 배송 방법 : 택배 배송 지역 : 전국지역 배송 비용 : 3,500원 배송 기간 : 3일 ~ 7일 배송 안내 : – 산간벽지나 도서지방은 별도의 추가금액을 지불하셔야 하는 경우가 있습니다. 고객님께서 주문하신 상품은 입금 확인후 배송해 드립니다. 다만, 상품종류에 따라서 상품의 배송이 다소 지연될 수 있습니다. 교환 및 반품정보 교환 및 반품이 가능한 경우 – 상품을 공급 받으신 날로부터 7일이내 단, 가전제품의 경우 포장을 개봉하였거나 포장이 훼손되어 상품가치가 상실된 경우에는 교환/반품이 불가능합니다. – 공급받으신 상품 및 용역의 내용이 표시.광고 내용과 다르거나 다르게 이행된 경우에는 공급받은 날로부터 3월이내, 그사실을 알게 된 날로부터 30일이내 교환 및 반품이 불가능한 경우 – 고객님의 책임 있는 사유로 상품등이 멸실 또는 훼손된 경우. 단, 상품의 내용을 확인하기 위하여 포장 등을 훼손한 경우는 제외 – 포장을 개봉하였거나 포장이 훼손되어 상품가치가 상실된 경우 (예 : 가전제품, 식품, 음반 등, 단 액정화면이 부착된 노트북, LCD모니터, 디지털 카메라 등의 불량화소에 따른 반품/교환은 제조사 기준에 따릅니다.) – 고객님의 사용 또는 일부 소비에 의하여 상품의 가치가 현저히 감소한 경우 단, 화장품등의 경우 시용제품을 제공한 경우에 한 합니다. – 시간의 경과에 의하여 재판매가 곤란할 정도로 상품등의 가치가 현저히 감소한 경우 – 복제가 가능한 상품등의 포장을 훼손한 경우 (자세한 내용은 고객만족센터 1:1 E-MAIL상담을 이용해 주시기 바랍니다.) ※ 고객님의 마음이 바뀌어 교환, 반품을 하실 경우 상품반송 비용은 고객님께서 부담하셔야 합니다. (색상 교환, 사이즈 교환 등 포함) So you have finished reading the 아두 이노 도어락 topic article, if you find this article useful, please share it. Thank you very much. See more: 아두이노 키패드 도어락, 아두이노 문 개폐, RFID 도어락

아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트

배송방법 택배

배송기간 평균 2일이내 발송 (영업일 기준)

청약철회 불가 사유/근거 전자상거래등에서의 소비자보호에 관한법률 제17조제2항 및 동 시행령 제21조에 의한 청약철회 제한 사유에 해당하는 경우 및 기타 객관적으로 이에 준하는 것으로 인정되는 경우

상품의 교환,반품 조건 및 품질보증기준 교환/반품/보증 및 품질보증기준은 소비자기본법 에 따른 소비자분쟁해결기준에 따라 피해를 보상

대금환불 및 환불지연에 따른 배상금 안내 판매자문의, 전자상거래 등에서의 소비자 보호에 관한 법률 등 관계

소비자 피해보상 및 A/S 관련 문의 판매자문의, 소비자기본법에 따른 소비자 분쟁 해결기준에 따름

P18 아두이노 RFID 도어락 실험키트 RDM6300 리더기

주문제작 상품 구매안내

해당상품은 고객님의 주문사항에 맞춰 제작되는 상품이므로 판매자의 의사에 반하여 취소 및 교환, 반품이 불가능 합니다. (상품하자시 제외)

이에 동의하시는 경우 동의버튼을 선택해 주세요.

NFC 도어락(DoorLock) Ver 1.0 & Ver 2.0

728×90

0. 목차

1. Ver 1.0 & Ver 2.0 : http://twinw.tistory.com/136(현재 페이지)

2. Ver 3.0 : http://twinw.tistory.com/168

3. Ver 4.0 : http://twinw.tistory.com/170

1. 개요

졸업전 만들고 싶었던 NFC를 이용한 도어락이다. 개인적으로 가졌던 로망으로 열쇠나 비밀번호가 아닌 핸드폰을 대는것으로 개인 사물함을 열고 싶었다. 개인적 취미로 프로젝트를 진행하였기 때문에 빠르게 진행하지 못하였고, 처음으로 진행하였던 제대로된 하드웨어 작업이여서 회로작업, 전원문제 등 어려운 점이 많았다.

2. 결과

우선적인 결과물에 대해 먼저 적겠다.

위 사진은 사물한 문의 앞, 뒤 모습이다. 실제적으로 사용하기 위해 만든 것으로 덮게도 만들었다. 아래 영상은 실제 도어락 사용하는 영상이다.

3. 제작 과정 – 사물함 문

우선적으로 기존 사물함 문을 때어 직접 글라인더로 커팅하였고, 다이소에서 2000원짜리 나무 장식품을 분해하여 커버 가장자리를 만들었다. 구매한 나무 장식품을 찍어둔다는 것을 잊어서 현재 사진은 남아 있지 않지만 울타리 모양 장식품이고 딱보면 홈이 있어 딱보면 케이스 뚜껑을 만들면 되겠다라는 생각이 든다.

4. 제작 과정 – 도어락

처음에는 즉 Ver 1.0은 도어락 모듈을 검색하여 제작하였다.

그러나 위 모듈의 정격 전압이 12V이였고, 1.5V 건전지 7개로 보드와 모듈을 모두 동작시키기에는 건전지 용량이 너무 부족하였다. 이러한 이유 및 학교 생활 때문에 프로젝트는 잠시 멈추었다가, 이후 도어락 부분을 모듈에서 실제 도어락으로 변경하였고 프로젝트를 다시 진행하게 되었다.

도어락은 일상 생활에서 자주 볼수 있는 Milre모델이다. 여담이지만 위 모듈은 1만 7천원에 구매를 하였지만 아래 사진의 도어락은 도어락 수리 및 판매하는 곳에서 만원에 구매를 하였다. 도어락은 앞 비밀번호 부분이 뒷부분 보다 많이 망가지고, 교체시 양쪽다 교체를 해야하기 때문에 뒷부분은 싸게 구하기 쉬울 것이다.

우선 도어락을 오픈하였고 버튼으로 도어락 장금을 제어하는 부분에 내가 따로 보드로 하여 제어할 수 있도록 선을 추가로 납땜을 하였다.

또한 기존 도어락은 모두 잠기면 구조상으로 회전으로 여는것이 아니라 눌러서 열지 못하도록 락이 걸리도록 되어있다. 이 부분을 전원이 떨어졌을 때 물리적으로 사물함을 열 수 있도록 플라스틱을 끼워 잠기지 않게 하였다.

5. 제작 과정 – 제어부 및 시나리오

먼저 구성도와 실제 회로를 보자.

위 사진을 보면 알 수 있듯이 회로는 PCB 기판 작업을 하였다. 아래 사진은 위 회로의 구성도이다.

회로에 대해 잠시 설명하면 다음과 같다.

1. 보드와 도어락 그리고 NFC 모듈은 독자적인 전원을 가지고 있다. 위 구성도에서는 9V 건전지 2개가 각각 보드와 NFC 모듈에 전원을 공급하고 있다.

2. 릴레이 모듈 2개는 보드로부터 전원을 공급받으며 하나는 도어락의 lock/unlock을 제어하며 하나는 NFC 모듈의 전원을 제어한다.

3. 보드는 Sleep모드로 되어 있으며 버튼을 누르면 깨어나 동작한다.

앞에 맨위 동영상을 보았다면 알겠지만 시나리오에 대해 자세히 설명하겠다.

1. 버튼을 눌러 Sleep모드 중인 아두이노 보드를 깨운다.

2. 아두이노는 NFC 모듈의 전원이 연결되어 있는 릴레이에 신호를 보내 NFC 모듈을 켠다.

3. NFC 모듈은 일정 시간 동안 데이터를 읽고 신호가 없다면 아두이노 보드는 다시 Sleep모드로 돌아간다.

4. 만약 NFC 모듈에 신호가 있다면, 즉 등록된 카드를 모듈에 댄다면, 아두이노는 도어락 제어선이 연결된 릴레이 모듈에 신호를 주어 도어락을 동작시킨다.

6. Source Code

아래 소스 코드를 보시기 전 해당 코드를 구현하는데 사용된 코드들을 먼저 보길 바란다.

1. 아두이노 – NFC(RFID-RC522) 모듈 사용하기 : http://twinw.tistory.com/111

2. 아두이노 – 슬립 모드(Sleep Mode), 절전 모드, 저전력 모드 : http://twinw.tistory.com/124

#include #include #include “LowPower.h” #define uchar unsigned char #define uint unsigned int #define MAX_LEN 16 AddicoreRFID myRFID; ///////////////////////////////////////////////////////////////////// //set the pins ///////////////////////////////////////////////////////////////////// const int chipSelectPin = 10; const int resetPin = 9; const int button = 2; const int power_Relay = 7; const int door_Relay = 8; void setup() { Serial.begin(9600); // 시리얼 모니터 출력 설정 SPI.begin(); pinMode(chipSelectPin,OUTPUT); // Set digital pin 10 as OUTPUT to connect it to the RFID /ENABLE pin pinMode(resetPin,OUTPUT); // Set digital pin 10 , Not Reset and Power-down pinMode(power_Relay,OUTPUT); pinMode(door_Relay,OUTPUT); pinMode(button,INPUT_PULLUP); digitalWrite(chipSelectPin, LOW); // Activate the RFID reader digitalWrite(resetPin, HIGH); myRFID.AddicoreRFID_Init(); } void loop() { attachInterrupt(0, wakeUp, LOW); //Serial.println(“sleep”); LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //set Sleep mode detachInterrupt(0); //Serial.println(“wake up”); checking(); } void wakeUp(){} void checking() //when wake up, this function will working { int button_state = 0; int count = 0; int k,check_nfc=0; digitalWrite(power_Relay, HIGH); count=15; delay(200); while(count!=0){ check_nfc=0; button_state = digitalRead(button); count–; if(button_state==0){ // this is safe Function. delay(100); for(k=0;k<35;k++){ button_state = digitalRead(button); if(button_state==0){ delay(200); check_nfc++; } else break; } if(check_nfc>30){ when you push Button for 30 seconds, door lock is unlock digitalWrite(door_Relay, HIGH); delay(500); digitalWrite(door_Relay, LOW); count=0; } }else{ uchar status; uchar str[MAX_LEN]; str[1] = 0x4400; String mynum = “”; //Find tags, return tag type status = myRFID.AddicoreRFID_Request(PICC_REQIDL, str); if (status == MI_OK) { if(str[0] == 100 && str[1] == 11) { digitalWrite(door_Relay, HIGH); delay(500); digitalWrite(door_Relay, LOW); } } status = myRFID.AddicoreRFID_Anticoll(str); if (status == MI_OK)//if attached card is registered card, doorlock will working { Serial.println(str[0]); Serial.println(str[1]); if(str[0] == 5 && str[1] == 167) { digitalWrite(door_Relay, HIGH); delay(500); digitalWrite(door_Relay, LOW); } else if(str[0] == 115 && str[1] == 5 ) { digitalWrite(door_Relay, HIGH); delay(500); digitalWrite(door_Relay, LOW); } else if(str[0] == 213 && str[1] == 143 ) { digitalWrite(door_Relay, HIGH); delay(500); digitalWrite(door_Relay, LOW); } delay(1000); count=0; } myRFID.AddicoreRFID_Halt(); } delay(100); } digitalWrite(power_Relay, LOW); }

프로젝트 풀 코드는 아래 Github페이지에서 받을 수 있다.

Github : https://github.com/cckr2/DoorLock

키워드에 대한 정보 아두 이노 도어락

다음은 Bing에서 아두 이노 도어락 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!

  • 라즈이노
  • 라즈이노IOT
  • 아두이노
  • 라즈베리파이
  • Arduino
  • RaspberryPi
  • 프로그래밍
  • 프로세싱
  • 영상강좌
  • 배우기강좌
  • RFID 도어락
  • 도어락만들기
  • 도어락키 추가
  • 아두이노 도어락 만들기
  • RFID RC522
  • Door Rock

【 #아두이노 #완공#4】 # #RFID #(RC522) #도어락 #만들기!


YouTube에서 아두 이노 도어락 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기! | 아두 이노 도어락, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.