[아두이노] RFID-RC522 + Servo Motor 제어

IOT/아두이노|2019. 5. 7. 09:00

[아두이노] RFID-RC522 + Servo Motor 제어



지난 시간에 RFID-RC522를 아두이노에 연결하여 제대로 인식하는지에 대해 예제를 통해 간단히 테스트를 하였습니다. MFRC522 라이브러리에서 초기 선언하는 세팅 부분만 간단히 살펴 보았기 때문에 뭔가 제어하는 실험이 부족한 것 같아서 오늘은 Servo Motor를 같이 연결하여 RFID-RC522를 제어하는 실험을 하고자 합니다. 어제 배웠던 내용에서 크게 변화 된 것은 없습니다. 단지 카드 UID 값을 읽고 그 값에 일치 하면 Servo Motor가 특정 각도로 회전이 일어나도록 하는 실험을 하고자 합니다. 일상에서의 도어락이나 전철을 탈때 출입 통로, 회사 출입 통로 등의 카드를 대면 인식하고 출입을 할 수 있도록 문을 열어주는 동작과 느낌을 실험하고자 Servo Motor의 Open 회전값과 Close 회전값을 주어 비슷한 느낌을 표현 하였습니다.


1. RFID-RC522 + Servo Motor 회로도



  • 준비물 : RFID-RC522, Servo Motor, 피에조부저, 아두이노우노
  • 내용 : SPI 통신을 할 수 있게 핀은 연결하고 Servo Pin 7번, 피에조부저 6번으로 연결해 보자.
  • 지난시간 회로도 참고 : RFID-RC522 제어(아두이노)


출처 : Fritzing

RFID-RC522 회로도가 좀 복잡해 보일 꺼에요. 지난 시간에 RFID-RC522 회로도에서 Servo Motor와 피에조부저 핀을 추가 하시면 됩니다. 오늘 회로도를 보고 선을 연결하지 마시고 링크 걸린 지난 시간의 회로도를 보고 회로도 선을 연결한 뒤에 오늘사용하는 7번 Servo 핀과 6번 피에조 핀만 연결하면 되니깐 그렇게 어렵지 않을 꺼에요.

2. 코딩



MFRC522

#include <SPI.h>
#include <MFRC522.h>
  • MFRC522 mfrc522(SS_PIN, RST_PIN) : MFRC522 인스턴스화
  • SPI.begin() :SPI bus 초기화
  • mfrc522.PCD_Init() : MFRC522 card 초기화
  • mfrc522.PICC_IsNewCardPresent() : 새카드 확인
  • frc522.PICC_ReadCardSerial() : 하나의 카드읽기 확인
  • rfid.uid.uidByte[] : 읽은 카드 키값이 들어 있음

피에조 부저

  • tone(tonePin ,음,음길이) : 음 시작
  • noTone(tonePin ) : 음 중지

Servo Motor

#include <Servo.h>
  • Servo servo : 서보모터 객체 선언
  • servo.attach(서보핀) : 서보 모터에 출력을 담당할 핀 선언
  • servo.write(회전각) : 회전각 만큰 서보모터를 회전 시킴

시리얼 통신

  • Serial.begin(9600) : 시리얼 통신 시작(9600 통신속도)
  • Serial.println(값) : 시리얼모니터 출력
  • Serial.available() : 시리얼통신으로 데이터가 들어놨는지 상태 확인
  • Serial.parseInt() : Int형으로 데이터를 읽음

지난 시간에 이여서 오늘도 위 함수 부분은 그대로 Post에 남겨 뒀습니다. 지난 시간의 Post를 왔다 갔다 하실 필요 없이 오늘 Post만 보시고 코딩을 생각할 수 있게 그대로 가져 왔네요.

[소스] MFRC522의 예제 중 하나( 출처 : miguelbalboa의 라이브러리)

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9       
#define SS_PIN          10      

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

void setup() {
    Serial.begin(9600);     // Initialize serial communications with the PC
    while (!Serial);        // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();            // Init SPI bus
    mfrc522.PCD_Init();     // Init MFRC522
    mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
    Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop() {
    // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
    }

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial()) {
        return;
    }

    // Dump debug info about the card; PICC_HaltA() is automatically called
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

지난 시간에 라이브러리에 있던 예제 소스입니다. 이 소스를 기반으로 Servo Motor를 제어 하겠습니다. 우선 위 소스를 DumpInfo 예제를 한번 실행 시켜 주세요.

