Go Down

Topic: WIEGAND 26bits format to Arduino UNO. Requesting guidances. (Read 15471 times) previous topic - next topic

zawman

Before I begin, I am a fellow programmer who learnt how to program by myself and it just started 2 months ago.

I am glad this forum exists to help fellow Arduino lovers and right now I do need some guidances about WIEGAND 26bits format device to communicate with ARDUINO UNO board.

So, from there I have a few problems that are too complicated to solve on my own, so I seek some pointers from readers here.

To begin,
I am using ARDUINO UNO board shown in the link.


And this is my fingerprint device whose communications are RS232 to PC and WIEGAND to ARDUINO.
http://www.futronic-tech.com/product_fs20.html



Lastly, this is my 2 relays board circuit connection.


The purpose of all these shown above is to get a fingerprint device to transmit signals of 26bits to Arduino UNO and then UNO will operate either relay depends on the user selection from the fingerprint device.

Which means UNO will have to operate as a "Converter or Middleman" between the fingerprint device and the 2 relays.

And so, problems surface as I edit Crazy People's arduino sketch from http://www.thebox.myzen.co.uk/Hardware/Crazy_People.html

Code: [Select]
/* Crazy People
* By Mike Cook April 2009
* One Fingerprint Reader outputing 26 bit Wiegand code to pins:-
* Reader A (Head) Pins 4 & 5
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
#include "pins_arduino.h"
/*
* an extension to the interrupt support for arduino.
* add pin change interrupts to the external interrupts, giving a way
* for users to have interrupts drive off of any pin.
*/

/*
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
* The PCINT corresponding to the pin must be enabled and masked, and
* an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
* must use some logic to actually implement a per-pin interrupt service.
*/

/* Pin to interrupt map:
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
*/

volatile uint8_t *port_to_pcmask[] = {
  &PCMSK0,
  &PCMSK1,
  &PCMSK2
};

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = {
  NULL };

volatile static uint8_t PCintLast[3];

/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  uint8_t slot;
  volatile uint8_t *pcmask;

  if (mode != CHANGE) {
    return;
  }
  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  }
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }
  slot = port * 8 + (pin % 8);
  PCintFunc[slot] = userFunc;
  // set the mask
  *pcmask |= bit;
  // enable the interrupt
  PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *pcmask;

  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  }
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }

  // disable the mask.
  *pcmask &= ~bit;
  // if that's the last one, disable the interrupt.
  if (*pcmask == 0) {
    PCICR &= ~(0x01 << port);
  }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
  uint8_t bit;
  uint8_t curr;
  uint8_t mask;
  uint8_t pin;

  // get the pin states for the indicated port.
  curr = *portInputRegister(port+2);
  mask = curr ^ PCintLast[port];
  PCintLast[port] = curr;
  // mask is pins that have changed. screen out non pcint pins.
  if ((mask &= *port_to_pcmask[port]) == 0) {
    return;
  }
  // mask is pcint pins that have changed.
  for (uint8_t i=0; i < 8; i++) {
    bit = 0x01 << i;
    if (bit & mask) {
      pin = port * 8 + i;
      if (PCintFunc[pin] != NULL) {
        PCintFunc[pin]();
      }
    }
  }
}

SIGNAL(PCINT0_vect) {
  PCint(0);
}
SIGNAL(PCINT1_vect) {
  PCint(1);
}
SIGNAL(PCINT2_vect) {
  PCint(2);
}

// End of interrupts code and start of the reader code

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

void reader1One(void) {
  if(digitalRead(4) == LOW){
  reader1Count++;
  reader1 = reader1 << 1;
  reader1 |= 1;
  }
}

void reader1Zero(void) {
  if(digitalRead(5) == LOW){
  reader1Count++;
  reader1 = reader1 << 1; 
  }
}


void setup()
{
  Serial.begin(57000);
  // Attach pin change interrupt service routines from the Wiegand Fingerprint reader
  PCattachInterrupt(4, reader1One, CHANGE);
  PCattachInterrupt(5, reader1Zero, CHANGE);

  delay(10);
  // the interrupt in the Atmel processor misses out the first negative pulse as the inputs are already high,
  // so this gives a pulse to each reader input line to get the interrupts working properly.
  // Then clear out the reader variables.
  // The readers are open collector sitting normally at a one so this is OK
  for(int i = 4; i<10; i++){
  pinMode(i, OUTPUT);
   digitalWrite(i, HIGH); // enable internal pull up causing a one
  digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
  pinMode(i, INPUT);
  digitalWrite(i, HIGH); // enable internal pull up
  }
  delay(10);
  // put the reader input variables to zero
  reader1 = 0;
  reader1Count = 0;
  digitalWrite(13, HIGH);  // show Arduino has finished initialization
}

void loop() {
  if(reader1Count >= 26){
//  Serial.print(" Reader 1 ");Serial.println(reader1,HEX);
  Serial.println("A");Serial.println(reader1 & 0xfffffff);
  reader1 = 0;
  reader1Count = 0;
     }
}


According to this sketch above, it is supposed to transmit 26bits signals over to arduino UNO in the form of 32bits, right?



From the picture above, HOW do I make the UNO to read only the USER CODE from WIEGAND so that I can get my fingerprint to match with the USER CODE and then I can choose to select which RELAY LED to activate? It's the even parity bit that is in the way...




Problem 1: Removing the parity bit and get only the USER CODE so that I can get my fingerprint ID to match with it.
Problem 2: How do I get PIN 10 or PIN 11 to activate when I have successfully match my fingerprint ID with the USER CODE and I have to select relay?


I seek your expertise in this area, readers!

