Wiegand sending - Finished/Resolved - Wiegand translator code posted

Hello All

just trying to send wiegand signals using an arduino 2009 - I will try to figure it out with testing but just wanting to confirm if i should be using Analog or Digital pins.

Oh and a noob question if i want to transmit from one arduino board to another. Will both of the boards grounds need to be connected?

Also just wanting to clarify if somethign similar to below algorithum will work.

// To transmit 0011
//this is more of an algorithum then code 
//Pin 2 will be D0
//Pin 3 will be D1

Set Pin 2 and 3 to output.

Set pin 2 and 3 to HIGH

Set pin 2 to Low

delayMicroseconds(50);

Set pin 2 to HIGH

delay(2)

Set pin 2 to Low

delayMicroseconds(50);

Set pin 2 to HIGH

delay(2)

Set pin 3 to Low

delayMicroseconds(50);

Set pin 3 to HIGH

delay(2)

Set pin 3 to Low

delayMicroseconds(50);

Set pin 3 to HIGH

Thanking you in advance for any replies.

Will both of the boards grounds need to be connected?

Absolutely.

Set pin 2 and 3 to HIGH
Set pin 2 to Low

Why bother setting pin 2 HIGH if you are going to immediately set it LOW?

Weigand defines a protocol more than a how to transmit the data. Perhaps if you defined what you were talking to, and what kind of data you are trying to send to it, we could offer real help.

just wanting to confirm if i should be using Analog or Digital pins.

Digital pins.

Wiegand outputs should be low for 50uS and there should be 2mS between pulses. When not sending anything both should be high.
It is best to use a variable to hold the data and go through looking at each byte in turn, then send the appropriate signal line low.

A simple way would to have your variable (0/1)and during the transmission only data high will == var and data low == !var,

Why bother setting pin 2 HIGH if you are going to immediately set it LOW?

Weigand defines a protocol more than a how to transmit the data. Perhaps if you defined what you were talking to, and what kind of data you are trying to send to it, we could offer real help.

I figured it was good practice to set both the pins to HIGH as Wiegand sits there with D0 and D1 sitting at a high state untill data transmission occurs.

Here is my project plan.

  1. Get Arduino accepting Wiegand / done
  2. Get Arduino transmitting Wiegand.
  3. I dont actually have a particular use for this yet. Maybe a biometric wiegand module. Users enrolled onto reader and finger prints are assigned a 26bit number which is transfered over Wiegand. This would allow it to interface with a wide range of products already on the market.

Below are the 2 peices of code i am using.

This is the one that accepts the Wiegand signal. I am aware an array may not be the best method of storage. But for now it is convienient.
When i connect a 26bit EM prox wiegand reader to this it works fine and spits out the binnary number.

/* Crazy People
 * By Mike Cook April 2009
 * Three RFID readers outputing 26 bit Wiegand code to pins:-
 * Reader A (Head) Pins 2 & 3
 * Interrupt service routine gathers Wiegand pulses (zero or one) until 26 have been recieved
 * Then a sting is sent to processing
 */
int i;
String reader1[30];
volatile int reader1Count = 0;

void reader1One(void) {
  reader1[reader1Count] = "1";
  reader1Count++;
}

void reader1Zero(void) {
reader1[reader1Count] = "0";
  reader1Count++;
}


void setup()
{
  Serial.begin(57600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, FALLING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, FALLING); //DATA1 to pin 3
  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 = 2; i<4; 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
  for (i = 0; i < 30; i = i + 1) {
  reader1[i] = 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");
  
 
for (i = 0; i < 26; i = i + 1) {
  Serial.print(reader1[i]);
  reader1[i] = 0;
}

Serial.println("");
  reader1Count = 0;
     }    
}

Here is the code that i am trying to get to send data. At the moment all i would like for it to do is keep sending 1’s (using D1). The other code should recognise that it has received 26x 1’s and display them.
Pin2 is connected to Pin2
Pin3 is connected to Pin3
Ground is connected to ground

