如何停止多次读取 RFID 卡

How to stop multiple reads of an RFID card

我正在使用带有 arduino nano 的 125Khz RFID 模块 RDM6300。 当卡片靠近 RFID reader 时,循环将多次读取卡片。我希望它只在卡靠近 reader 时读取一次,然后在建立新连接时再次读取。 *这段代码不是我写的,这是来源: 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;

    }
  }
}

谢谢。

感谢您的回答。我试图接受多次读取并只打印一次,但它一直打印 "already read" 而不是第一次读取卡片,这是代码:

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

您可以在读取(标签结束)后设置延迟(例如delay(2000))。延迟(比如说)2 秒将允许用户将卡片移到离 reader 足够远的地方。请注意,delay 是一个阻塞命令,可能不适合您的目的,在这种情况下,您可以考虑使用 millis 计数到 activate/deactivate Serial.read.

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

我猜你想要的是边沿触发而不是带时间限制的电平触发。

For example, you may prefer to read a RFID card when it firstly comes near to the antenna, once only; when it keeps to contact the antenna, still take no more actions. When you remove the card and place it again near to the antenna, the MCU starts to read the card again.

If so, the following code could be for your reference. What I have done is just to add 1 more flag to keep checking the card_status before checking if a RFID card comes near to the antenna.

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; 
    } 
    
} 

reset the card status when no RFID signal comes in && card status is true,

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

原来的问题过了很长时间,但也许我的回答对以后的访客有用。

RDM6300 的工作原理:

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

把它想象成机场的行李传送带。 carousel(reader)上有多个行李(数据),你一个一个挑(转buffer)。

所以,多次读取的问题是,你在reader(行李在传送带上)中读取了数据,你的代码正在逐渐将它们传输到缓冲区(捡起行李) .

在我们的示例中,如果您不喜欢收集所有行李,您可以在他们到达您之前请人帮您拿走一些。

下面的代码就是这样做的。当您在 reader 中有数据时(卡靠近 reader),它将数据从 reader 传输到缓冲区,然后将缓冲区中的所有数据清零:

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

boolean multipleRead = false;

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

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

之后
 multipleRead = true;

当您的标签被读取时,它会将变量更改为 true。这告诉程序您的第一次读取已完成,下一次读取将是“多次读取”,您不需要它们。

然后把这个放在RFID reader代码的末尾(如果你的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;
}

它清空 reader 然后将缓冲区清零,同时附近有一张卡。当您将卡移开时,multipleRead 值将变为 false,从而启动另一个 RFID 读取循环。

希望对您有所帮助:)