RFID с протоколом Wiegand. Что такое DATA0?

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Никак не могу найти, в описании написано подключить PIN1 к DATA0. Это RX на ардуино?

step962
Offline
Зарегистрирован: 23.05.2011

JollyBiber пишет:

Никак не могу найти, в описании написано подключить PIN1 к DATA0. Это RX на ардуино?

Дарю. На долгую память (328-я ничем особенным в плане ного не отличается):

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Спасибо за подарок. Может я неточно выразился... У меня 125Khz RFID module RDM630- Wiegand, существует такая же, но "TTL interface RS232 data format". В описании Wiegand: PIN1 to DATA0, PIN2 to DATA1, в подключении TTL: PIN1 to TX, PIN2 to RX. Отсюда вопрос если DATA0 != digital PIN 0 и  DATA1 != digital PIN1, то где они (DATA0 и DATA1)? Если это одно и то же то почему так пишут? Пруфлинк

maksim
Offline
Зарегистрирован: 12.02.2012

DATA0 это не  RX, а  DATA1 это не TX.

Это интерфейс Wiegand, в вашем случае Wiegand 26.

Подключают через прерывания на 2 и 3 выводы вот пример кода

/* 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
 */

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

void reader1One(void) {
  reader1Count++;
  reader1 = reader1 << 1;
  reader1 |= 1;
}

void reader1Zero(void) {
  reader1Count++;
  reader1 = reader1 << 1;
}

void setup()
{
  Serial.begin(9600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, RISING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, RISING); //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
  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);
 int serialNumber=(reader1 >> 1) & 0x3fff;
 int siteCode= (reader1 >> 17) & 0x3ff;

 Serial.print(siteCode);
 Serial.print("  ");
 Serial.println(serialNumber);
  reader1 = 0;
  reader1Count = 0;
  digitalWrite(13,HIGH);
  delay(2000);
  digitalWrite(13,LOW);
     }
}

Вот источник.

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Спасибо! Вечером буду пробовать!

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Все шикарно работает!! Спасибо!

vlkam
Offline
Зарегистрирован: 17.02.2013

Наверное имеет смысл разместить исходник

 

/*
 * By Mike Cook April 2009
 * Three RFID readers outputing 26 bit Wiegand code to pins:-
 * Reader A  Pins 4 & 5
 * Reader B  Pins 6 & 7
 * Reader C  Pins 8 & 9
 * 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.
 * Refer to avr-gcc header files, arduino source and atmega datasheet.
 */

/*
 * 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,reader2 = 0, reader3 = 0;
volatile int reader1Count = 0, reader2Count = 0,  reader3Count = 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 reader2One(void) {
  if(digitalRead(6) == LOW){
  reader2Count++;
  reader2 = reader2 << 1;
  reader2 |= 1;
  }
}

void reader2Zero(void) {
  if(digitalRead(7) == LOW){
  reader2Count++;
  reader2 = reader2 << 1;  
  }
}

void reader3One(void) {
  if(digitalRead(8) == LOW){
  reader3Count++;
  reader3 = reader3 << 1;
  reader3 |= 1;
  }
}

void reader3Zero(void) {
  if(digitalRead(9) == LOW){
  reader3Count++;
  reader3 = reader3 << 1;  
  }
}

void setup()
{
  Serial.begin(57000);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  PCattachInterrupt(4, reader1One, CHANGE);
  PCattachInterrupt(5, reader1Zero, CHANGE);
  PCattachInterrupt(6, reader2One, CHANGE);
  PCattachInterrupt(7, reader2Zero, CHANGE);
  PCattachInterrupt(8, reader3One, CHANGE);
  PCattachInterrupt(9, reader3Zero, 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 = reader2 = reader3 = 0;
  reader1Count = reader2Count =  reader3Count = 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;
     }
     
  if(reader2Count >= 26){
  Serial.println("B");Serial.println(reader2 & 0xfffffff);
  reader2 = 0;
  reader2Count = 0;
     }
     
 if(reader3Count >= 26){
  Serial.println("C");Serial.println(reader3 & 0xfffffff);
  reader3 = 0;
  reader3Count = 0;
     }
    
}

Отсюда

http://arduino.cc/forum/index.php/topic,19755.0.html

CityCat
CityCat аватар
Offline
Зарегистрирован: 13.06.2013

maksim пишет:

DATA0 это не  RX, а  DATA1 это не TX.

Это интерфейс Wiegand, в вашем случае Wiegand 26.

Подключают через прерывания на 2 и 3 выводы вот пример кода


/* 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
 */

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

void reader1One(void) {
  reader1Count++;
  reader1 = reader1 << 1;
  reader1 |= 1;
}

void reader1Zero(void) {
  reader1Count++;
  reader1 = reader1 << 1;
}

