I have two Raspberry Pis running python code to retrieve the serial number of an RFID tag. One has an RFID reader with a Wiegand interface hooked to GPIO pins and other has an RFID reader that behaves like a keyboard connected over USB. However, I get different numbers from the two reader when scanning the same RFID tag.
For example, for one tag, I get 57924897 from the Raspberry Pi with the Wiegand reader and 0004591983 from the Raspberry Pi with the USB keyboard reader.
Can sombody explain the difference? Are both readers reading the same? Or are they just reading some different parameter?
Looking at those two values, it seems that you do not properly read and convert the value from the Wiegand interface.
The USB keyboard reader reads the serial number in 10 digit decimal form. A Wiegand reader typically trunkaes the serial number into a 26 bit value (1 parity bit + 8 bit site code + 16 bit tag ID + 1 parity bit).
So let's look at the two values that you get:
+--------------+------------+-------------+-----------------------------------------+
| READER | DECIMAL | HEXADECIMAL | BINARY |
+--------------+------------+-------------+-----------------------------------------+
| USB keyboard | 0004591983 | 0046116F | 0000 0000 0100 0110 0001 0001 0110 1111 |
| Wiegand | 57924897 | 373DD21 | 1 1011 1001 1110 1110 1001 0000 1 |
+--------------+------------+-------------+-----------------------------------------+
When you take a close look at the binary representation of those two values, you will see that they correlate with each other:
USB keyboard: 0000 0000 0100 0110 0001 0001 0110 1111
Wiegand: 1 1011 1001 1110 1110 1001 0000 1
So it seems as if the Wiegand value matches the inverted value obtained from the USB keyboard reader:
USB keyboard: 0000 0000 0100 0110 0001 0001 0110 1111
NOT(Wiegand): 0 0100 0110 0001 0001 0110 1111 0
So the inverted value (logical NOT) from the Wiegand interface matches the value read by the USB reader.
Next, let's look at the two parity bits. The data over the Wiegand interface typically looks like:
b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16 b17 b18 b19 b20 b21 b22 b23 b24 b25
PE D23 D22 D21 D20 D19 D18 D17 D16 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 PO
The first line being the bits numbered as they arrive over the Wiegand wires. The second line being the same bits as they need to be interpreted by the receiver, where PE
(b0
) is an even parity bit over D23..D12
(b1..b12
), PO
(b25
) is an odd parity bit over D11..D0
(b13..b24
), and D23..D0
are the data bits representing an unsigned integer number.
So looking at your number, you would have received:
PE D23 D22 D21 D20 D19 D18 D17 D16 D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 PO
0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 1 1 0 1 1 1 1 0
If we check the parity bits PE
and PO
, we get:
PE D23........D12
0 0100 0110 0001
contains 4 ones (1
), hence even parity is met.
D21.........D0 PO
0001 0110 1111 0
contains 7 ones (1
), hence odd parity is met.
So, to summarize the above, your code reading from the Wiegand interface does not properly handle the Wiegand data format. First, it does not trim the parity bits and second, it reads the bits with wrong polarity (zeros are ones and ones are zeros).
In order to get the correct number from the Wiegand reader, you either have to fix you code for reading from the Wiegand interface (to fix polarity, to skip the first and the last bit from the data value, and to possibly check the parity bits). Or you can take the value that you currently get, invert that value, and strip the lower and upper bits. In C, that would look something like this:
int unsigned currentWiegandValue = ...;
int unsigned newWiegandValue = ((~currentWiegandValue) >> 1) & 0x0FFFFFF;