본문으로 이동

아두이노:RFID(13.56MHz): 두 판 사이의 차이

학교의 모든 지식. SMwiki
 
(같은 사용자의 중간 판 8개는 보이지 않습니다)
9번째 줄: 9번째 줄:


아두이노에서는 RFID 리더 모듈을 연결하여 태그의 고유 식별번호인 UID를 읽거나, 지원되는 태그의 메모리에 데이터를 읽고 쓸 수 있다.
아두이노에서는 RFID 리더 모듈을 연결하여 태그의 고유 식별번호인 UID를 읽거나, 지원되는 태그의 메모리에 데이터를 읽고 쓸 수 있다.
== RFID 시스템의 구성 ==
RFID 시스템은 일반적으로 다음과 같이 구성된다.
{| class="wikitable"
|+
!요소
!설명
!비고
|-
|'''태그(Tag)'''
|
* 카드, 열쇠고리, 스티커 등의 형태로 제작됨.
* UID와 사용자 데이터를 저장할 수 있음.
* 수동형 태그는 별도의 배터리 없이 리더가 만드는 전자기장으로부터 동작에 필요한 에너지를 얻음.
|
|-
|'''리더(Reader)'''
|
* 태그와 무선으로 통신함.
* 태그의 UID 또는 저장된 데이터를 읽음.
* 일부 리더는 태그 메모리에 데이터를 기록할 수 있음.
|
|-
|'''제어 장치'''
|
* 아두이노, ESP32, 라즈베리파이 등의 마이크로컨트롤러 또는 컴퓨터를 사용함.
* RFID 리더로부터 받은 정보를 처리함.
* LED, 부저, 디스플레이, 도어록 등의 장치를 제어할 수 있음.
|
|}
=== 작동 원리 ===
13.56 MHz RFID의 기본 동작 과정은 다음과 같다.
* RFID 리더가 13.56 MHz의 전자기장을 형성함.
* 리더 가까이에 있는 수동형 태그가 전자기장으로부터 동작에 필요한 에너지를 얻음.
* 리더가 태그에 명령을 전송함.
* 태그가 UID 또는 저장된 데이터를 응답함.
* 리더가 응답을 수신하여 아두이노 등의 제어 장치로 전달함.
* 제어 장치가 UID 확인, 출입 허용, 출결 기록 등의 작업을 수행함.


== 13.56MHz와 통신 규격의 구분 ==
== 13.56MHz와 통신 규격의 구분 ==
108번째 줄: 63번째 줄:
따라서 스마트폰과의 통신이 필요한 경우에는 단순히 13.56 MHz를 지원하는지만 확인하지 말고, 사용하는 모듈이 필요한 NFC 동작 모드와 태그 규격을 지원하는지 확인해야 한다.
따라서 스마트폰과의 통신이 필요한 경우에는 단순히 13.56 MHz를 지원하는지만 확인하지 말고, 사용하는 모듈이 필요한 NFC 동작 모드와 태그 규격을 지원하는지 확인해야 한다.


