KKM: PN532 NFC + RFID

Početnik si s Croduinom. Ili s elektronikom? Za oko ti je zapeo određeni modul, ali ne znaš kako ga koristiti? Bez brige, tu je KKM! Kako Koristiti Module (KKM) je serija blog tutorijala e-radionice na kojoj ćeš pronaći sve što ti treba kako bi započeo rad sa svojim omiljenim modulom. Tutorijali obuhvaćaju: tehničke karakteristike, princip rada, upute kako povezati modul s Croduinom te osnovni kod. Sve ostalo prepuštamo tebi na maštu.

UVOD

U ovom tutorijalu upoznat ćemo se sa PN532 modulom koji nam omogućuje NFC i RFID komunikaciju.
RFID komunikaciju smo već spominjali prije u tutorijalu za RDM6300 modul, te znamo da s njom možemo čitati kodove s kartica, a u nastavku ćemo vidjeti što je drukčije kod NFC komunikacije te kako koristiti modul.
 

KAKO RADI?

RFID je vrsta jednosmjerne komunikacije koja nam omogućuje da s kartice ili taga pročitamo kod koji je spremljen u čipu koji se nalazi na kartici (tagu). NFC se ne razlikuje puno od RFID komunikacije, no jedna od bitnijih razlika je što s ovom vrstom komunikacije možemo osim čitanja UID koda kartice i pisati/čitati poruke na karticu(tag).
Ovaj modul radi kao i svaki RFID ili NFC modul. Na pločici ima ugrađenu antenu koja je označena s bijelom linijom oko ruba pločice, te prilikom korištenja moramo paziti da sve linije za komunikaciju ili napajanje idu okomito na antenu kako ne bi imali smetnje. Kartice i tagovi također imaju antene i čipove unutar sebe, a pomoću njih se napajaju i komuniciraju sa RFID/NFC modulom. Kada karticu dovoljno približimo modulu ona se aktivira( preko antene čip u njoj dobije napajanje) te RFID/NFC modul može komunicirati s njom.
PN532 modul daje nam mogućnost čitanja RFID i NFC kartica, kao i pisanje i čitanje poruka na NFC kartice što ćemo vidjeti u primjerima koda.

KAKO POVEZATI?

Modul je vrlo praktičan za povezivanje s mikrokontrolerom jer podržava I2C, HSU ( High Speed UART) i SPI komunikaciju, te možemo birati koja komunikacija nam bolje odgovara za određenu upotrebu. Za izbor komunikacije potrebno je pomaknuti prekidače koji se nalaze na modulu. U primjeru ćemo proći kroz sva tri načina spajanje modula i dati primjer koda za sve tri komunikacije, a zatim ćemo proći pisanje i čitanje poruka na NFC karticu. Za SPI komunikaciju koristimo 8 pinski header( spaja se 6 pinova) , te spajamo potrebne pinove s mikrokontrolerom kako je prikazano u primjeru. Za I2C i HSU komunikaciju se koristi 4 pinski header na kojemu imamo GND, VCC, TXD(SDA) i RXD(SCL) pinove, te kako možemo primijetiti za HSU i I2C se koriste isti pinovi( oznake za HSU su sa stražnje strane, a za I2C s prednje strane modula).
Za početak ćemo proći HSU i SPI komunikaciju s jednostavnim primjerom koda za očitavanje UID koda s RFID kartica, a nakon toga testiramo NFC komunikaciju, te ćemo za tu primjenu modul sa Croduinom povezati preko I2C komunikacije.

ARDUINO KOD

Za korištenje modula trebamo preuzeti biblioteku s linka. Kada preuzmemo zip datoteku potrebno ju je raspakirati i dodati sve mape (ima ih 6) u Arduino library mapu. Ako ne znate gdje se nalazi Arduino library mapa pogledajte tutorijal kako instalirati novu biblioteku.

RFID

 

HSU (HIGH SPEED UART)

Modul dolazi podešen za HSU komunikaciju ( obje sklopke trebaju biti u položaju 0), pa ćemo prvi primjer napraviti s tom vrstom komunikacije između modula i Croduina. Modul spojimo prema shemi, te na Croduino prebacimo dani kod i trebali bi moći pročitati UID kod s kartice ili taga ovisno što koristimo.
 

