เรียนรู้และฝึกปฏิบัติ RFID ไปกับชุด RFID Basic Starter Kit (ตอนที่ 2 เริ่มต้นทดลองใช้งาน RFID ร่วมกับ NFC Shield)

เรียนรู้และฝึกปฏิบัติ RFID ไปกับชุด RFID Basic Starter Kit

(ตอนที่ 2 เริ่มต้นทดลองใช้งาน RFID ร่วมกับ NFC Shield)

07

ดูสารบัญบทความ “เรียนรู้และฝึกปฏิบัติ RFID ไปกับชุด RFID Basic Starter Kit”

ตอนที่ 2 : เริ่มต้นทดลองใช้งาน RFID ร่วมกับ NFC Shield

18

ในการทดลองนี้ใช้บอร์ด Arduino ต่อเข้ากับ NFC Shield โดยทดลองอ่านข้อมูล UID บนบัตร เขียนข้อมูลลงไปในบัตร และอ่านข้อมูลบนบัตร โดยใช้พอร์ต SPI ติดต่อกับ NFC Shield โดยกำหนดขาดังนี้

19

ภาพแสดงการต่อ NFC Shield เข้ากับบอร์ด Arduino

        ติดตั้ง Library PN532 ดาวน์โหลดได้จาก https://github.com/Seeed-Studio/PN532 หรือดาวน์โหลดจาก Example Code & Library

21

 แตกไฟล์ แล้วนำไปวางไว้ในโฟลเดอร์ .. Arduino\libraries

22

เมื่อเปิดโปรแกรม Arduino ไปที่ File > Example > PN532 จะเห็นตัวอย่างโปรแกรมของ NFC Shield อยู่

23

1.1 ทดลองอ่านข้อมูลของบัตรหรือ UID (Unique Identifier)
ในการทดลองนี้ให้ Arduino ส่งคำสั่งไปที่ NFC Shield อ่านข้อมูลของบัตร MIFARE และแสดงข้อมูลที่อ่านได้ผ่านพอร์ต Serial 
โค้ดโปรแกรมบนบอร์ด Arduino มีดังนี้

#include <SPI.h>
#include <PN532_SPI.h>
#include "PN532.h"
PN532_SPI pn532spi(SPI, 10);
PN532 nfc(pn532spi);
 
void setup()
 {
    Serial.begin(9600);
    Serial.println("Arduino_test_mifare!");
   nfc.begin();
   uint32_t versiondata = nfc.getFirmwareVersion();
      if (! versiondata) 
       {
         Serial.print("Didn't find PN53x board");
          while (1); 
      }
    Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
   Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
   Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
   nfc.SAMConfig();
   Serial.println("Waiting for an ISO14443A Card ...");
 }
 
void loop() 
{
  uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
  uint8_t uidLength;                   
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
    if (success) 
   {
      Serial.println("Found an ISO14443A card");
      Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
      Serial.print("  UID Value: ");
      nfc.PrintHex(uid, uidLength);
      Serial.println("");
   }
}

จากโค้ดจะเห็นได้ว่า ?

#include <SPI.h>
#include <PN532_SPI.h>
#include "PN532.h"
PN532_SPI pn532spi(SPI, 10);
PN532 nfc(pn532spi);

เรียกใช้งานไลบรารี่ SPI และ PN532 กำหนดขา Select Chip เป็นขา 10 จากนั้นสร้าง object PN532 ชื่อ nfc ซึ่งถูกกำหนดค่าโดย object pn532spi อีกทีหนึ่ง?

Serial.begin(9600);
    Serial.println("Arduino_test_mifare!");
   nfc.begin();
   uint32_t versiondata = nfc.getFirmwareVersion();
      if (! versiondata) 
       {
         Serial.print("Didn't find PN53x board");
          while (1); 
      }

ในฟังก์ชั่น main() กำหนดให้พอร์ต Serial Baud rate เป็น 9600 bps จากนั้นส่งข้อความ “Arduino_test_mifare!” เริ่มใช้งาน NFC Shield โดยใช้คำสั่ง .begin() ใช้คำสั่ง getFirmwareVersion() เมื่อผู้ใช้ต้องการทราบเวอร์ชัน firmware ของชิปตระกูล PN53x จากนั้นโปรแกรมจะตรวจสอบตัวแปร versiondata ถ้ามีค่าเป็น 0 ให้แสดงข้อความ “Didn’t find PN53x board” คือไม่พบ NFC Shield ต่ออยู่?

Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
   Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
   Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
   nfc.SAMConfig();
   Serial.println("Waiting for an ISO14443A Card ...");

ถ้า Arduino ตรวจสอบได้ว่ามีการเชื่อมต่อกับ Shield อยู่ แสดงข้อความ “Found chip PN5” ตามด้วยรหัสชิปตัวสุดท้าย และเวอร์ชั่น Firmware?

uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
  uint8_t uidLength;                   
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
    if (success) 
   {
      Serial.println("Found an ISO14443A card");
      Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
      Serial.print("  UID Value: ");
      nfc.PrintHex(uid, uidLength);
      Serial.println("");
   } 

ในฟังก์ชั่น loop() โปรแกรมวนตรวจสอบบัตร MIFARE ผ่านการใช้ฟังชั่น readPassiveTargetID โปรแกรมตรวจสอบมีบัตรอยู่ในระยะหรือไม่ ผ่านค่าที่ return ออกมาให้กับตัวแปร success ถ้าเป็น 1 คือมีบัตรอยู่ให้แสดงข้อความ “Found an ISO14443A card” และแสดงรหัส UID ของบัตร

24

