Há alguns anos, a equipe do Solucionática fez um projeto com leitores RFID. O modelo disponível usava o protocolo Wiegand, ao contrário de outros que se valem do uart (RS232). A diferença é que a leitura dos cartões é feita lendo os 26 bits de dados, usando os pinos 2 e 3 do Arduino Mega (pinos ISR). No segundo caso, é possível usar tanto as portas seriais físicas do Arduino, quanto as virtuais (Softwarseerial). A escolha foi feita apenas pelo custo. Agora atualizamos a montagem, para não perdermos de vista essa tecnologia, que hoje já está bem difundida, ao contrário da época da primeira montagem.
Como funciona?
O quadro abaixo, retirado de http://www.pagemac.com/azure/data_formats.php, explica o protocolo usado nesse tipo particular de cartão, que é o mais comum. Dos 26 bits, há 8 para determinar o "Facility Code" (bits 2 a 9), ou seja, uma sequência que ajuda a diferenciar os cartões. São até 256 "empresas" possíveis. Outros 16 bits (bits 10 a 25) permitem ter 65.535 cartões diferentes para cada "Facility code". Assim, muito provavelmente, é possível encontrar dois cartões iguais, em um universo de 16.776.960 cartões fabricados por todos os fornecedores que usam esse formato denominado Wiegand. Há, atualmente, outros formatos que usam mais bits e assim nunca repetem um mesmo código. Mas, muito provavelmente, aquele cartão usado nos crachás será semelhante aos usados no nosso projeto. Exitem tags, pequenos chaveirinhos que podem faciltar o uso da tecnologia rfid para fazer coisas legais, tais como alimentadores automáticos para cães e gatos. Basta pendurar na coleira a tag rfid e bolar a parte mecânica para que ao se aproximar, o seu animal de estimação vai receber a quantidade certa de ração.
Ok, quem fez as contas percebeu que está faltando dois bit ( 1 e 26), que são os bits de paridade (par e ímpar). Não usamos nesse exemplo
O sketch é simples, parecido com o usado pelo Arduino - Auriol. Foi obtido de http://www.pagemac.com/source.php?f=azure/progs/arduino_hid_wiegand.ino. O site é novo nas nossas pesquisas e recomendamos uma visita para quem quer aprofundar o tema.
/*
* HID RFID Reader Wiegand Interface for Arduino Uno
* Written by Daniel Smith, 2012.01.30
* www.pagemac.com
*
* This program will decode the wiegand data from a HID RFID Reader (or, theoretically,
* any other device that outputs weigand data).
* The Wiegand interface has two data lines, DATA0 and DATA1. These lines are normall held
* high at 5V. When a 0 is sent, DATA0 drops to 0V for a few us. When a 1 is sent, DATA1 drops
* to 0V for a few us. There is usually a few ms between the pulses.
*
* Your reader should have at least 4 connections (some readers have more). Connect the Red wire
* to 5V. Connect the black to ground. Connect the green wire (DATA0) to Digital Pin 2 (INT0).
* Connect the white wire (DATA1) to Digital Pin 3 (INT1). That's it!
*
* Operation is simple - each of the data lines are connected to hardware interrupt lines. When
* one drops low, an interrupt routine is called and some bits are flipped. After some time of
* of not receiving any bits, the Arduino will decode the data. I've only added the 26 bit and
* 35 bit formats, but you can easily add more.
*/
#define MAX_BITS 100 // max number of bits
#define WEIGAND_WAIT_TIME 3000 // time to wait for another weigand pulse.
unsigned char databits[MAX_BITS]; // stores all of the data bits
unsigned char bitCount; // number of bits currently captured
unsigned char flagDone; // goes low when data is currently being captured
unsigned int weigand_counter; // countdown until we assume there are no more bits
unsigned long facilityCode=0; // decoded facility code
unsigned long cardCode=0; // decoded card code
// interrupt that happens when INTO goes low (0 bit)
void ISR_INT0()
{
//Serial.print("0");
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
{
//Serial.print("1");
databits[bitCount] = 1;
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
void setup()
{
pinMode(13, OUTPUT); // LED
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
Serial.begin(9600);
Serial.println("RFID Readers");
// binds the ISR functions to the falling edge of INTO and INT1
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
weigand_counter = WEIGAND_WAIT_TIME;
}
void loop()
{
// This waits to make sure that there have been no more data pulses before processing data
if (!flagDone) {
if (--weigand_counter == 0)
flagDone = 1;
}
// if we have bits and we the weigand counter went out
if (bitCount > 0 && flagDone) {
unsigned char i;
Serial.print("Read ");
Serial.print(bitCount);
Serial.print(" bits. ");
// we will decode the bits differently depending on how many bits we have
// see www.pagemac.com/azure/data_formats.php for mor info
if (bitCount == 35)
{
// 35 bit HID Corporate 1000 format
// facility code = bits 2 to 14
for (i=2; i<14; i++)
{
facilityCode <<=1;
facilityCode |= databits[i];
}
// card code = bits 15 to 34
for (i=14; i<34; i++)
{
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 26)
{
// standard 26 bit format
// facility code = bits 2 to 9
for (i=1; i<9; i++)
{
facilityCode <<=1;
facilityCode |= databits[i];
}
// card code = bits 10 to 23
for (i=9; i<25; i++)
{
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else {
// you can add other formats if you want!
Serial.println("Unable to decode.");
}
// cleanup and get ready for the next card
delay(800);
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i=0; i<MAX_BITS; i++)
{
databits[i] = 0;
}
}
}
void printBits()
{
// I really hope you can figure out what this function does
Serial.print("FC = ");
Serial.print(facilityCode);
Serial.print(", CC = ");
Serial.println(cardCode);
}
O HARDWARE
De simplicidade franciscana, o hardware é composto pelo leitor RFID de 125KHz, um Arduino Mega 2560, alguns resistores e um led.
É importante conhecer a pinagem do leitor para tornar a montagem à prova de erros:
O nosso leitor rfid tem três conjuntos de barramentos (P1, P2 e P3):