=== 규격 관련. ===
= 13.56 MHz의 주요 통신 규격 =
!규격
같은 주파수를 사용하는 태그와 리더라도 지원하는 통신 규격이 다르면 서로 통신할 수 없다.
!분류
{| class="wikitable" style="text-align:center;"
!주요 특징
! 규격
!대표적인 활용
! 분류
! 사용 주파수
! 주요 특징
! 대표 기술 및 제품
! 주요 용도
|-
|-
|ISO/IEC 14443 Type A
| ISO/IEC 14443 Type A
|근접형(Proximity)
| 근접형
|가까운 거리에서 비접촉식 카드와 통신함. 충돌 방지와 카드 선택 절차를 포함함.
| 13.56 MHz
|MIFARE 계열 카드, 교통카드, 출입카드, 일부 NFC 태그
| Type A 방식의 변조, 부호화, 충돌 방지 및 카드 선택 절차를 사용함.
| MIFARE Classic, MIFARE Ultralight, MIFARE DESFire, NTAG 계열
| 교통카드, 출입카드, 학생증, NFC 태그
|-
|-
|ISO/IEC 14443 Type B
| ISO/IEC 14443 Type B
|근접형(Proximity)
| 근접형
|Type A와 같은 주파수를 사용하지만 변조, 부호화 및 초기화 방식이 다름.
| 13.56 MHz
|전자신분증, 전자여권, 비접촉식 스마트카드
| Type A와 같은 주파수를 사용하지만 변조, 부호화 및 초기화 방식이 다름.
| Type B 비접촉식 스마트카드
| 전자신분증, 전자여권, 비접촉식 스마트카드
|-
|-
|FeliCa
| FeliCa
|근접형 비접촉 통신
| 근접형
|13.56 MHz를 사용하는 비접촉식 카드 기술로, ISO/IEC 14443 Type A/B와는 별도의 통신 방식을 사용함.
| 13.56 MHz
|교통카드, 전자화폐, 출입관리
| ISO/IEC 14443 Type A/B와는 다른 통신 방식을 사용하는 비접촉식 카드 기술임.
| FeliCa 카드 및 모바일 FeliCa
| 교통카드, 전자화폐, 출입관리
|-
|-
|ISO/IEC 15693
| ISO/IEC 15693
|근방형(Vicinity)
| 근방형
|ISO/IEC 14443보다 비교적 먼 거리에서 태그를 식별하는 용도에 적합함.
| 13.56 MHz
|도서 관리, 자산 관리, 문서 관리, 산업용 태그
| ISO/IEC 14443보다 비교적 먼 거리에서 태그를 식별하는 용도에 적합함.
| ICODE, ST25TV 계열
| 도서 관리, 자산 관리, 문서 추적, 산업용 태그
|-
|-
|ISO/IEC 18000-3
| ISO/IEC 18000-3
|품목 관리용 HF RFID
| 품목 관리용 HF RFID
|13.56 MHz 대역에서 물품 식별 및 관리에 사용하는 무선 인터페이스를 정의함.
| 13.56 MHz
|물류, 재고 및 품목 관리
| 물품 식별과 관리를 위한 HF RFID 무선 인터페이스를 규정함.
| 산업용 HF RFID 태그
| 물류, 재고 및 품목 관리
|-
|-
|NFC Forum 규격
| NFC Forum 규격
|NFC
| NFC
|스마트폰과 NFC 장치 사이의 상호 운용을 위한 태그 유형, 데이터 형식 및 동작 방식을 규정함.
(NFC 기기간 통신 가능)
|스마트폰 태그 인식, 기기 연결, 정보 전달
| 13.56 MHz
| NFC 장치 상호 운용을 위한 태그 유형, 동작 방식 및 데이터 형식을 규정함.
| NFC Forum Type 1~5 Tag, NDEF
| 스마트폰 태그 인식, 정보 전달, 기기 연결
|}
|}
 
 
=== ISO/IEC 14443 ===
=== ISO/IEC 14443 ===
'''ISO/IEC 14443'''은 13.56 MHz를 사용하는 근접형 비접촉식 카드 규격이다. 가까운 거리에서 카드를 인식하고 데이터를 빠르게 교환하는 용도에 적합하다.
ISO/IEC 14443은 13.56 MHz를 사용하는 근접형 비접촉식 카드 규격이다. 가까운 거리에서 카드를 인식하고 데이터를 빠르게 교환하는 용도에 적합하다. ISO/IEC 14443은 크게 Type A와 Type B로 구분된다.
 
ISO/IEC 14443은 크게 '''Type A'''와 '''Type B'''로 구분된다.
 
