Does not read a tag because the system leaves the condition

#include <SPI.h>
#include <MFRC522.h>
#include <EEPROM.h>
#include <Keypad.h>
#include <LiquidCrystal.h>




#define SS_PIN 53
#define RST_PIN 9

MFRC522 rfid(SS_PIN, RST_PIN);   // Configura los pines RST y SS del mrfc522

MFRC522::MIFARE_Key key; 





///////////////////////LCD///////////////////////////////////////

//Incializa la libreria con los numeros de pines a interactuar el LCD
LiquidCrystal lcd(A8, A9, A10, A11, A12, A13);

///////////////////////////////////////////////////////////////////


//////////////Teclado/////////////////////////////////////////////

//Definición de filas y columnas
const byte Filas = 4; //Cuatro filas
const byte Cols = 4; //Cuatro columnas

//Definición de los pines
byte Pins_Filas[] = {37, 35, 33, 31}; //Pines Arduino para las filas
byte Pins_Cols[] =  {29, 27, 25, 23}; // Pines Arduino para las columnas


//Definición de las teclas
char Teclas [ Filas ][ Cols ] =
{
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//Se crea una instancia llamada Teclado1 y el cual asignara las teclas que tenemos en el arreglo "Teclas" y le decimos
//que se han conectados los pines de las filas y columnas


Keypad kpd = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas, Cols);


char Teclado ()
{
  do{
    
   char Tecla = kpd.getKey();
   
    if (Tecla != NO_KEY)
    {
      return Tecla;
    } 
  } while (1);
}

/////////////////////////////////////////////////////////////////////////////////////////

#define CREDENTIALSOFFSET  11


struct USERCREDENTIALS
{
  // space for 9 character id and terminating nul character
  char id[6];
  // space for 15 character password and terminating nul character
  char pwd[10];
  byte rfid[3];
} usercredential;

// array with user credentials
USERCREDENTIALS credentials[15];



char  contrasena_ingresada[6];
char  contrasena_tecleada[10];
char  contrasena_tecleada1[10];

boolean A = LOW; 



void setup() {
  // put your setup code here, to run once:
  lcd.begin(20, 4); //Configura el LCD con el numero de columas y filas. Para un LCD 16x4: 16 columnas y 4 filas.
  lcd.display(); //Enciende el display

  SPI.begin();               // Incializa la comunicacion SPI 
  rfid.PCD_Init(); // Init MFRC522
  
}

void loop() {
  
int estado;
int user;

//para llenar las primeras posiciones de datos
for(int i=0; i<11; i++){
  EEPROM.write(i, 1);
}


    for (byte i = 0; i < 6; i++) {
      key.keyByte[i] = 0xFF;
    }

   lcd.clear();
   lcd.setCursor(0,0);lcd.print("Modo lectura");   //Imprime en la LCD
   lcd.setCursor(3,3);lcd.print("Presione *");   //Imprime en la LCD
   int Tecla = kpd.getKey();

   leer_usuario();  //If the reader reads a tag, check the system if it exists or not.

        
    if(Tecla == '*'){ //If the push asterisk user, keep the tag in the system
        guardar_tag();
           
}

}




void leer_usuario(){


   // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return;


   //for(int user=0; user < sizeof(credentials) / sizeof(USERCREDENTIALS); user ++){ //cambiar por credential, usarios credenciales
    
                //if ((rfid.uid.uidByte[0] == credentials[user].rfid[0]) && (rfid.uid.uidByte[1] == credentials[user].rfid[1]) && (rfid.uid.uidByte[2] == credentials[user].rfid[2]) && (rfid.uid.uidByte[3] == credentials[user].rfid[3])) { //cambiar por credenciales
                    
               if ((rfid.uid.uidByte[0] == credentials[0].rfid[0]) && (rfid.uid.uidByte[1] == credentials[0].rfid[1]) && (rfid.uid.uidByte[2] == credentials[0].rfid[2]) && (rfid.uid.uidByte[3] == credentials[0].rfid[3])) { //cambiar por credenciales
                   
                    
                    lcd.clear ();
                    lcd.setCursor(0,0); lcd.print("Abrir puerta");
                    delay(1000);
                    lcd.clear ();
                }

                else{
                    // if(user == (sizeof(credentials) / sizeof(USERCREDENTIALS)-1)){ //cambiar por credential, usarios credenciales
                       lcd.clear ();
                       lcd.setCursor(0,0); lcd.print("Tag inexistente");
                       delay(1000);
                       lcd.clear ();
                   // }
                }
           // }

      // Terminamos la lectura de la tarjeta  actual
           rfid.PICC_HaltA();
        
          // Stop encryption on PCD
          rfid.PCD_StopCrypto1();
            
}


