weigand rfid card reader using arduino

Hii all

I am using the code that is got from github to read from an rfid card reader. I’m using arduio nano and sebury reader byt when i try to upload it to the board it is showing error compiling for board arduino nano. can someone please help me with this. I am new to arduino.

The code i used

#include “Wiegand.h”

volatile unsigned long WIEGAND::_cardTempHigh=0;
volatile unsigned long WIEGAND::_cardTemp=0;
volatile unsigned long WIEGAND::_lastWiegand=0;
unsigned long WIEGAND::_code=0;
volatile int WIEGAND::_bitCount=0;
int WIEGAND::_wiegandType=0;

WIEGAND::WIEGAND()
{
}

unsigned long WIEGAND::getCode()
{
return _code;
}

int WIEGAND::getWiegandType()
{
return _wiegandType;
}

bool WIEGAND::available()
{
bool ret;
noInterrupts();
ret=DoWiegandConversion();
interrupts();
return ret;
}

void WIEGAND::begin()
{
begin(2,3);
}

void WIEGAND::begin(int pinD0, int pinD1)
{
_lastWiegand = 0;
_cardTempHigh = 0;
_cardTemp = 0;
_code = 0;
_wiegandType = 0;
_bitCount = 0;
pinMode(pinD0, INPUT); // Set D0 pin as input
pinMode(pinD1, INPUT); // Set D1 pin as input

attachInterrupt(digitalPinToInterrupt(pinD0), ReadD0, FALLING); // Hardware interrupt - high to low pulse
attachInterrupt(digitalPinToInterrupt(pinD1), ReadD1, FALLING); // Hardware interrupt - high to low pulse
}

void WIEGAND::ReadD0 ()
{
_bitCount++; // Increament bit count for Interrupt connected to D0
if (_bitCount>31) // If bit count more than 31, process high bits
{
_cardTempHigh |= ((0x80000000 & _cardTemp)>>31); // shift value to high bits
_cardTempHigh <<= 1;
_cardTemp <<=1;
}
else
{
_cardTemp <<= 1; // D0 represent binary 0, so just left shift card data
}
_lastWiegand = millis(); // Keep track of last wiegand bit received
}

void WIEGAND::ReadD1()
{
_bitCount ++; // Increment bit count for Interrupt connected to D1
if (_bitCount>31) // If bit count more than 31, process high bits
{
_cardTempHigh |= ((0x80000000 & _cardTemp)>>31); // shift value to high bits
_cardTempHigh <<= 1;
_cardTemp |= 1;
_cardTemp <<=1;
}
else
{
_cardTemp |= 1; // D1 represent binary 1, so OR card data with 1 then
_cardTemp <<= 1; // left shift card data
}
_lastWiegand = millis(); // Keep track of last wiegand bit received
}

unsigned long WIEGAND::GetCardId (volatile unsigned long *codehigh, volatile unsigned long *codelow, char bitlength)
{

if (bitlength==26) // EM tag
return (*codelow & 0x1FFFFFE) >>1;

if (bitlength==34) // Mifare
{
*codehigh = *codehigh & 0x03; // only need the 2 LSB of the codehigh
*codehigh <<= 30; // shift 2 LSB to MSB
*codelow >>=1;
return *codehigh | *codelow;
}
return *codelow; // EM tag or Mifare without parity bits
}

char translateEnterEscapeKeyPress(char originalKeyPress) {
switch(originalKeyPress) {
case 0x0b: // 11 or * key
return 0x0d; // 13 or ASCII ENTER

case 0x0a: // 10 or # key
return 0x1b; // 27 or ASCII ESCAPE

default:
return originalKeyPress;
}
}

