I've been a long-time lurker of the forums and thought I'd finally contribute something useful to the community. I had trouble finding a simple code to interface a Wiegand 26 bit RFID reader with the UNO. I still have a problem where a card will be misread and the site code and serial will be random numbers. For example, card 419-7610 will sometimes read as 443-13777, 931-7610, 116-15287, or other variants. Rereading the card will eventually match. I'm not sure if it is a reader problem or a problem with the code, but either way, it works. Sometimes it just takes an extra swipe or two. Any help with that would be appreciated!
/* Wiegand RFID Door Lock (CrazyPeople)
* Code By Mike Cook April 2009, Edited by Kushballz April 2014
* Standard 5-wire Weigand RFID Reader (13.56MHz)
* (BLK=GND,RED=12-15VDC,GRN=DATA0, WHT=DATA1, GRY=Buzzer, VIOLET=disconnected for Wiegand 26 and GND for Wiegand 44)
* Reader DATA 0 (GRN) to Pin 2, DATA 1 (WHT) to Pin 3
* Site codes are first portion of RFID card, Serial is Last portion of RFID card (sitecode#-serial#)
* LOW output "strike" var sent to pin 12. Connect to relay to drive door lock solenoid
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
int strike = 12;
int validSiteCodes[] = {419, 149, 151, 411, 164};
int validSerialNumbers[] = {7610, 11962, 11018, 8346, 4506};// see if site code and serial number are in the lists...
volatile long reader1 = 0;
volatile int reader1Count = 0;
void reader1One(void) {
reader1Count++;
reader1 = reader1 << 1;
reader1 |= 1;
}
void reader1Zero(void) {
reader1Count++;
reader1 = reader1 << 1;
}
void setup()
{
pinMode(strike,OUTPUT);
digitalWrite(strike,HIGH);
Serial.begin(9600);
// Attach pin change interrupt service routines from the Wiegand RFID readers
attachInterrupt(0, reader1Zero, RISING);//DATA0 to pin 2
attachInterrupt(1, reader1One, RISING); //DATA1 to pin 3
delay(10);
// the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
// so this gives a pulse to each reader input line to get the interrupts working properly.
// Then clear out the reader variables.
// The readers are open collector sitting normally at a one so this is OK
for(int i = 2; i<4; i++){
pinMode(i, OUTPUT);
digitalWrite(i, HIGH); // enable internal pull up causing a one
digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
pinMode(i, INPUT);
digitalWrite(i, HIGH); // enable internal pull up
}
delay(10);
// put the reader input variables to zero
reader1 = 0;
reader1Count = 0;
}
void loop()
{
if(reader1Count >=26){
int serialNumber=(reader1 >> 1) & 0x3fff;
int siteCode= (reader1 >> 17) & 0x3ff;
Serial.print("Site Code: ");
Serial.print(siteCode);
Serial.print(" Serial: ");
Serial.println(serialNumber);
reader1 = 0;
reader1Count = 0;
if(IsTagValid(siteCode, serialNumber)
){
digitalWrite(strike,LOW);
}
else
digitalWrite(strike,HIGH);
delay(3000);
digitalWrite(strike,HIGH); // Open the door. It's cold out here!
}
}
boolean IsTagValid(int siteCode, int serialNumber)
{
boolean valid = false;
// Determine how many valid tags there are
int validTagCount = sizeof(validSiteCodes)/sizeof(int);
// Loop through the arrays to see if siteCode
// and serialNumber are present
for(int t=0; t<validTagCount; t++)
{
if(validSiteCodes[t] == siteCode &&
validSerialNumbers[t] == serialNumber)
{
valid = true;
break;
}
}
return valid;
}