如何停止多次读取RFID卡

时间:2018-02-13 06:11:55

标签: arduino rfid

我正在使用带有arduino nano的125Khz RFID模块RDM6300。 当卡在RFID读取器附近时,环路将多次读取卡。我希望它只读取一次,当卡在读卡器附近时,如果正在建立新连接,则再次读取它。  *此代码不是由我写的,这是来源: https://github.com/Wookai/arduino-rfid

    // define constants for pins
//int SUCCESS = 10;
//int ERROR = 13;

// variables to keep state
int readVal = 0; // individual character read from serial
unsigned int readData[10]; // data read from serial
int counter = -1; // counter to keep position in the buffer
char tagId[11]; // final tag ID converted to a string

char* authorizedTags[4]; // array to hold the list of authorized tags

// fills the list of authorzied tags
void initAuthorizedTags() {
  // add your own tag IDs here
  authorizedTags[0] = "0400680B85";
  authorizedTags[1] = "0400063EB9";
  authorizedTags[2] = "040004F3F5";
  authorizedTags[3] = "04006813AB";
}

void setup() {
  Serial.begin(9600);
  // pinMode(SUCCESS, OUTPUT);
  //pinMode(ERROR, OUTPUT);
  initAuthorizedTags();
}

// check if the tag ID we just read is any of the authorized tags
int checkTag() {
  int i;

  for (i = 0; i < 4; ++i) {
    if (strcmp(authorizedTags[i], tagId) == 0) {
      return 1;
    }
  }
  return 0;
}

// convert the int values read from serial to ASCII chars
void parseTag() {
  int i;
  for (i = 0; i < 10; ++i) {
    tagId[i] = readData[i];
  }
  tagId[10] = 0;
}

// once a whole tag is read, process it
void processTag() {
  // convert id to a string
  parseTag();

  // print it
  printTag();

  // check if the tag is authorized
  if (checkTag() == 1) {
    tagSuccess(); // if so, perform an action (blink a led, open a door, etc...)
  } else {
    tagFailed(); // otherwise, inform user of failure
  }
}

void printTag() {
  Serial.print("Tag value: ");
  Serial.println(tagId);
}

// perform an action when an authorized tag was read
void tagSuccess() {
  Serial.println("Tag authorized.");

  // here, we simply turn on the success LED for 2s
  // digitalWrite(SUCCESS, HIGH);
  //digitalWrite(ERROR, LOW);
  // delay(2000);
}

// inform the user that the tag is not authorized
void tagFailed() {
  Serial.println("Unauthorized access!");

  //digitalWrite(SUCCESS, LOW);
  // digitalWrite(ERROR, HIGH);
  // delay(2000);
}

// this function clears the rest of data on the serial, to prevent multiple scans
void clearSerial() {
  while (Serial.read() >= 0) {
    ; // do nothing
  }
}

void loop() {
  // turn LEDs off
  // digitalWrite(SUCCESS, LOW);
  //  digitalWrite(ERROR, LOW);

  if (Serial.available() > 0) {
    // read the incoming byte:
    readVal = Serial.read();

    // a "2" signals the beginning of a tag
    if (readVal == 2) {
      counter = 0; // start reading
    }
    // a "3" signals the end of a tag
    else if (readVal == 3) {
      // process the tag we just read
      processTag();

      // clear serial to prevent multiple reads
      clearSerial();

      // reset reading state
      counter = -1;
    }
    // if we are in the middle of reading a tag
    else if (counter >= 0) {
      // save valuee
      readData[counter] = readVal;

      // increment counter
      ++counter;

    }
  }
}

谢谢。

感谢您的回答。我试图接受多次读取并只打印一次,但它会保持打印“已读”而不是第一次读卡,这是代码:

void printTag() {
  if(strcmp(tagId,previous)==1){
  strcpy(previous, tagId);

  Serial.print("Tag value: ");
  Serial.println(tagId);
  }
  else
  {
    Serial.print("already read");
  }

}

我还尝试在标签结束后延迟,但它仍然会多次读取卡片。

我尝试了另一个代码,它仍然多次读取标记。

#include <SoftwareSerial.h>

// RFID  | Nano
// Pin 1 | D2
// Pin 2 | D3
SoftwareSerial Rfid = SoftwareSerial(2,3);
int timer=0;
int reference = 1000;
int card_status = 0;
void setup() {
  // Serial Monitor to see results on the computer
  Serial.begin(9600);
  // Communication to the RFID reader
  Rfid.begin(9600);
}

void read() {
  // check, if any data is available

    // as long as there is data available...
    while(Rfid.available() > 0 ){
      // read a byte
      int r = Rfid.read();
      // print it to the serial monitor
      Serial.print(r, DEC);
      Serial.print(" ");
    }
    // linebreak
    Serial.println();
  timer=0;
}

void loop()
{
 if((Rfid.available() > 0 ) && (card_status == 0) )
 {
 read();
 }
 if((!Rfid.available() > 0 ) && (card_status == 1) )
 {
  card_status=0;
 }
}

对于迟到的回复我很抱歉。我忘记了这个话题。

我通过在第一次写入RFID代码之后让arduino等待响应来解决问题。 我能够做到这一点,因为我的arduino通过串口将代码发送到C#应用程序。

以下是它的工作原理:arduino在串行打印RFID代码,从那里它被C#应用程序拾取,该应用程序搜索数据库以查看代码是否存储在那里。根据结果​​,应用程序打印一个由arduino拾取的字符('y'或'n')。根据收到的字符,arduino会点亮LED(绿色或红色)并发出噪音。现在可以进行新的RFID阅读。