sonnyyu

did you try http://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino ?

The standard Wiegand format had one parity bit, 8 bits of facility code, 16 bits of ID code, and a trailing parity bit for a total of 26 bits. The first parity bit is calculated from the first 12 bits of the code and the trailing parity bit from the last 12 bits. Yours is seem like standard.

zawman

#2
May 23, 2013, 03:22 am Last Edit: May 23, 2013, 05:36 am by zawman Reason: 1
sonnyyu, the link you provided is included with a library that is not working correctly on my sketch because Arduino is unable to import .cpp and .h from that file.

Yes, my sketch is standard. All I need to understand is how am I able to extract the USER CODE (16bits) from the 26bits WIEGAND so that I can bring it over to my LED RELAY CONTROL as a known variable.

From there, I am stuck.

Updated: alright, it is working now. from what I see from the link above, I don't think it is capable of storing 26 bits value to EEPROM since I need to store a 26bits WIEGAND value of which only 16bit out of 26bit is what I really need in order to do ID MATCHING.

Grumpy_Mike

Take the 26 bit Weagand code into a long int variable. Shift it to the right one place and mask out the lower 16 bits to just give you the user code.
Code: [Select]

user = ( weagand >> 1) & 0xffff;

zawman

#4
May 27, 2013, 04:30 am Last Edit: May 27, 2013, 07:58 am by zawman Reason: 1
Yes, I found how how to shift bits register to the right by 1 bit to "remove" the odd parity and mask out the other bits. THANK YOU!

Now, next to a bigger problem yet.

How do I convert the newly read bits onto EEPROM? I heard it uses 12 bits formats?

Sigh, converting bits formats are really troublesome.


updated:

according to http://forum.arduino.cc/index.php?topic=157574.0

I have to break down 26 bits WIEGAND format into separate byte on which I must get USERID bits to break down into 16 different bits.
Am I correct on this?

Grumpy_Mike

It is much simpler and is just a variant on what you have done already.
You have removed both parity bits so younare left with 24 bits or three bytes. Just convert them into bits by shift and mask and store the bits in EEPROM.

zawman

#6
May 28, 2013, 03:29 am Last Edit: May 28, 2013, 05:02 am by zawman Reason: 1
From what I see, I had only removed the even parity. I do not know how to remove the odd parity.

Code: [Select]
/* Crazy People
* By Mike Cook April 2009
* One Fingerprint Reader outputing 26 bit Wiegand code to pins:-
* Reader A (Head) Pins 4 & 5
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
#include "pins_arduino.h"
/*
* an extension to the interrupt support for arduino.
* add pin change interrupts to the external interrupts, giving a way
* for users to have interrupts drive off of any pin.
*/

/*
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
* The PCINT corresponding to the pin must be enabled and masked, and
* an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
* must use some logic to actually implement a per-pin interrupt service.
*/

/* Pin to interrupt map:
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
*/

volatile uint8_t *port_to_pcmask[] = {
 &PCMSK0,
 &PCMSK1,
 &PCMSK2
};

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = {
 NULL };

volatile static uint8_t PCintLast[3];

/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 uint8_t slot;
 volatile uint8_t *pcmask;

 if (mode != CHANGE) {
   return;
 }
 // map pin to PCIR register
 if (port == NOT_A_PORT) {
   return;
 }
 else {
   port -= 2;
   pcmask = port_to_pcmask[port];
 }
 slot = port * 8 + (pin % 8);
 PCintFunc[slot] = userFunc;
 // set the mask
 *pcmask |= bit;
 // enable the interrupt
 PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 volatile uint8_t *pcmask;

 // map pin to PCIR register
 if (port == NOT_A_PORT) {
   return;
 }
 else {
   port -= 2;
   pcmask = port_to_pcmask[port];
 }

 // disable the mask.
 *pcmask &= ~bit;
 // if that's the last one, disable the interrupt.
 if (*pcmask == 0) {
   PCICR &= ~(0x01 << port);
 }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
 uint8_t bit;
 uint8_t curr;
 uint8_t mask;
 uint8_t pin;

 // get the pin states for the indicated port.
 curr = *portInputRegister(port+2);
 mask = curr ^ PCintLast[port];
 PCintLast[port] = curr;
 // mask is pins that have changed. screen out non pcint pins.
 if ((mask &= *port_to_pcmask[port]) == 0) {
   return;
 }
 // mask is pcint pins that have changed.
 for (uint8_t i=0; i < 8; i++) {
   bit = 0x01 << i;
   if (bit & mask) {
     pin = port * 8 + i;
     if (PCintFunc[pin] != NULL) {
       PCintFunc[pin]();
     }
   }
 }
}

SIGNAL(PCINT0_vect) {
 PCint(0);
}
SIGNAL(PCINT1_vect) {
 PCint(1);
}
SIGNAL(PCINT2_vect) {
 PCint(2);
}

// End of interrupts code and start of the reader code

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

void reader1One(void) {
 if(digitalRead(4) == LOW){
 reader1Count++;
 reader1 = reader1 >> 1 & 0xffff;  // user = ( weagand >> 1) & 0xffff;
 reader1 |= 1;
 }
}

void reader1Zero(void) {
 if(digitalRead(5) == LOW){
 reader1Count++;
 reader1 = reader1 >> 1 & 0xffff;  // user = ( weagand >> 1) & 0xffff;
 }
}


