O módulo RFID RC522 nos permite fazer a leitura de certos cartões (tags) apenas pela aproximação dos mesmos. Neste post aprenderemos algumas características do módulo e como utilizá-lo com o Arduino (com bibliotecas).

Informações básicas

O que é o módulo RFID

O RC522 é um Circuito Integrado (CI) capaz de ler e escrever em “cartões de proximidade” segundo a norma ISO/IEC 14443. O significado disso tudo é que o CI pode ler ou escrever informações em cartões especiais sem precisar do contato direto, utilizando ondas eletromagnéticas (“rádio frequência”).

Este tipo de aplicação é conhecida como RFID, que significa “Radio Frequency Identification” ou Identificação por Rádio Frequência (creio que o nome seja autoexplicativo). Entretanto, a identificação por rádio frequência, de forma genérica, pode ter muitos ‘formatos’ e o RC522 trabalha apenas com um deles.

Neste caso, o RC522 trabalha seguindo a norma ISO/IEC 14443, que normalmente é focada para tags RFID para sistemas de pagamento. Tags são dispositivos que armazenam certas informações e que se comunicam com os leitores de RFID. Um exemplo de tag são os cartões de alguns sistemas de transporte, que permitem o pagamento da passagem apenas aproximando o cartão. A norma ISO/IEC 14443 será comentada em outro tópico.

Voltando ao foco do post, o módulo RFID-RC522 vem com o circuito base do RC522. E ele pode ser visto na imagem abaixo, junto à duas tags que vieram com ele (um cartão e um chaveiro).

Módulo RFID RC522

Na imagem acima, o CI RC522 é apenas a “caixinha” preta na parte superior do módulo. A maior parte do módulo é ocupada pela antena que faz a leitura/escrita das tags.

Aplicações do RFID

As aplicações são bem similares, pois todas envolvem a identificação de uma ‘tag’ única.

  • Controle de acesso:

    Executa uma determinada função apenas se passar a tag certa. Por exemplo, logar em um computador, ligar uma máquina restrita, abrir uma porta etc.

  • Sistema de pagamento:

    Utiliza a tag como uma forma de carteira digital.

  • Sistema de cadastro:

    Utiliza a tag como uma forma de acessar o cadastro de um pessoa em um determinado lugar.

  • Catalogar itens de um estoque:

    Talvez não seja a forma mais barata de se fazer isto, mas é possível vincular uma ‘tag’ a cada item de um estoque para identificá-los facilmente.

Existem muitas outras aplicações e o limite é a imaginação.

Norma ISO/IEC 14443

Segundo a norma, o leitor de ‘tags’ (módulo neste exemplo) é chamado oficialmente de PCD (Dispositivo Acoplado por Aproximação) e a ‘tag’ é chamada de PICC (Cartão de Aproximação de Circuito Integrado). Os nomes em português foram uma tradução livre que fiz, então eles podem acabar sendo um pouco diferentes do nome técnico correto.

Para definir este tipo de sistema, a norma separa as regras em 4 partes:

1 – Norma ISO/IEC 14443-1: Define características físicas dos cartões de proximidade.

2 – Norma ISO/IEC 14443-2: Define características elétricas dos dois tipos de dispositivos utilizados na comunicação (o PCD e o PICC).

3 – Norma ISO/IEC 14443-3: Define como inicializar a comunicação e o procedimento “anti-colisão” (colisão de dados em caso de múltiplos PICC comunicando simultaneamente).

4 – Norma ISO/IEC 14443-4: Define o protocolo de transmissão.

Não pretendo detalhar o conteúdo destas normas, até porque os documentos não são gratuitos. Mas, adiante, estão descritas algumas informações gerais da norma que podem ser obtidas inclusive no datasheet do RC522 (página 8).

  • Frequência de comunicação: 13,56MHz +- 7kHz.
  • Modulação ASK para a portadora principal.
  • Modulação BPSK para a portadora secundária.
    • Utilizada pelo PICC (tag) para “responder” ao PCD (leitor).
  • Taxa de transmissão padrão: 106 kbits/s.
  • Comunicação half-duplex.
    • Só um comunica por vez (ou o PCD ou o PICC).

