Как не учитывать повторно поднесенную RFID-метку?

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013
На базе скетча Brett Martin написан код для игры. Суть простая: при правильной последовательности прикладывания 3-х RFID-карт зажечь табло.
Все работает, но с косяком: если три раза приложить одинаковую карту, тоже срабатывает. Как игнорировать уже ранее поднесенную карту?
/*
Цель игры. 
Легкий уровень: при правильной последовательности прикладывания 3-х RFID-карт зажечь табло. 
Сложный уровень: то же самое, но надо еще приложить i-button.

Для периодической замены RFID-карт есть мастер-карта и кнопка очистки памяти
 */


/* Исходник: скетч Arduino RC522 RFID Door Unlocker
 * MFRC522 Library also lets us to use some authentication
 * mechanism, writing blocks and reading back
 * and there is great example piece of code
 * about reading and writing RFIDs
 * here > http://makecourse.weebly.com/week10segment1.html
 *
 * Idea and most of code from Brett Martin's project
 * http://www.instructables.com/id/Arduino-RFID-Door-Lock/
 * www.pcmofo.com
 *
 * MFRC522 Library
 * https://github.com/miguelbalboa/rfid
 * Based on code Dr.Leong   (WWW.B2CQSHOP.COM)
 * Created by Miguel Balboa (circuitito.com), Jan, 2012.
 * Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 
 * (Translation to English, refactored, comments, anti collision, cascade levels.)
 *
 * Arduino Forum Member luisilva for His Massive Code Correction
 * http://forum.arduino.cc/index.php?topic=257036.0
 * http://forum.arduino.cc/index.php?action=profile;u=198897
 *
 * License
 * You are FREE what to do with this code
 * Just give credits who put effort on this code
 */
#include <OneWire.h> // http://www.pjrc.com/teensy/td_libs_OneWire.html
#include <EEPROM.h>  // We are going to read and write RFID's UIDs from/to EEPROM
#include <SPI.h>      // RC522 Module uses SPI protocol
#include <MFRC522.h>   // Library for Mifare RC522 Devices
#include <SoftwareSerial.h>

#define AMBI_GREEN 5  // подсветка панели - зеленый
#define AMBI_PINK 6  // подсветка панели - розовый
#define LED_ALARM 3  // индикатор "событие" (для отладки)
#define LED_READY 2// индикатор "приложите карту"
#define LVL 4 // герон выбора простой/сложный уровень
#define IBUTTON A3 // ключ-таблетка iButton
#define BUZZER 9 // баззер пищалка для событий
#define RELAY A2 // реле для включения табло (3 лампы 220 В)
#define LED13 13 // внутренний индикатор для отладки без табло
#define WIPE_BUTTON 8 // кнопка для удаления из памяти всех ID

/* A6 & A7 are analog input only. You cannot digital write to them. */

const unsigned int tabloFlashTime = 60000; // время горения табло, мсек (не более 65535)

long previousMillis = 0;        // will store last time LED was updated
//long yellowResetInterval = 900000L;  // // Интервал сброса по таймауту, мсек (10 мин)
boolean match = false; // initialize card match to false
boolean programMode = false; // initialize programming mode to false
const unsigned int ledBlink = 2000; // частота мигания светодиода (2 сек)
unsigned long currTime;     // переменная, где храним текущее время проверки
unsigned long prevBlinkTime; // переменная, где храним время последнего включения LED
enum state{
  READY, ALARM, BINGO};   // события системы
boolean level2 = false;  // флаг: включен ли сложный уровень
boolean iButtonAccess = false;  // флаг: разрешен ли доступ по 2 уровню (приложен правильный ключ)
boolean onceTabloFlash = false;  // флаг: было ли включено табло

byte Counter = 0;    // счетчик количества правильных прикладываний карт. 
// При каждом правильном прикладывании ключа: +1, при =3 включаем реле, при неправильной карте сбрасываем в 0.
int successRead; // Variable integer to keep if we have Successful Read from Reader