void setup(){
 pinMode(2, OUTPUT);   
 pinMode(3, OUTPUT); 
 
 digitalWrite(2, HIGH);
 digitalWrite(3, HIGH);
 
 delay(5000);
 
}

void writeD0(){
digitalWrite(2, LOW);
delayMicroseconds(50);
digitalWrite(2, HIGH);

}
void writeD1(){
  digitalWrite(3, LOW);
  delayMicroseconds(50);
  digitalWrite(3, HIGH);
}

void loop(){
  writeD1; //1
  delay(2);
}

If somone could point me in the right direction it would be much aprpeaciated.

Not sure if it is relevant or not.

The receiving board is a Arduino 2009
The sending board is a Arduino UNO

Again to confirm Pin2 on sender is connected to Pin2 on receiver - this is D0
Again to confirm Pin3 on sender is connected to Pin3on receiver - this is D1
Ground is connected to ground.

I am starting to think that the issue may be with the way i have wired it. For the hell of doing it i am going to test it using differant pins for the output but i assume this will have no effect.

I would use this modification of your code to send the data:-

void setup(){
 pinMode(2, OUTPUT);   
 pinMode(3, OUTPUT); 
 
 digitalWrite(2, HIGH);
 digitalWrite(3, HIGH);
 
 delay(1000);
 
}

void writeD0(){
digitalWrite(2, LOW);
delayMicroseconds(50);
digitalWrite(2, HIGH);

}
void writeD1(){
  digitalWrite(3, LOW);
  delayMicroseconds(50);
  digitalWrite(3, HIGH);
}
long unsigned int number = 0x1765;  // the number you want to send
void loop(){
  int mask = 1;
  for(int i=0; i<26; i++){  // send the first 26 bits of it
  if((mask & number) == 0) writeD0; else writeD1;
  mask = mask << 1;
  delay(2);
  }
  delay(1000);
}

LOL i eventually had it working by taking the send D0/D1 out of the functions and handlign it within the loop statement. I finally got it working Friday last week saved my code came back in on Saturday and it has stoped working.

Anyway i have a use for this code and i will post it once the issue is resolved.

Basically there are differant card formats and some “jumble” the bits to be decoded/re organised once received. This is obviously for security(to make cards harder to read).

I am currently working on code that decodes a particular format. Unforunately i will not be able to share this particular information due to an NDA. But once finished i will remove the patented formatting code and post the code. (had it working fine before it died…)

Starting to drive me slightly crazy :smiley:

Having some issues that dont seem to make sense.

Firstly modified your code to work with my output pins…

void setup(){
 pinMode(10, OUTPUT);   
 pinMode(11, OUTPUT); 
 
 digitalWrite(10, HIGH);
 digitalWrite(11, HIGH);
 
 delay(1000);
 
}

void writeD0(){
digitalWrite(10, LOW);
delayMicroseconds(50);
digitalWrite(10, HIGH);

}
void writeD1(){
  digitalWrite(11, LOW);
  delayMicroseconds(50);
  digitalWrite(11, HIGH);
}
long unsigned int number = 0x1765;  // the number you want to send
void loop(){
  int mask = 1;
  for(int i=0; i<26; i++){  // send the first 26 bits of it
  if((mask & number) == 0) writeD0; else writeD1;
  mask = mask << 1;
  delay(2);
  }
  delay(1000);
}

The Wiegand reader does not seem to accept this at all it looks good to me and i do not understand why it is not working.

Below is my code. It accepts a 27 bit code and spits out a 26bit code. This works fine. (had to remove formatting due to NDA format simply reversed)

int i;
int reader1[30];
int readerTmp[30];
volatile int reader1Count = 0;

void reader1One(void) {
  reader1[reader1Count] = 1;
  reader1Count++;
}

void reader1Zero(void) {
reader1[reader1Count] = 0;
  reader1Count++;
}