void setup()
{
 Serial.begin(57000);
 // Attach pin change interrupt service routines from the Wiegand Fingerprint reader
 PCattachInterrupt(4, reader1One, CHANGE);
 PCattachInterrupt(5, reader1Zero, CHANGE);

 delay(10);
 // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
 // so this gives a pulse to each reader input line to get the interrupts working properly.
 // Then clear out the reader variables.
 // The readers are open collector sitting normally at a one so this is OK
 for(int i = 4; i<10; i++){
 pinMode(i, OUTPUT);
  digitalWrite(i, HIGH); // enable internal pull up causing a one
 digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
 pinMode(i, INPUT);
 digitalWrite(i, HIGH); // enable internal pull up
 }
 delay(10);
 // put the reader input variables to zero
 reader1 = 0;
 reader1Count = 0;
 digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
 if(reader1Count >= 26){
//  Serial.print(" Reader 1 ");Serial.println(reader1,HEX);
 Serial.println("A");Serial.println(reader1 & 0xfffffff);
 reader1 = 0;
 reader1Count = 0;
    }
}



Your helpful code had been modified into my reader1One and reader1Zero

So by doing that I am left with 25 bit signal with only the userID bit not masked instead.

0xFFFF is 16 bit values of all 1, right? meaning the 16bit all 1 is on USERID code? Why is it masked? Can the arduino send the masked userID over to selection of LED 1 or LED 2 by using case select structure?





Another thing about EEPROM,

Code: [Select]
#include <EEPROM.h>

#define EEPROM_MAX 1024 // Maximum capacity of the EEPROM memory

void EEPROMClearMemory() {
  for (int addr=0;addr<EEPROM_MAX;addr++) {EEPROM.write(addr,0);} //overwrite all memory with 0s
}

void EEPROMWriteLong(int p_address, long p_value) // Long = 4 bytes
{
  byte Byte1 = ((p_value >> 0) & 0xFF);
  byte Byte2 = ((p_value >> 8) & 0xFF);
  byte Byte3 = ((p_value >> 16) & 0xFF);
  byte Byte4 = ((p_value >> 24) & 0xFF);

  EEPROM.write(p_address, Byte1);
  EEPROM.write(p_address + 1, Byte2);
  EEPROM.write(p_address + 2, Byte3);
  EEPROM.write(p_address + 3, Byte4);
}

long EEPROMReadLong(int p_address)
{
  byte Byte1 = EEPROM.read(p_address);
  byte Byte2 = EEPROM.read(p_address + 1);
  byte Byte3 = EEPROM.read(p_address + 2);
  byte Byte4 = EEPROM.read(p_address + 3);

  long firstTwoBytes = ((Byte1 << 0) & 0xFF) + ((Byte2 << 8) & 0xFF00);
  long secondTwoBytes = (((Byte3 << 0) & 0xFF) + ((Byte4 << 8) & 0xFF00));
  secondTwoBytes *= 65536; // multiply by 2 to power 16 - bit shift 24 to the left

  return (firstTwoBytes + secondTwoBytes);
}



From the EEPROM sketch above,
First the memory inside, the stored values will be cleared. 0 values all over. That is the purpose of EEPROMClearMemory.

Then, the program will start to write values from somewhere, assuming WIEGAND 26bit.
From EEPROMWriteLong, I am unable to comprehend the functions operated. May I have your guidance to explain this to me?

Finally, in EEPROMReadLong,
From what I see, it will call the EEPROMWriteLong void and get the 4 bytes over to, assuming LEDS as outputs.
Am I right on this?


Grumpy_Mike

Quote
I do not know how to remove the odd parity.

Code: [Select]

removed = number & 0xfffff;

That will take the top bit out and give you a variable of only 24 bits. This will need only 3 bytes of EEPROM to store the two numbers from the card.

Quote
0xFFFF is 16 bit values of all 1, right?

Yes
Quote
meaning the 16bit all 1 is on USERID code?

No.
If you apply a mask to a variable using a a bitwise and operation & then all the bits in the variable with a corresponding bit of zero in the mask will give a zero in the result. All the bits in the variable with a corresponding bit of one in the mask will leave the bit in the result the same as it was in the original variable. So the bitwise and operation & selectively clears bits.
So applying a mask of 0xffff will leave only the two least significant bytes of the three byte number.

I don't know what you mean by:-
Quote
assuming LEDS as outputs


zawman


Quote
I do not know how to remove the odd parity.

Code: [Select]

removed = number & 0xfffff;

That will take the top bit out and give you a variable of only 24 bits. This will need only 3 bytes of EEPROM to store the two numbers from the card.
Code: [Select]
volatile long reader1 = 0;
volatile int reader1Count = 0;

void reader1One(void) {
  if(digitalRead(4) == LOW){
  reader1Count++;
  reader1 = reader1 >> 1 & 0xffff;
  reader1 |= 1;
  }
}

void reader1Zero(void) {
  if(digitalRead(5) == LOW){
  reader1Count++;
  reader1 = reader1 >> 1 & 0xffff; 
  }
}

By putting this [ removed = number & 0xfffff; ] to the 2 voids above, this is puzzling me, if I want to remove the even parity bit, I should put the code that you gave me at AFTER the count++; or after the shift register;?

I don't know what you mean by:-
Quote
assuming LEDS as outputs

For this EEPROM, what I meant was that is EEPROM capable of sending a 16 bit signal from the EEPROM memory over to the output pin where I write a program about ID MATCHING?

And by doing that, I must verify (match, I mean,) the EEPROM variable = USERID CODE from WIEGAND variable right? So if the EEPROM 16bits signal matches the USERID CODE from WIEGAND, the output pin which has a LED will light on.

So for this operation, is it possible? I just started learning C++ and I am getting the hang of it thank to you, Grumpy_Mike. I am surprised you have a high level of tolerance towards new comers like me. You make a great teacher. Thank you for the big help, again!!