void guardar_tag(){

    
        // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return;

    for (byte j = 0; j < 4; j++) {
         credentials[0].rfid[j] = rfid.uid.uidByte[j];
    }
    
     lcd.clear ();
     lcd.setCursor(0,0); lcd.print("save");
     delay(1000);
     lcd.clear();


      // Terminamos la lectura de la tarjeta  actual
           rfid.PICC_HaltA();
        
          // Stop encryption on PCD
          rfid.PCD_StopCrypto1();
          
}

I have a problem, when user push asterisk (to keep the tag in the system) program exits quickly condition since it does not read any card

    if(Tecla == '*'){ //If the push asterisk user, keep the tag in the system
        guardar_tag();
           
}

Even if I have the card near the rfid reader, the system exits fast since everything goes too fast and the reader does not give you time to read the card.

Only once managed to keep the code card in the system.

How do I get the system to wait some time to read a tag, without getting out of the condition?

By please help

(translate.google)

How do I get the system to wait some time to read a tag, without getting out of the condition?

The question does not make a lot of sense. If the one function in the body of the statement does not way for a tag, make it wait. Of course "the condition" is going to send as soon as that function returns.

I'm guessing that you didn't write that code. Most of it is crap. instead of all the negative stuff that function does, it should only do something if there is something to do. The entire logic structure of that function is backwards. If the function acted on when there was a tag present, you could easily wrap the code in a while statement, to make it wait forever, or for some maximum time, for a tag to be scanned. As is, the function needs a complete re-write.

PaulS:
As is, the function needs a complete re-write.

Hello, what happens is I'm doing a program for a system access control.

Where the user wants to enter the place, needs a tag, to bring the reader rfid tag, the system validates if the user exists or not.

On the other hand, the system has a menu of "User" and "Administrator" and to access the menu, push a button and followed the user enters his password.

The administrator has the option to add a new card in the system.
In this part is where I have problems. Since the condition runs too fast and not gives you time to verify if there is a card or not. And as a result is out of the system.

Attached a picture of the logic of the system, which is in yellow what is me is giving problems since the program run very fast that condition

Thank you very much for your help.

That USERCREDENTIALS looks a lot like the one that I presented in as you would make a user login system for access control system? example please.

Note: when you update code, update the comments as well !!

I think the problem is that leer_usuario() does not return a value (e.g. true or false) so in loop() you can't check if a card was present or not.

/*
  read a card
  returns:
    true if a card was read, else false
*/
bool leer_usuario()
{
  // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return false;

  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return false;

  ...
  ...
  
  // Terminamos la lectura de la tarjeta  actual
  rfid.PICC_HaltA();

  // Stop encryption on PCD
  rfid.PCD_StopCrypto1();


  return true;
}