bool WIEGAND::DoWiegandConversion ()
{
unsigned long cardID;
unsigned long sysTick = millis();

if ((sysTick - _lastWiegand) > 25) // if no more signal coming through after 25ms
{
if ((_bitCount==24) || (_bitCount==26) || (_bitCount==32) || (_bitCount==34) || (_bitCount==8) || (_bitCount==4)) // bitCount for keypress=4 or 8, Wiegand 26=24 or 26, Wiegand 34=32 or 34
{
_cardTemp >>= 1; // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance
if (_bitCount>32) // bit count more than 32 bits, shift high bits right to make adjustment
_cardTempHigh >>= 1;

if (_bitCount==8) // keypress wiegand with integrity
{
// 8-bit Wiegand keyboard data, high nibble is the “NOT” of low nibble
// eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
char highNibble = (_cardTemp & 0xf0) >>4;
char lowNibble = (_cardTemp & 0x0f);
_wiegandType=_bitCount;
_bitCount=0;
_cardTemp=0;
_cardTempHigh=0;

if (lowNibble == (~highNibble & 0x0f)) // check if low nibble matches the “NOT” of high nibble.
{
_code = (int)translateEnterEscapeKeyPress(lowNibble);
return true;
}
else {
_lastWiegand=sysTick;
_bitCount=0;
_cardTemp=0;
_cardTempHigh=0;
return false;
}

// TODO: Handle validation failure case!
}
else if (4 == _bitCount) {
// 4-bit Wiegand codes have no data integrity check so we just
// read the LOW nibble.
_code = (int)translateEnterEscapeKeyPress(_cardTemp & 0x0000000F);

_wiegandType = _bitCount;
_bitCount = 0;
_cardTemp = 0;
_cardTempHigh = 0;

return true;
}
else // wiegand 26 or wiegand 34
{
cardID = GetCardId (&_cardTempHigh, &_cardTemp, _bitCount);
_wiegandType=_bitCount;
_bitCount=0;
_cardTemp=0;
_cardTempHigh=0;
_code=cardID;
return true;
}
}
else
{
// well time over 25 ms and bitCount !=8 , !=26, !=34 , must be noise or nothing then.
_lastWiegand=sysTick;
_bitCount=0;
_cardTemp=0;
_cardTempHigh=0;
return false;
}
}
else
return false;
}

Pls help me with this. It is very urgent.
Thanks in advance

Hi everyone
i am using a code by Daniel Smith from www.pagemac.com with my arduino nano to read weigand rfid cards. Although i am able to compile and upload it to the board whenever it scans a card it is showing unable to decode in the serial monitor. Can someone pls help me with this. I am new to arduino.

code that is used

#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*;*

  • }*

  • // card code = bits 15 to 34*

  • for (i=14; i<34; i++)*

  • {*

  • cardCode <<=1;*
    _ cardCode |= databits*;_
    _
    }*_

* 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*;
}*_

* // card code = bits 10 to 23*
* for (i=9; i<25; i++)*
* {*
* cardCode <<=1;*
_ cardCode |= databits*;
}*_

* 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 = 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);
}*

It would be graet if someone could help me out. It is extreemely urgent.
thanks in advance_

(deleted)

    // we will decode the bits differently depending on how many bits we have
    // see www.pagemac.com/azure/data_formats.php for mor info
    else {
      // you can add other formats if you want!
     Serial.println("Unable to decode."); 
    }

I think you need to add another format. It only checks for 35 bits or 26 bits. How many bits in your format?

Hi John
thank you so much for your reply
when i just change the code a bit it shows that it is reading 8 bit and each time i try with the same card it reads different number of bits 3 bits, 4bits 6 bits that way. is there anyway i could make it read 26 bits always so that it always gives an output something like this

Read 26 bits- facility code- card number-

what should i do to make it read 26 bits always so that i get the ssame facility code and card number when i scan a particular card.

Thank You so much

It could be that the “timer” is timing out in the middle of a message. Here is a version that uses the millis() timer to make sure it gives a full half second before a timeout. Try this to see if it at least comes up with the same number of bits each time! Also check that the ground wire between the Arduino and the reader is properly connected.

#define MAX_BITS 100                 // max number of bits 
#define WEIGAND_WAIT_TIME  500      // time (milliseconds) to wait for another Weigand pulse.  


uint8_t DataBits[MAX_BITS];    // stores all of the data bits
uint8_t BitCount;              // number of bits currently captured
boolean FlagDone = true;              // Set low when ready to capture data
volatile unsigned long WeigandWaitStartTime;  // countdown until we assume there are no more bits


// interrupt that happens when INTO goes low (0 bit)
void ISR_INT0()
{
  if (!FlagDone && BitCount < (MAX_BITS - 1))
  {
    DataBits[BitCount++] = 0;
    WeigandWaitStartTime = millis(); // Re-start the timer
  }
}


// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
{
  if (!FlagDone && BitCount < (MAX_BITS - 1))
  {
    DataBits[BitCount++] = 1;
    WeigandWaitStartTime = millis(); // Re-start the timer
  }
}


