Trouble Converting Wiegand W26 Output to DEC

Hi Everyone and thanks for stopping by!

I´ve bought an Arduino UNO Rev3 and a Seeed Studio Grove 125KHz RFID Reader (uem4100 Card).

I figured out how to set up the Card Reader and I´ve got a Program Reading RFID Dongles in Mode UART und another Programm for Reading the same dongles in WIEGAND Mode. - When changing the Programm you also need to set a Jumper on the Board, which I also Did.

On my RFID Dongles I have there is a 10 Digit Number writen. If I User the Reader which came with the dongles under windows in Texteditor, it writes the 10 Digit Number (including Trailing Zeros and LineFeed/CR)

The Dongles I have are 125 kHz EM4100 ISO14443A Dongles.

When Reading UART I found out that the Transfered String is HEX and I need to Calculate 5th to 10th Digit to get the exact 10 Digit Number writen on the Dongle.

However when reading the WIEGAND String, I can´t figure out how to Translate/ Convert it.

This is my Result for 5 Dongles:

Dongle 1
Aufschrift 0001217496
Scan with UART 01001293D858
Convert Hex to DEC Hex: 1293D8 --> DEC: 1217496
Scan W26 01101111101101011011000010

Dongle 2
Aufschrift 0001217485
Scan with UART 01001293CD4D
Convert Hex to DEC Hex:1293CD --> DEC: 1217485
Scan W26 01110111101101011011000011

Dongle 3
Aufschrift 0013477100
Scan with UART 0100CDA4EC84
Convert Hex to DEC Hex:CDA4EC --> DEC: 13477100
Scan W26 00101000110010010110110001

Dongle 4
Aufschrift 0013477183
Scan with UART 0100CDA53F56
Convert Hex to DEC Hex:CDA53F --> DEC: 13477183
Scan W26 00110000110010010110101100

Dongle 5
Aufschrift 0014594826
Scan with UART 2900DEB30A4E
Convert Hex to DEC Hex:DEB30A --> DEC: 14594826
Scan W26 00000000100001010011001111

The RFID-Reader gives this hints, but still I can´t figure out how it Works.

Starting with ParityBits Even and Odd.

Counting the 1 in First and Second PArt including the PB:
1111011010110 1100001001110 = 9 & 6
1111011010110 1100001100101 = 9 & 6
0001100100101 1010110000000 = 5 & 4

Without PB:
1 111011010110 8 110000100111 0 5
1 111011010110 8 110000110010 1 5
0 001100100101 4 101011000000 0 3

as you can see, this isn´t consistent or I´m do something wrong.

I´m actually Fine with Using UART, but for interest and because I know for Entry-Control-Systems Wiegand is the Standard, i would love to know the solution to this Riddle. Thinking about it for 2 days now I hope to get some help her.

Here is the ProgrammCode for UART:

/*
  link between the computer and the SoftSerial Shield
  at 9600 bps 8-N-1
  Computer is connected to Hardware UART
  SoftSerial Shield is connected to the Software UART:D2&D3
*/

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(2, 3);
unsigned char buffer[64];       // buffer array for data receive over serial port - No Difference if Length is 1 or 64 or 256? (Changed here and in Line 28
int count = 0;                    // counter for buffer array

void setup()
{
    SoftSerial.begin(9600);     // the SoftSerial baud rate
    Serial.begin(9600);         // the Serial port of Arduino baud rate.
}

void loop()
{
    // if date is coming from software serial port ==> data is coming from SoftSerial shield
    if (SoftSerial.available())              
    {
        while(SoftSerial.available())               // reading data into char array
        {
            buffer[count++] = SoftSerial.read();      // writing data into array
            if(count == 64)break;
        }
        Serial.write(buffer, count);     // if no data transmission ends, write buffer to hardware serial port
        clearBufferArray();             // call clearBufferArray function to clear the stored data from the array
        count = 0;                      // set counter of while loop to zero
    }
    if (Serial.available())             // if data is available on hardware serial port ==> data is coming from PC or notebook
    SoftSerial.write(Serial.read());    // write it to the SoftSerial shield
}
void clearBufferArray()                 // function to clear buffer array
{
    // clear all index of array with command NULL
    for (int i=0; i<count; i++)
    {
        buffer[i]=NULL;
    }                  
}

Even that it´s working you see in my Comment that i can give buffer almost every size and it´s still working. This is something i don´t get, but as seen above, i´m able to translate to the given 10 digit number which is written on the dongle.

And here´s the Wiegand Code:

//  RFID_Wiegand_INT.pde  to read card ID number from the RFID with
//  wiegand interface.
//  see http://www.seeedstudio.com/depot/ for details on 125K RFID module
//  ... [Copyright and license information]
// Global variables
byte RFIDcardNum[4]; // Not used in this version
unsigned long cardValue = 0; // Variable to store the card value
int bitCount = 0; // Counter for the number of received bits

void setup() {
  Serial.begin(9600);
  // Set up the interrupt pins, attach the interrupt routines
  pinMode(2, INPUT_PULLUP); // Set up pin 2 as input with internal pull-up
  pinMode(3, INPUT_PULLUP); // Set up pin 3 as input with internal pull-up
  attachInterrupt(digitalPinToInterrupt(2), ISRreceiveData0, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), ISRreceiveData1, FALLING);
}

void loop() {
  // If all bits have been received, process the data
  if (bitCount == 26) {
    // The card data is ready to be processed
    // You may implement parity check here

    // Print the card value in binary format
    Serial.print("Card Value (Binary): ");
    for (int i = 25; i >= 0; i--) {
      Serial.print((cardValue >> i) & 1);
    }
    Serial.println();

    // Reset for next read
    bitCount = 0;
    cardValue = 0;
  }
}