I still do not get the EEPROM operations of reading and writing at all.. Where are the stored values being called upon and stayed into? Especially the calling part, I need to call out the variable before I break it down into 4 bytes or call the byte 1 by 1? And by calling, it means by writing or reading?




Grumpy_Mike

#9
May 30, 2013, 11:02 am Last Edit: May 30, 2013, 11:07 am by Grumpy_Mike Reason: 1
Quote
By putting this  removed = number & 0xfffff;  to the 2 voids above, this is puzzling me,

No you do it after all 26 bits of the wiegand code has been inputted.
So:-
Code: [Select]

void loop() {
 if(reader1Count >= 26){
long int rawToken = (reader1 >> 1) & 0xffffff); // remove both parity bits
int facilityCode = rawToken >> 16; // just get the top 8 bits
int userID = rawToken & 0xffff; // bottom 16 bits are the user code
 Serial.print("Facility Code ");
 Serial.println(facilityCode); // use Serial.println(facilityCode, HEX); // to see the result in hex
 Serial.print("User ID ");
 Serial.println(userID);

 reader1 = 0;
 reader1Count = 0;
    }
}


Now you need to find a place in EEPROM to store it, you need only 3 bytes to store this so you invent a number called say slot which is the number which you use to identify what virtual slot you will store it in. The "real" point in the EEPROM is thus three times this slot number. So you can write a function that stores the token in a slot number:-
Code: [Select]

void storeToken(int slot, long int token){
int byteAddress = slot * 3; // the start point of where you will store it in EEPROM
  EEPROM.write(byteAddress, token >> 16); // store facility code
  EEPROM.write(byteAddress + 1, (token >> 8) & 0xff); // store upper 8 bits of id
  EEPROM.write(byteAddress + 2,  token  & 0xff); // store lower 8 bits of id
}

and you can write the corresponding one that retrieves the token:-
Code: [Select]

long int getToken(int slot){
long int recoverdToken;
int byteAddress = slot * 3; // the start point of where you will store it in EEPROM
  recoverdToken = EEPROM.read(byteAddress) << 16;
  recoverdToken |= EEPROM.read(byteAddress + 1) << 8; // note the |= is an OR operation on the existing variable
  recoverdToken |= EEPROM.read(byteAddress + 2);
return recoverdToken;
}



So the whole of the token value minus parity bits is in a long int variable and you can use the normal if == to test it.
Code: [Select]

if(rawToken == getToken(0) ) { // do this if the value in rawToken matches what is in the first slot
// do stuff
}

This of course will be in a loop where
Code: [Select]
getToken(0) is replaced by
Code: [Select]
getToken(i) with i being the loop variable.

zawman

#10
Jun 03, 2013, 07:14 am Last Edit: Jun 04, 2013, 04:30 am by zawman Reason: 1
Grumpy_Mike, thank you so much for the teaching of EEPROM to me! Now that I have read all about EEPROM, I finally understand the operation of EEPROM. REALLY THANK YOU A LOT!

I had tested the WIEGANDtoARDUINO sketch and... I will show you the full sketch first.


And the serial monitor print out 4 times after scanning my fingerprint for 4 times.
Code: [Select]
Facility Code 0
User ID 0
Facility Code 0
User ID 0
Facility Code 0
User ID 0
Facility Code 0
User ID 0


Why are they zeroes?
I removed the masked bits and the shift register and the serial monitor still shows 0 for userid and facility codes.
I used the oscilloscope to test D1 and GND, D0 and GND.
They showed the correct electrical format similarly shown in the wiegand format.

4 different fingerprint scans and they all yield 0 in both facility and userid.


Updated:
Code: [Select]
/* Crazy People
* By Mike Cook April 2009
* One Fingerprint Reader outputing 26 bit Wiegand code to pins:-
* Reader A (Head) Pins 4 & 5
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
#include "pins_arduino.h"
/*
* an extension to the interrupt support for arduino.
* add pin change interrupts to the external interrupts, giving a way
* for users to have interrupts drive off of any pin.
*/

/*
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
* The PCINT corresponding to the pin must be enabled and masked, and
* an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
* must use some logic to actually implement a per-pin interrupt service.
*/

/* Pin to interrupt map:
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
*/

volatile uint8_t *port_to_pcmask[] = {
 &PCMSK0,
 &PCMSK1,
 &PCMSK2
};

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = {
 NULL };

volatile static uint8_t PCintLast[3];

/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 uint8_t slot;
 volatile uint8_t *pcmask;

 if (mode != CHANGE) {
   return;
 }
 // map pin to PCIR register
 if (port == NOT_A_PORT) {
   return;
 }
 else {
   port -= 2;
   pcmask = port_to_pcmask[port];
 }
 slot = port * 8 + (pin % 8);
 PCintFunc[slot] = userFunc;
 // set the mask
 *pcmask |= bit;
 // enable the interrupt
 PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 volatile uint8_t *pcmask;

 // map pin to PCIR register
 if (port == NOT_A_PORT) {
   return;
 }
 else {
   port -= 2;
   pcmask = port_to_pcmask[port];
 }

 // disable the mask.
 *pcmask &= ~bit;
 // if that's the last one, disable the interrupt.
 if (*pcmask == 0) {
   PCICR &= ~(0x01 << port);
 }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
 uint8_t bit;
 uint8_t curr;
 uint8_t mask;
 uint8_t pin;

 // get the pin states for the indicated port.
 curr = *portInputRegister(port+2);
 mask = curr ^ PCintLast[port];
 PCintLast[port] = curr;
 // mask is pins that have changed. screen out non pcint pins.
 if ((mask &= *port_to_pcmask[port]) == 0) {
   return;
 }
 // mask is pcint pins that have changed.
 for (uint8_t i=0; i < 8; i++) {
   bit = 0x01 << i;
   if (bit & mask) {
     pin = port * 8 + i;
     if (PCintFunc[pin] != NULL) {
       PCintFunc[pin]();
     }
   }
 }
}