void setup()
{
  Serial.begin(57600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, FALLING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, FALLING); //DATA1 to pin 3
  delay(10);
  
  //Set pins 10/D0 and 11/D1 to output for re transmission
   pinMode(10, OUTPUT);
   pinMode(11, OUTPUT);
   
   digitalWrite(10, HIGH);
   digitalWrite(11, HIGH);
  
  
  // 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 = 2; i<4; 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
  for (i = 0; i < 30; i = i + 1) {
  reader1[i] = 0;
}
  reader1Count = 0;
  digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
  if(reader1Count >= 27){
  Serial.println("A");
  

readerTmp[0] = reader1[25] ;
readerTmp[1] = reader1[24] ;
readerTmp[2] =  reader1[23] ;
readerTmp[3] =  reader1[22] ;
readerTmp[4] =  reader1[21] ;
readerTmp[5] =  reader1[20] ;
readerTmp[6] =  reader1[19] ;
readerTmp[7] =  reader1[18] ;
readerTmp[8] =  reader1[17] ;
readerTmp[9] =  reader1[16] ;
readerTmp[10] =  reader1[15] ;
readerTmp[11] =  reader1[14] ;
readerTmp[12] =  reader1[13] ;
readerTmp[13] =  reader1[12] ;
readerTmp[14] =  reader1[11] ;
readerTmp[15] =  reader1[10] ;
readerTmp[16] =  reader1[9] ;
readerTmp[17] =  reader1[8] ;
readerTmp[18] =  reader1[7] ;
readerTmp[19] =  reader1[6] ;
readerTmp[20] =  reader1[5] ;
readerTmp[21] =  reader1[4] ;
readerTmp[22] =  reader1[3] ;
readerTmp[23] =  reader1[2] ;
readerTmp[24] =  reader1[1] ;
readerTmp[25] =  reader1[0] ;

 
for (i = 0; i < 26; i = i + 1) {

  if(readerTmp[i] == 0){
    delay(2);
  digitalWrite(10, LOW);
  delayMicroseconds(50);
  digitalWrite(10, HIGH); 
  }else{
   delay(2);
  digitalWrite(11, LOW);
  delayMicroseconds(50);
  digitalWrite(11, HIGH); 
  }
  
  Serial.print(reader1[i]);
  reader1[i] = 0;
}

Serial.println("");
  reader1Count = 0;
     }    
}

Now as far as i can tell your code and my code are doing the exact same thing as far as the output therefore i do not understand why one works and not hte other. I am having simular issues with my code.

As advised the above code works. But if i modify it to add the parity bits it stops working. It also seems to stop working when i put certain vales in certain places. When i say its not working it accepts the signal - shows the conversion in the serial monitor but the clock is not receiving hte transmission. I know its not a cabling issue as it works on one sketch and not the other. I have reviewed my code numerious times but am getting no where.

IF somone could point me in the right direction it would be much appreaciated.

int i;
int reader1[30];
int readerTmp[30];
volatile int reader1Count = 0;

void reader1One(void) {
  reader1[reader1Count] = 1;
  reader1Count++;
}

void reader1Zero(void) {
reader1[reader1Count] = 0;
  reader1Count++;
}


