RC522 쓰기 읽기 2탄

Checker




17.11.28


요즘은 문서작업 할 것이 많아 바쁘네요. 작업에 진전이 그다지 없었습니다.
시간이 많지 않아서 RC522 쓰기를 이용해 타입을 구분해보는 작업을 하려고 합니다.


우선 모듈을 연결하고 태그를 2개 준비했습니다.


그리고 위의 태그 2개에 시리얼 모니터를 통해 쓰기를 시작합니다.




소스코드는 RC522 라이브러리에서 가져왔습니다.
코드를 대강 분석해보면 RFID TAG의 어느파트에 데이터를 쓰는지 알 수 있습니다.
readBytesUntil 은 해당 문자가 나올때까지 데이터를 읽는 함수인데, 이 녀석을 이용하여 시리얼 통신에서 보낸 ‘#’ 문자를 포함한 데이터를 버퍼에 담고, 그 데이터를 RFID TAG에 쓰는 방식입니다. 저는 RFID 타입 파트를 1번 블럭주소에 입력했고
RFID 옵션 파트를 4번에 입력했습니다.


** 코드를 보면 블럭주소 1에만 입력하는게 아니라 2에도 하는것처럼 보이는데, readBytesUntil() 에서 받는 버퍼는 34바이트 배열이고 write 할때는 16바이트 입니다. 1번 블럭에 16바이트를 쓰고 이후에 2번 블럭에 이어서 쓰는 것이라서 length를 구한 후 빈공간을 공란으로 채워서 1,2에 담는 것입니다.**



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

constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above

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

void setup() {
 Serial.begin(9600);        // Initialize serial communications with the PC
 SPI.begin();               // Init SPI bus
 mfrc522.PCD_Init();        // Init MFRC522 card
 Serial.println(F("Write personal data on a MIFARE PICC "));
}

void loop() {

 // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
 MFRC522::MIFARE_Key key;
 for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

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

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

 Serial.print(F("Card UID:"));    //Dump UID
 for (byte i = 0; i < mfrc522.uid.size; i++) {
   Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
   Serial.print(mfrc522.uid.uidByte[i], HEX);
 }
 Serial.print(F(" PICC type: "));   // Dump PICC type
 MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
 Serial.println(mfrc522.PICC_GetTypeName(piccType));

 byte buffer[34];
 byte block;
 MFRC522::StatusCode status;
 byte len;

 Serial.setTimeout(20000L) ;     // wait until 20 seconds for input from serial
 // Ask personal data: Family name
 Serial.println(F("RFID 타입을 입력하세요. 마지막에 '#'을 붙이세요"));
 len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
 for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces

 block = 1;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("PCD_Authenticate() success: "));

 // Write block
 status = mfrc522.MIFARE_Write(block, buffer, 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));

 block = 2;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // Write block
 status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));

 Serial.println(F("RIFD 옵션을 입력하세요. 마지막에 '#'을 붙이세요"));
 len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial
 for (byte i = len; i < 20; i++) buffer[i] = ' ';     // pad with spaces

 block = 4;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // Write block
 status = mfrc522.MIFARE_Write(block, buffer, 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));

 block = 5;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // Write block
 status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));


 Serial.println(" ");
 mfrc522.PICC_HaltA(); // Halt PICC
 mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD

}

위의 코드를 이용하여 두개의 태그를
타입 : A / 옵션 : TAEWOO
타입 : B / 옵션 : EXERCISE
라고 입력했습니다.


아래는 읽기 라이브러리 소스코드 입니다.

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

constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above

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

//*****************************************************************************************//
void setup() {
 Serial.begin(9600);                                           // Initialize serial communications with the PC
 SPI.begin();                                                  // Init SPI bus
 mfrc522.PCD_Init();                                              // Init MFRC522 card
 Serial.println(F("Read personal data on a MIFARE PICC:"));    //shows in serial that it is ready to read
}

//*****************************************************************************************//
void loop() {

 // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
 MFRC522::MIFARE_Key key;
 for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

 //some variables we need
 byte block;
 byte len;
 MFRC522::StatusCode status;

 //-------------------------------------------

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

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

 Serial.println(F("**Card Detected:**"));

 //-------------------------------------------

 mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card

 //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex


//---------------------------------------- 타입얻기
 byte buffer1[18];
 block = 1;
 len = 18;

 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Authentication failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 status = mfrc522.MIFARE_Read(block, buffer1, &len);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Reading failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // 타입 프린트 하기
 Serial.print(F("타입 : "));
 for (uint8_t i = 0; i < 16; i++) {
   if (buffer1[i] != 32)  { // 32가  ' ' 공란의 바이트 값
     Serial.write(buffer1[i]);
   }
 }  
 Serial.println();

 
 //-------------------------------------------
 byte buffer2[18];
 block = 4;

 //------------------------------------------- 옵션 얻기
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Authentication failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 status = mfrc522.MIFARE_Read(block, buffer2, &len);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Reading failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 //옵션 프린트하기
 Serial.print("옵션 : ");
 for (uint8_t i = 0; i < 16; i++)  {
   if (buffer2[i] != 32)  {
     Serial.write(buffer2[i]);
   }
 }
 
 //----------------------------------------

 Serial.println(F("\n**End Reading**\n"));

 delay(1000); //change value if you want to read cards faster

 mfrc522.PICC_HaltA();
 mfrc522.PCD_StopCrypto1();
}
//***************************************************************************************//





위의 코드로 리딩을 해보니 결과는 이렇습니다. 옵션: 하고 왜 줄 바꿈이 일어나는지는 잘 모르겠습니다. 시리얼 모니터에서 텍스트를 보낼 때, 캐리지 리턴, 라인피드가 입력돼서 그렇네요.

아래와 같이 코드를 마구잡이로 수정해서 태그의 값에 따라서 분기를 줬습니다.

 String buffer1Str;
 Serial.print(F("타입 : "));
 for (uint8_t i = 0; i < 16; i++) {
   if (buffer1[i] != 32)  { // 32가  ' ' 공란의 바이트 값
     Serial.write(buffer1[i]);
   } else {
     buffer1[i] = '\0';
     buffer1Str = String((char*)buffer1);
     break;
   }
 }  
 Serial.println();

 if (buffer1Str.equals("A")) {
   Serial.println(F("타입 A 입니다."));
 } else if (buffer1Str.equals("B")){
   Serial.println(F("타입 B 입니다."));
 }



결과화면입니다. 이제 RC522를 통해 분기를 줄 수 있네요.



BatteCoins 프로젝트

BattleCoins 17.12.26 요 몇 일 전부터 코인 매니저인 송대표가 찾아왔습니다. 그리고 이런저런 이야기를 나누다가 지금 진행중인 Checker를 잠깐 일시정지하고 코인 관련 아이템을 짧게 진행해보기로 했습니다. 그...