byte storedCard[4];   // Stores an ID read from EEPROM
byte readCard[4];           // Stores scanned ID read from RFID Module
byte masterCard[4]; // Stores master card's ID read from EEPROM
// ID ключа iButton
byte key[8] = {
  1, 27, 220, 173, 1, 0, 0, 126};

/* We need to define MFRC522's pins and create instance
 * Pin layout should be as follows (on Arduino Uno):
 * MOSI: Pin 11 / ICSP-4 / ATmega328-17
 * MISO: Pin 12 / ICSP-1 / ATmega328-18
 * SCK : Pin 13 / ICSP-3 / ATmega328-19
 * SS/SDA : Pin 10 (Configurable) / ATmega328-16
 * RST : Pin 9 (Configurable) / ATmega328-15
 * look MFRC522 Library for
 * pin configuration for other Arduinos.
 */
#define SS_PIN A1  // SDA
#define RST_PIN 10
MFRC522 mfrc522(SS_PIN, RST_PIN);	// Create MFRC522 instance.
OneWire ds(IBUTTON);    

///////////////////////////////////////// Setup ///////////////////////////////////
void setup() {
  //Arduino Pin Configuration
  pinMode(WIPE_BUTTON, INPUT); 
  pinMode(LVL, INPUT_PULLUP);
  pinMode(AMBI_GREEN, OUTPUT);
  pinMode(AMBI_PINK, OUTPUT);
  pinMode(LED13, OUTPUT);
  pinMode(LED_ALARM, OUTPUT);
  pinMode(LED_READY, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(RELAY, OUTPUT);

  //Protocol Configuration
  Serial.begin(9600);	 // Initialize serial communications with PC
  SPI.begin();           // MFRC522 Hardware uses SPI protocol
  mfrc522.PCD_Init();    // Initialize MFRC522 Hardware
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); //Set Antenna Gain to Max- this will increase reading distance

  Serial.println("Ready.");

  //Check if master card defined, if not let user choose a master card
  //This also useful to just redefine Master Card
  //You can keep other EEPROM records just write other than 1 to EEPROM address 1
  checkEEPROM(); 
}


///////////////////////////////////////// Main Loop ///////////////////////////////////
void loop () 
{  
  do {
    currTime = millis(); // обновляем текущее время проверки
    level2 = digitalRead(LVL);    
    if (level2) 
    { 
      readiButton();
    }

    //Serial.print("WipeButton State: "); 
    //Serial.println(!digitalRead(WIPE_BUTTON));
    if (!digitalRead(WIPE_BUTTON) == HIGH) 
    {
      //digitalWrite(LED_YELLOW, LOW);
      wipe();
      checkEEPROM();      
      programMode = false;
    }
    successRead = getID(); // sets successRead to 1 when we get read from reader otherwise 0
    if (programMode) {
      cycleLeds(); // Program Mode cycles through RGB waiting to read a new card
    }
    else {
      normalModeOn(); // Normal mode, green Power LED is on, all others are off 
      unsigned long currentMillis = millis();
      /*
      if(currentMillis - previousMillis > yellowResetInterval) 
       {
       //digitalWrite(LED_YELLOW, LOW);
       // save the last time you blinked the LED 
       previousMillis = currentMillis;  
       }
       */
    }
  }
  while (!successRead); //the program will not go further while you not get a successful read
  //digitalWrite(LED_YELLOW, LOW);   // как только прочитали следующую карту - гасим желтый
  if (programMode) {
    if (isMaster(readCard)) {  //If master card scanned again exit program mode
      Serial.println("This is Master Card"); 
      Serial.println("Exiting Program Mode");
      Serial.println("-----------------------------");
      programMode = false;
      return;
    }
    else {	
      if (findID(readCard)) { //If scanned card is known delete it
        Serial.println("I know this RFID, so removing");
        deleteID(readCard);
        programMode = false;  // добавлено мной
        Serial.println("-----------------------------");
      }
      else {                    // If scanned card is not known add it
        Serial.println("I do not know this RFID, adding...");
        writeID(readCard);
        programMode = false;  // добавлено мной
        Serial.println("-----------------------------");
      }
    }
  }
  else {
    if (isMaster(readCard)) {  // If scanned card's ID matches Master Card's ID enter program mode
      programMode = true;
      Serial.println("Hello Master - Entered Program Mode");
      int count = EEPROM.read(0); // Read the first Byte of EEPROM that
      Serial.print("I have ");    // stores the number of ID's in EEPROM
      Serial.print(count);
      Serial.print(" record(s) on EEPROM");
      Serial.println("");
      Serial.println("Scan a RFID to ADD or REMOVE");
      Serial.println("-----------------------------");
    }
    else {
      if (findID(readCard)) {        // Если карта правильная If not, see if the card is in the EEPROM 
        Serial.println("flashTablo!");
        accessGranted();
        Counter = Counter++;
        debugMessage();
        if (Counter == 3)  // поднесено три правильных карты
        {
          if (level2) // если второй уровень
          {
            if (iButtonAccess) // и поднесен правильный ключ
            {
              Serial.println("BINGO!");
              flashTablo();
              iButtonAccess = false;
              Counter = 0;
              debugMessage();
            }
            else // если второй уровень и неправильный ключ
            {
              Serial.println("Access DENIED! Need right 1-Wire Key!");
              Counter = 0;
              debugMessage();
              failed(); 
            }
          }
          else // если первый уровень
          {
            Serial.println("BINGO!");
            flashTablo();
            iButtonAccess = false;
            Counter = 0;
            debugMessage();
          };
        }
        //delay(500);
      }
      else {				// If not, show that the ID was not valid
        Serial.println("Access DENIED!");
        Counter = 0;
        debugMessage();
        failed(); 
      }
    }
  }
}

