Wiegand Data aFormat Reader and Arduino

/*
 * 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");   // uncomment this line to display raw binary
  bitCount++;
  flagDone = 0;
  weigand_counter = WEIGAND_WAIT_TIME;  
 
}
 
// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
{
  //Serial.print("1");   // uncomment this line to display raw binary
  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(2, ISR_INT0, FALLING);  
  attachInterrupt(3, 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
     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); 
}

So I am trying to use this code to decode the 35 bit from my card. However, when I first run the program, it starts reading random values which I am not sure where it comes from.

Also, when I try to read a card, there is nothing that outputs onto the serial monitor. Supposedly, this code worked for many users in 2013ish so what could be the issue here?

What is connected to your input pins? If they are not actively pulled high or low by an external device, you will get random data.

You're checking for falling edges so I assume that the pin is normally high; so you can change

  pinMode(2, INPUT);     // DATA0 (INT0)
  pinMode(3, INPUT);     // DATA1 (INT1)

to

  pinMode(2, INPUT_PULLUP);     // DATA0 (INT0)
  pinMode(3, INPUT_PULLUP);     // DATA1 (INT1)

and see if that silves the problem.

The input pins are connected to DATA1 and DATA0 from the Prox Pro HID Reader

I tried what you suggested but it is still reading from nothing at first and doesn't read the card after

Can anyone suggest anything?

Are you saying that when no card is present you get random values displayed and when a card is present you get NO values displayed?

If you can get access to an oscilloscope, check the data lines. Make sure you have a ground line connected between the reader and the Arduino.

The code has no protection against receiving more bits than the array can handle.

Perhaps the WEIGAND_WAIT_TIME is too low (ending the input prematurely) or too high (allowing for repeated messages to be merged).

It worked when I shared ground, can someone explain why you have to do this

jlukose6:
It worked when I shared ground, can someone explain why you have to do this

http://www.thebox.myzen.co.uk/Tutorial/Power_Supplies.html

jlukose6:
It worked when I shared ground, can someone explain why you have to do this

LOW and HIGH signals are voltages (below 30% of Vcc for LOW, above 60% of Vcc for HIGH) referenced to 'ground'. If the two circuits don't share a 'ground' then the signals have no fixed reference and may read randomly.

Above concept is suitable for UHF RFID reader. can i read with wiegand data with DATA0 and DATA 1 pin in arduino

Above concept is suitable for UHF RFID reader.

Why should it not be?

The frequency of the RFID signal has nothing to do with the data format of the signal coming out of the reader.

I am using UHF long range reader.that's way i am asking and wiegand data is 26 and 34 you used 35 in above code is that ok. Please suggest idea

balamurugan_k:
I am using UHF long range reader.that's way i am asking and wiegand data is 26 and 34 you used 35 in above code is that ok. Please suggest idea

That is not my code, I did not write it.