//uključujemo biblioteku SoftwareSerial koja softverski implementira serijsku komunikaciju na određenim pinovima
#include <SoftwareSerial.h>
 
//uključujemo biblioteku za softverski HSU(High-speed UART) i biblioteku za PN532 modul
#include <PN532_SWHSU.h>
#include <PN532.h>
 
SoftwareSerial SWSerial( 10, 11 );//(RX,TX) Konstruktor za našu biblioteku SoftwareSerial u kojem definiramo pinove na koje spajamo modul
//Konstruktori za biblioteke koje služe za komunikaciju s modulom
PN532_SWHSU pn532swhsu( SWSerial );//Konstruktor za High speed UART
PN532 nfc( pn532swhsu ); // konstruktor za PM532 biblioteku
 
void setup(void) {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("Hello!");//ispisujemo pozdravnu poruku na Serial monitor
nfc.begin();//Inicijalizacija komunikacije s modulom
uint32_t versiondata = nfc.getFirmwareVersion(); //tražimo od modula verziju Firmwarea i spremamo u varijablu versiondata
//ako nismo dobili verziju firmwarea od modula ispisujemo na Serial monitor da nije pronađen modul i ostajemo u beskonačnoj while petlji
if (! versiondata) {
Serial.print("Modul PN532 nije pronadjen..Provjerite kako je spojen");
while (1);
}
//ako je komunikacija s modulom uspostavljena ispisujemo verziju firmwarea
Serial.print("Pronadjen modul 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);
//konfiguriramo modul
nfc.SAMConfig();
//Ispisujemo poruku da treba prisloniti karticu
Serial.println("Prislonite karticu ili tag ...");
}
 
void loop(void) {
boolean success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // buffer u koji spremamo kod s kartice
uint8_t uidLength; // zapisujemo duljinu UID koda (4 ili 7 byta)
// tražimo od modula da pročita karticu( u varijablu success sprema dali ima ili nema kartice, a ako ima u varijablu uid sprema kod s kartice
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
 
//ako je modul pročitao karticu ispisujemo kolike je duljine kod na kartici( 4 ili 7 byta) te nakon toga i kod kartice
if (success) {
Serial.println("Pronadjena kartica!");
Serial.print("Duljina UID koda: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
Serial.print("UID Kod: ");
// u HEX obliku ispisujemo kod s kartice
for (uint8_t i=0; i < uidLength; i++)
{
Serial.print(" 0x");Serial.print(uid[i], HEX);
}
Serial.println("");
 
delay(1000);// pauza od jedne sekunde do ponovnog očitavanja
}
// ako kartica nije pronađena ispisujemo poruku da čekamo karticu
else
{
Serial.println("Vrijeme isteklo.. Cekam karticu");
delay(500);// pauza od pola sekunde da ne ispisuje konstantno poruku ako nema kartice
}
}
 

SPI KOMUNIKACIJA

Kao što znamo za SPI komunikaciju potrebno nam je 4 voda + još 2 za napajanje, ali unatoč tome što ima više vodova ova komunikacija ima veću brzinu prijenosa od I2C i HSU komunikacije. Da bi modul znao kako ćemo koristiti SPI potrebno je prvu sklopku ostaviti u položaju 0, a drugu prebaciti na položaj 1 što je prikazano u prethodnom dijelu tutorijala. Kako se modul spaja s mikrokontrolerom i koji su nam sve pinovi potrebno prikazano je na shemi spajanja. Nakon što spojimo modul sa Croduinom prema danoj shemi potrebno je prebaciti primjer koda za SPI komunikaciju na Croduino pločicu. Kao i prethodni kod i ovaj nam omogućava samo čitanje UID koda s kartica ili tagova.
 

//uključujemo SPI biblioteku koja nam služi za SPI komunikaciju
#include <SPI.h>
//uključujemo biblioteku za SPI_komunikaciju s modulom i biblioteku za PN532 modul
 #include <PN532_SPI.h>
#include "PN532.h"
//Konstruktori za biblioteke koje služe za komunikaciju s modulom
PN532_SPI pn532spi(SPI, 10); //Konstruktor za SPI komunikaciju s modulom
PN532 nfc(pn532spi); //Konstruktor za PM532 biblioteku
 
void setup(void) {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("Hello!");//ispisujemo pozdravnu poruku na Serial monitor
nfc.begin();//Inicijalizacija komunikacije s modulom
uint32_t versiondata = nfc.getFirmwareVersion(); //tražimo od modula verziju Firmwarea i spremamo u varijablu versiondata
//ako nismo dobili verziju firmwarea od modula ispisujemo na Serial monitor da nije pronađen modul i ostajemo u beskonačnoj while petlji
if (! versiondata) {
Serial.print("Modul PN532 nije pronadjen..Provjerite kako je spojen");
while (1);
}
//ako je komunikacija s modulom uspostavljena ispisujemo verziju firmwarea
Serial.print("Pronadjen modul 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);
//konfiguriramo modul
nfc.SAMConfig();
//Ispisujemo poruku da treba prisloniti karticu
Serial.println("Prislonite karticu ili tag ...");
}
 
void loop(void) {
boolean success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // buffer u koji spremamo kod s kartice
uint8_t uidLength; // zapisujemo duljinu UID koda (4 ili 7 byta)
// tražimo od modula da pročita karticu( u varijablu success sprema dali ima ili nema kartice, a ako ima u varijablu uid sprema kod s kartice
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
//ako je modul pročitao karticu ispisujemo kolike je duljine kod na kartici( 4 ili 7 byta) te nakon toga i kod kartice
if (success) {
Serial.println("Pronadjena kartica!");
Serial.print("Duljina UID koda: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
Serial.print("UID Kod: ");
// u HEX obliku ispisujemo kod s kartice
for (uint8_t i=0; i < uidLength; i++)
{
Serial.print(" 0x");Serial.print(uid[i], HEX);
}
Serial.println("");
delay(1000);// pauza od jedne sekunde do ponovnog očitavanja
}
// ako kartica nije pronađena ispisujemo poruku da čekamo karticu
else
{
Serial.println("Vrijeme isteklo.. Cekam karticu");
delay(500);// pauza od pola sekunde da ne ispisuje konstantno poruku ako nema kartice
}
}

NFC

 

I2C_KOMUNIKACIJA

Nešto jednostavnija za spajanje i korištenje je I2C komunikacija koju ćemo koristiti u sljedećim primjerima. Shema spajanje kao i raspored sklopki za ovu komunikaciju dana je na slici.
 

Kao što smo ranije vidjeli NFC se razlikuje od RFID u tome što nam omogućuje, osim čitanja UID koda sa kartica, i čitanje kao i pisanje poruka na karticu ili tag. Kao prvo da objasnimo kako za pisanje kartice ona mora biti određenog formata kako bi mogli pisati poruku na nju. Taj format je NDEF, te kako kartice nisu prethodno formatirane kao prvo moramo napraviti formatiranje kako bi mogli pisati na kartice.
Da bi formatirali karticu jednostavno trebam prebaciti kod za formatiranje kartice(taga) na Croduino i prisloniti karticu na PN532 modul, te će se u Serial monitoru ispisati poruka da je kartica formatirana. Ako je kartica već prethodno bila formatirana ispisuje se poruka da je formatiranje neuspješno.
 

KOD ZA FORMATIRANJE KARTICE
//uključujemo biblioteku za I2C komunikaciju
#include <Wire.h>
 
//Uključujemo biblioteke za I2C komunikaciju sa PN532 modulom, biblioteku za PN532 modul i biblioteku za NFC
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
 
//Konstruktori za biblioteke za I2C komunikaciju s modulom i za NFC
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
 
void setup(void) {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("NDEF Formatiranje.");//Ispisujemo na Serial monitor da modul koristimo za NDEF formatiranje
nfc.begin();//Inicijalizacija komunikacije s modulom
}
 
void loop(void) {
//Na serial monitor ispisujemo da se prisloni neformatiran kartica
Serial.println("\nStavite ne formatiranu karticu ili tag na modul");
if (nfc.tagPresent()) {//provjeravamo dali je kartica prislonjena te ako je formatiramo karticu
bool success = nfc.format();//naredba za formatiranje kartice koja nam vraća podatak dali je kartica formatirana ili ne
if (success) {
//ako je kartica formatirana ispisujemo poruku na Serial monitor o uspješnom formatiranju
Serial.println("\n KArtica(tag) uspjesno formatirana u NTAG.");
} else {
// ako formatiranje nije uspjelo ispisujemo poruku o grešci
Serial.println("\nNeuspjelo formatiranje.");
}
}
delay(2000);//pauza od 2 sekunde kako se poruke ne bi stalno ispisivale
}

Nakon što formatiramo karticu možemo pisati i čitati poruke s kartice. Pošto je kartica tek formatirana na njoj se nalazi prazna poruka u što se možemo uvjeriti ako pročitamo karticu s primjerom koda za čitanje. Da bi nešto zapisali na karticu potrebno je prebaciti kod za pisanje na Croduino. U kodu je potrebno promijeniti što želimo zapisati na karticu, te nakon toga samo prebacimo kod i prislonimo karticu te ako je sve dobro napravljeno trebali bi dobiti poruku kako je poruka uspješno zapisana te da ju pročitamo sa čitačem ili mobitelom(noviji mobiteli podržavaju NFC komunikaciju pa možete probati dali možete s mobitelom pročitati poruku).
 

KOD ZA PISANJE NA KARTICU
//uključujemo biblioteku za I2C komunikaciju
#include <Wire.h>
//Uključujemo biblioteke za I2C komunikaciju sa PN532 modulom, biblioteku za PN532 modul i biblioteku za NFC
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
 
//Konstruktori za biblioteke za I2C komunikaciju s modulom i za NFC
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
 
void setup() {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("NDEF Writer");//Ispisujmo da modul sprema poruku koja je definirana u kodu na karticu
nfc.begin();//Inicijalizacija komunikacije s modulom
}
 
void loop() {
Serial.println("\nStavite formatiranu karticu na citac.");
if (nfc.tagPresent()) {
NdefMessage message = NdefMessage(); // kreiramo varijablu tipa NdefMessage
//ovisno dali želimo zapisati neki tekst ili url trebamo otkomentirati ili zakomentirati odgovarajuću liniju koda
//message.addTextRecord("Hello, Arduino!");//dodajemo tekst u varijablu message
message.addUriRecord("http://arduino.cc");//dodajemo url u varijablu message
 
//zapisujemo varijablu message na karticu kao poruku, te nam funkcija vraća podatak dali je zapisivanje uspjelo ili ne
bool success = nfc.write(message);
if (success) {
//ako je zapisivanje uspjelo ispisujemo poruku o tome
Serial.println("Uspjesno. Probaj procitati poruku sa citacem ii mobitelom.");
} else {
//ako zapisivanje poruke nije uspjelo ispisujemo da se dogodila greška
Serial.println("Zapisivanje neuspjesno.");
}
}
//pauza od 2 sekunde
delay(2000);
}

Kada je u karticu upisana poruka, ona je beskorisna ako ju ne možemo pročitati te je zato tu primjer koda za čitanje NFC kartica koji nam osim UID koda ispisuje i poruku koju smo prethodno zapisali na karticu.
 

KOD ZA ČITANJE KARTICE
//uključujemo biblioteku za I2C komunikaciju
#include <Wire.h>
//Uključujemo biblioteke za I2C komunikaciju sa PN532 modulom, biblioteku za PN532 modul i biblioteku za NFC
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
 
//Konstruktori za biblioteke za I2C komunikaciju s modulom i za NFC
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
 
void setup(void) {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("NDEF Citac"); //ispisujemo poruku da modul radi kao NDEF čitač
nfc.begin();//Inicijalizacija komunikacije s modulom
}
 
void loop(void) {
Serial.println("\nTrazim NFC karticu/tag\n");
if (nfc.tagPresent())//ako imamo prislonjenu karticu čitamo poruku s nje te ju odmah ispisujemo na Serial monitoru.
{
NfcTag tag = nfc.read(); //čitamo NFC karticu ili tag
tag.print(); //ispisujemo podatke sa kartice/taga
}
//Pauza od 2 sekunde kako ne bi stalno ispisivali pročitane podatke
delay(2000);
}

Ako iz nekog razloga ne želimo da na kartici ostane poruka karticu možemo jednostavno obrisati, odnosno poruku s kartice te će onda na kartici biti prazna poruka kao što smo imali kada je kartica bila formatirana.
 

KOD ZA BRISANJE PORUKE
//uključujemo biblioteku za I2C komunikaciju
#include <Wire.h>
 
//Uključujemo biblioteke za I2C komunikaciju sa PN532 modulom, biblioteku za PN532 modul i biblioteku za NFC
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
 
//Konstruktori za biblioteke za I2C komunikaciju s modulom i za NFC
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
 
void setup(void) {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("NFC Brisanje podataka s kartice");
nfc.begin();//Inicijalizacija komunikacije s modulom
}
 
void loop(void) {
//Ispisujemo poruku da modul briše podatke s prislonjene kartice
Serial.println("\nPrislonite karticu koju zelite obrisati.");
//provjeravamo dali je prislonjena kartica te ako je pozivamo funkciju za brisanje kartice.
if (nfc.tagPresent()) {
bool success = nfc.erase();//funkcija za brisanje kartice koja vraća podatak dali je kartica obrisana ili ne
if (success) {
//Ako su obrisani podaci s kartice vraćamo poruku o tome
Serial.println("\nUspjesno, obrisani podaci s kartice.");
} else {
//ispisujemo da brisanje podataka nije uspjelo
Serial.println("\nNeuspjelo brisanje podataka.");
}
}
//Pauza od 2 sekunde kakao se ne bi stalno provjeravalo dali je kartica prislonjena
delay(2000);
}

Naravno da ćemo nekada nešto krivo napraviti pa će nam trebati nova kartica koja nije formatirana na NDEF format i bez poruka. Tu je zato kod koji čisti karticu i vrača na tvorničke postavke. Nakon što ovaj kod prebacimo na Croduino i karticu prislonimo modulu s nje će se izbrisati poruka i kartica će se vratiti na tvorničke postavke. Ako ponovno želimo pisati poruke na karticu nakon čišćenja, moramo ju prethodno formatirati.
 

KOD ZA ČIŠĆENJE KARTICE
//uključujemo biblioteku za I2C komunikaciju
#include <Wire.h>
 
//Uključujemo biblioteke za I2C komunikaciju sa PN532 modulom, biblioteku za PN532 modul i biblioteku za NFC
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>
 
//Konstruktori za biblioteke za I2C komunikaciju s modulom i za NFC
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
 
void setup(void) {
Serial.begin(115200);////Inicijalizacija serijske komunikacije( brzina 115200 bauda)
Serial.println("NFC Tag Cleaner");// ispisujem da modul čisti prislonjenu karticu, odnosno vraća prvobitne postavke
nfc.begin();//Inicijalizacija komunikacije s modulom
}
 
void loop(void) {
//Ispisujemo poruku da se prisloni kartica koja se želi očistiti
Serial.println("\nPrislonite karticu koju želite ocistiti.");
//provjeravamo dali je prislonjena kartica te ako je pozivamo funkciju za čišćenje kartice.
if (nfc.tagPresent()) {
bool success = nfc.clean();//funkcija za čišćenje kartice koja vraća podatak dali je kartica očišćena ili ne
if (success) {
//Ako je kartica očišćena ispisujemo poruku da je vraćena na tvorničke postavke
Serial.println("\nUspjesno, kartica vracena na tvornicke postavke.");
} else {
//ako čišćenje nije uspjelo ispisujemo poruku da se dogodila greška
Serial.println("\nError, neuspjelo ciscenje kartice.");
}
}
//Pauza od 2 sekunde kakao se ne bi stalno provjeravalo dali je kartica prislonjena
delay(2000);
}
Leave a Reply