Wiegand RFID (attachinterrupt) + new functions

Good Day Guys!

I am trying to read a wiegand RFID with the use of this code

#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(){
  rfid();
}

void rfid()
{
  // 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); 
}

This code actually works fine...instead of the content of void RFID() being inside void loop(), I seperatd it like the one shown in the code so that I can add additional functions...
The problem is that when I add additional functions on void loop, the code no longer functions properly.
Like when I add Serial.println("Test"); on void loop(); I cannot read tags anymore?

So what seems to be the problem on this? Thx Guys!

You're changing variables in an interrupt handler (like databits[], bitCount, flagDone, etc.) without declaring them as volatile. If you don't do that results may be unpredictable as the compiler is free to optimize in a way that may change the functionality.

Those Serial.print()s, even though they are commented out, do not belong in the interrupt service routines. Get rid of them.

What have you added to loop()? What happened when you did that? What serial output do you see?

You're changing variables in an interrupt handler (like databits[], bitCount, flagDone, etc.) without declaring them as volatile. If you don't do that results may be unpredictable as the compiler is free to optimize in a way that may change the functionality.

I haven't notice any unpredictable results before...but I guess no harm will be done by declaring them as volatile so I'll add them anyway...thx!

Those Serial.print()s, even though they are commented out, do not belong in the interrupt service routines. Get rid of them.

What have you added to loop()? What happened when you did that? What serial output do you see?

I simply add a Serial.println("test"); on the loop just to test If the reading of RFID will work with other functions.
( If this worked, I'm going to add additional functions such as reading compasses with software serial..and also some codes for ethernet)

By adding it the output was purely

test
test
test
test

even though i swiped a card already.
My expected output was

test
test
test
FC=99999, CC=000000 (this will appear if i swipe a card)
test
test
test

something like this

You could add some LEDs, and toggle them in the ISRs, to see if ISRs are being activated. You could add more Serial.print()s in rfid(), to see where it really gets to.

You could add some LEDs, and toggle them in the ISRs, to see if ISRs are being activated. You could add more Serial.print()s in rfid(), to see where it really gets to.

I tried what you said..I included a digitalwrite HIGH on isrint0 and a LOW on isrint1 and noticed that when I swipe the card 1st time the LED lit up and the 2nd time the LED blinks a little..so it seems the ISR are getting activated but still it doesn't print the card value in the serial monitor

And this part?

You could add more Serial.print()s in rfid(), to see where it really gets to.

I also added more Serial.prints on rfid() an it prints them all out

I tried adding a digitalWrite LOW inside the if( bitcount==26) and also if(bitcount==35)
and the LED doesnt turn off?
So i guess these mean i'm not getting all the bits I need?

what can be a solution for this?

**EDIT

I found the problem..it seems that I can't even enter if (bitCount > 0 && flagDone)
because flagdone won't get 1.

What seems to be causing this?

I found the problem..it seems that I can't even enter if (bitCount > 0 && flagDone)
because flagdone won't get 1.

What seems to be causing this?

I already made it work! Thx PaulS for teaching me the debugging part using LEDs....i forgot doing that..lol
But anyway...how does a simple Serial.println messes up the value of my flagdone?

Here is the code that worked...I removed the wiegand counter option which changes the flagdone value
I hope by doing so I dont get wrong values in the long run xD

#define MAX_BITS 100                 // max number of bits 

unsigned char databits[MAX_BITS];    // stores all of the data bits
unsigned char bitCount;              // number of bits currently captured

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()
{
  digitalWrite(13,HIGH);
  bitCount++; 
  
}

// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
{
  digitalWrite(13,LOW);
  databits[bitCount] = 1;
  bitCount++;
}

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);
  

}

void loop(){
  Serial.println("aw");
  rfid();
}

void rfid()
{
  
  // if we have bits and we the weigand counter went out
  if (bitCount > 25) {
    unsigned char i;
    digitalWrite(13,LOW);  
    // 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)
    {
      digitalWrite(13,LOW);
      // 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)
    {
      digitalWrite(13,LOW);
      // 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 {
      digitalWrite(13,LOW);
      delay(200);
      digitalWrite(13,HIGH);
     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); 
}

But anyway...how does a simple Serial.println messes up the value of my flagdone?

By not declaring variables used in interrupt routines volatile. As I told you the results are weired, sometimes it works, insert a single line of code somewhere and it stops working. You didn't believe me but if you disassemble the code you'll see what I mean.