Go Down

Topic: RFID Wiegand Output (Read 2 times) previous topic - next topic

WhiteNite1971

Hey Gang

I am relatively new to Arduino but I am loving it. I am interested in connecting an RFID Reader with a Wiegand output to my Arduino. I have found the following on the old forum;

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1240374471

I do have some questions with regard to the code if anyone could help?

1. I was wondering why it uses a baud rate of 57600? Is this the standard for Wiegand?

2. I don't quite understand the following code;

  //Not sure what this section does exactly
  for(int i = 2; i < 4; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH);
    digitalWrite(i, LOW);
    pinMode(i, INPUT);
    digitalWrite(i, HIGH);
  }
}

3. I'd like some help extracting the tag number and to serial print this as binary, hex and decimal.

Any help would be greatly appreciated.

Kind Regards

Jason




johnwasser

> 1. I was wondering why it uses a baud rate of 57600? Is this the standard for Wiegand?

I don't think the Wiegand uses serial at all.  That might be for communication to the PC.

> 2. I don't quite understand the following code;

The comments in the original code say that they are forcing an initial interrupt on each line.   Not sure why.

> 3. I'd like some help extracting the tag number and to serial print this as binary, hex and decimal.
Code: [Select]

if(reader1Count >= 26)
  {
  Serial.print(" Binary: ");Serial.println(reader1,BIN);
  Serial.print(" Hex: ");Serial.println(reader1,HEX);
  Serial.print(" Decimal: ");Serial.println(reader1,DEC);
  reader1 = 0;
  reader1Count = 0;
  }
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

WhiteNite1971

Hi John

Thanks for your reply. I have tried using a few different tags and getting some odd results. They seem to vary in length. I would assume for each tag I should get 26 binary digits? I was hoping that from here I can parse out the tag ID. It seems to vary depending on the batch/ type of tag I use. Is this normal or is there something I'm doing wrong in the code?

Cheers

Jason

johnwasser

The code is written to work with 26-bit tokens.  If you have tokens with different numbers of bits you will have to add some additional code, such as detecting a delay after the last bit.  34-bit seems to be a popular size.

In the 26-bit standard:
    The first bit is an Even Parity bit for the next 12 bits.
    The next 8 bits are the Facility Code
    The next 16 bits are the Card Number
    The last bit is an Odd Parity bit for the previous 12 bits.

http://www.hidglobal.com/documents/understandCardDataFormats_wp_en.pdf
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

WhiteNite1971

Hi John

Great to hear from you again. So correct me if I'm wrong; tags can have varying number of bits along with different formats? I have a variety of tags i.e. bracelets, card and fobs. Depending on what I'm using I get a different number of bits.

Kind Regards

Jason

johnwasser

That is what HID says in the document I pointed to.  There is nothing magic about the number 26, it's just one of the many available formats.

What I would do is note the time when the latest bit arrived.  If it has been more than, say, 100 milliseconds (0.1 second) since the last bit arrived, the code is probably complete.  Then from the number of bits and the pattern of bits you can identify each tag.  For tags with more than 32 bits of data you should probably just keep the last 32 rather than trying to keep all the bits.

Code: [Select]

if(reader1Count > 0 && millis() - LastBitArrivalTime > 100)
 {
 Serial.print(" Bits received: ");Serial.print(reader1Count);
 Serial.print(" Binary: ");Serial.print(reader1,BIN);
 Serial.print(" Hex: ");Serial.print(reader1,HEX);
 Serial.print(" Decimal: ");Serial.println(reader1,DEC);
 reader1 = 0;
 reader1Count = 0;
 }

[/quote].
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

WhiteNite1971

Hey Gang

I have been playing with this for the last couple of hours and something just doesn't seem right. I have purchased a 100 identical tags but when I read them some have 26 bits while others have less. Two things I have noticed/ thought of.

1. I am not using pull ups on the Data0 or Data1

2. Every tag I read starts with a 1

Been interested in your thoughts.

Kind Regards

Jason

johnwasser

> 1. I am not using pull ups on the Data0 or Data1

The Arduino has internal pull-up resistors that are enabled by digitalWrite(pin,HIGH) after pinMode(pin, INPUT).  Is that code missing?

> 2. Every tag I read starts with a 1

Is that binary, hex, or decimal?

The first bit is a parity bit for the first 12 data bits.  The 12 data bits are the facility code (which should be all the same for a single batch of cards) and the top four bits of the card sequence number (which I would not expect to change until the lower 12 bits overflow).  That would meant that the first 13 bits in a batch of cards will likely always be the same.

The code only prints wen you get 26 or more bits.  How do you know that you are sometimes getting fewer than 26?  Please post your full program and a sample of your serial monitor results.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

WhiteNite1971

Hi John

Really appreciate you looking at this for me. Below is a chopped down version of code developed by Mike Cook;

Code: [Select]
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(){
  Serial.begin(57600);
  attachInterrupt(0, reader1Zero, FALLING);
  attachInterrupt(1, reader1One, FALLING);
  delay(10);
 
  for(int i = 2; i<4; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH);
    digitalWrite(i, LOW);
    pinMode(i, INPUT);
    digitalWrite(i, HIGH);
    delay(10);
    reader1 = 0;
    reader1Count = 0;
  }
}

void loop(){
  if(reader1Count >= 26){
    Serial.println(reader1, BIN);
    reader1 = 0;
    reader1Count = 0;
  }
}