จากภาพเมื่อผู้ใช้ทาบบัตร Arduino จะแสดงข้อมูลของบัตร MIFARE ที่อ่านได้ แสดงผลผ่าน Serial Monitor
1.2 ทดลองเขียนข้อมูลบัตร MIFARE
ในการทดลองนี้ให้ NFC Shield เขียนข้อมูลลงไปที่บัตร MIFARE โดยใช้คำสั่ง Login ใน Sector ที่ต้องการเขียน จากนั้นส่งคำสั่งเขียนข้อมูลโดยกำหนด Block และข้อมูลลงไป 
โค้ดโปรแกรมบนบอร์ด Arduino มีดังนี้

#include <SPI.h>
#include <PN532_SPI.h>
#include "PN532.h"
uint8_t data[16];  
bool authenticated = false;  
uint8_t currentblock; 
uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
PN532_SPI pn532spi(SPI, 10);
PN532 nfc(pn532spi);
 
void setup() 
{
  Serial.begin(9600);
  Serial.println("Arduino_test_write_data_mifare!");
   nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
    if (! versiondata)  {
     Serial.print("Didn't find PN53x board");
     while (1); 
    }
  nfc.SAMConfig(); 
  Serial.println("Waiting for an ISO14443A Card ..."); 
}
 
void loop() {
   uint8_t success;
   uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
   uint8_t uidLength;                   
   success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
     if (success)  {
      Serial.println("Found an ISO14443A card");
      Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
      Serial.print("  UID Value: ");
      nfc.PrintHex(uid, uidLength);
     Serial.println("");
   }  
   if (uidLength == 4) {
       Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
         if (!authenticated) {
            Serial.print("------------------------Sector ");
            Serial.print(currentblock/4, DEC);
            Serial.println("-------------------------");
            success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);
              if (success) {
              Serial.println("Authentication complete");
              success = nfc.mifareclassic_WriteDataBlock(2,data);
                if (success) {
               Serial.println("Write data complete");
              } 
              else {
               Serial.println("Write data fail!");
                     }
            }
           else {
            Serial.println("Authentication error");
           }
        }    
    } 
}

จากโค้ดจะเห็นได้ว่า?

if (uidLength == 4) {
       Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
         if (!authenticated) {
            Serial.print("------------------------Sector ");
            Serial.print(currentblock/4, DEC);
            Serial.println("-------------------------");
            success = nfc.mifareclassic_AuthenticateBlock (uid, uidLength, currentblock, 1, keyuniversal);

ในฟังก์ชั่น loop หลังจากที่ใช้คำสั่ง readPassiveTargetID เพื่อตรวจสอบบัตรอยู่หรือไม่ และตรวจสอบชนิดของบัตรจากตัวแปร uidLength

ถ้าเท่ากับ 4 คือบัตร MIFARE Classic ถ้าในครั้งแรก คือตัวแปร authenticated เป็น false ส่งคำสั่ง AuthenticateBlock พร้อมกำหนดพารามิเตอร์ รหัส UID ,ขนาดรหัสUID,Block ที่ต้องการเขียน ,Key A กำหนดเป็น 1 และรหัส Key A 

if (success) {
   Serial.println("Authentication complete");
   success = nfc.mifareclassic_WriteDataBlock(2,data);
    if (success) {
     Serial.println("Write data complete");
     }
      else {
     Serial.println("Write data fail!");
      }
     }
else {
  Serial.println("Authentication error");
}

ถ้าการ Login สำเร็จ จากนั้นใช้คำสั่ง WriteDataBlock พร้อม Block ที่ต้องการเขียนข้อมูล ในที่นี้กำหนดเป็น Block ที่ 2 และข้อมูลที่ต้องการเขียนในตัวแปร data เราสามารถตรวจสอบสถานะการเขียนข้อมูลได้จากค่าที่ return เก็บไว้ในตัวแปร success ถ้าเป็น true คือ การเขียนข้อมูลสำเร็จ หรือถ้าเป็น false คือเขียนข้อมูลไม่สำเร็จ

25

จากภาพแสดงสถานการณ์เขียนข้อมูลลงบนบัตร MIFARE ผ่าน Serial Monitor

1.3 ทดลองอ่านข้อมูลบัตร MIFARE
ในการทดลองนี้ให้ NFC Shield เขียนข้อมูลลงไปที่บัตร MIFARE ขั้นตอนจะคล้ายกับการสั่งอ่านข้อมูล คือ ใช้คำสั่ง Login ใน Sector ที่ต้องการอ่าน จากนั้นส่งคำสั่งอ่านข้อมูลโดยกำหนด Block 
โค้ดโปรแกรมบนบอร์ด Arduino มีดังนี้

#include <SPI.h>
#include <PN532_SPI.h>
#include "PN532.h"
PN532_SPI pn532spi(SPI, 10);
PN532 nfc(pn532spi);
 
void setup() {
   Serial.begin(115200);
   Serial.println("Arduino_test_write_data_mifare!");
   nfc.begin();
   uint32_t versiondata = nfc.getFirmwareVersion();
     if (! versiondata) {
     Serial.print("Didn't find PN53x board");
     while (1); // halt
    }
    nfc.SAMConfig(); 
   Serial.println("Waiting for an ISO14443A Card ..."); 
}
 
void loop() {
 uint8_t success;
 uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  
 uint8_t uidLength;  
 success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  if (success) {
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    Serial.println("");
  }
  if (uidLength == 4) {
     Serial.println("Seems to be a Mifare Classic card (4 byte UID)");
     Serial.println("Trying to authenticate block 4 with default KEYA value");
     uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
       if (success) {
        Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
        uint8_t data[16];
        success = nfc.mifareclassic_ReadDataBlock(4, data);
         if (success) {
            Serial.println("Reading Block 4:");
            nfc.PrintHexChar(data, 16);
            Serial.println("");
           delay(1000);
         }
        else {
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
    }
}