SIGNAL(PCINT0_vect) {
 PCint(0);
}
SIGNAL(PCINT1_vect) {
 PCint(1);
}
SIGNAL(PCINT2_vect) {
 PCint(2);
}

// End of interrupts code and start of the reader code

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

void reader1One(void) {
 if(digitalRead(4) == LOW){
   reader1Count++;
   reader1 = reader1 << 1; // shift value right to remove odd parity in D1
   reader1 |= 1;

 }
}

void reader1Zero(void) {
 if(digitalRead(5) == LOW){
   reader1Count++;
   reader1 = reader1 << 1;  // shift value right to remove odd parity in D0
 }
}


void setup()
{
 Serial.begin(57000);
 // Attach pin change interrupt service routines from the Wiegand Fingerprint reader
 PCattachInterrupt(4, reader1One, CHANGE);
 PCattachInterrupt(5, reader1Zero, CHANGE);

 delay(10);
 // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
 // so this gives a pulse to each reader input line to get the interrupts working properly.
 // Then clear out the reader variables.
 // The readers are open collector sitting normally at a one so this is OK
 for(int i = 4; i<10; i++){
   pinMode(i, OUTPUT);
   digitalWrite(i, HIGH); // enable internal pull up causing a one
   digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
   pinMode(i, INPUT);
   digitalWrite(i, HIGH); // enable internal pull up
 }
 delay(10);
 // put the reader input variables to zero
 reader1 = 0;
 reader1Count = 0;
 digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
 if(reader1Count >= 26){
   long int rawToken = ((reader1 >> 1) & 0xffffff); // remove both parity bits
   int facilityCode = rawToken >> 16; // just get the top 8 bits
   int userID = rawToken & 0xffff; // bottom 16 bits are the user code
   Serial.print("Facility Code ");
   Serial.println(facilityCode); // use Serial.println(facilityCode, HEX); // to see the result in hex
   Serial.print("User ID ");
   Serial.println(userID);

   reader1 = 0;
   reader1Count = 0;
 }
}


The facility code and userid have been set correctly. The bits register at the reader1zero/one void setup is wrong so I change from >> 1 to << 1.

Everything from wiegand to arduino has been setup correctly, mostly thank to you! Thank you!
In my next post, I have a question about EEPROM.

zawman

#11
Jun 04, 2013, 05:21 am Last Edit: Jun 04, 2013, 08:10 am by zawman Reason: 1
According to;

Code: [Select]
/* Crazy People
* By Mike Cook April 2009
* One Fingerprint Reader outputing 26 bit Wiegand code to pins:-
* Reader A (Head) Pins 4 & 5 (pin 4 = data1, pin 5 = data0)
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
#include "pins_arduino.h"
/*
* an extension to the interrupt support for arduino.
* add pin change interrupts to the external interrupts, giving a way
* for users to have interrupts drive off of any pin.
*/

/*
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
* The PCINT corresponding to the pin must be enabled and masked, and
* an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
* must use some logic to actually implement a per-pin interrupt service.
*/

/* Pin to interrupt map:
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
*/

volatile uint8_t *port_to_pcmask[] = {
 &PCMSK0,
 &PCMSK1,
 &PCMSK2
};

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = {
 NULL };

volatile static uint8_t PCintLast[3];

/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 uint8_t slot;
 volatile uint8_t *pcmask;

 if (mode != CHANGE) {
   return;
 }
 // map pin to PCIR register
 if (port == NOT_A_PORT) {
   return;
 }
 else {
   port -= 2;
   pcmask = port_to_pcmask[port];
 }
 slot = port * 8 + (pin % 8);
 PCintFunc[slot] = userFunc;
 // set the mask
 *pcmask |= bit;
 // enable the interrupt
 PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
 uint8_t bit = digitalPinToBitMask(pin);
 uint8_t port = digitalPinToPort(pin);
 volatile uint8_t *pcmask;

 // map pin to PCIR register
 if (port == NOT_A_PORT) {
   return;
 }
 else {
   port -= 2;
   pcmask = port_to_pcmask[port];
 }

 // disable the mask.
 *pcmask &= ~bit;
 // if that's the last one, disable the interrupt.
 if (*pcmask == 0) {
   PCICR &= ~(0x01 << port);
 }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
 uint8_t bit;
 uint8_t curr;
 uint8_t mask;
 uint8_t pin;

 // get the pin states for the indicated port.
 curr = *portInputRegister(port+2);
 mask = curr ^ PCintLast[port];
 PCintLast[port] = curr;
 // mask is pins that have changed. screen out non pcint pins.
 if ((mask &= *port_to_pcmask[port]) == 0) {
   return;
 }
 // mask is pcint pins that have changed.
 for (uint8_t i=0; i < 8; i++) {
   bit = 0x01 << i;
   if (bit & mask) {
     pin = port * 8 + i;
     if (PCintFunc[pin] != NULL) {
       PCintFunc[pin]();
     }
   }
 }
}

SIGNAL(PCINT0_vect) {
 PCint(0);
}
SIGNAL(PCINT1_vect) {
 PCint(1);
}
SIGNAL(PCINT2_vect) {
 PCint(2);
}

// End of interrupts code and start of the reader code

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