And something that you need to learn is separation of functionalities; leer_usuario() is there to read a card, not to display information on a lcd as well (that can be done in e.g. loop().

In loop() you can now check if a card was read

  int Tecla = kpd.getKey();

  //If the reader reads a tag, check the system if it exists or not.
  if ( leer_usuario() == true)
  {
    // display the tag information on the lcd
    ...
    ...

    //If the push asterisk user, keep the tag in the system
    if (Tecla == '*')
    {
      guardar_tag();
    }
  }

I'm not familiar with the MFRC library so I don't now if it can read a tag while you're waiting for your keypad. It would however make sense to me to only read the keypad when needed, so after displaying the tag information in the above part of loop().

sterretje:
That USERCREDENTIALS looks a lot like the one that I presented in as you would make a user login system for access control system? example please.

Hello it is my other account, is that me I forgot the password, hope to regain it soon.

With respect to the program, I can save a TAG in the arrangement and also the system reads.

Following code:

#include <SPI.h>
#include <MFRC522.h>
#include <EEPROM.h>
#include <Keypad.h>
#include <LiquidCrystal.h>




#define SS_PIN 53
#define RST_PIN 9

MFRC522 rfid(SS_PIN, RST_PIN);   // Configura los pines RST y SS del mrfc522

MFRC522::MIFARE_Key key; 





///////////////////////LCD///////////////////////////////////////

//Incializa la libreria con los numeros de pines a interactuar el LCD
LiquidCrystal lcd(A8, A9, A10, A11, A12, A13);

///////////////////////////////////////////////////////////////////


//////////////Teclado/////////////////////////////////////////////

//Definición de filas y columnas
const byte Filas = 4; //Cuatro filas
const byte Cols = 4; //Cuatro columnas

//Definición de los pines
byte Pins_Filas[] = {37, 35, 33, 31}; //Pines Arduino para las filas
byte Pins_Cols[] =  {29, 27, 25, 23}; // Pines Arduino para las columnas


//Definición de las teclas
char Teclas [ Filas ][ Cols ] =
{
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//Se crea una instancia llamada Teclado1 y el cual asignara las teclas que tenemos en el arreglo "Teclas" y le decimos
//que se han conectados los pines de las filas y columnas


Keypad kpd = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas, Cols);


char Teclado ()
{
  do{
    
   char Tecla = kpd.getKey();
   
    if (Tecla != NO_KEY)
    {
      return Tecla;
    } 
  } while (1);
}

/////////////////////////////////////////////////////////////////////////////////////////

#define CREDENTIALSOFFSET  11


struct USERCREDENTIALS
{
  // space for 9 character id and terminating nul character
  char id[6];
  // space for 15 character password and terminating nul character
  char pwd[10];
  byte rfid[3];
} usercredential;

// array with user credentials
USERCREDENTIALS credentials[15];



char  contrasena_ingresada[6];
char  contrasena_tecleada[10];
char  contrasena_tecleada1[10];

boolean A = LOW; 



void setup() {
  // put your setup code here, to run once:
  lcd.begin(20, 4); //Configura el LCD con el numero de columas y filas. Para un LCD 16x4: 16 columnas y 4 filas.
  lcd.display(); //Enciende el display

  SPI.begin();               // Incializa la comunicacion SPI 
  rfid.PCD_Init(); // Init MFRC522
  
}

void loop() {
  
int estado;
int user;

//para llenar las primeras posiciones de datos
for(int i=0; i<11; i++){
  EEPROM.write(i, 1);
}


    for (byte i = 0; i < 6; i++) {
      key.keyByte[i] = 0xFF;
    }

   lcd.clear();
   lcd.setCursor(0,0);lcd.print("Modo lectura");   //Imprime en la LCD
   lcd.setCursor(3,3);lcd.print("Presione *");   //Imprime en la LCD
   int Tecla = kpd.getKey();

   leer_usuario();

        
    if(Tecla == '*'){

           guardar_tag();
             
      }       
}

}




bool leer_usuario(){


   // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return false;

  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return false;


   //for(int user=0; user < sizeof(credentials) / sizeof(USERCREDENTIALS); user ++){ 
    
                //if ((rfid.uid.uidByte[0] == credentials[user].rfid[0]) && (rfid.uid.uidByte[1] == credentials[user].rfid[1]) && (rfid.uid.uidByte[2] == credentials[user].rfid[2]) && (rfid.uid.uidByte[3] == credentials[user].rfid[3])) { 
                    
               if ((rfid.uid.uidByte[0] == credentials[0].rfid[0]) && (rfid.uid.uidByte[1] == credentials[0].rfid[1]) && (rfid.uid.uidByte[2] == credentials[0].rfid[2]) && (rfid.uid.uidByte[3] == credentials[0].rfid[3])) {
                   
                    
                    lcd.clear ();
                    lcd.setCursor(0,0); lcd.print("Open door");
                    delay(1000);
                    lcd.clear ();
                }

                else{
                    // if(user == (sizeof(credentials) / sizeof(USERCREDENTIALS)-1)){ //cambiar por credential, usarios credenciales
                       lcd.clear ();
                       lcd.setCursor(0,0); lcd.print("Tag inexistente");
                       delay(1000);
                       lcd.clear ();
                   // }
                }
           // }

      // Terminamos la lectura de la tarjeta  actual
           rfid.PICC_HaltA();
        
          // Stop encryption on PCD
          rfid.PCD_StopCrypto1();
            
}


