당신은 주제를 찾고 있습니까 “아두 이노 도어락 – 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!“? 다음 카테고리의 웹사이트 you.tfvp.org 에서 귀하의 모든 질문에 답변해 드립니다: https://you.tfvp.org/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 라즈이노 IOT 이(가) 작성한 기사에는 조회수 8,097회 및 좋아요 52개 개의 좋아요가 있습니다.
아두 이노 도어락 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 【 아두이노 완공#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
아두 이노 도어락 주제에 대한 자세한 내용은 여기를 참조하세요.
아두이노 – 디지털 도어락 예제, delay() 함수 대체 방법 – postpop
아두이노와 키패드, LED, 피에조부저, 서보모터, keypad.h 라이브러리와 EEPROM 라이브러리를 활용하여 디지털 도어락을 구현해 보겠다.
Source: postpop.tistory.com
Date Published: 2/7/2022
View: 7308
【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기!
【 아두이노모듈#13】 RFID #3(RC522) 도어락 만들기! RFID(Radio Frequancy Identification)는 무선 주파수를 이용하여 RFID 태그와 RFID리더간 …
Source: rasino.tistory.com
Date Published: 8/30/2022
View: 7910
[아두이노] 디지털 도어락 KIT – Capstonemall – 캡스톤몰
상품명, [아두이노] 디지털 도어락 KIT ; 판매가, 120,000원 ; 제조사, [씨앤디아이 주식회사] ; 원산지, 국내 ; 배송비 · 3,500원 …
Source: capstonemall.co.kr
Date Published: 12/5/2022
View: 3856
‘아두이노 도어락’ 태그의 글 목록 – Daum 블로그
Arduino Uno 로 MFRC-522 RC522 RFID 모듈과 서보모터를 사용해 도어락 만들어 보기 … 근접 키체인 모듈을 가져다 댔을때 아두이노 IDE의 시리얼 모니터로 IC카드 …
Source: m.blog.daum.net
Date Published: 6/1/2021
View: 6454
아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 … – 인터파크
4%할인, 추가 회원 중복 할인 쿠폰, 기타에 대한 상품입니다.
Source: m.shop.interpark.com
Date Published: 11/10/2022
View: 5410
아두이노 프로젝트 – NFC 도어락(DoorLock) Ver 3.0 – 흰고래의꿈
Ver 1.0은 아래 그림과 아두이노로 릴레이에 연결된 도어락 모듈을 제어하는 단순한 방식이다. Ver 1.0 의 NFC 도어락은 …
Source: twinw.tistory.com
Date Published: 12/23/2021
View: 9321
[DU012] 아두이노 키패드 도어락 키트
아두이노 우노 R3 보드와 4X4 키패드, 부저, LCD, RGB, 서보 모터를 이용해서 도어락 기능을 간단히 구현 할 수 있는 키트입니다. ( 자료 및 소스코드 제공 / 우노 R3 …
Source: daduino.co.kr
Date Published: 2/17/2022
View: 7910
주제와 관련된 이미지 아두 이노 도어락
주제와 관련된 더 많은 사진을 참조하십시오 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 아두 이노 도어락
- Author: 라즈이노 IOT
- Views: 조회수 8,097회
- Likes: 좋아요 52개
- 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번에 연결된 케이블을 뽑아놓은 상태에서 스케치를 업로드하고 업로드 후에 다시 연결을하면 키패드와 블루투스를 통해 제어를 할 수 있게 된다.
라즈이노 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상담을 이용해 주시기 바랍니다.)
※ 고객님의 마음이 바뀌어 교환, 반품을 하실 경우 상품반송 비용은 고객님께서 부담하셔야 합니다.
(색상 교환, 사이즈 교환 등 포함)
‘아두이노 도어락’ 태그의 글 목록
Arduino Uno 로 MFRC-522 RC522 RFID 모듈과 서보모터를 사용해 도어락 만들어 보기
Arduino Uno 로 MFRC-522 RC522 RFID 의 사용방법을 알아보고 LED와 SG90 마이크로 서보모터를 사용해서 도어락을 구성해 보는 프로젝트 입니다 먼저 Arduino Uno 로 MFRC-522 RC522 RFID 모듈을 사용해 IC카드 리더, 근접 키체인 모듈을 가져다 댔을때 아두이노 IDE의 시리얼 모니터로 IC카드 리더, 근접 키체인 모듈의 ID 출력값을 표시해 보는 프로젝트 입니다 MFRC-522 RC522 RFID IC카드 리더, 근접 키체인 모듈은 RFID 카드와 리더에서 사용되는 기술의 이해와 MIFARE Classic RFID cards 의 기본적인 하드웨어 및 소프트웨어 기능을 이해하는데 도움이 됩니다 SPI bus devices 를 사용하는 방법을 배우는데 도움이 되..
아두이노 MFRC-RC522 RFID 키트/Arduino 도어락 키트
배송방법 택배
배송기간 평균 2일이내 발송 (영업일 기준)
청약철회 불가 사유/근거 전자상거래등에서의 소비자보호에 관한법률 제17조제2항 및 동 시행령 제21조에 의한 청약철회 제한 사유에 해당하는 경우 및 기타 객관적으로 이에 준하는 것으로 인정되는 경우
상품의 교환,반품 조건 및 품질보증기준 교환/반품/보증 및 품질보증기준은 소비자기본법 에 따른 소비자분쟁해결기준에 따라 피해를 보상
대금환불 및 환불지연에 따른 배상금 안내 판매자문의, 전자상거래 등에서의 소비자 보호에 관한 법률 등 관계
소비자 피해보상 및 A/S 관련 문의 판매자문의, 소비자기본법에 따른 소비자 분쟁 해결기준에 따름
NFC 도어락(DoorLock) Ver 3.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. 개요(이전 버전)
Ver 1.0은 아래 그림과 아두이노로 릴레이에 연결된 도어락 모듈을 제어하는 단순한 방식이다.
Ver 1.0 의 NFC 도어락은 http://twinw.tistory.com/136에 가면 동영상을 볼 수 있다. 도어락 모듈을 따로 물어보시는 분들이 계신데 URL은 기억이 나지 않고 네이버 쇼핑에서 도어락 모듈 검색을 하다 구매한 기억이 남아있다.
Ver 2.0는 많은 시행착오를 겪고 실제 사물함에 설치한 버전이다.
시나리오에 대해 자세히 설명하겠다.
1. 버튼을 눌러 Sleep모드 중인 아두이노 보드를 깨운다.
2. 아두이노는 NFC 모듈의 전원이 연결되어 있는 릴레이에 신호를 보내 NFC 모듈을 켠다.
3. NFC 모듈은 일정 시간 동안 데이터를 읽고 신호가 없다면 아두이노 보드는 다시 Sleep모드로 돌아간다.
4. 만약 NFC 모듈에 신호가 있다면, 즉 등록된 카드를 모듈에 댄다면, 아두이노는 도어락 제어선이 연결된 릴레이 모듈에 신호를 주어 도어락을 동작시킨다.
앞서 말했지만 Ver.01과 Ver.02는 http://twinw.tistory.com/136에가면 더욱 더 자세히 볼 수 있다.
2. Ver.03
먼저 Ver.02과 Ver.03의 모습을 비교해 보자. 가장 먼저 눈에 띄는건 9V 사각전지가 샤오미 배터리로 변경되면서 복잡하던 회로가 모두 사라졌다. 또한 사각 전지가 각각 보드, 릴레이, NFC모듈에게 전원을 주던것을 배터리가 하나로 줄면서 보드가 받은 전압을 다시 모듈들에게 전달한다. 그리고 회로만 변경되었지 동작 시나리오는 변경되지 않았다.
회로를 Symbol로 만들어 보면 위와 같다. Fritzing으로 만들기 너무 귀찮아서 PowerPoint로 만들었다.
대체된 NFC 모듈은 NFC Module for Arduino v1.0이라는 모듈이고 기존 SPI통신으로 핀 4개를 사용하여 전류를 더럽게 먹던 RFID-RC522 모듈과 달리 Serial 통신을 하여 2개의 통신 핀만 사용해서 상대적으로 전류 사용량이 적다. 그러나 4000원 하던 RFID-RC522 모듈과 달리 20000원 정도 한다.
NFC Module for Arduino v1.0 모듈의 기본 Sample 코드는 https://www.dfrobot.com/wiki/index.php/NFC_Module_for_Arduino_(SKU:DFR0231)에 잘 설명되어 있다. (Google에 모듈명 치면 바로 나옴)
해당 버전에는 치명적인 문제가 있다. 바로 샤오미 !!
현재 전력소모를 적게 하기 위해 동작 시를 제외하고는 Sleep모드로 보드가 동작하는데 샤오미는 일정이상의 전력을 소비하지 않으면 꺼져버린다. 따라서 아래와 같은 독자적인 리튬 전지를 이용하기를 바란다.
해당 문제점을 해결한 것이 다음 버전인 Ver 4.0이고 http://twinw.tistory.com/170에서 볼 수 있다.
3. Ver 3.0 Source Code
소스 코드는 https://github.com/cckr2/DoorLock에서 전 버전 다 다운 받을 수 있다.
#include “LowPower.h” #define wake_result 15 #define firmware_result 19 #define tag_result 25 const unsigned char wake[24]={ 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module const unsigned char firmware[9]={ 0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};// const unsigned char tag[11]={ 0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command const unsigned char std_ACK[25] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C, \ 0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00}; unsigned char old_id[5]; unsigned char cur_id[5]; unsigned char receive_ACK[25];//Command receiving buffer const int button = 2; const int power_Relay = 7; const int door_Relay = 8; void setup() { Serial.begin(115200); // open serial with PC delay(100); pinMode(power_Relay,OUTPUT); pinMode(door_Relay,OUTPUT); pinMode(button,INPUT_PULLUP); } void loop() { attachInterrupt(0, wakeUp, LOW); LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //set Sleep mode detachInterrupt(0); checking(); } void UART_Send_Byte(unsigned char command_data) {//send byte to device Serial.write(command_data); Serial.flush();// complete the transmission of outgoing serial data } void wake_card(void) {//send wake[] to device unsigned char i; for(i=0;i<24;i++) //send command UART_Send_Byte(wake[i]); } void firmware_version(void) {//send firmware[] to device unsigned char i; for(i=0;i<9;i++) //send command UART_Send_Byte(firmware[i]); } void send_tag(void) {//send tag[] to device unsigned char i; for(i=0;i<11;i++) //send command UART_Send_Byte(tag[i]); } void read_ACK(unsigned char temp) {//read ACK into reveive_ACK[] //Serial.println("read the result"); unsigned char i; for(i=0;i
20){ digitalWrite(door_Relay, HIGH); delay(500); digitalWrite(door_Relay, LOW); count=0; } }else{ send_tag(); read_ACK(tag_result); read_id(); if (!no_detection()) { //print_id(); count = check_id(count); } } delay(100); } digitalWrite(power_Relay, LOW); }
키워드에 대한 정보 아두 이노 도어락
다음은 Bing에서 아두 이노 도어락 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기!
- 라즈이노
- 라즈이노IOT
- 아두이노
- 라즈베리파이
- Arduino
- RaspberryPi
- 프로그래밍
- 프로세싱
- 영상강좌
- 배우기강좌
- RFID 도어락
- 도어락만들기
- 도어락키 추가
- 아두이노 도어락 만들기
- RFID RC522
- Door Rock
【 #아두이노 #완공#4】 # #RFID #(RC522) #도어락 #만들기!
YouTube에서 아두 이노 도어락 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 【 아두이노 완공#4】 RFID (RC522) 도어락 만들기! | 아두 이노 도어락, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.