Os detalhes sobre o formato dos dados e quais são os procedimentos corretos de comunicação podem ser encontrado nas normas. E apesar dos nomes oficiais dos dispositivos serem PCD e PICC, vou chamá-los de “leitor” e “tag” para facilitar o entendimento.

Tags RFID

As tags RFID possuem, internamente, uma antena e um circuito integrado responsável por fazer a comunicação com o dispositivo leitor. A antena nada mais é do que um enrolado de fios (uma bobina) e ela normalmente ocupa boa parte do espaço interno da tag.

O objetivo da antena é criar a comunicação com o “leitor”, e também é obter energia o suficiente das ondas recebidas para alimentar os circuitos internos.

A imagem abaixo ilustra o circuito base da tag.

Fonte: hpluspedia

E a primeira imagem abaixo mostra como é a parte interna de um bilhete eletrônico utilizado para pagar passagem, enquanto a segunda imagem mostra a parte interna de um cartão genérico.

Fonte: Wikipedia
Fonte: Topflight

Características do RFID

Neste tópico, irei mostrar as características do CI RC522,  do módulo RFID e das tags que vieram junto. E não serão informações cruciais para a implementação no Arduino. Então, se desejar, pode pular para o tópico seguinte.

Características

  • Alimentação de 2,5 a 4,0V:
    • A tensão típica é de 3,3V.
  • Tensão máxima dos pinos digitais:
    • Esta informação é um pouco ambígua no datasheet, pois na página 74 está indicado que a tensão de entrada máxima é Vdd + 0,5 (máximo 4,5V). E na página 75 o nível máximo de tensão (HIGH-level input voltage) não é especificado.
    • Embora exista esta “confusão”, não acho uma boa ideia ligar os pinos de dados do módulo diretamente nos pinos do Arduino (operam em 5V).
    • De toda forma, é possível encontrar diversos circuitos online onde a ligação direta com o Arduino foi feita sem problemas aparentes.
  • Interface SPI:
    • É a interface utilizada no módulo.
    • Velocidade de até 10 Mbits/s.
  • Interface I2C:
    • Pode operar no modo “Fast mode” (400 kbit/s) ou no modo “High-speed” (3400 kbits/s).
  • Interface UART (RS-232):
    • Velocidade de até 1228,8 kbits/s.
  • Consumo de corrente:
    • Operação normal: 13 a 26mA.
    • Modo de baixo consumo: 10uA.
  • Alcance de alguns centímetros (3 cm).

Mais informações podem ser lidas no datasheet.

Interfaces

O RC522 identifica qual interface está sendo utilizada por meio de seus pinos “I2C” (pino 1 do CI) e “EA” (pino 32 do CI). No caso do módulo RFID, o pino “I2C” já vem pré-conectado ao GND e o pino EA ao 3,3V. Este arranjo faz com que o CI utilize a interface SPI por padrão. Trocar esta configuração é uma tarefa complicada, pois exige que a placa seja levemente danificada para alterar as conexões.

Tags - Cartão e chaveiro RFID

Tanto o cartão quanto o chaveiro são uma tag do tipo “MIFARE Classic” com uma memória de 1 kbytes (1024 bytes).

Esta memória é organizada em 16 setores, cada setor dividido em 4 blocos e cada bloco possui 16 bytes de dados. Ao todo existem 64 blocos (4 blocos/setor * 16 setores) e como cada bloco tem 16 bytes, o total são 1024 bytes (16 bytes/bloco * 64 blocos).

Dentro de cada setor existe um bloco especial chamado de “Sector Trailer” que é inteiramente reservado para o armazenamento de informações importantes para garantir o acesso aos blocos do setor em específico. O “Sector Trailer” é o 4º bloco de cada setor.

Existe ainda outro bloco reservado que é o bloco 0 do setor 0. Ele contém informações sobre o fabricante da tag e um código chamado de Identificador Único (UID). O identificador único é um código de 4 bytes (neste caso) que teoricamente é único para cada tag. Com 4 bytes é possível existirem 4.294.967.295 identificadores diferentes.