void reader1One(void) {
 if(digitalRead(4) == LOW){
   reader1Count++;
   reader1 = reader1 << 1; // shift value right to remove odd parity in D1
   reader1 |= 1;

 }
}

void reader1Zero(void) {
 if(digitalRead(5) == LOW){
   reader1Count++;
   reader1 = reader1 << 1;  // shift value right to remove odd parity in D0
 }
}


void setup()
{
 Serial.begin(57000);
 // Attach pin change interrupt service routines from the Wiegand Fingerprint reader
 PCattachInterrupt(4, reader1One, CHANGE);
 PCattachInterrupt(5, reader1Zero, CHANGE);

 delay(10);
 // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
 // so this gives a pulse to each reader input line to get the interrupts working properly.
 // Then clear out the reader variables.
 // The readers are open collector sitting normally at a one so this is OK
 for(int i = 4; i<10; i++){
   pinMode(i, OUTPUT);
   digitalWrite(i, HIGH); // enable internal pull up causing a one
   digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
   pinMode(i, INPUT);
   digitalWrite(i, HIGH); // enable internal pull up
 }
 delay(10);
 // put the reader input variables to zero
 reader1 = 0;
 reader1Count = 0;
 digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
 if(reader1Count >= 26){
   long int rawToken = ((reader1 >> 1) & 0xffffff); // remove both parity bits
   int facilityCode = rawToken >> 16; // just get the top 8 bits
   int userID = rawToken & 0xffff; // bottom 16 bits are the user code
   Serial.print("Facility Code ");
   Serial.println(facilityCode); // use Serial.println(facilityCode, HEX); // to see the result in hex
   Serial.print("User ID ");
   Serial.println(userID);

   reader1 = 0;
   reader1Count = 0;
 }
}



Include EEPROM.H and the program will call the library, so..

Code: [Select]
void storeToken(int slot, long int token){
int byteAddress = slot * 3; // the start point of where you will store it in EEPROM
  EEPROM.write(byteAddress, token >> 16); // store facility code
  EEPROM.write(byteAddress + 1, (token >> 8) & 0xff); // store upper 8 bits of id
  EEPROM.write(byteAddress + 2,  token  & 0xff); // store lower 8 bits of id
}


storeToken is a void function, with slot as integer and token as long integer.
Under EEPROM.write,
byteAddress integer is referring to the name of the variable for the starting point where I will start to store my USERID and facility code in. (16bits / 2 and the facility code 8bits) ??? Am I right?

So in other words, byteAddress is actually the combined of 24bits without the even and odd parity?

or

Is the byteAddress referring to the 16bits USERID that print out in serial monitor?

byteAddress+1 and +2 is to move to the next point, this I understand.

Now, my project only wants up to 15 people to use 2 lockers.
So that means binary 1 1 1 1 = 15 in dec and F in hex.
So in userid I will only take last 4 bits value since 1111max is 15 people

So I write only 1 bytes for 1 address, needing only the last 4 bits of userID. facility code does not matter.
Hence,
Code: [Select]
//EEPROM
void storeToken(int slot, long int token){
int byteAddress = slot * 1; // the start point of where you will store it in EEPROM
  EEPROM.write(byteAddress, (token <<20) & 0xff); // store last 4 bits of userID


Is the code above correct? I suck at shifting registers since I am new to binary registers in C++
Now I am not sure where to call the storeToken(int,long int). Is it inside the loop and inside the if loop? It shows up argument errors if I put that.

zawman

Now this is my draft sketch of ALL in 1 sketch, WIEGAND to ARDUINO to EEPROM


Code: [Select]
#include <EEPROM.h>

/* Crazy People
* By Mike Cook April 2009
* One Fingerprint Reader outputing 26 bit Wiegand code to pins:-
* Reader A (Head) Pins 4 & 5
* Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
* Then a sting is sent to processing
*/
#include "pins_arduino.h"
/*
* an extension to the interrupt support for arduino.
* add pin change interrupts to the external interrupts, giving a way
* for users to have interrupts drive off of any pin.
*/

/*
* Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts.
* The PCINT corresponding to the pin must be enabled and masked, and
* an ISR routine provided.  Since PCINTs are per port, not per pin, the ISR
* must use some logic to actually implement a per-pin interrupt service.
*/

/* Pin to interrupt map:
* D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2
* D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0
* A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1
*/

volatile uint8_t *port_to_pcmask[] = {
  &PCMSK0,
  &PCMSK1,
  &PCMSK2
};

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = {
  NULL };

volatile static uint8_t PCintLast[3];

/*
* attach an interrupt to a specific pin using pin change interrupts.
* First version only supports CHANGE mode.
*/
void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  uint8_t slot;
  volatile uint8_t *pcmask;

  if (mode != CHANGE) {
    return;
  }
  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  }
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }
  slot = port * 8 + (pin % 8);
  PCintFunc[slot] = userFunc;
  // set the mask
  *pcmask |= bit;
  // enable the interrupt
  PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *pcmask;

  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  }
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }

  // disable the mask.
  *pcmask &= ~bit;
  // if that's the last one, disable the interrupt.
  if (*pcmask == 0) {
    PCICR &= ~(0x01 << port);
  }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
  uint8_t bit;
  uint8_t curr;
  uint8_t mask;
  uint8_t pin;

  // get the pin states for the indicated port.
  curr = *portInputRegister(port+2);
  mask = curr ^ PCintLast[port];
  PCintLast[port] = curr;
  // mask is pins that have changed. screen out non pcint pins.
  if ((mask &= *port_to_pcmask[port]) == 0) {
    return;
  }
  // mask is pcint pins that have changed.
  for (uint8_t i=0; i < 8; i++) {
    bit = 0x01 << i;
    if (bit & mask) {
      pin = port * 8 + i;
      if (PCintFunc[pin] != NULL) {
        PCintFunc[pin]();
      }
    }
  }
}