Card UID: 55 AF 07 88

Card UID의 값을 확인 하세요. 참고로 제가 실험하는 Card UID 값하고 여러분이 실험하는 Card UID는 다릅니다. 이 Card UID로 실험하기 때문에 한번 실행해서 자신의 Card UID를 알아내야 합니다. 확인이 되면 이 Card UID 값을 배열 변수로 저장 하세요.

byte CardUidByte[4] = {0x55, 0xAF, 0x07, 0x88};

참고로, 숫자가 알파벳이 나오면 16진수라고 여기세요. 여기서 그냥 숫자를 기입하시면 안되고 앞에 '0x'을 꼭 붙여주셔야 이 수가 16진수이구나 하고 프로그램이 인식합니다. 이렇게 해서 비교 할 Card UID값을 저장해 놓았습니다.

카드를 읽게 되면 그 값은 어디에 들어 있을까요.

mfrc522.uid.uidByte[]

이곳에 담겨져 있습니다. 4개의 UID 숫자값이 Card UID 값을 가지고 있으니 mfrc522.uid.uidByte[0] ~ mfrc522.uid.uidByte[3] 까지해서 그 값을 가지고 있습니다. 그러면, IF문으로 해서 저장된 값과 비교하면 됩니다.

  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
                읽어온 Card UID 값과 저장된 Card UID값이 일치하면 참;
                명령문;
  }

이렇게 해서 카드를 RFID-RC522에 대면 두 Card UID 값을 서로 비교하게 됩니다. 그리고 일치하면 if문 안의 명령문을 수행하게 됩니다.

코딩은 거의 다 했습니다. 이제는 Servo Motor를 회전 시켜야 겠죠. 카드의 UID가 일치하니깐 Servo Motor가 Open 시키는 의미로 일정 각도로 회전 시키는 동작과 다시 카드를 RFID-RC522에 대면 Servo Motor가 Close 시키는 의미로 원래 각도로 회전 시켜는 동작을 표현 할 에정입니다. Card를 대면 Open or Close가 교차로 반복되는 실험입니다.

이 동작을 수행하기 위해서는 어떻게 코딩해야 할까요.

boolean state = false;

이렇게 하나의 ServoMotor의 상태값 변수를 만들어 놓습니다. 그리고 나서 아래와 같은 코딩을 하면 됩니다.

  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
          
          state=!state;  //Servo Motor(Open or Close)
                
          if(state == true){
           Serial.println("Open");
           servo.write(180);
           delay(1000);
          }
          else{           
           Serial.println("Close");
           servo.write(0);
           delay(1000);
          }
          delay(2000);              
  }

초기 state은 false 상태이고 Cade UID 값이 일치하면 state은 반전 true가 되어 다음 if문에서 "state == ture"이면 참이니깐 "Open"으로 Servo Motor를 180도 회전 시키고 1초 대기 했다가 다시 연속으로 카드값이 인식하지 못하도록 2초동안 딜레이 시간을 추가로 더 연장 했습니다. 총 3초 동안은 Card가 인식되지 못하게 했습니다. 3초가 지난 후 Card가 다시 RFID-RC522에서 인식하면 state은 !state로 반전으로 state은 false가 되어 다음 if문 "state == ture"가 거짓으로 else 이하 문장을 수행 합니다. 그러면 "Close"로 Servo Motor은 0도로 원래 각도로 회전 되어 돌아오게 됩니다. Card가 RFID-RC522에 대면 교차로 "Open" 과 "Close"가 반복 됩니다.

이렇게 해서 Card로 Servo Motor를 회전 시킬 수 있게 되었습니다.

여기서, 추가로 Card가 읽혔는지 확인 할 방법이 없습니다. Servo Motor가 회전 되었을 때 확인이 됩니다. 즉, 카드를 Servo Motor가 회전 될 때 까지 RFID-RC522에 대고 있어야 한다는 소리가 됩니다. 좀 불편하죠.

그래서, 카드를 읽은 순간 그때 뭔가 메세지를 외부로 보여준다면 이 문제가 해결 할 수 있습니다. 그 역할을 소리로 표현하기 위해서 피에조부저를 이용하고자 합니다.

  // 새 카드 확인
  if ( ! mfrc522.PICC_IsNewCardPresent()) return; 

  // 카드 읽기
  if ( ! mfrc522.PICC_ReadCardSerial()) return;
    
  tone(tonePin ,523,1000/8);     // 도음으로 8분음표(음길이)
  delay(1000/4*1.30);             
  noTone(tonePin ); 