Se você quiser saber mais informações sobre a tag “MIFARE Classic” leia, este documento.

Pinos do módulo RFID

O módulo RFID possui 8 pinos:

  • 3.3V – Pino de alimentação do módulo (2,5 a 4V).
  • RST – Pino reset que serve para colocar o RC522 no modo de baixo consumo (“power-down”).
    • Nível alto = Funcionamento normal.
    • Nível baixo = Modo “power-down”.
  • GND – Terra da alimentação.
  • IRQ – Pino de interrupção.
    • Pode ser utilizado para indicar certos eventos. Os possíveis eventos podem ser vistos na página 31 do datasheet.
  • MISO – Pino de entrada do mestre da comunicação SPI.
    • A interface I2C também pode utilizar este pino como SCL.
  • MOSI – Pino de saída do mestre da comunicação SPI.
  • SCK – Pino de clock da comunicação SPI.
  • SDA – Pino SS ou NSS da comunicação SPI.
    • A interface I2C também pode utilizar este pino como SDA.

Circuito do módulo

Encontrei o seguinte esquemático disponível online:

Fonte: Sunrom

O circuito do módulo basicamente é o circuito típico recomendado no datasheet do RC522 (página 81). A grande questão do módulo é a construção da antena. No caso, ela nada mais é do que uma bobina feita com trilhas na PCB. Veja abaixo:

É por meio dela que o CI é capaz de comunicar com as tags. Então, na hora de usar, a tag precisa se aproximar desta antena e não do CI.

Utilizando o RFID com o Arduino (com biblioteca)

Circuito

Conforme comentei, é altamente provável que o módulo não seja tolerante à 5V. Então, é preciso adaptar os níveis de tensão dos pinos do Arduino (5v) pro nível de tensão aceitável pelo módulo (3,3V). Uma forma de fazer isto é utilizando um conversor de nível igual na imagem abaixo ou um divisor de tensão para cada pino de dados.

Veja a ligação abaixo:

Ligação com o módulo RFID

O módulo é alimentado com 3,3V e GND do Arduino. Os demais pinos seguem a seguinte relação:

  • Pino SDA do módulo (SS da interface SPI) é ligado no pino 10 do Arduino.
  • Pino MOSI do módulo é ligado no pino 11 do Arduino.
  • Pino MISO do módulo é ligado no pino 12 do Arduino.
  • Pino SCK do módulo é ligado no pino 13 do Arduino.

Claro que, para cada ligação indicada acima, é preciso fazer a conversão do nível lógico. Por isto existe um conversor de nível lógico no meio das ligações. O conversor de nível lógico é alimentado com 5V no lado de alta e 3,3V no lado de baixa.

Repare que liguei o pino RST diretamente no 3,3V. Fiz isso, pois não pretendo utilizar o modo “power-down”. Assim, não preciso utilizar outro conversor de nível para ligar o pino RST no Arduino.

Baixando biblioteca

A biblioteca pode ser baixada na própria IDE do Arduino em Sketch -> Incluir Biblioteca -> Gerenciar Bibliotecas… E é só pesquisar por “RC522” e baixar a primeira opção, que tem como autor “GithubComunnity”.

Esta biblioteca em específico utiliza a interface SPI do módulo e não tem suporte para as demais interfaces. E ela vem com uma série de exemplos mostrando como ler e escrever informações da tag. Em seguida, vou mostrar alguns exemplos de como isso pode ser feito.

Lendo memória da tag

O código abaixo é adaptado de um código de exemplo da biblioteca. Leia os comentários para entender.

Assim que fiz o upload do código, abri o monitor serial e mantive o cartão próximo do leitor até que a leitura fosse finalizada (demorou alguns segundos).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <SPI.h>
#include <MFRC522.h>

// Pino para colocar no modo "power-down"
// Não estamos utilizando no circuito proposto
#define PINO_RST  9
// Pino SS (no módulo está escrito SDA neste pino)
#define PINO_SS   10