SIGNAL(PCINT0_vect) {
  PCint(0);
}
SIGNAL(PCINT1_vect) {
  PCint(1);
}
SIGNAL(PCINT2_vect) {
  PCint(2);
}

// End of interrupts code and start of the reader code

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

void reader1One(void) {
  if(digitalRead(4) == LOW){
    reader1Count++;
    reader1 = reader1 << 1; // shift value left to remove even parity in D1
    reader1 |= 1;

  }
}

void reader1Zero(void) {
  if(digitalRead(5) == LOW){
    reader1Count++;
    reader1 = reader1 << 1;  // shift value left to remove even parity in D0
  }
}
//EEPROM
void storeToken(int slot, long int token){
  int byteAddress = slot * 1; // the start point of where you will store it in EEPROM
  EEPROM.write(byteAddress, (token <<20) & 0xff); // store last 4 bits of userID
}

long int getToken(int slot){
  long int recoverdToken;
  int byteAddress = slot * 1; // the start point of where you will store it in EEPROM
  recoverdToken = EEPROM.read(byteAddress) >> 20; // call out userid of last 4 bits from EEPR
  return recoverdToken;
}


void setup()
{
  Serial.begin(57000);
  // Attach pin change interrupt service routines from the Wiegand Fingerprint reader
  PCattachInterrupt(4, reader1One, CHANGE);
  PCattachInterrupt(5, reader1Zero, CHANGE);

  delay(10);
  // the interrupt in the Atmel processor mises out the first negitave pulse as the inputs are already high,
  // so this gives a pulse to each reader input line to get the interrupts working properly.
  // Then clear out the reader variables.
  // The readers are open collector sitting normally at a one so this is OK
  for(int i = 4; i<10; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, HIGH); // enable internal pull up causing a one
    digitalWrite(i, LOW); // disable internal pull up causing zero and thus an interrupt
    pinMode(i, INPUT);
    digitalWrite(i, HIGH); // enable internal pull up
  }
  delay(10);
  // put the reader input variables to zero
  reader1 = 0;
  reader1Count = 0;
  digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
  if(reader1Count >= 26){
    long int rawToken = ((reader1 >> 1) & 0xffffff); // remove both parity bits
    int facilityCode = rawToken >> 16; // just get the top 8 bits
    int userID = rawToken & 0xffff; // bottom 16 bits are the user code
    Serial.print("Facility Code ");
    Serial.println(facilityCode); // use Serial.println(facilityCode, HEX); // to see the result in hex
    Serial.print("User ID ");
    Serial.println(userID);
    reader1 = 0;
    reader1Count = 0;
   
//calling out storeToken function... how??
   storeToken(userID,userID); // not sure what to call int and long int variables.
  Serial.print("16 bit is: ");
  Serial.println(userID,DEC); //not sure what int slot to call?
  Serial.print("userID is : ");
  Serial.println(userID,BIN); // not sure about this too
 
    if(rawToken == getToken(0) ) { // do this if the value in rawToken matches what is in the first slot
Serial.println(rawToken);
}
  }


}



I want serial monitor to tell me that I have successfully store my last(most right) 4bits of 16bits userID and call the bytes.

Please tell me what should I do next...

Grumpy_Mike

Do not put the store function inside the loop function. You only want to store stuff when you have new stuff to store, otherwise if you do it constantly you will damage the EEPROM it only has 10,000 write cycles and while that sounds a lot you can exceed it in a few minutes if you put it in the wrong place.

You basically have two modes of operation, new token enrolling and verifying tokens, make sure you have that distinction clear in your mind before writing code.

Quote
So in other words, byteAddress is actually the combined of 24bits without the even and odd parity?

No the variable called byteAddress points to the location where you will store your data,

Quote
Now, my project only wants up to 15 people to use 2 lockers.

So you need 15 slots, don't worry about the byteAddress that is low level stuff, as far as your code is concerned just use slots, one for each token you want to store. The fact that the function turns this into an address you can conveniently forget when writing the code.

Quote
So in userid I will only take last 4 bits value since 1111max is 15 people

No. I have no idea what you are thinking here.

Quote
Is the code above correct?

no
Code: [Select]
EEPROM.write(byteAddress, (token <<20) & 0x0f); // store last 4 bits of userID

Quote
It shows up argument errors if I put that.

No it only show up argument errors if you have an error in the arguments of the function, that is the numbers you are giving it when you call it.



zawman

#14
Jun 05, 2013, 03:49 am Last Edit: Jun 05, 2013, 04:41 am by zawman Reason: 1

Quote
You basically have two modes of operation, new token enrolling and verifying tokens, make sure you have that distinction clear in your mind before writing code.
yeah. enrolling tokens means all the 15 slots inside EEPROM has the values from 0000 to 1111 stored. verifying means 15 users' fingerprint ID of last 4 bits must match with the 15 slots respectively.