이렇게 카드가 읽기와 카드를 비교하기 전 사이에 사이에 피에조부저의 음이 울리게 하면 쉽게 확인이 되겠죠.

종합해 보면,

[소스]

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>

const int RST_PIN = 9;
const int SS_PIN = 10;

MFRC522 mfrc522(SS_PIN, RST_PIN);   // MFRC522 인스턴스

byte CardUidByte[4] = {0x55, 0xAF, 0x07, 0x88}; //card UID 
boolean state = false; //Servo Motor 상태값

Servo servo;
const int SERVO_PIN = 7;
const int TONEPIN = 6;

void setup() {
  Serial.begin(9600);  
  while (!Serial);     
  SPI.begin();         //SPI 시작
  mfrc522.PCD_Init();  //MFRC522 card 초기화
  Serial.println(F("Warning: this example clears your mifare UID, use with care!"));

  servo.attach(SERVO_PIN);
  servo.write(0);
  delay(50);
}

void loop() {
  // 새 카드 확인
  if ( ! mfrc522.PICC_IsNewCardPresent()) return; 

  // 카드 읽기
  if ( ! mfrc522.PICC_ReadCardSerial()) return;

  //카드 확인 메세지 음
  tone(tonePin ,523,1000/8);     // 도음으로 8분음표(음길이)
  delay(1000/4*1.30);             
  noTone(tonePin ); 

  //읽은 Card UID와 등록된 Card UID가 일치하는 확인
  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
   
         state=!state;    
                 
         if(state == true){
           Serial.println("Open");
           servo.write(180);
           delay(1000);
          }
          else{
           Serial.println("Close");
           servo.write(0);
           delay(1000);
         }
         delay(2000);
   }  
}

3. 결과



4. 추가 코딩


위 코딩은 약간 도어락 같은 느낌 이였다면 출입문일 경우는 카드로 열고 닫고를 안하고 한번 대면은 열리고 나서 일정시간이 지나면 닫히게 됩니다. 출입문 경우는 어떻게 코딩할까요.

위 소스에서 한 부분만 수정하면 됩니다.

  //읽은 Card UID와 등록된 Card UID가 일치하는 확인
  if (mfrc522.uid.uidByte[0] == CardUidByte[0] && mfrc522.uid.uidByte[1] == CardUidByte[1] &&
        mfrc522.uid.uidByte[2] == CardUidByte[2] && mfrc522.uid.uidByte[3] == CardUidByte[3] ){
   
           Serial.println("Open");
           servo.write(180);
           delay(5000);
           Serial.println("Close");
           servo.write(0);
           delay(1000);                 
   }  

이렇게 수정하시면 끝납니다. 실험에서는 5초 동안 열렸다가 다시 닫히는 걸로 했는데요. 실제 출입문이면 이러지는 않겠죠. 적어도 수십초는 열려 있다가 닫혀야 겠죠. 아니면 초음파 센서같은 인간 감지 센서를 이용하여 지나 가면 자동으로 닫히게 하면 되겠죠. 그렇게 하자면 부품이 추가로 늘어나고 오히려 오늘 전달하고자 하는 의미가 제대로 전달되지 않기 때문에 이정도 까지만 하겠습니다.

[결과]


마무리


RFID-RC522 라이브러리는 쉽지 않지만 간단한 부분만 가져다가 응용하면 그래도 재밌는 표현들을 할 수 있습니다. 여러분들도 한번 이 RFID-RC522 모듈을 구하셔서 실험을 해보셨으면 합니다. 가격도 비싸지 않고 싼편이라서 괜찮은 실험 도구라고 생각 되네요.

아두이노우노에서 실험하면 SPI 통신을 하기 때문에 사실 다른 부품을 추가 할 자리가 많지 않습니다. 그럴 때는 두개 이상의 아두이노로 통신을 통해 제어하면 좋은데 그 실험을 하려면 2대정도 있어야 하는데 한대 뿐이라 아쉽네요.

아무튼 오늘 배운 내용을 토대로 다른 부품 특징들을 머리속에서 떠올려서 RFID-RC522와 연결하는 상상을 한번 해보셨으면 합니다.


댓글()