// Instância do módulo
MFRC522 mfrc522(PINO_SS, PINO_RST);

void setup()
{
  // Inicia a comunicação serial (monitor serial)
  Serial.begin(9600);

  // Inicia a comunicação SPI
  SPI.begin();

  // Inicia o módulo
  mfrc522.PCD_Init();
  // Delay optativo (talvez necessário em algumas placas)
  delay(4);
  // Informa os detalhes do módulo
  mfrc522.PCD_DumpVersionToSerial();

  Serial.println("Passe um cartão no leitor para obter algumas informações dele.");
}

void loop()
{
  // Verifica se existe um cartão presente para leitura
  if (mfrc522.PICC_IsNewCardPresent())
  {
    // Se sim, começa a ler o cartão
    if (mfrc522.PICC_ReadCardSerial())
    {
      // Coloca as informações do cartão no monitor serial
      mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
    }
  }
}

Interpretando dados lidos

A imagem abaixo mostra o resultado obtido ao ler a memória do cartão.

O significado de algumas partes foi explicado no tópico “Tags – Cartão e chaveiro RFID”, mas recapitulando:

  • Card UID: Identificador Único da tag lida.
  • Card SAK: Identifica o fabricante e o código do produto. Neste caso o 08 significa que é uma tag feita pela NXP do tipo “Mifare Classic 1k”.
  • PICC type: Tipo da tag. Informação interpretada a partir do SAK.
  • Restante dos dados: leitura dos bytes da memória interna organizados por setor e blocos.
    • Repare que o último bloco de cada setor (63, 59 … 3) é o único bloco com dados escritos (exceto o bloco 0 do setor 0). Isto, porque ele é o “Sector Trailer”. Os demais blocos podem ser escritos de acordo com sua vontade (exceto o bloco 0 do setor 0).
    • Observe o UID no início do bloco 0 do setor 0. E também é possível ver o SAK nele.

Escrevendo dados na tag

A ideia deste código é escrever “Mundo Projetado” no bloco 5 e escrever de 0 a 15 no bloco 6.

O código abaixo é adaptado de um código de exemplo da biblioteca. Leia os comentários para entender.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <SPI.h>
#include <MFRC522.h>

// Pino para colocar no modo "power-down"
// Não estamos utilizando no circuito proposto
#define PINO_RST  9
// Pino SS (no módulo está escrito SDA neste pino)
#define PINO_SS   10

// Instância do módulo
MFRC522 mfrc522(PINO_SS, PINO_RST);

// Chave utilizada para permitir a escrita no cartão
MFRC522::MIFARE_Key key;

void setup()
{
  // Inicia a comunicação serial (monitor serial)
  Serial.begin(9600);

  // Inicia a comunicação SPI
  SPI.begin();

  // Inicia o módulo
  mfrc522.PCD_Init();

  Serial.println("Escrita de dados no cartão.");

  // Define o valor da chave
  // Para tags novas ela é FFFFFFFFFFFFh
  for (uint8_t i = 0; i < 6; i++)
  {
    key.keyByte[i] = 0xFF;
  }
}