Code: [Select]
No. I have no idea what you are thinking here.
My project is to get 15 users to register their fingerprint into wiegand (wiegand device can store fingerprint id). So after 15 users registered in WIEGAND, I also want the 15 users to register to EEPROM as well. EEPROM is to represent which 2 lockers for which of the 15 users are in use. Meaning if EEPROM store 0011 and the user which is 0011 scan via WIEGAND and prompt success with EEPROM, locker 2 which has been registered before will open ONLY TO 0011. (it's similar to one fingerprint device = one locker concept, but my concept is one fingerprint device, 15 fingerprint ids and 2 lockers concept.)

Quote
Code: [Select]
EEPROM.write(byteAddress, (token <<20) & 0x0f); // store last 4 bits of userID
alright, 0x0f is to write only the last 4 bits, not 0xff. Thanks!

Quote
No it only show up argument errors if you have an error in the arguments of the function, that is the numbers you are giving it when you call it.

So I must not put storeToken function inside the loop function?




This is my EEPROM part inside my main sketch, before the void setup() and the void loop() like you said.
Code: [Select]
//EEPROM function begins
void storeToken(int slot, long int token){
int byteAddress = slot * 15; // the start point of where you will store it in EEPROM
EEPROM.write(byteAddress, (token <<20) & 0x0f); // store last 4 bits of userID. (is this for userID 0000 to store in his fingerprint id? dec = 0
EEPROM.write(byteAddress+1, (token <<20) & 0x0f); // userID 0001 to store in his fingerprint id. dec = 1
EEPROM.write(byteAddress+2, (token <<20) & 0x0f); // userID 0010 to store in his fingerprint id. dec = 2
EEPROM.write(byteAddress+3, (token <<20) & 0x0f); // userID 0011 to store in his fingerprint id. dec = 3
EEPROM.write(byteAddress+4, (token <<20) & 0x0f); // userID 0100 to store in his fingerprint id. dec = 4
EEPROM.write(byteAddress+5, (token <<20) & 0x0f); // userID 0101 to store in his fingerprint id. dec = 5
EEPROM.write(byteAddress+6, (token <<20) & 0x0f); // userID 0110 to store in his fingerprint id. dec = 6
EEPROM.write(byteAddress+7, (token <<20) & 0x0f); // userID 0111 to store in his fingerprint id. dec = 7
EEPROM.write(byteAddress+8, (token <<20) & 0x0f); // userID 1000 to store in his fingerprint id. dec = 8
EEPROM.write(byteAddress+9, (token <<20) & 0x0f); // userID 1001 to store in his fingerprint id. dec = 9
EEPROM.write(byteAddress+10, (token <<20) & 0x0f); // userID 1010 to store in his fingerprint id. dec = 10
EEPROM.write(byteAddress+11, (token <<20) & 0x0f); // userID 1011 to store in his fingerprint id. dec = 11
EEPROM.write(byteAddress+12, (token <<20) & 0x0f); // userID 1101 to store in his fingerprint id. dec = 12
EEPROM.write(byteAddress+13, (token <<20) & 0x0f); // userID 1110 to store in his fingerprint id. dec = 13
EEPROM.write(byteAddress+14, (token <<20) & 0x0f); // userID 1111 to store in his fingerprint id. dec = 14
} // end storing part of EEPROM

//begin calling EEPROM
long int getToken(int slot){
long int recoverdToken;
int byteAddress = slot * 15; // the start point of where you will store it in EEPROM
recoverdToken |= EEPROM.read(byteAddress) >> 20; // call out userid of last 4 bits from EEPROM. (This token from user 0000, dec = 0, will match with the EEPROM value of 0000 stored in, by calling)
recoverdToken |= EEPROM.read(byteAddress + 1) >> 20; // user 0001 dec=1
recoverdToken |= EEPROM.read(byteAddress + 2) >> 20; // user 0010 dec=2
recoverdToken |= EEPROM.read(byteAddress + 3) >> 20; // user 0011 dec=3
recoverdToken |= EEPROM.read(byteAddress + 4) >> 20; // user 0100 dec=4
recoverdToken |= EEPROM.read(byteAddress + 5) >> 20; // user 0101 dec=5
recoverdToken |= EEPROM.read(byteAddress + 6) >> 20; // user 0110 dec=6
recoverdToken |= EEPROM.read(byteAddress + 7) >> 20; // user 0111 dec=7
recoverdToken |= EEPROM.read(byteAddress + 8) >> 20; // user 1000 dec=8
recoverdToken |= EEPROM.read(byteAddress + 9) >> 20; // user 1001 dec=9
recoverdToken |= EEPROM.read(byteAddress + 10) >> 20; // user 1010 dec=10
recoverdToken |= EEPROM.read(byteAddress + 11) >> 20; // user 1011 dec=11
recoverdToken |= EEPROM.read(byteAddress + 12) >> 20; // user 1100 dec=12
recoverdToken |= EEPROM.read(byteAddress + 13) >> 20; // user 1101 dec=13
recoverdToken |= EEPROM.read(byteAddress + 14) >> 20; // user 1111 dec=14
return recoverdToken;
} // end of EEPROM function

So basically, I am to write 15 IDs into 15 slots for 15 users to scan and match. Is it correct?


and in the void loop()
Code: [Select]
void loop() {
  if(reader1Count >= 26){
    long int rawToken = ((reader1 >> 1) & 0xffffff); // remove both parity bits
    int facilityCode = rawToken >> 16; // just get the top 8 bits
    int userID = rawToken & 0xffff; // bottom 16 bits are the user code
    Serial.print("Facility Code ");
    Serial.println(facilityCode); // use Serial.println(facilityCode, HEX); // to see the result in hex
    Serial.print("User ID ");
    Serial.println(userID);
    reader1 = 0;
    reader1Count = 0;
  } //end if
// grumpy_mike's code starts here for eeprom operation?
if(rawToken == getToken(0) ) { // do this if the value in rawToken matches what is in the first slot
// do stuff
}
//getToken(0) or getToken(i) where i is the loop variable <--- this code is to stop operating the loop?
}

Go Up