///////////////////////////////////////// Читаем ID метки ///////////////////////////////////
int getID() {
  // Getting ready for Reading RFIDs
  if (!mfrc522.PICC_IsNewCardPresent()) { //If a new RFID placed to RFID reader continue
    return 0;
  }
  if (!mfrc522.PICC_ReadCardSerial()) { //Since a RFID placed get Serial and continue
    return 0;
  }
  // There are Mifare RFIDs which have 4 byte or 7 byte UID care if you use 7 byte RFID
  // I think we should assume every RFID as they have 4 byte UID
  // Until we support 7 byte RFIDs
  Serial.println("\nScanned RFID's UID:");
  for (int i = 0; i < 4; i++) {  // 
    readCard[i] = mfrc522.uid.uidByte[i];
    Serial.print(readCard[i], HEX);
  }
  Serial.println("");
  mfrc522.PICC_HaltA(); // Stop reading
  return 1;
}

///////////////////////////////////////// Мигаем светиками (Режим программирования) ///////////////////////////////////
void cycleLeds() {
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_GREEN, HIGH);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED_ALARM, HIGH);
  digitalWrite(LED_READY, LOW);
  tone(BUZZER, 512); // шумим
  delay(128);
  noTone(BUZZER);
  digitalWrite(LED13, LOW);
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(AMBI_PINK, HIGH);
  digitalWrite(LED_ALARM, LOW);
  digitalWrite(LED_READY, HIGH);
  delay(128);
}