void guardar_tag(){

    
        // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent()){

  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial()){


    for (byte j = 0; j < 4; j++) {
         credentials[0].rfid[j] = rfid.uid.uidByte[j];
    }
    
     lcd.clear ();
     lcd.setCursor(0,0); lcd.print("guardado");
     delay(1000);
     lcd.clear();


      // Terminamos la lectura de la tarjeta  actual
           rfid.PICC_HaltA();
        
          // Stop encryption on PCD
          rfid.PCD_StopCrypto1();

  }

  }
          
}

This version of code worked well because you add a zero in credentials

credentials[0].rfid[j] = rfid.uid.uidByte[j];
 if ((rfid.uid.uidByte[0] == credentials[0].rfid[0]) && (rfid.uid.uidByte[1] == credentials[0].rfid[1]) && (rfid.uid.uidByte[2] == credentials[0].rfid[2]) && (rfid.uid.uidByte[3] == credentials[0].rfid[3])) {

By which the system is makes it easy search, the downside is only 1 tag you can save. So I did the next version

It attached in a file

The file that attach works correctly, I can save up to 2 tags. And the system when it enters mode reading read them well.

The problem starts is that when I pressed asterisks (and do not approach any card) execute the "guardar_tag" condition. And when the system exits and enters mode reading (at the beginning of the loop void loop) approached a card and execute condition "open door" (without existing in the system)

also attached the logic of the system in an image

(Already almost works my programming but not is if this polluting the arrangement or is giving problems the condition "guardar_tag")

Please help

(Sorry for the English, I use google translator)

Help.ino (5.37 KB)

sterretje:
I think the problem is that leer_usuario() does not return a value (e.g. true or false) so in loop() you can't check if a card was present or not.

/*

read a card
 returns:
   true if a card was read, else false
*/
bool leer_usuario()
{
 // Look for new cards
 if ( ! rfid.PICC_IsNewCardPresent())
   return false;

// Verify if the NUID has been readed
 if ( ! rfid.PICC_ReadCardSerial())
   return false;

...
 ...
 
 // Terminamos la lectura de la tarjeta  actual
 rfid.PICC_HaltA();

// Stop encryption on PCD
 rfid.PCD_StopCrypto1();

return true;
}

My programming suits my project; I did all what you I said that made and operates a 99%; already I could save a new tag, the system recognizes the label and takes the decision of open or not the door.

Only I have a problem, and they are the 'return'

For function leer_usuario() leave it exactly same as you told me.
Change the function to "bool" and put the corresponding 'return'.

But for the feature that saves a tag:

bool save_tag(){

 //Verifica si hay una nueva tarjeta
              if ( ! rfid.PICC_IsNewCardPresent()){
                
                   //Verifica si el ID se ha leido            
                   if ( ! rfid.PICC_ReadCardSerial()){


                        for (byte j = 0; j < 4; j++) {
                             credenciales[user].rfid[j] = rfid.uid.uidByte[j];
                        }


    
                       lcd.clear ();
                       lcd.setCursor(0,0); lcd.print("guardado");
                       delay(1000);
                       lcd.clear();


                    // Terminamos la lectura de la tarjeta  actual
                         rfid.PICC_HaltA();
        
                  // Detiene la  encryptacion on PCD
                  rfid.PCD_StopCrypto1();

                  return true;
}

you remove the "return"

  if ( ! rfid.PICC_IsNewCardPresent()){
                
               
   if ( ! rfid.PICC_ReadCardSerial()){

Because at the time the user enters the menu, followed choose the option Save label, the system does not allow to enter the condition.

However if I remove the return if you allow to enter the condition, so a new tag can be stored.

at the end I put a return true

 // Detiene la  encryptacion on PCD
                  rfid.PCD_StopCrypto1();

                  return true;

The only problem I get is that when you save a tag, and returns to the beginning and the reader reads the tag to save the rfid reader is frozen.

And to unfreeze I have to put a different card into the reader.

After placing a different card, thawed and can read the card that was saved in the system.