void setup()
{
  Serial.begin(57600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, FALLING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, FALLING); //DATA1 to pin 3
  delay(10);
  
  //Set pins 10/D0 and 11/D1 to output for re transmission
   pinMode(10, OUTPUT);
   pinMode(11, OUTPUT);
   
   digitalWrite(10, HIGH);
   digitalWrite(11, HIGH);
  
  
  // 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 = 2; i<4; 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
  for (i = 0; i < 30; i = i + 1) {
  reader1[i] = 0;
}
  reader1Count = 0;
  digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
  if(reader1Count >= 27){
  Serial.println("A");
  

readerTmp[0] = reader1[25] ;
readerTmp[1] = reader1[24] ;
readerTmp[2] =  reader1[23] ;
readerTmp[3] =  reader1[22] ;
readerTmp[4] =  reader1[21] ;
readerTmp[5] =  reader1[20] ;
readerTmp[6] =  reader1[19] ;
readerTmp[7] =  reader1[18] ;
readerTmp[8] =  reader1[17] ;
readerTmp[9] =  reader1[16] ;
readerTmp[10] =  reader1[15] ;
readerTmp[11] =  reader1[14] ;
readerTmp[12] =  reader1[13] ;
readerTmp[13] =  reader1[12] ;
readerTmp[14] =  reader1[11] ;
readerTmp[15] =  reader1[10] ;
readerTmp[16] =  reader1[9] ;
readerTmp[17] =  reader1[8] ;
readerTmp[18] =  reader1[7] ;
readerTmp[19] =  reader1[6] ;
readerTmp[20] =  reader1[5] ;
readerTmp[21] =  reader1[4] ;
readerTmp[22] =  reader1[3] ;
readerTmp[23] =  reader1[2] ;
readerTmp[24] =  reader1[1] ;
readerTmp[25] =  reader1[0] ;

//If sum of segments 2 to 13 even then First parity 1
if ((readerTmp[1] + readerTmp[2] + readerTmp[3] + readerTmp[4] + readerTmp[5] + readerTmp[6] + readerTmp[7] + readerTmp[8] + readerTmp[9] + readerTmp[10] + readerTmp[11] + readerTmp[12]) % 2){
 readerTmp[0] = 0;
  Serial.println("even = odd");
}else{
 readerTmp[0] = 1;
  Serial.println("even = even");
}


//If sum of segments 14 to 25 even then last parity 1
if ((readerTmp[13] + readerTmp[14] + readerTmp[15] + readerTmp[16] + readerTmp[17] + readerTmp[18] + readerTmp[19] + readerTmp[20] + readerTmp[21] + readerTmp[22] + readerTmp[23] + readerTmp[24]) % 2){
 readerTmp[25] = 0;
 Serial.println("odd = odd");
}else{
 readerTmp[25] = 1;
 Serial.println("odd = even");
}

 
for (i = 0; i < 26; i = i + 1) {

  if(readerTmp[i] == 0){
    delay(2);
  digitalWrite(10, LOW);
  delayMicroseconds(50);
  digitalWrite(10, HIGH); 
  }else{
   delay(2);
  digitalWrite(11, LOW);
  delayMicroseconds(50);
  digitalWrite(11, HIGH); 
  }
  
  Serial.print(reader1[i]);
  reader1[i] = 0;
}

Serial.println("");
  reader1Count = 0;
     }    
}

It is all working i have no idea why tho started from scratch.

I have removed the stuff covered under NDA.

If you want to adjust this for your own formats…
increase both array size’s if bit range is larger then 31

Within the loop() function change the initial if statement to the range of the ID cards you are reading…This is set to 27 as its reading 27bit
Change your bits etc around using the arrays. You will see in teh example it sets all of the bits to 0.
If no parity bits are used remove parity if statements. If they are in differant locations or there are more move/change them as required.
Within the loop() function change the the for statement to the bit range you are outputting +1. As i am trying to output 26bit it is 27.

You now have a wiegand convertor/translator.

I am worried that if half a card is read it may get stuck in a loop of reading the incorrect card number. But i beleive the resetting of this should avoid this in that it may get one incorrect read but the next should be fine as the interupts happen that fast. Not sure if this has been explained correctly.

If anyone has any suggestions it would be much aprpeaciated.

int i;
int reader1[30];
int readerTmp[30];
volatile int reader1Count = 0;

void reader1One(void) {
  reader1[reader1Count] = 1;
  reader1Count++;
}

void reader1Zero(void) {
reader1[reader1Count] = 0;
  reader1Count++;
}