The results I'm getting is as follows;

Quote
10001011101001000111000010
11110101111100001111100101
110011100001100
1100101100100100010000100
1110101111001111000001011
11110101111010010001111000
10001011101000110101011010
1110110010110110110001110
11110101111011101000111100
11110110010101011110100111


As you can see, some results are 26 bits while others are slightly more or less?

Very confused.  :(

Kind Regards

Jason

johnwasser

I can imagine that Serial.print() drops leading zeros but that data looks too random to be right.  Is that the same token each time or different tokens each time?

Try this:

Code: [Select]

volatile long reader1 = 0;
volatile int reader1Count = 0;
volatile unsigned long reader1LastBitTime;

void reader1One(void){
  reader1LastBitTime = millis();
  reader1Count++;
  reader1 = reader1 << 1;
  reader1 |=1;
}

void reader1Zero(void){
  reader1LastBitTime = millis();
  reader1Count++;
  reader1 = reader1 << 1;
}

void setup(){
  Serial.begin(57600);
  attachInterrupt(0, reader1Zero, FALLING);
  attachInterrupt(1, reader1One, FALLING);
  delay(10);

  for(int i = 2; i<4; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH);
    digitalWrite(i, LOW);
    pinMode(i, INPUT);
    digitalWrite(i, HIGH);
    delay(10);

    reader1 = 0;
    reader1Count = 0;
  }
}

void loop(){
  if(reader1Count > 0 && (millis() - reader1LastBitTime) > 100){
    Serial.print(reader1Count);
    Serial.print(" bits = ");
    Serial.println(reader1, BIN);
    reader1 = 0;
    reader1Count = 0;
  }
}

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

WhiteNite1971

Hi John

I have run your code and get the following;

Quote
26 bits = 11110101111100001111100101
26 bits = 110011100001100
26 bits = 10001011101001000111000010
26 bits = 1100101100100100010000100
5 bits = 11110
20 bits = 1111010010001111000
26 bits = 10001011101000110101011010
20 bits = 1110101111001111000
4 bits = 1011
26 bits = 11110101111011101000111100
26 bits = 11110110010101011110100111
25 bits = 111011001011011011000111
26 bits = 1100101100100100010000100
26 bits = 110011100001100


They are all the same type of tag from the same batch of 100 I purchased.

Very odd. :(

Be interested in your thoughts.

Kind Regards

Jason

WhiteNite1971

Hi John

I have reverted to the old code and tried another batch of tags. Below is what I get on the serial monitor;

Quote
10001111100100100000001
10001111100011110100101
1011010101110101101011001
110001000011011010111011
10010000001100000010000
11101100001111001101101100
10010000001000001011111
1000011111110111111111110
10101000110101101100000111
11011010110010100111110010


If I do the following;

1. Remove the right most bit from the code (parity bit)
2. Retain the next 24 bits
3. Add 0's to the left most part of the code to make a total of 24 bits (I think println() gets rid of zeros to the left)

Then the numbers match with what is printed on the tag. :)

Example:

10001111100100100000001

0010 0011 1110 0100 1000 00001

Now it is a matter of doing this within the program.

On the old forum this was discussed but I didn't quite grasp what they were talking about. The term bit manipulation was used along with masking. I understood the bit manipulation aspect.

Example:

10001111100100100000001

tagID=(reader1 >> 1)

10001111100100100000001

This means that the code is shifted one step to the right. The one drops off. This gets rid of the parity bit.

The masking I am not entirely sure about.

tagID=(reader1 >> 1) & 0xFFFFFF

I think this grabs a specific number of bits from what is left in the code. The 0xFFFFFF is HEX for 24.

Example

0010 0011 1110 0100 1000 0000

I have tried to do this in the sketch but not quite there;

Code: [Select]
void loop(){
  if(reader1Count >= 26){
    int tagID=(reader1 >> 1) & 0xFFFFFF;
    Serial.println(tagID, BIN);
    reader1 = 0;
    reader1Count = 0;
    tagID=0;


I'm sure whether I should be declaring tagID as a int for one.

Be interested in your thoughts.

Kind Regards

Jason

WhiteNite1971

Hey Gang

Me again. I have modified the code as follows;

Code: [Select]
void loop(){
  if(reader1Count >= 26){
    long tagID=(reader1 >> 1) & 0xFFFFFF;
    Serial.println(tagID, DEC);
    reader1 = 0;
    reader1Count = 0;
    tagID=0;
  }
}


The variable tagID needs to be declared as long NOT int. An int can only handle 16 bits while a long can handle 32 bits which is slightly more than what we need.

John, thanks so much for your help. I'm a very happy man!  :D

Kind Regards

Jason

johnwasser


I think this grabs a specific number of bits from what is left in the code. The 0xFFFFFF is HEX for 24.


0xFFFFFF (also 0x00FFFFFF) is HEX for 0b00000000111111111111111111111111

The bitwise AND operation (&) will put a 1 where both values have a 1 and 0 where either value has a 0.

Since you are not working with signed numbers (numbers that can be less than zero) you should probably use 'unsigned long' for both reader1 and tagID.  They will work as plain long integers but using unsigned values where you don't need the sign is good practice.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

WhiteNite1971

Hi John

Thanks for your assistance.  :)

Kind Regards

Jason

Go Up