//////////////////////////////////////// Индикация ожидания карты  ///////////////////////////////////
void normalModeOn () {
  digitalWrite(LED_ALARM, LOW);
  digitalWrite(AMBI_GREEN, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  // призываем приложить карту
  if(currTime - prevBlinkTime > ledBlink) // если прошло более 3 сек с момента мигания LED
  {
    digitalWrite(LED_READY, HIGH);  // мигаем индикатором
    digitalWrite(LED13, HIGH);
    //Serial.println("Ready");
    delay(512);
    digitalWrite(LED_READY, LOW);
    digitalWrite(LED13, LOW);
    prevBlinkTime = currTime;                 // запоминаем время мигания
  }
}

//////////////////////////////////////// Читаем ID из EEPROM //////////////////////////////
void readID(int number) {
  int start = (number * 4) + 2; // Figure out starting position
  for (int i = 0; i < 4; i++) { // Loop 4 times to get the 4 Bytes
    storedCard[i] = EEPROM.read(start+i); // Assign values read from EEPROM to array
  }
}

///////////////////////////////////////// Добавляем ID в EEPROM   ///////////////////////////////////
void writeID(byte a[]) {
  if (!findID(a)) { // Before we write to the EEPROM, check to see if we have seen this card before!
    int num = EEPROM.read(0); // Get the numer of used spaces, position 0 stores the number of ID cards
    int start = (num * 4) + 6; // Figure out where the next slot starts
    num++; // Increment the counter by one
    EEPROM.write(0, num); // Write the new count to the counter
    for (int j = 0; j < 4; j++) { // Loop 4 times
      EEPROM.write(start+j, a[j]); // Write the array values to EEPROM in the right position
      tone(BUZZER, 400+(j*200));
      delay(100);
      noTone(BUZZER);
    }
    successWrite();
  }
  else {
    failedWrite();
  }
}

///////////////////////////////////////// Стираем ID из EEPROM   ///////////////////////////////////
void deleteID(byte a[]) {
  if (!findID(a)) { // Before we delete from the EEPROM, check to see if we have this card!
    failedWrite(); // If not
  }
  else {
    int num = EEPROM.read(0); // Get the numer of used spaces, position 0 stores the number of ID cards
    int slot; // Figure out the slot number of the card
    int start;// = (num * 4) + 6; // Figure out where the next slot starts
    int looping; // The number of times the loop repeats
    int j;
    int count = EEPROM.read(0); // Read the first Byte of EEPROM that stores number of cards
    slot = findIDSLOT(a); //Figure out the slot number of the card to delete
    start = (slot * 4) + 2;
    looping = ((num - slot) * 4);
    num--; // Decrement the counter by one
    EEPROM.write(0, num); // Write the new count to the counter
    for (j = 0; j < looping; j++) { // Loop the card shift times
      EEPROM.write(start+j, EEPROM.read(start+4+j)); // Shift the array values to 4 places earlier in the EEPROM
    }
    for (int k = 0; k < 4; k++) { //Shifting loop
      EEPROM.write(start+j+k, 0);
      tone(BUZZER, 1400-(j*200));
      delay(100);
      noTone(BUZZER);
    }
    successDelete();
  }
}

///////////////////////////////////////// Check Bytes   ///////////////////////////////////
boolean checkTwo (byte a[], byte b[]) {
  if (a[0] != NULL) // Make sure there is something in the array first
    match = true; // Assume they match at first
  for (int k = 0; k < 4; k++) { // Loop 4 times
    if (a[k] != b[k]) // IF a != b then set match = false, one fails, all fail
      match = false;
  }
  if (match) { // Check to see if if match is still true
    return true; // Return true
  }
  else  {
    return false; // Return false
  }
}

///////////////////////////////////////// Find Slot   ///////////////////////////////////
int findIDSLOT(byte find[]) {
  int count = EEPROM.read(0); // Read the first Byte of EEPROM that
  for (int i = 1; i <= count; i++) { // Loop once for each EEPROM entry
    readID(i); // Read an ID from EEPROM, it is stored in storedCard[4]
    if(checkTwo(find, storedCard)) { // Check to see if the storedCard read from EEPROM
      // is the same as the find[] ID card passed
      return i; // The slot number of the card
      break; // Stop looking we found it
    }
  }
}

///////////////////////////////////////// Ищем ID в EEPROM   ///////////////////////////////////
boolean findID(byte find[]) {
  int count = EEPROM.read(0); // Read the first Byte of EEPROM that
  for (int i = 1; i <= count; i++) {  // Loop once for each EEPROM entry
    readID(i); // Read an ID from EEPROM, it is stored in storedCard[4]
    if(checkTwo(find, storedCard)) {  // Check to see if the storedCard read from EEPROM
      return true;
      break; // Stop looking we found it
    }
    else {  // If not, return false   
    }
  }
  return false;
}

///////////////////////////////////////// Индикация об успешной записи в EEPROM   ///////////////////////////////////
// Flashes the green LED 3 times to indicate a successful write to EEPROM
void successWrite() {
  Serial.println("Succesfully added ID record to EEPROM");
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_GREEN, HIGH);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED_ALARM, HIGH);
  digitalWrite(LED_READY, LOW);
  digitalWrite(AMBI_GREEN, LOW);
  delay(200);
  digitalWrite(AMBI_GREEN, HIGH);
  delay(200);
  digitalWrite(AMBI_GREEN, LOW);
  delay(200);
  digitalWrite(AMBI_GREEN, HIGH);
  delay(200);
  digitalWrite(AMBI_GREEN, LOW);
  delay(200);
  digitalWrite(AMBI_GREEN, HIGH);
  delay(200);  
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(LED13, LOW);
  digitalWrite(LED_ALARM, LOW);
}