void setup()
{
  Serial.begin(9600);
  // Attach pin change interrupt service routines from the Wiegand RFID readers
  attachInterrupt(0, reader1Zero, RISING);//DATA0 to pin 2
  attachInterrupt(1, reader1One, RISING); //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
  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);
 int serialNumber=(reader1 >> 1) & 0x3fff;
 int siteCode= (reader1 >> 17) & 0x3ff;

 Serial.print(siteCode);
 Serial.print("  ");
 Serial.println(serialNumber);
  reader1 = 0;
  reader1Count = 0;
  digitalWrite(13,HIGH);
  delay(2000);
  digitalWrite(13,LOW);
     }
}

Вот источник.

У меня почему-то с этим кодом выдает только два значения (причем почти рандомом):

511 16383
1023 16383
511 16383
511 16383
1023 16383
511 16383
1023 16383
511 16383
511 16383
1023 16383

Что может быть не так?

UPD.

Отвечаю сам себе.

Нашёл интересную статью: http://www.seeedstudio.com/wiki/Grove_-_125KHz_RFID_Reader, немного перделал под себя и снабдил комментариями - может кому будет полезно (так работает):

#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(2, 3);             // 2 - RX, 3 - TX
unsigned char buffer[64];                    // Массив для полученных данных (номер карты)
int count=0;                                 // Счетчик полученных символов

void setup()
{
  Serial.begin(9600);                        // Инициализация первого Serial'a
  SoftSerial.begin(9600);                    // Инициализация Soft Serial'a
}
 
void loop()
{  
  if (SoftSerial.available())                // Пришли данные из SoftSeral порта
  {
    while (SoftSerial.available())           // В порт пришли данные
    {
      byte ch=SoftSerial.read();
      if ((ch != 2) & (ch != 3))             // Если не символ начала или конца посылки (данные - номер карты)
        buffer[count++] = ch;                // Запись принятого символа в массив
      if (ch == 3) break;                    // Если конец посылки - выходим из цикла чтения
    }
    Serial.write(buffer,count);              // Выводим данные в аппаратный порт (Serial)
    Serial.println();                        // Пустая строка
    delay(500);                              // Задержка полсекунды (подавление дребезга)
    clrBuff();                               // Вызываем функцию очистки массива для данных
    count = 0;                               // Обнуляем счетчик количества полученных символов
  }
  if (Serial.available())                    // Если пришли данные в аппаратный порт
    SoftSerial.write(Serial.read());         // Отправляем их в Soft Serial
}

// Функция, очищающая приемный буфер
void clrBuff()
{
  for (int i=0; i<count;i++)                 // Цикл от нуля до кол-ва полученных символов
    buffer[i]=NULL;                          // Очищаем каждый элемент массива
}

 

apav
Offline
Зарегистрирован: 17.03.2014

Кстати проверять на 26 бит лучше в обработке прерывания.

И заносить во временную переменную, которую уже обрабатывать.

Ибо есть помехи. и После считанного кода может прилететь еще 1 или 0 до обработки кода.

Также лучше учесть таймаут между сигналами, и обрабатывать его - ибо может прилететь не 26, а меньше помех и потом они пойдут к нормально считанному коду.

Vladimirf
Offline
Зарегистрирован: 18.12.2015

CityCat пишет:

У меня почему-то с этим кодом выдает только два значения (причем почти рандомом):

511 16383
1023 16383
511 16383
511 16383
1023 16383
511 16383
1023 16383
511 16383
511 16383
1023 16383

Что может быть не так?

Подскажите, и что может быть не так?

CityCat
CityCat аватар
Offline
Зарегистрирован: 13.06.2013

Vladimirf пишет:

Подскажите, и что может быть не так?

В том же посте ниже есть рабочий код - его пробовал?

Vladimirf
Offline
Зарегистрирован: 18.12.2015

По com-порту получалось принимать корректно. Проблема в том, что последовательные порты softserial на прием не могут работать больше одного.  
И мне мне этот код с wiegandom нужен, потому что у меня 5 считывателей. И с этим кодом есть пример, работающий на всех пинах.Программа принимает данные со всех 5 считывателей, но выдает те же значения, что и у Вас. 

Vladimirf
Offline
Зарегистрирован: 18.12.2015

хм... посмотрел, что в том коде  все значения одинаковые. Все 26 бит заполены "1". 
Функция reader1Zero(void) никогда не запускается по прерыванию и не вставляет "0". А в чем про проблема не могу прошарить. 

kristow
kristow аватар
Offline
Зарегистрирован: 08.08.2013

Всем привет.

Использую считыватель с wiegand-26. Проблема в том, что когда считыватель стоит без действия, arduino иногда принимает какие-то значения, хотя считыватель карту в этот момент не считывал. Подскажите, может надо DATA0 или DATA1 через резистор на землю подтянуть? Чтобы избавиться от паразитной информации?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

kristow пишет:

Подскажите, может надо DATA0 или DATA1 через резистор на землю подтянуть? 

Можно, только надо смотреть, куда подтягивать ;) Зависит от, что называется.