เรียนรู้และฝึกปฏิบัติ RFID ไปกับชุด RFID Basic Starter Kit
(ตอนที่ 2 เริ่มต้นทดลองใช้งาน RFID ร่วมกับ NFC Shield)
ดูสารบัญบทความ “เรียนรู้และฝึกปฏิบัติ RFID ไปกับชุด RFID Basic Starter Kit”
ตอนที่ 2 : เริ่มต้นทดลองใช้งาน RFID ร่วมกับ NFC Shield
![18](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_18.png)
ในการทดลองนี้ใช้บอร์ด Arduino ต่อเข้ากับ NFC Shield โดยทดลองอ่านข้อมูล UID บนบัตร เขียนข้อมูลลงไปในบัตร และอ่านข้อมูลบนบัตร โดยใช้พอร์ต SPI ติดต่อกับ NFC Shield โดยกำหนดขาดังนี้
![19](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_19.png)
![](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_20-1.png)
ภาพแสดงการต่อ NFC Shield เข้ากับบอร์ด Arduino
ติดตั้ง Library PN532 ดาวน์โหลดได้จาก https://github.com/Seeed-Studio/PN532 หรือดาวน์โหลดจาก Example Code & Library
![21](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_21.png)
แตกไฟล์ แล้วนำไปวางไว้ในโฟลเดอร์ .. Arduino\libraries
![22](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_22-1024x353.png)
เมื่อเปิดโปรแกรม Arduino ไปที่ File > Example > PN532 จะเห็นตัวอย่างโปรแกรมของ NFC Shield อยู่
![23](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_23.png)
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](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_24.png)
จากภาพเมื่อผู้ใช้ทาบบัตร 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](https://blog.thaieasyelec.com/wp-content/uploads/2020/08/112_25.png)
จากภาพแสดงสถานการณ์เขียนข้อมูลลงบนบัตร 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?"); } } } }