El protocolo WiegandUna visión general de qué es, para qué sirve y cómo se utiliza. Práctica descripción del protocolo que implementaron los lectores de tarjetas de Efecto Wiegand.
Primero y antes de empezar, es importante no confundir el
Protocolo Wiegand con el
Efecto Wiegand. El efecto Wiegand es un concepto físico en el que intervienen las distintas formas de reaccionar magnéticamente distintas áreas de un hilo conductor ante la influencia de un campo magnético. (Para mas detalles consultar
Wikipedia : Wiegand effect)
El caso es que en base a este Efecto Wiegand se construyeron cierto tipos de Tarjetas de Identificación y sus correspondientes Lectores de Tarjetas de Proximidad para usarlos en Control de Accesos y/o Presencia. Dichos Lectores de Tarjetas debían conectarse a los dispositivos de Control de Acceso de algún modo (véase en este mismo foro
Fundamentos de la Transmisión Síncrona) y en lugar de usar algún protocolo ya preestablecido se inventaron uno propio: El protocolo Wiegand, que es al que se refiere este artículo.
Como todo protocolo de comunicaciones el Wiegand consta de dos partes fundamentales: Aquella que describe el modo en que físicamente se transmite la información digital y la forma de interpretar numéricamente dicha información.
Probablemente debido a mis propias limitaciones y/o desconocimiento no sería capaz de deciros si el protocolo Wiegand es un protocolo serie Síncrono o Asíncrono ya que es fundamentalmente distinto a los que conozco de estos dos tipos anteriores: El
ABA Track 2 como ejemplo de Síncrono o el RS-232 del Asíncrono. En cualquier caso os describo como funciona y ustedes mismos decidís.
Sistema de transmisión: La transmisión de datos Wiegand usa
tres hilos. La línea para enviar los unos lógicos o
DATA1, la línea para hacer lo propio con los ceros lógicos o
DATA0 y la línea de masa de referencia de ambos o
GND. Los niveles que se usan son ó Bajo, a nivel de GND, o Alto a +5V o VCC.
En estado de
reposo, o sea: sin transmitir, la línea de GND es exactamente lo que es GND y siempre está en bajo y ya no nos referiremos más a ella, y las líneas
DATA1 y DATA0 están en
alto, a nivel de +5V ó VCC.
Para transmitir un
Bit 1 lo que se hace es mandar un
pulso a Bajo, normalmente de
50 uS (microsegundos) de duración, por la línea
DATA1, mientras DATA0 permanece en Alto.
Para transmitir un
Bit 0 lo que se hace por el contrario es mandar un
pulso a Bajo, también de la misma duración
50 uS (microsegundos), por la línea
DATA0, mientras ahora es DATA1 la que permanece en Alto.
Normalmente la
separación entre cada pulso y el siguiente es de unos
2 mS (milisegundos).
Como podéis ver, y a diferencia de los protocolos mencionados anteriormente, los dos tipos de Bits, ceros y unos, son transmitidos de forma idéntica aunque por líneas distintas. En el
cronograma siguiente vemos una representación gráfica de este sistema de transmisión:
En este ejemplo vemos cómo se transmitiría la secuencia de bits
1010.
Y hasta aquí todo lo referente a la primera parte a la que nos referimos mas arriba como el modo en que físicamente se transmite la información digital.
Interpretación de los Datos:
Mediante el sistema descrito anteriormente se puede transmitir cualquier número de bits que queramos, sin embargo hay un cierto consenso en ciertos números de bits:
26, el más utilizado,
32,
44 ó
128. Y la interpretación de los mismos, salvo el de 26 bits, es tan diversa como fabricantes lo utilizan.
Como hemos dicho el
Wiegand 26 es el formato de trama mas utilizado con diferencia y su interpretación es como sigue:
- El primer Bit,
B0, es la
Paridad Par de los
primeros 12 bits transmitidos (
B1:12).
- Los 8 siguientes,
B1:B8 son un Byte, un
Entero de 8 bits, al que llaman
Facility Code.
- Los 16 siguientes:
B9:B24 son dos Bytes, un
Entero de 16 Bits, al que llaman
User Code - El último bit,
B25, es la
Paridad Impar de los
últimos 12 bits transmitidos (
B13:24).
Curioso ¿verdad? Aquí podéis ver una típica interpretación de un código
Wiegand 26:
Este ejemplo constituye el Facility Code + User Code
4-24610, la paridad E es 1 para hacer Par la secuencia de
00000100011 que tiene tres unos y la paridad O es también 1 para hacer impar la secuencia
0000000100010 que sólo tiene dos unos.
Los demás tipos de Wiegand's tienen interpretaciones distintas, así el Wiegand 32 no lleva paridad y tanto el Facility Code como el User Code son dos números enteros de 16 bits. El Wiegand 44 es mas simpático aún si cabe, los 8 primeros bits son el Facility Code, los 32 siguientes son el User Code y los 4 últimos son el OR EXCLUSIVO de los 40 bits anteriores tomados de 4 en 4. Sorprendente pero cierto.
Programa que recoge e interpreta un Wiegand 26 y lo vuelca sobre el canal serie:
// reader_wiegand26
//
// hardware MAHSA GP-20 Proximity cards
//
// red -> vcc -> +12V
// green -> data0 -> rb0 -> con-ml-10 -> 6
// white -> data1 -> rb1 -> con-ml-10 -> 4
// black -> gnd -> gnd -> con-ml-10 -> 2
#include <18f4550.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include <string.h>
#bit PIN_DATA0 = 0xF81.0
#bit PIN_DATA1 = 0xF81.1
const int CodeBits = 26;
int1 first_exp=0;
int1 read_complete=0;
int nextbit=0;
char Code[CodeBits+1];
int FacilityCode;
long IdCardCode;
char bits[5]={0x01,0x02,0x04,0x08,0x10};
int i;
// INTERRUPCION por EXT0 Data0 ------------------------------------------------
#int_ext
ext_handler() {
if(first_exp==1){
Code[nextbit]='0';
if(++nextbit==CodeBits){
read_complete=1;
}
}
first_exp=1;
}
// INTERRUPCION por EXT1 Data1 ------------------------------------------------
#int_ext1
ext1_handler() {
if(first_exp==1){
Code[nextbit]='1';
if(++nextbit==CodeBits){
read_complete=1;
}
}
first_exp=1;
}
void limpia_data(void){
for(i=0;i<CodeBits+1;i++) Code[i]=0x00;
nextbit=0;
}
void ajusta_code(void){
// Finaliza Code
Code[CodeBits]=0x00;
// Facility Code
FacilityCode=0x00;
for(i=1;i<9;i++){
if(Code[i]=='1'){
FacilityCode=FacilityCode+bits[i-1];
}
}
// Id Card Code
IdCardCode=0x00;
for(i=9;i<CodeBits;i++){
if(Code[i]=='1'){
IdCardCode=IdCardCode+bits[i-9];
}
}
}
void main() {
disable_interrupts(global);
set_tris_b(0b00000111);
printf("Wiegand26 Reader listen\r\n\n");
limpia_data();
ext_int_edge(0,L_TO_H);
ext_int_edge(1,L_TO_H);
first_exp=0;
enable_interrupts(int_ext);
enable_interrupts(int_ext1);
enable_interrupts(global);
do{
if(read_complete==1){
read_complete=0;
disable_interrupts(global);
ajusta_code();
printf("Facility Code = %u IdCardCode = %lu\r\n\n",FacilityCode,IdCardCode);
limpia_data();
enable_interrupts(global);
}
} while (TRUE);
}
Ea, y eso es todo por hoy. Mañana más.