// ISR for Data0 (representing bit '0')
void ISRreceiveData0() {
  if (bitCount < 26) {
    cardValue <<= 1; // Shift the earlier bits
    bitCount++;
  }
}

// ISR for Data1 (representing bit '1')
void ISRreceiveData1() {
  if (bitCount < 26) {
    cardValue <<= 1; // Shift the earlier bits
    cardValue |= 1; // Add '1' to the LSB of cardValue
    bitCount++;
  }
}


thanks and best regards
Richard

just a note as I was reading the the Wiegand Code, you are using interrupts so cardValue and bitCount should be declared volatile and accessed in the loop within a critical section

1 Like

Thanks Mate, this is a very good Comment. I´m new to arduino, so i´m happy to learn.

This is the changed Code:

// Globale Variablen als volatile deklarieren
volatile unsigned long cardValue = 0; // Variable, um den Kartenwert zu speichern
volatile int bitCount = 0; // Zähler für die Anzahl der empfangenen Bits

// RFID-Reader Set-Up
void setup() {
  Serial.begin(9600);
  // Set up the interrupt pins, attach the interrupt routines
  pinMode(2, INPUT_PULLUP); // Set up pin 2 as input with internal pull-up
  pinMode(3, INPUT_PULLUP); // Set up pin 3 as input with internal pull-up
  attachInterrupt(digitalPinToInterrupt(2), ISRreceiveData0, FALLING);
  attachInterrupt(digitalPinToInterrupt(3), ISRreceiveData1, FALLING);
}

void loop() {
  // Kritischer Abschnitt: Speichern des aktuellen Zustands der Interrupts und Deaktivieren der Interrupts
  noInterrupts();
  unsigned long value = cardValue;
  int count = bitCount;
  // Interrupts wieder aktivieren
  interrupts();

  // Wenn alle Bits empfangen wurden, die Daten verarbeiten
  if (count == 26) {
    // Kartenwert im Binärformat ausgeben
    Serial.print("Card Value (Binary): ");
    for (int i = 25; i >= 0; i--) {
      Serial.print((value >> i) & 1);
    }
    Serial.println();

    // Kritischer Abschnitt: Zum Zurücksetzen der Variablen Interrupts deaktivieren
    noInterrupts();
    bitCount = 0;
    cardValue = 0;
    // Interrupts wieder aktivieren
    interrupts();
  }
}

// ISR for Data0 (representing bit '0')
void ISRreceiveData0() {
  if (bitCount < 26) {
    cardValue <<= 1; // Shift the earlier bits
    bitCount++;
  }
}

// ISR for Data1 (representing bit '1')
void ISRreceiveData1() {
  if (bitCount < 26) {
    cardValue <<= 1; // Shift the earlier bits
    cardValue |= 1; // Add '1' to the LSB of cardValue
    bitCount++;
  }
}

does it work any better?

let´s say: Different :smiley:

I can´t figure out how to get the dec number when using wiegand mode. Now with the new Code I get new results:

Dongle 1
Aufschrift 0001217496
Scan with UART 01001293D858
Convert Hex to DEC Hex: 1293D8 --> DEC: 1217496
Scan W26 01101111101101011011000010
Scan W26 new 11110110101101100001001110

Dongle 2
Aufschrift 0001217485
Scan with UART 01001293CD4D
Convert Hex to DEC Hex:1293CD --> DEC: 1217485
Scan W26 01110111101101011011000011
Scan W26 new 11110110101101100001100101

Dongle 3
Aufschrift 0013477100
Scan with UART 0100CDA4EC84
Convert Hex to DEC Hex:CDA4EC --> DEC: 13477100
Scan W26 00101000110010010110110001
Scan W26 new 00011001001011011000100110

Dongle 4
Aufschrift 0013477183
Scan with UART 0100CDA53F56
Convert Hex to DEC Hex:CDA53F --> DEC: 13477183
Scan W26 00110000110010010110101100
Scan W26 new 00011001001011010110000000

Dongle 5
Aufschrift 0014594826
Scan with UART 2900DEB30A4E
Convert Hex to DEC Hex:DEB30A --> DEC: 14594826
Scan W26 00000000100001010011001111
Scan W26 new 00010000101001100111101010

But still have no idea how to convert to the Dec number printed on the dongles.

Also i don´t know if the wiegand string is correct, as i think with the parity bits it´s the other way arround as shown in the manual.

1111011010110 1100001001110 9 6
1111011010110 1100001100101 9 6
0001100100101 1011000100110 5 6
0001100100101 1010110000000 5 4
0001000010100 1100111101010 3 8

If i understand that correctly, then my parity bits are the opposite and that would mean corrupt data.

I´ve found the solution in the seeedgroove Forum

The Pins in WIEGAND Mode are the other way arround.

Now I get:
15:21:54.789 -> Card Value (Binary): 00001001010010011110110001

15:23:40.341 -> Card Value (Binary): 00001001010010011110011010

15:23:47.541 -> Card Value (Binary): 11100110110100100111011001

15:23:51.117 -> Card Value (Binary): 11100110110100101001111111

15:23:54.922 -> Card Value (Binary): 11101111010110011000010101

which also makes sense in parity bits:
0000100101001 0011110110001 4 7
0000100101001 0011110011010 4 7
1110011011010 0100111011001 8 7
1110011011010 0101001111111 8 9
1110111101011 0011000010101 10 5

and perfectly converts to the writen on dec numbers.
Thanks for your help.

good catch

have fun

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.