///////////////////////////////////////// Индикация ошибки записи в EEPROM   ///////////////////////////////////
// Flashes the red LED 3 times to indicate a failed write to EEPROM
void failedWrite() {
  Serial.println("Failed!There is something wrong with ID or bad EEPROM");
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED13, LOW);
  delay(200);
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED13, LOW);
  delay(200);
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED13, LOW);
  delay(200);
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED13, LOW);
  digitalWrite(LED_ALARM, LOW);
}

///////////////////////////////////////// Индикация успешного удаления ID из EEPROM  ///////////////////////////////////
// Flashes the blue LED 3 times to indicate a success delete to EEPROM
void successDelete() {
  Serial.println("Succesfully removed ID record from EEPROM");
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  delay(200);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  delay(200);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(AMBI_PINK, LOW);
  delay(200);
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(LED13, LOW);
}

////////////////////// Проверка: является ли метка МАСТЕРОМ   ///////////////////////////////////
// Check to see if the ID passed is the master programing card
boolean isMaster(byte test[]) {
  if (checkTwo(test, masterCard))
  {    
    for(byte kk = 0; kk <= 200; kk++) // шумим
    {
      digitalWrite(BUZZER, HIGH);
      delay(2);
      digitalWrite(BUZZER, LOW);
      delay(2);
    } 
    return true;
  }
  else
    return false;
}

///////////////////////////////////////// Зажигаем табло    ///////////////////////////////////
void flashTablo() {
  digitalWrite(LED13, HIGH);
  digitalWrite(RELAY, HIGH);
  delay(tabloFlashTime);
  digitalWrite(LED13, LOW);
  digitalWrite(RELAY, LOW);
  // исходный режим
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED_ALARM, LOW);
  digitalWrite(LED_READY, LOW);
}


///////////////////////////////////////// Мигаем зеленым, если правильная карта   ///////////////////////////////////
void accessGranted() {
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_GREEN, HIGH);
  delay(1000);
  digitalWrite(LED13, LOW);
  digitalWrite(AMBI_GREEN, LOW);
}

///////////////////////////////////////// Отказ в доступе (неверная карта) ///////////////////////////////////
void failed() {
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  digitalWrite(LED_ALARM, HIGH);
  /*
    for (byte z = 0; z < 3; z++) { 
   tone(BUZZER, 400);
   delay(256);
   noTone(BUZZER);
   delay(256);
   }
   */
  delay(1000);
  digitalWrite(LED13, LOW);
  digitalWrite(AMBI_PINK, LOW);
  digitalWrite(LED_ALARM, LOW);
}