void setup()
{
  pinMode(13, OUTPUT);    // LED
  pinMode(2, INPUT);      // DATA0 (INT0)
  pinMode(3, INPUT);      // DATA1 (INT1)


  Serial.begin(9600);
  Serial.println("RFID Readers");

  // The two data lines idle HIGH
  if (digitalRead(2) == LOW) {
    Serial.println(F("WARNING: D0 line (on Pin 2) is not in a HIGH state.  Wiring error?"));
  }

  if (digitalRead(3) == LOW) {
    Serial.println(F("WARNING: D1 line (on Pin 3) is not in a HIGH state.  Wiring error?"));
  }


  // binds the ISR functions to the falling edge of INTO and INT1
  attachInterrupt(0, ISR_INT0, FALLING);
  attachInterrupt(1, ISR_INT1, FALLING);


  FlagDone = false;  // Allow the collection of data bits
}


void loop()
{
  unsigned long currentTime = millis();


  // Grab the
  noInterrupts();
  boolean done = FlagDone;
  uint8_t bits = BitCount;
  unsigned long timer = WeigandWaitStartTime;
  interrupts();


  //  If we have started receiving bits, wait until we have not had a new one for a while
  if (bits > 0)
  {
    digitalWrite(13, HIGH);
    if (currentTime - timer > WEIGAND_WAIT_TIME)
    {
      noInterrupts();
      FlagDone = true;  // Stop accepting data
      done = true;
      interrupts();
      
      digitalWrite(13, LOW);
    }
  }


  // if the timer completed, process the data
  if (done)
  {
    Serial.print("Read ");
    Serial.print(bits);
    Serial.println(" 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
      unsigned long facilityCode = 0;
      unsigned long cardCode = 0;


      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(facilityCode, cardCode);
      }
      else
      {
      // you can add other formats if you want!
      Serial.println("Unable to decode.");
      }
    */


    // Display the received bits
    for (int i = 0; i < bits; i++)
    {
      Serial.print((int)DataBits[i]);
    }


    // cleanup and get ready for the next card
    noInterrupts();
    BitCount = 0;
    FlagDone = false;  // Stop accepting data
    interrupts();
  }
}


void printBits(unsigned long facilityCode, unsigned long cardCode)
{
  // I really hope you can figure out what this function does
  Serial.print("FC = ");
  Serial.print(facilityCode);
  Serial.print(", CC = ");
  Serial.println(cardCode);
}

hi John
Thank you so much for the code you provided.
By using that code now when i use two different cards i am getting that it reads 9 bit for one and 13 bits for the other one. I'm getting the output as follows
Read 9 bits.
111111111Read 9 bits.
111111111Read 13 bits.
1111111111111Read 13 bits.
1111111111111Read 13 bits.
1111111111111Read 13 bits.
1111111111111Read 13 bits.
1111111111111Read 9 bits.
111111111Read 9 bits.
111111111Read 9 bits.
111111111Read 9 bits.
111111111Read 9 bits.
111111111Read 9 bits.

I need to read 26 bits data and decode it.I have just been given some random cards and dont know the format of the cards. Could it be the problem of the cards that im not getting 26 bit data. Is it that the format of cards are different and because of that im not able to read 26 bit and is there anyway i can decode the data and get the code of the cards displaying these 13bits and 9 bits.

Thank you so much

Hi John

I also tried one of the other programs that you had posted in this forum some time back. At that time also i got the result as follows. one card was reading 13bits the other was reading 9 bits.

13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
9 bits = 111111111
9 bits = 111111111

Im getting all the bits as one. Is this correct or is there something wrong with my output.

roshini_nair:
Hi John

I also tried one of the other programs that you had posted in this forum some time back. At that time also i got the result as follows. one card was reading 13bits the other was reading 9 bits.

13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
13 bits = 1111111111111
9 bits = 111111111
9 bits = 111111111

Im getting all the bits as one. Is this correct or is there something wrong with my output.

There is something wrong. It looks like you are getting no pulses from the D0 line. Try swapping the D0 and D1 wires to see if the problem is the sending device or the Arduino. If the problem is in the sending device you should get 13 0's or 9 0's. That would indicate that the D0 line (now connected to the 1's pin) is dead.

Hi John

yes when i swapped the D0 and D1 lines im getting zeroes. so there must be something wrong with the reading device. Is that why it is not able to read 26 bits and it is getting stuck at 13 bits and 9 bits? why is it not able to read 26 bit ?

Thank you so much

If a 26-bit code has thirteen 1's it should also have thirteen 0's. If the 0's output isn't working you will only see the thirteen pulses on the 1's output. Similarly, if the code has nine 1's it should have seventeen 0's and you will only see the nine 1's if the 0's output is not working.

Thank you so much John. I will try doing it using a different reader. Thank you so much.