-
-
Save ShakataGaNai/4319d3e82a858c9d00c1d80f20da81a3 to your computer and use it in GitHub Desktop.
/* | |
* HID RFID Reader Wiegand Interface for Arduino Uno | |
* Originally by Daniel Smith, 2012.01.30 -- http://www.pagemac.com/projects/rfid/arduino_wiegand | |
* | |
* Updated 2016-11-23 by Jon "ShakataGaNai" Davis. | |
* See https://obviate.io/?p=7470 for more details & instructions | |
*/ | |
#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 | |
int LED_GREEN = 11; | |
int LED_RED = 12; | |
int BEEP_BEEP = 10; | |
// 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(LED_RED, OUTPUT); | |
pinMode(LED_GREEN, OUTPUT); | |
pinMode(BEEP_BEEP, OUTPUT); | |
digitalWrite(LED_RED, HIGH); // High = Off | |
digitalWrite(BEEP_BEEP, HIGH); // High = off | |
digitalWrite(LED_GREEN, LOW); // Low = On | |
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. "); | |
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() { | |
Serial.print("FC = "); | |
Serial.print(facilityCode); | |
Serial.print(", CC = "); | |
Serial.println(cardCode); | |
// Now lets play with some LED's for fun: | |
digitalWrite(LED_RED, LOW); // Red | |
if(cardCode == 12345){ | |
// If this one "bad" card, turn off green | |
// so it's just red. Otherwise you get orange-ish | |
digitalWrite(LED_GREEN, HIGH); | |
} | |
delay(500); | |
digitalWrite(LED_RED, HIGH); // Red Off | |
digitalWrite(LED_GREEN, LOW); // Green back on | |
// Lets be annoying and beep more | |
digitalWrite(BEEP_BEEP, LOW); | |
delay(500); | |
digitalWrite(BEEP_BEEP, HIGH); | |
delay(500); | |
digitalWrite(BEEP_BEEP, LOW); | |
delay(500); | |
digitalWrite(BEEP_BEEP, HIGH); | |
} |
Not the author, but I suspect I can answer your questions:
char
just means a 1-byte value, and can be used numerically (think like the ordinal of a value, 'A' == 65, etc). If the author had declared it as anint
, it would be 4 bytes long, which was not needed in this case.- the
databits
structure is initialized to all zeros on line 123, so there's no need to write a zero. Essentially what's going on is you have a buffer and a pointer into it (e.g.[0]00000
). If you read a zero, just move the pointer ([0]00000
->0[0]0000
), while if you read a one you need to overwrite the value and then move the pointer (0[0]0000
->0[1]0000
->01[0]000
) - lines 84 and 90 shift the value one bit to the left, and then
or
in the new value pulled fromdatabits
. Those lines aren't resetting the values, they're completing them, after whichprintBits()
is called on line 94, after which the values are reset on lines 119 and 120.
Hey, I love the code, it is the only one I could find that I could edit to decode my 36bit badge!
I'm not done troubleshooting yet, but can you think of any reason this code would crash an Arduino if left to run for over a few hours? I know I have the raw option enabled, but none of the data is stored to a cache or ram or anything like that, correct? (Sorry, I'm a noob).
Thanks!!
if left to run for over a few hours
I don't see a reason why it would be a problem. The code does very very little beyond exactly what is required to decode the bits. There is a small memory of stuff, but only used to keep track of the bits coming in. If it's been longer than 3 seconds since the bits came in, then that memory is reset.
In short, I can't see any reason why it would be a problem, but I never actually tested this in production.
Dear Mr Davis,
I have got my hands on a HID reader and the sketch now works fine with all HID Keyfobs III and Keyfobs II, so thank you very much for that.
I am now trying to incorporate your HID sketch in the 13.56 mHz RFID MFRC 522 sketch called "Acces Control", which is in the Arduino Library as an example. I have not succeeded yet, but also ran into a few questions:
Your help much appreciated.