以下是代码:

#include <SoftwareSerial.h>
#include "RDM6300.h"

SoftwareSerial rdm_serial(8, 9);
RDM6300<SoftwareSerial> rdm(&rdm_serial);
String comanda;
char c="";

int led_verde = 2;
int led_rosu = 7;
int buzzer = 12;
int i;

void buzz(int n = 1)
{
  for (int i = 0; i < n; i++) {
    digitalWrite(buzzer, LOW);
    delay(200);
    digitalWrite(buzzer, HIGH);
    delay(200);
  }
}

void ledVerde()
{
  digitalWrite(led_verde, HIGH);
  buzz(1);
  delay(1000);
  digitalWrite(led_verde, LOW);
}

void ledRosu()
{
  digitalWrite(led_rosu, HIGH);
  buzz(3);
  delay(1000);
  digitalWrite(led_rosu, LOW);
}


void setup()
{
  pinMode(led_verde, OUTPUT);
  pinMode(led_rosu, OUTPUT);
  pinMode(buzzer, OUTPUT);
  digitalWrite(led_verde, LOW);
  digitalWrite(led_rosu, LOW);
  digitalWrite(buzzer, HIGH);
  Serial.begin(9600);

}

void loop()
{

  static unsigned long long last_id = 0;
  last_id = rdm.read();
    rdm.print_int64(last_id);
    Serial.println();

  rdm_serial.end();
  Serial.flush();
  while(!Serial.available());
   c=Serial.read();

  if(c=='y')
  {
  ledVerde();
  c="";
  }
 if(c=='n')
  {
    ledRosu();
  }

  Serial.flush();
  last_id="";
  c="";
  rdm_serial.begin(9600);
}

您可以在此处找到RDM6300库:https://github.com/arliones/RDM6300-Arduino

3 个答案:

答案 0 :(得分:0)

您可以在阅读(标签结尾)后设置延迟(例如delay(2000))。 (例如)2秒的延迟将允许用户将卡移动远离读取器。请注意,delay是一个阻止命令,可能不适合您的目的,在这种情况下,您可能会考虑使用millis计数来激活/停用Serial.read

另一种选择是接受多次读取,但保持已读取哪种卡的状态。如果新卡号与旧卡号相同(在合理的时间范围内),则忽略。

答案 1 :(得分:0)

我想你想要的是边缘触发而不是时间限制的水平触发。

  

例如,您可能更喜欢在首次接近天线时读取RFID卡一次;当它不断接触天线时,仍然不再采取行动。当您取出卡并将其再次放置在天线附近时,MCU会再次开始读取卡。

     

如果是这样,以下代码可供您参考。我所做的只是在检查RFID卡是否靠近天线之前再添加1个标志以继续检查card_status

int card_status = 0; //0:readable; 1:not-readable

if ( (Serial.available() > 0) && (card_status == 0) ) { 
    card_status = 1; //disable to read card after exit this loop 
    //your code, a card is near to the antenna, try to read it. 

    readVal = Serial.read(); 

    if (readVal == 2) { 
        counter = 0; // start reading 
    } else if (readVal == 3) { 
        processTag(); 
        clearSerial(); 
        counter = -1; 
    } else if (counter >= 0) { 
        readData[counter] = readVal; 
        ++counter; 
    } 

} 
  

在没有RFID信号进入时重置卡状态&amp;&amp;卡状态为真,

if ( (!(Serial.available() > 0)) && (card_status == 1) ) { 
    card_status = 0; //enable to read card again
    //no signal, no card is near to the antenna.
}

答案 2 :(得分:0)

很长时间过去了最初的问题,但也许我的回答对将来的访问者有用。

RDM6300的工作原理:

  1. 自动读取数据,然后
  2. 您的代码将读取的数据传输到缓冲区以进行进一步处理。

把它想象成机场的行李传送带。转盘(读取器)上有多个行李(数据),您可以一个接一个地挑选它们(转移到缓冲区)。

因此,多次读取的问题是,您已经在读取器中读取了数据(轮播中的行李),您的代码正在将它们逐渐转移到缓冲区(捡起行李)。

在我们的示例中,如果您不想收拾所有行李,则可以要求某人在他们拿到您之前将其中一些拿走。

下面的代码可以做到这一点。当读取器中有数据时(卡靠近读取器),它将数据从读取器传输到缓冲区,然后将缓冲区中的所有数据清零:

首先,将此代码放在“ void setup()”之前:

boolean multipleRead = false;

这定义了一个false / true变量,以告诉您这是您是第一次读取标签(false),还是被多次读取(true)。

然后,将其放在代码块的末尾,以显示标记已被完全读取。如果将Michael Schoeffler的库用于RDM6300 / 630 RFID,请将其放在“ else if(ssvalue == 3){”之后:

 multipleRead = true;

读取标签后,它将变量更改为true。这表明程序已完成您的第一次读取,而下一个即将发生的读取将是“多次读取”,而您不希望它们。

然后将其放在RFID阅读器代码的末尾(如果您的RFID代码在void loop()下,请将下面的代码放在“ void loop(){”之后:

if (multipleRead) {
  while (ssrfid.available() > 0) {
    int ssvalue = ssrfid.read(); // read
    if (ssvalue == -1) { // no data was read
      break;
    }
  }
  for (int x = 0; x < 14; x++)
  {
    buffer[x] = 0;
  }
  multipleRead = false;
}

在附近有卡的情况下,它将清空读取器,然后将缓冲区清零。当您将卡移开时,multipleRead值将变为false,这将启动另一个RFID读取循环。

希望有帮助:)