void wipe() {     // when button pressed pin should get low, button connected to ground
  digitalWrite(LED13, HIGH);
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(AMBI_PINK, HIGH);
  digitalWrite(LED_ALARM, HIGH);
  Serial.println("\nWipe Button Pressed");
  Serial.println("You have 5 seconds to Cancel");
  Serial.println("This will be remove all records and cannot be undone");
  tone(BUZZER, 800);
  delay(2000);
  noTone(BUZZER);
  //delay(5000);    // Give user enough time to cancel operation
  /*  if (digitalRead(WIPE_BUTTON) == LOW) {  // If button still be pressed, wipe EEPROM 
   */
  Serial.println("Starting Wiping EEPROM");
  for (int x=0; x<1024; x++){ //Loop end of EEPROM address
    if (EEPROM.read(x) == 0){ //If EEPROM address 0 
      // do nothing, already clear, go to the next address in order to save time and reduce writes to EEPROM
    } 
    else{
      EEPROM.write(x, 0); // if not write 0, it takes 3.3mS
    }
  }
  for (int j = 0; j < 4; j++) { // Loop 4 times
    tone(BUZZER, 400+(j*200));
    delay(100);
    noTone(BUZZER);
  }
  Serial.println("Wiped\n");
  digitalWrite(LED13, HIGH); // visualize successful wipe
  digitalWrite(AMBI_GREEN, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  digitalWrite(LED_ALARM, HIGH);
  digitalWrite(LED_READY, HIGH);
  delay(200);
  digitalWrite(LED13, LOW);
  digitalWrite(LED_ALARM, LOW);
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(AMBI_PINK, LOW);
  delay(200);
  digitalWrite(LED13, HIGH);
  digitalWrite(LED_ALARM, HIGH);
  digitalWrite(AMBI_GREEN, HIGH);
  digitalWrite(AMBI_PINK, HIGH);
  delay(200);
  digitalWrite(LED13, LOW);
  digitalWrite(LED_ALARM, LOW);
  digitalWrite(AMBI_GREEN, LOW);
  digitalWrite(AMBI_PINK, LOW);
  /*  }
   else {
   Serial.println("!!Wiping Cancelled !!");
   digitalWrite(LED_RED, LOW);
   }*/
}


void checkEEPROM()
//Check if master card defined, if not let user choose a master card
//This also useful to just redefine Master Card
//You can keep other EEPROM records just write other than 1 to EEPROM address 1
{  
  if (EEPROM.read(1) != 143) {  // Look EEPROM if Master Card defined, EEPROM address 1 holds if defined
    // 143 our magical number
    Serial.println("\nNo Master RFIDs Defined");
    Serial.println("Scan a RFID to Define as Master");
    digitalWrite(LED_READY, LOW);
    digitalWrite(AMBI_GREEN, LOW);
    for (byte z = 0; z < 4; z++) { 
      tone(BUZZER, 800);
      delay(256);
      noTone(BUZZER);
      delay(128);
    }
    do {
      successRead = getID(); // sets successRead to 1 when we get read from reader otherwise 0
      digitalWrite(LED13, HIGH); // Visualize Master Card need to be defined
      digitalWrite(LED_ALARM, HIGH);
      digitalWrite(AMBI_PINK, HIGH);
      delay(50);
      digitalWrite(LED13, LOW);
      digitalWrite(LED_ALARM, LOW);
      digitalWrite(AMBI_PINK, LOW);
      delay(50);
    }
    while (!successRead); //the program will not go further while you not get a successful read
    for (int j = 0; j < 4; j++) { // Loop 4 times
      EEPROM.write(2+j, readCard[j]); // Write scanned RFID's UID to EEPROM, start from address 3
      tone(BUZZER, 400+(j*200));
      delay(100);
      noTone(BUZZER);
    }
    EEPROM.write(1,143); //Write to EEPROM we defined Master Card.
    Serial.println("Master RFID Defined\n");
  }

  Serial.println("Master RFID's UID");
  for (int i = 0; i < 4; i++) {     // Read Master Card's UID from EEPROM
    masterCard[i] = EEPROM.read(2+i); // Write it to masterCard
    Serial.print(masterCard[i], HEX);
  }
  Serial.println("");
  Serial.println("Waiting RFIDs to bo scanned :)");
  // cycleLeds();    // Everything ready lets give user some feedback by cycling leds
}



void readiButton(void) 
{
  byte addr[8];
  byte val = 0;  // внутренний счетчик проверки "правильного" ключа

  if (ds.search(addr)) 
  {
    Serial.print("R=");
    for (byte i = 0; i < 8; i++) 
    {
      Serial.print(addr[i], DEC);
      Serial.print(" ");
      if (addr[i] == key[i]) val++;
    }
    Serial.println();
    ds.reset();  // нужна ли?

    if (OneWire::crc8(addr, 7) != addr[7]) 
    {
      Serial.print("CRC is not valid!\n");
      for (int k = 0; k < 4; k++) 
      { 
        tone(BUZZER, 400);
        delay(1000);
        noTone(BUZZER);
      }
      return;
    }

    if (addr[0] != 0x01) 
    {
      Serial.print("Device is not a DS1990A family device.\n");
      for (int k = 0; k < 4; k++) 
      { 
        tone(BUZZER, 400);
        delay(1000);
        noTone(BUZZER);
      }
      return;
    }

    if (val == 8)
    {
      Serial.println("flashTablo!\n Acces permitted for Layer 2");
      for (int j = 0; j < 4; j++) 
      { // Loop 4 times
        tone(BUZZER, 400+(j*200));
        delay(100);
        noTone(BUZZER);
      }
      iButtonAccess = true;
    }
    else
    {
      Serial.println("Denied!");
      for (int k = 0; k < 4; k++) 
      { 
        tone(BUZZER, 400);
        delay(128);
        noTone(BUZZER);
      }
    }
    ds.reset_search();
  }
}


void debugMessage()
{
  Serial.print("Counter: ");
  Serial.println(Counter);
  Serial.print(level2?"Level: Hard.":"Level: Easy."); 
  if (level2) Serial.println(iButtonAccess?"\tiButton verified":"\tiButton NOT verified");
  else Serial.println("");
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Самое тупое хранить массив (типа byte readyCard[CARD_LEN][MAX_SAMPLES], плюс индекс кол-ва введенных карт) и после получения кода карты искать его в массиве, если нет, то записывать и дальше по алгоритму.

Поскольку мусора в скетче много, лучше вставить это отдельной функцией, которая вернет, например, валидность карты (что она не введена повторно. Вставить, например, в строку 199, типа:

if (findID(readCard) && (!repeatedCardInput(readCard))) {

 

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

Эммм. пожалуй не соглашусь. В твоем варианте проканает вариант 1+2+1 и ему подобные.

arr[0] = 123

arr[1] = 234

arr[2] = 345

Массив с номерами меток в порядке прикладывания.

Перемнная Х=0.

Как только считываем правильную метку на правильном шагу

if(readed == arr[X]) {

Х++;

if(X == 3) {

елочка гори!

Х=0

}

}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

JollyBiber пишет:

Эммм. пожалуй не соглашусь. В твоем варианте проканает вариант 1+2+1 и ему подобные.

arr[0] = 123

arr[1] = 234

arr[2] = 345

Массив с номерами меток в порядке прикладывания.

Перемнная Х=0.

Как только считываем правильную метку на правильном шагу

if(readed == arr[X]) {

Х++;

if(X == 3) {

елочка гори!

Х=0

}

}

 

Если это мне, то еще как прокатит, я предлагал хранить все введенные номера в отдельном массиве и при вводе очередной карты искать введенный номер в этом массиве. Если это ответ ТС, то игнорируй мой коммент. Ограничивать по количеству введенных значений - это совсем другой вопрос.

Вообще весь текст скетча достаточно плохо структурирован, ввод допустимых карт (программирование), ввод в игре, всё в одном месте, а не оформлено отдельными функциями, что было бы намного читабельней и меньше шансов ошибиться.

 

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

Тебе, тебе :)

у тебя учитывается только предидущая карта. то есть вариант 1+2+1 будет расценен как правильный, что не есть кошерно по ТС.

 

а скетч я даже не смотрел - не интересно :)

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Я сегодня не выспался и не могу сообразить - эта ветка тоже стёб?