More Wiegands at one Arduino

This article describes the possibility to service more than one Wiegand device by one Arduino/328.

So far available interrupt-driven Wiegand receivers for Arduino have one big disadvantage. The AtMega 328 supports only two hardware external interrupts, assigned to pin 2 and 3. Thus, the well-known Wiedand receivers use the same technique – attach one of them to the Wiegand D0 signal, the other to the D1 and at every interrupt „shift in“ the appropriate zero or one bit. This way only one Wiegand device can be serviced.

My approach shares the interrupt via diode wired-OR matrix and decodes the state of the wires later. Thus, you can attach more, than one wiegand device – up to about 8 or more. How? See the picture:arduino-more-wg

This way every „low“ pulse at any wiegand wire initiates an hardware interrupt. Then, the pin values are read as a whole port read (minimising delay) and decoded later, because, between the pulses, there is a plenty of time (about 2 milliseconds) to do that.

 

 

 

Everything is clear from the following code fragments (three readers example):

// hardware pins
#define HWINT 2
#define R1D0 14
#define R1D1 15
#define R2D0 16
#define R2D1 17
#define R3D0 8
#define R3D1 9

// code buffers
unsigned long b1 = 0;
unsigned long b2 = 0;
unsigned long b3 = 0;

// bit counters
byte bc1 = 0;
byte bc2 = 0;
byte bc3 = 0;
pinMode(HWINT,INPUT);       // set HW int pin in as input
pinMode(R1D0,INPUT_PULLUP); // set wiegand pins as inputs with pullups
pinMode(R1D1,INPUT_PULLUP);
pinMode(R2D0,INPUT_PULLUP);
pinMode(R2D1,INPUT_PULLUP);
pinMode(R3D0,INPUT_PULLUP);
pinMode(R3D1,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(HWINT), processIntr, FALLING);
void processIntr()
 {
  byte vc = PINC;
  byte vb = PINB; 

  //R1
  if (bc1 < 26)
   {   
    if (!bitRead(vc,0)) { b1 = (b1<<1); bitWrite(b1,0,0); bc1++; };    // D0
    if (!bitRead(vc,1)) { b1 = (b1<<1); bitWrite(b1,0,1); bc1++; };    // D1
   };

  //R2
  if (bc2 < 26)
   {   
    if (!bitRead(vc,2)) { b2 = (b2<<1); bitWrite(b2,0,0); bc2++; };    // D0
    if (!bitRead(vc,3)) { b2 = (b2<<1); bitWrite(b2,0,1); bc2++; };    // D1
   };

  //R3
  if (bc3 < 26)
   {   
    if (!bitRead(vb,0)) { b3 = (b3<<1); bitWrite(b3,0,0); bc3++; };    // D0
    if (!bitRead(vb,1)) { b3 = (b3<<1); bitWrite(b3,0,1); bc3++; };    // D1
   };

Limitation:

Yes, there is one importatnt limitation – the code does not correctly solve the transmission congestion. Thus, when two (or more) codes collide in time, they get mixed up. But, for the intended use (RFID identification) the probability of the 50 millisecond congestion is very low. But, I do recommend to check the wiegand’s internal parity bits, they detect the congestion reliably enough.

Why?

Why there is an external pullup resistor of 2k2, instead of internal processor’s pullup? Because the IRQ should be more glitchproof, than the relatively weak internal pullup (about 100k) offers. If you feel safe enough, you can omit this and set the internal pullup at the interrupt pin, sure.