Gadgets

21 jun, 2017

Leitor de tags NFC com Arduino

Publicidade

Hoje eu quero usar o módulo de leitura de tags NFC com o meu Arduíno. A ideia é construir um protótipo simples para ler tags NFC e validá-las contra um servidor remoto (por exemplo, um servidor node tcp). Dependendo da tag, vamos desencadear uma saída digital ou outra. No exemplo, conectaremos leds a essas saídas, mas na vida real podemos abrir portas ou algo parecido.

Usaremos um módulo MFRC522. É um leitor e escritor de tags Mifare RFID/NFC barato.

Conexão MFRC522:

  • sda: 10 (*) -> 8
  • sck: 13
  • Mosi: 11
  • Miso: 12
  • Rq: —
  • Gnd: Gnd
  • Rst: 9
  • 3.3V: 3.3V

Neste exemplo, usaremos um escudo ethernet para conectar nossa placa Arduíno à LAN. Devemos tomar cuidado com disso. Se usarmos o escudo ethernet com um MFRC522, há um conflito SPI (devido ao leitor de cartão SD do escudo ethernet). Precisamos usar outro pin SDA (aqui estou usando o pin 8 em vez do 10) e desabilitar o SPI do w5100 antes de configurar a Ethernet.

// disable w5100 SPI
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

Aqui está o código Arduino

#include <SPI.h>
#include <MFRC522.h>
#include <Ethernet.h>
#include <EthernetClient.h>
 
#define RST_PIN 9
#define SS_PIN  8
#define ERROR_PIN 7
#define OPEN_PIN 6
#define OPEN_DELAY 2000
 
char server[] = "192.168.1.104";
int port = 28001;
 
signed long timeout;
 
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
MFRC522 mfrc522(SS_PIN, RST_PIN);
EthernetClient client;
 
void printArray(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}
 
String dump_byte_array(byte *buffer, byte bufferSize) {
          String out = "";
    for (byte i = 0; i < bufferSize; i++) {
        out += String(buffer[i] < 0x10 ? " 0" : " ") + String(buffer[i], HEX);
    }
    out.toUpperCase();
    out.replace(" ", "");
     
    return out;
}
 
void resetLeds() {
  digitalWrite(OPEN_PIN, LOW);
  digitalWrite(ERROR_PIN, LOW);
}
 
void open() {
  Serial.println("OPEN!");
  digitalWrite(OPEN_PIN, HIGH);
  delay(OPEN_DELAY);
  digitalWrite(OPEN_PIN, LOW);
}
 
void error() {
  Serial.println("ERROR!");
  digitalWrite(ERROR_PIN, HIGH);
  delay(OPEN_DELAY);
  digitalWrite(ERROR_PIN, LOW);
}
 
void scanCard() {
  byte status;
  byte buffer[18];
  int err = 0;
  byte size = sizeof(buffer);
  EthernetClient c;
       
  if (mfrc522.PICC_IsNewCardPresent()) {
    if (mfrc522.PICC_ReadCardSerial()) {
      const String ID = dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
      Serial.println("New tag read: " + ID);
      mfrc522.PICC_HaltA();
      
      if (client.connect(server, port)) {
        timeout = millis() + 3000;
        client.println("OPEN:" + ID);
        delay(10);
 
        while(client.available() == 0) {
          if (timeout - millis() < 1000) {
              error();
              goto close;
          }
        } 
        int size;
        bool status;
         
        while((size = client.available()) > 0) {
          uint8_t* msg = (uint8_t*)malloc(size);
          size = client.read(msg,size);
          //Serial.write(msg, size);
          // 4F4B   -> OK
          // 4E4F4B -> NOK
          status = dump_byte_array(msg, size) == "4F4B";
          free(msg);
        }
         
        Serial.println(status ? "OK!" : "NOK!");
        if (status) {
          open();
        } else {
          error();
        }
close:
        client.stop();
      } else {
        Serial.println("Connection Error");
        error();
      }
    }
  }
}
 
void setup()
{
  resetLeds();
  Serial.begin(9600);
  Serial.println("Setup ...");
 
  // disable w5100 SPI
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
 
  SPI.begin();
  mfrc522.PCD_Init();
 
  if (Ethernet.begin(mac) == 0) {
    Serial.println("DHCP Error");
    error();
    while (true) {}
  }
  Serial.print("My IP: ");
  for (byte B = 0; B < 4; B++) {
    Serial.print(Ethernet.localIP()[B], DEC);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("Finish setup");
  timeout = 0;
}
 
void loop()
{
  resetLeds();
  scanCard();
  delay(200);
}

Agora, só precisamos criar um servidor tcp simples com node para validar nossas tags NFC.

var net = require('net');
 
var LOCAL_PORT = 28001;
var validTags = ['X3C86AD9'];
 
var validateTag = function(tag) {
    return validTags.indexOf(tag) > -1;
};
 
var server = net.createServer(function (socket) {
    console.log(socket.remoteAddress + ":" + socket.remotePort);
    socket.on('data', function(msg) {
        var out;
        [action, tag] = msg.toString().toUpperCase().trim().split(":");
        console.log(action, tag);
        switch (action) {
            case 'OPEN':
                out = validateTag(tag) ? "OK" : "NOK";
                console.log(out);
                socket.write(out);
                break;
            default:
                console.log("unknown action:", action);
        }
 
        socket.destroy();
    });
});
 
server.listen(LOCAL_PORT, '0.0.0.0');

E isso é tudo. Aqui, um vídeo com o exemplo de trabalho

O código completo disponível na minha conta do github.

Referências sobre rfid e Arduino: aqui, aqui e aqui.

***

Gonzalo Ayuso faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://gonzalo123.com/2017/06/12/nfc-tag-reader-with-arduino/