void setup()
{
  Serial.begin(57600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, FALLING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, FALLING); //DATA1 to pin 3
  delay(10);
  
  //Set pins 10/D0 and 11/D1 to output for re transmission
   pinMode(10, OUTPUT);
   pinMode(11, OUTPUT);
   
   digitalWrite(10, HIGH);
   digitalWrite(11, HIGH);
  
  
  // 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 = 2; i<4; 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
  for (i = 0; i < 30; i = i + 1) {
  reader1[i] = 0;
}
  reader1Count = 0;
  digitalWrite(13, HIGH);  // show Arduino has finished initilisation
}

void loop() {
  if(reader1Count >= 27){
  Serial.println("A");
  

readerTmp[0] = reader1[25] ;

readerTmp[1] = 0 ;
readerTmp[2] = 0 ;
readerTmp[3] = 0 ;
readerTmp[4] = 0 ;
readerTmp[5] = 0 ;
readerTmp[6] = 0 ;
readerTmp[7] = 0 ;
readerTmp[8] = 0 ;

readerTmp[9] = 0 ;
readerTmp[10] = 0 ;
readerTmp[11] = 0 ;
readerTmp[12] = 0 ;
readerTmp[13] = 0 ;
readerTmp[14] = 0 ;
readerTmp[15] = 0 ;
readerTmp[16] = 0 ;
readerTmp[17]= 0 ;
readerTmp[18] = 0 ;
readerTmp[19] = 0 ;
readerTmp[20] = 0 ;
readerTmp[21] = 0 ;
readerTmp[22] = 0 ;
readerTmp[23] = 0 ;
readerTmp[24] = 0 ;

readerTmp[25] =  reader1[0] ;

//If sum of segments 2 to 13 even then First parity 1
if ((readerTmp[1] + readerTmp[2] + readerTmp[3] + readerTmp[4] + readerTmp[5] + readerTmp[6] + readerTmp[7] + readerTmp[8] + readerTmp[9] + readerTmp[10] + readerTmp[11] + readerTmp[12]) % 2){
 readerTmp[0] = 1;
  Serial.println("even = odd");
}else{
 readerTmp[0] = 0;
  Serial.println("even = even");
}


//If sum of segments 14 to 25 even then last parity 1
if ((readerTmp[13] + readerTmp[14] + readerTmp[15] + readerTmp[16] + readerTmp[17] + readerTmp[18] + readerTmp[19] + readerTmp[20] + readerTmp[21] + readerTmp[22] + readerTmp[23] + readerTmp[24]) % 2){
 readerTmp[25] = 0;
 Serial.println("odd = odd");
}else{
 readerTmp[25] = 1;
 Serial.println("odd = even");
}

 
for (i = 0; i < 26; i = i + 1) {

  if(readerTmp[i] == 0){
    delay(2);
  digitalWrite(10, LOW);
  delayMicroseconds(50);
  digitalWrite(10, HIGH); 
  }else{
   delay(2);
  digitalWrite(11, LOW);
  delayMicroseconds(50);
  digitalWrite(11, HIGH); 
  }
  
  Serial.print(readerTmp[i]);
  readerTmp[i] = 0;
}

Serial.println("");
  reader1Count = 0;
     }    
}
if((mask & number) == 0) writeD0; else writeD1;

Should be

if((mask & number) == 0) writeD0(); else writeD1();

If you want the function to be called.

Will take note. When it was previously working i accidentially was powering it via the VIN pin. Then during later testing the VIN pin had been disconnected.

I am starting to suspect my issues where due to the board being supplied with power via USB then trying to have 2 pins set to HIGH prob drained the supply a bit. Does this sound like a likely cause?.

Just happy its working but i feel its always good to understand what you are doing :smiley:

then trying to have 2 pins set to HIGH prob drained the supply a bit. Does this sound like a likely cause?.

No setting two pins high is a perfectly acceptable thing to do.

I am worried that if half a card is read it may get stuck in a loop of reading the incorrect card number.

Not sure where this could happen. In the reader there will be parity bit checking to ensure that only completely read codes are passed on. In your code that could only happen if you use a while loop not a for loop.

I am starting to suspect my issues

Can you reiterate what your current issues are please.