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); }