{| class="wikitable"
{| class="wikitable"
!구분
!구분
174번째 줄: 143번째 줄:
|Type A만 지원하는 리더에서는 Type B 태그를 인식할 수 없음.
|Type A만 지원하는 리더에서는 Type B 태그를 인식할 수 없음.
|Type B만
|Type B만
|}
= RC522 모듈 =
입문용으로 많이 사용하는 모듈.
{| class="wikitable"
!항목
!사양
|-
|동작 주파수
|13.56 MHz
|-
|지원 규격
|ISO/IEC 14443 Type A
|-
|지원 태그
|MIFARE 및 NTAG 계열
|-
|일반적인 전원
|3.3 V
|-
|대표 인식거리
|최대 약 50 mm
|}
{| class="wikitable" style="text-align:center;"
!규격
! RC522 지원
|-
|ISO/IEC 14443 Type A
| 지원
|-
|ISO/IEC 14443 Type B
| 미지원
|-
|FeliCa
| 미지원
|-
|ISO/IEC 15693
| 미지원
|-
|ISO/IEC 18000-3
| 미지원
|-
|NFC Forum 규격
| 일부 Type A 태그만 제한적으로 인식
|}
=== 연결 예시 ===
https://javalab.org/wp-content/uploads/arduino_rfid_test_4.png
{| class="wikitable" style="text-align:center; width:100%;"
! 아두이노 우노 R3
! RFID-RC522 리더
!역할
|-
| 3.3V
| VCC
|RC522에 3.3V 전원을 공급
|-
| GND
| GND
|두 장치의 전압 기준을 통일하는 접지
|-
| D13
| SCK
|SPI 통신의 클록 신호 전송
|-
| D12
| MISO
|RC522가 읽은 데이터를 Arduino로 전송
|-
| D11
| MOSI
|Arduino가 명령과 데이터를 RC522로 전송
|-
| D10
| SDA
|통신할 RC522를 선택하는 장치 선택 신호
|-
| D9
| RST
|RC522를 초기화하거나 재시작하는 리셋 신호
|-
|연결 안함
|IRQ
|카드 감지 등의 사건을 알리는 인터럽트 신호
|}
=== 다룰 때 유의사항 ===
* 사용 중, 리더에 전원 공급이 끊기면 보드를 다시 시작 해야 제대로 작동한다.
== 코드 작성 예시 ==
=== 일반 읽기 ===
MFRC522 라이브러리 설치가 필요하다.<syntaxhighlight lang="c++">#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
constexpr byte SS_PIN = 10;
constexpr byte RST_PIN = 9;
MFRC522 mfrc522(SS_PIN, RST_PIN);
void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();
  Serial.println(F("RFID UID Reader Ready"));
}
void loop() {
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  if (!mfrc522.PICC_ReadCardSerial()) {
    mfrc522.PCD_AntennaOff();
    delay(10);
    mfrc522.PCD_AntennaOn();
    return;
  }
  Serial.print(F("UID: "));
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    if (mfrc522.uid.uidByte[i] < 0x10) {
      Serial.print('0');
    }
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    if (i < mfrc522.uid.size - 1) {
      Serial.print(' ');
    }
  }
  Serial.println();
  Serial.print(F("Type: "));
  Serial.println(mfrc522.PICC_GetTypeName(
      mfrc522.PICC_GetType(mfrc522.uid.sak)));
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  Serial.println();
  delay(200);
}</syntaxhighlight>
= 세부 함수 =
기본적으로 dump(모듈과 구조 넣어준다.)로 읽고, 여기에서 반환한 배열을 read 함수로 정리한다.
기본 사용 구조는 다음과 같다.<syntaxhighlight lang="c++">
CardData card;
dumpCardData(mfrc522, card);  // 태그 → card
readCardData(card);          // card 내용 확인
// card 내용 변경(선택)
for (byte i = 0; i < 16; i++) {
  card.memory[1][i] = 0x00;
}
writeCardData(mfrc522, card); // card → 태그
</syntaxhighlight>
=== 정보 저장 구조 ===
한번에 모든 정보를 저장하기 위해 이처럼 다룬다.<syntaxhighlight lang="c++">
struct CardData {
  byte uid[10];
  byte uidSize;
  byte sak;
  byte memory[64][16];
};
</syntaxhighlight>
=== dump 함수 ===
변수를 먼저 정의하고 값을 바꾸는 방식.<syntaxhighlight lang="c++">
bool dumpCardData(MFRC522 &mfrc522, CardData &card) {
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  // UID 저장
  card.uidSize = mfrc522.uid.size;
  for (byte i = 0; i < card.uidSize; i++) {
    card.uid[i] = mfrc522.uid.uidByte[i];
  }
  // SAK 저장
  card.sak = mfrc522.uid.sak;
  byte buffer[18];
  // MIFARE Classic 1K
  for (byte block = 0; block < 64; block++) {
    // 새로운 섹터마다 인증
    if (block % 4 == 0) {
      MFRC522::StatusCode status =
        mfrc522.PCD_Authenticate(
          MFRC522::PICC_CMD_MF_AUTH_KEY_A,
          block,
          &key,
          &(mfrc522.uid)
        );
      if (status != MFRC522::STATUS_OK) {
        Serial.print("Authentication failed: block ");
        Serial.println(block);
        return false;
      }
    }
    byte size = sizeof(buffer);
    MFRC522::StatusCode status =
      mfrc522.MIFARE_Read(block, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
      Serial.print("Read failed: block ");
      Serial.println(block);
      return false;
    }
    for (byte i = 0; i < 16; i++) {
      card.memory[block][i] = buffer[i];
    }
  }
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  return true;
}
</syntaxhighlight>
=== read 함수 ===
dump에서 조작한 값을 읽어 정보를 반환한다.<syntaxhighlight lang="c++">
void readCardData(const CardData &card) {
  Serial.println();
  Serial.println("================================");
  Serial.println("          CARD INFORMATION");
  Serial.println("================================");
  // UID
  Serial.print("UID      : ");
  for (byte i = 0; i < card.uidSize; i++) {
    if (card.uid[i] < 0x10)
      Serial.print("0");
    Serial.print(card.uid[i], HEX);
    if (i < card.uidSize - 1)
      Serial.print(":");
  }
  Serial.println();
  // UID 크기
  Serial.print("UID SIZE  : ");
  Serial.print(card.uidSize);
  Serial.println(" bytes");
  // SAK
  Serial.print("SAK      : 0x");
  if (card.sak < 0x10)
    Serial.print("0");
  Serial.println(card.sak, HEX);
  Serial.println();
  Serial.println("----------- MEMORY -----------");
  for (byte block = 0; block < 64; block++) {
    Serial.print("Block ");
    if (block < 10)
      Serial.print(" ");
    Serial.print(block);
    Serial.print(" : ");
    for (byte i = 0; i < 16; i++) {
      if (card.memory[block][i] < 0x10)
        Serial.print("0");
      Serial.print(card.memory[block][i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
  Serial.println("================================");
}
</syntaxhighlight>
=== write 함수 ===
<syntaxhighlight lang="c++">bool writeCardData(MFRC522 &mfrc522, const CardData &card) {
  MFRC522::MIFARE_Key key;
  // 기본 Key A
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  Serial.println();
  Serial.println("================================");
  Serial.println("          WRITE CARD DATA");
  Serial.println("================================");
  for (byte block = 1; block < 64; block++) {
    // Sector Trailer는 일단 건너뜀
    if (block % 4 == 3)
      continue;
    // 각 Sector의 첫 번째 데이터 블록에서 인증
    if (block % 4 == 1) {
      MFRC522::StatusCode status =
        mfrc522.PCD_Authenticate(
          MFRC522::PICC_CMD_MF_AUTH_KEY_A,
          block,
          &key,
          &(mfrc522.uid)
        );
      if (status != MFRC522::STATUS_OK) {
        Serial.print("AUTH FAILED - Block ");
        Serial.println(block);
        mfrc522.PCD_StopCrypto1();
        return false;
      }
    }
    // card.memory의 내용을 그대로 기록
    MFRC522::StatusCode status =
      mfrc522.MIFARE_Write(
        block,
        card.memory[block],
        16
      );
    if (status != MFRC522::STATUS_OK) {
      Serial.print("WRITE FAILED - Block ");
      Serial.println(block);
      mfrc522.PCD_StopCrypto1();
      return false;
    }
    Serial.print("Block ");
    Serial.print(block);
    Serial.println(" : OK");
  }
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  Serial.println("================================");
  return true;
}</syntaxhighlight>

2026년 9월 10일 (목) 08:54 기준 최신판

아두이노 관련 정보를 모으기 위한 틀. 틀:아두이노

  1. 아두이노:개요
  2. 아두이노:하드웨어
    1. 아두이노:우노보드
    2. 아두이노:ESP32
  3. 아두이노:코드
    1. 아두이노:컴퓨터에서 보드로
      1. 아두이노:VSCode에서 작업
    2. 아두이노:안드로이드에서 보드로
    3. 아두이노:기초 문법
    4. 아두이노:라이브러리
  4. 아두이노:핀 사용
    1. 아두이노:전원공급
  5. 아두이노:시리얼 통신
    1. 아두이노:엑셀기록
    2. 아두이노:파이썬과 통신
  6. 아두이노:편의함수
  7. 센서 사용
    1. 아두이노:모션센서(미완)
    2. 아두이노:온습도센서
    3. 아두이노:조도센서(미완)
    4. 아두이노:인체감지센서(미완)
    5. 아두이노:pH미터 만들기(Gravity 아날로그 pH센서)
    6. 가스센서
      1. 아두이노:MOS 센서
  8. 아두이노:LCD 사용
  9. 아두이노:스위치 사용
  10. 아두이노:릴레이
  11. 통신 관련, 정보 교환
    1. 아두이노:2.4GHz 송수신
      1. 아두이노:WIFI
      2. 아두이노:블루투스(외장모듈)
      3. 아두이노:RF통신 nRF24L01+
    2. 아두이노:IR 송수신
    3. 아두이노:RFID
      1. 아두이노:RFID(13.56MHz)
  12. 아두이노:해결되지 않은 다양한 의문들
  13. 수업용 간단 실습
    1. 아두이노:LED
    2. 아두이노:초음파센서
    3. 아두이노:전압계 만들기
    4. 아두이노:저항계 만들기
  14. 아두이노 모터 출력
    1. 아두이노:서보 모터
    2. 아두이노:DC 모터
    3. 아두이노:BLDC 모터
  15. 키 조작
    1. 아두이노:아케이드 버튼 입력
    2. 아두이노:키보드 키 조작
  16. 미완문서
    1. 아두이노:스테핑 모터(미완)
  17. 분류:아두이노 프로젝트

아두이노로 RFID 13.56MHz 규격을 다루는 것에 관한 문서.

RFID 자체에 관한 내용은 RFID 문서 참고

13.56 MHz 대역을 사용하는 RFID는 일반적으로 HF(High Frequency) RFID로 분류되며, 교통카드, 학생증, 사원증, 출입카드, 전자여권, NFC 태그 등에 활용된다.

아두이노에서는 RFID 리더 모듈을 연결하여 태그의 고유 식별번호인 UID를 읽거나, 지원되는 태그의 메모리에 데이터를 읽고 쓸 수 있다.

13.56MHz와 통신 규격의 구분

[편집 | 원본 편집]

13.56 MHz는 RFID 통신에서 사용하는 반송파 주파수를 의미한다. 같은 13.56 MHz를 사용하더라도 모든 리더와 태그가 서로 호환되는 것은 아니다.

모듈 선택 기준

[편집 | 원본 편집]
목적 적합한 모듈 예시 선택 이유
저비용 입문 실습 RC522 배선과 UID 읽기 실습이 비교적 간단함.
스마트폰 NFC와의 연동 PN532 또는 NFC 전용 모듈 RC522보다 NFC 관련 지원 범위가 넓음.
ISO/IEC 15693 태그 실습 해당 규격을 지원하는 리더 RC522는 일반적으로 ISO/IEC 15693을 지원하지 않음.
다양한 종류의 13.56 MHz 태그 실험 복수 규격을 지원하는 리더 13.56 MHz라는 주파수만으로는 태그 호환성을 보장할 수 없음.
출입통제 보안 실험 보안 기능을 지원하는 태그와 리더 단순 UID 비교보다 인증 및 암호화 기능이 필요함.

주의 사항

[편집 | 원본 편집]
  • RFID 리더와 태그가 모두 13.56 MHz를 사용하더라도 통신 규격이 다르면 인식되지 않을 수 있음.
  • RC522 모듈은 일반적으로 3.3 V 전원을 사용함.
  • 안테나 주변에 금속이 있으면 인식 성능이 저하될 수 있음.
  • 태그와 리더의 방향 및 거리에 따라 인식 여부가 달라질 수 있음.
  • 하나의 리더가 모든 MIFARE 및 NFC 기능을 지원하는 것은 아님.
  • UID는 카드 종류에 따라 길이가 다를 수 있으므로 UID 길이를 고정하여 처리하지 않는 것이 좋음.
  • 결제카드나 실제 출입카드의 데이터를 임의로 읽거나 복제해서는 안 됨.
  • 실습에는 교육용으로 제공된 RFID 카드와 태그를 사용해야 함.

RFID와 NFC의 관계

[편집 | 원본 편집]

NFC는 13.56 MHz 대역을 사용하는 근거리 무선 통신 기술이다. RFID와 관련된 기술이지만, 모든 13.56 MHz RFID 장치가 NFC의 모든 기능을 지원하는 것은 아니다.

따라서 스마트폰과의 통신이 필요한 경우에는 단순히 13.56 MHz를 지원하는지만 확인하지 말고, 사용하는 모듈이 필요한 NFC 동작 모드와 태그 규격을 지원하는지 확인해야 한다.

13.56 MHz의 주요 통신 규격

[편집 | 원본 편집]

같은 주파수를 사용하는 태그와 리더라도 지원하는 통신 규격이 다르면 서로 통신할 수 없다.

규격 분류 사용 주파수 주요 특징 대표 기술 및 제품 주요 용도
ISO/IEC 14443 Type A 근접형 13.56 MHz Type A 방식의 변조, 부호화, 충돌 방지 및 카드 선택 절차를 사용함. MIFARE Classic, MIFARE Ultralight, MIFARE DESFire, NTAG 계열 교통카드, 출입카드, 학생증, NFC 태그
ISO/IEC 14443 Type B 근접형 13.56 MHz Type A와 같은 주파수를 사용하지만 변조, 부호화 및 초기화 방식이 다름. Type B 비접촉식 스마트카드 전자신분증, 전자여권, 비접촉식 스마트카드
FeliCa 근접형 13.56 MHz ISO/IEC 14443 Type A/B와는 다른 통신 방식을 사용하는 비접촉식 카드 기술임. FeliCa 카드 및 모바일 FeliCa 교통카드, 전자화폐, 출입관리
ISO/IEC 15693 근방형 13.56 MHz ISO/IEC 14443보다 비교적 먼 거리에서 태그를 식별하는 용도에 적합함. ICODE, ST25TV 계열 도서 관리, 자산 관리, 문서 추적, 산업용 태그
ISO/IEC 18000-3 품목 관리용 HF RFID 13.56 MHz 물품 식별과 관리를 위한 HF RFID 무선 인터페이스를 규정함. 산업용 HF RFID 태그 물류, 재고 및 품목 관리
NFC Forum 규격 NFC

(NFC 기기간 통신 가능)

13.56 MHz NFC 장치 간 상호 운용을 위한 태그 유형, 동작 방식 및 데이터 형식을 규정함. NFC Forum Type 1~5 Tag, NDEF 스마트폰 태그 인식, 정보 전달, 기기 연결

ISO/IEC 14443

[편집 | 원본 편집]

ISO/IEC 14443은 13.56 MHz를 사용하는 근접형 비접촉식 카드 규격이다. 가까운 거리에서 카드를 인식하고 데이터를 빠르게 교환하는 용도에 적합하다. ISO/IEC 14443은 크게 Type A와 Type B로 구분된다.

구분 Type A Type B
사용 주파수 13.56 MHz 13.56 MHz
분류 근접형 카드 근접형 카드
통신 방식 Type A 방식의 변조, 부호화 및 초기화 절차 사용 Type B 방식의 변조, 부호화 및 초기화 절차 사용
대표 사례 MIFARE 계열, 일부 NFC 태그 전자신분증 및 비접촉식 스마트카드의 일부
상호 호환성 Type A만 지원하는 리더에서는 Type B 태그를 인식할 수 없음. Type B만

RC522 모듈

[편집 | 원본 편집]

입문용으로 많이 사용하는 모듈.

항목 사양
동작 주파수 13.56 MHz
지원 규격 ISO/IEC 14443 Type A
지원 태그 MIFARE 및 NTAG 계열
일반적인 전원 3.3 V
대표 인식거리 최대 약 50 mm
규격 RC522 지원
ISO/IEC 14443 Type A 지원
ISO/IEC 14443 Type B 미지원
FeliCa 미지원
ISO/IEC 15693 미지원
ISO/IEC 18000-3 미지원
NFC Forum 규격 일부 Type A 태그만 제한적으로 인식

연결 예시

[편집 | 원본 편집]

arduino_rfid_test_4.png

아두이노 우노 R3 RFID-RC522 리더 역할
3.3V VCC RC522에 3.3V 전원을 공급
GND GND 두 장치의 전압 기준을 통일하는 접지
D13 SCK SPI 통신의 클록 신호 전송
D12 MISO RC522가 읽은 데이터를 Arduino로 전송
D11 MOSI Arduino가 명령과 데이터를 RC522로 전송
D10 SDA 통신할 RC522를 선택하는 장치 선택 신호
D9 RST RC522를 초기화하거나 재시작하는 리셋 신호
연결 안함 IRQ 카드 감지 등의 사건을 알리는 인터럽트 신호

다룰 때 유의사항

[편집 | 원본 편집]
  • 사용 중, 리더에 전원 공급이 끊기면 보드를 다시 시작 해야 제대로 작동한다.

코드 작성 예시

[편집 | 원본 편집]

일반 읽기

[편집 | 원본 편집]

MFRC522 라이브러리 설치가 필요하다.

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

constexpr byte SS_PIN = 10;
constexpr byte RST_PIN = 9;

MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();

  Serial.println(F("RFID UID Reader Ready"));
}

void loop() {
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  if (!mfrc522.PICC_ReadCardSerial()) {
    mfrc522.PCD_AntennaOff();
    delay(10);
    mfrc522.PCD_AntennaOn();
    return;
  }

  Serial.print(F("UID: "));

  for (byte i = 0; i < mfrc522.uid.size; i++) {
    if (mfrc522.uid.uidByte[i] < 0x10) {
      Serial.print('0');
    }

    Serial.print(mfrc522.uid.uidByte[i], HEX);

    if (i < mfrc522.uid.size - 1) {
      Serial.print(' ');
    }
  }

  Serial.println();
  Serial.print(F("Type: "));
  Serial.println(mfrc522.PICC_GetTypeName(
      mfrc522.PICC_GetType(mfrc522.uid.sak)));

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();

  Serial.println();
  delay(200);
}

세부 함수

[편집 | 원본 편집]

기본적으로 dump(모듈과 구조 넣어준다.)로 읽고, 여기에서 반환한 배열을 read 함수로 정리한다.

기본 사용 구조는 다음과 같다.

CardData card;

dumpCardData(mfrc522, card);  // 태그 → card

readCardData(card);           // card 내용 확인

// card 내용 변경(선택)
for (byte i = 0; i < 16; i++) {
  card.memory[1][i] = 0x00;
}

writeCardData(mfrc522, card); // card → 태그

정보 저장 구조

[편집 | 원본 편집]

한번에 모든 정보를 저장하기 위해 이처럼 다룬다.

struct CardData {
  byte uid[10];
  byte uidSize;

  byte sak;

  byte memory[64][16];
};

dump 함수

[편집 | 원본 편집]

변수를 먼저 정의하고 값을 바꾸는 방식.

bool dumpCardData(MFRC522 &mfrc522, CardData &card) {

  MFRC522::MIFARE_Key key;

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }

  // UID 저장
  card.uidSize = mfrc522.uid.size;

  for (byte i = 0; i < card.uidSize; i++) {
    card.uid[i] = mfrc522.uid.uidByte[i];
  }

  // SAK 저장
  card.sak = mfrc522.uid.sak;

  byte buffer[18];

  // MIFARE Classic 1K
  for (byte block = 0; block < 64; block++) {

    // 새로운 섹터마다 인증
    if (block % 4 == 0) {

      MFRC522::StatusCode status =
        mfrc522.PCD_Authenticate(
          MFRC522::PICC_CMD_MF_AUTH_KEY_A,
          block,
          &key,
          &(mfrc522.uid)
        );

      if (status != MFRC522::STATUS_OK) {
        Serial.print("Authentication failed: block ");
        Serial.println(block);
        return false;
      }
    }

    byte size = sizeof(buffer);

    MFRC522::StatusCode status =
      mfrc522.MIFARE_Read(block, buffer, &size);

    if (status != MFRC522::STATUS_OK) {
      Serial.print("Read failed: block ");
      Serial.println(block);
      return false;
    }

    for (byte i = 0; i < 16; i++) {
      card.memory[block][i] = buffer[i];
    }
  }

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();

  return true;
}

read 함수

[편집 | 원본 편집]

dump에서 조작한 값을 읽어 정보를 반환한다.

void readCardData(const CardData &card) {

  Serial.println();
  Serial.println("================================");
  Serial.println("          CARD INFORMATION");
  Serial.println("================================");

  // UID
  Serial.print("UID       : ");

  for (byte i = 0; i < card.uidSize; i++) {

    if (card.uid[i] < 0x10)
      Serial.print("0");

    Serial.print(card.uid[i], HEX);

    if (i < card.uidSize - 1)
      Serial.print(":");
  }

  Serial.println();

  // UID 크기
  Serial.print("UID SIZE  : ");
  Serial.print(card.uidSize);
  Serial.println(" bytes");

  // SAK
  Serial.print("SAK       : 0x");

  if (card.sak < 0x10)
    Serial.print("0");

  Serial.println(card.sak, HEX);

  Serial.println();
  Serial.println("----------- MEMORY -----------");

  for (byte block = 0; block < 64; block++) {

    Serial.print("Block ");

    if (block < 10)
      Serial.print(" ");

    Serial.print(block);
    Serial.print(" : ");

    for (byte i = 0; i < 16; i++) {

      if (card.memory[block][i] < 0x10)
        Serial.print("0");

      Serial.print(card.memory[block][i], HEX);
      Serial.print(" ");
    }

    Serial.println();
  }

  Serial.println("================================");
}

write 함수

[편집 | 원본 편집]
bool writeCardData(MFRC522 &mfrc522, const CardData &card) {

  MFRC522::MIFARE_Key key;

  // 기본 Key A
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }

  Serial.println();
  Serial.println("================================");
  Serial.println("          WRITE CARD DATA");
  Serial.println("================================");

  for (byte block = 1; block < 64; block++) {

    // Sector Trailer는 일단 건너뜀
    if (block % 4 == 3)
      continue;

    // 각 Sector의 첫 번째 데이터 블록에서 인증
    if (block % 4 == 1) {

      MFRC522::StatusCode status =
        mfrc522.PCD_Authenticate(
          MFRC522::PICC_CMD_MF_AUTH_KEY_A,
          block,
          &key,
          &(mfrc522.uid)
        );

      if (status != MFRC522::STATUS_OK) {

        Serial.print("AUTH FAILED - Block ");
        Serial.println(block);

        mfrc522.PCD_StopCrypto1();

        return false;
      }
    }

    // card.memory의 내용을 그대로 기록
    MFRC522::StatusCode status =
      mfrc522.MIFARE_Write(
        block,
        card.memory[block],
        16
      );

    if (status != MFRC522::STATUS_OK) {

      Serial.print("WRITE FAILED - Block ");
      Serial.println(block);

      mfrc522.PCD_StopCrypto1();

      return false;
    }

    Serial.print("Block ");
    Serial.print(block);
    Serial.println(" : OK");
  }

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();

  Serial.println("================================");

  return true;
}