void loop()
{
  // Verifica se existe um cartão presente para escrita
  if (mfrc522.PICC_IsNewCardPresent())
  {
    // Se sim, começa a escrever no cartão
    if (mfrc522.PICC_ReadCardSerial())
    {
      // Printa os 4 bytes da UID
      Serial.print("Card UID:");
      for (byte i = 0; i < mfrc522.uid.size; i++)
      {
        Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522.uid.uidByte[i], HEX);
      }
      Serial.println("");

      // Variaveis importantes para a escrita
      byte buffer[16] = "Mundo Projetado";
      byte block;
      MFRC522::StatusCode status;

      // ----- Escrita no bloco 5 -----
      block = 5;
     
      // Tenta autenticar
      status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
     
      if (status != MFRC522::STATUS_OK)
      {
        Serial.print("Falha na autenticação: ");
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      else
      {
        Serial.println("Autenticação bem sucedida!");
      }

      // Escreve no bloco
      status = mfrc522.MIFARE_Write(block, buffer, 16);
     
      if (status != MFRC522::STATUS_OK)
      {
        Serial.print("A escrita falhou: ");
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      else
      {
        Serial.println("Escrita bem sucedida!");
      }

      // ----- Escrita no bloco 6 -----
      block = 6;
     
      // Preenche o buffer de escrita com números de 0 a 15
      for(uint8_t i = 0; i < 16; i++)
      {
        buffer[i] = i;
      }
     
      // Tenta autenticar
      status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
     
      if (status != MFRC522::STATUS_OK)
      {
        Serial.print("Falha na autenticação: ");
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      else
      {
        Serial.println("Autenticação bem sucedida!");
      }

      // Escreve no bloco
      status = mfrc522.MIFARE_Write(block, buffer, 16);
     
      if (status != MFRC522::STATUS_OK)
      {
        Serial.print("A escrita falhou: ");
        Serial.println(mfrc522.GetStatusCodeName(status));
        return;
      }
      else
      {
        Serial.println("Escrita bem sucedida!");
      }

      Serial.println(" ");
      // Interrompe a comunicação
      mfrc522.PICC_HaltA();
      // Interrompe a encriptação
      mfrc522.PCD_StopCrypto1();
    }
  }
}

Resultados da escrita

Após fazer upload do código anterior e aproximar um cartão, obtive o seguinte:

Escrita na tag RFID

Para confirmar se o código de fato funcionou, fiz upload do código de leitura mostrado anteriormente e obtive a leitura seguinte:

Para converter os números em texto é só utilizar a tabela ASCII (4D = M, 75 = u, 50 = P …). Então, realmente deu certo: na posição 5 o texto “Mundo Projetado” foi armazenado, e na posição 6 foram armazenados valores de 0 a 15 (0 a F em hexadecimal). 

Controle de acesso

Apesar de que o código de leitura já conta com a leitura do UID, acho interessante mostrar um código que faz apenas a leitura dele para, por exemplo, abrir uma porta.

A UID que garante o acesso está declarada na linha 11. No meu caso foi a UID do chaveiro.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <SPI.h>
#include <MFRC522.h>

// Pino para colocar no modo "power-down"
// Não estamos utilizando no circuito proposto
#define PINO_RST  9
// Pino SS (no módulo está escrito SDA neste pino)
#define PINO_SS   10

// UID da tag responsável por liberar o acesso
uint8_t uid_tag_desejada[4] = {0xA9, 0xD8, 0xC6, 0xA2};

// Instância do módulo
MFRC522 mfrc522(PINO_SS, PINO_RST);

void setup()
{
  // Inicia a comunicação serial (monitor serial)
  Serial.begin(9600);

  // Inicia a comunicação SPI
  SPI.begin();

  // Inicia o módulo
  mfrc522.PCD_Init();

  Serial.println("Aguardando tag certa para abrir a porta...");
}

void loop()
{
  // Verifica se existe um cartão presente para leitura
  if (mfrc522.PICC_IsNewCardPresent())
  {
    // Se sim, começa a ler o cartão
    if (mfrc522.PICC_ReadCardSerial())
    {
      uint8_t liberado = 1;
     
      // Verifica os 4 bytes da UID
      Serial.print("Tag identificada: ");
      for (byte i = 0; i < 4; i++)
      {
        // Printa o byte atual
        Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522.uid.uidByte[i], HEX);

        // Se o byte for diferente da tag esperada, não libera o acesso
        if(uid_tag_desejada[i] != mfrc522.uid.uidByte[i])
        {
          liberado = 0;
        }
      }
      Serial.println("");

      if(liberado)
      {
        Serial.println("Acesso liberado!");
        // Executa outras ações, como abrir uma porta
      }
      else
      {
        Serial.println("Acesso negado!");
      }
    }
   
    // Delay para não ficar lendo rapidamente
    delay(1000);
  }
}

Resposta do controle de acesso

Após fazer upload do código, aproximei o cartão e apareceu “Acesso negado!”. Em seguida aproximei o chaveiro e apareceu “Acesso liberado!”.

Controle de acesso com RFID