Problema con dos RFID

Hola a todos. Llevo días buscando información para resolver el problema que tengo con mi proyecto de Arduino UNO pero no soy capaz de dar con ello.
El objetivo es que cuando se coloque la tarjeta A en el lector rfid A y la B en el lector B, se active un relé (que desactiva una cerradura electromagnética). En un principio iban a ser tres, pero a veces uno de los sensores dejaba de funcionar (unas veces uno y otras otro...), otras se congelaba, etc.
Resumiendo: al cabo de un rato el programa se reinicia (por el watchdog, antes de este simplemente se quedaba pillado) y no entiendo el porqué. Si alguien sabe qué pasa o se le ocurre alguna solución, agradezco cualquier comentario.

Por cierto, la idea es que se desactive el electroimán unos segundos y después se bloquee de nuevo, pero las tarjetas se quedan en los lectores, de ahí la variable "unavez". Y no adjunto el esquema porque no creo que sea el problema ya que en un primer momento funciona, es al cabo de unos 30-40 minutos cuando empieza a bloquearse.

#include <SPI.h>   //Incluye las librerías
#include <MFRC522.h> 
#include <avr/wdt.h>                                    

#define RST_PIN 9   //Define el pin que va a RST
#define PIN_A 10    //Define el pin que va a SDA del lector A
#define PIN_B 8   //Define el pin que va a SDA del lector B

#define Rele 2  //Rele normalmente cerrado conectado al pin 2 que activa(LOW)/desactiva(HIGH) un electroimán

byte TARJETA_A[4] = {0x37, 0x01, 0x11, 0x3C};   //Código de la TARJETA_A
byte TARJETA_B[4] = {0x8B, 0x7C, 0xD7, 0x10};  //Código de la TARJETA_B
byte Lectura_A[4];            
byte Lectura_B[4];         

bool verifica_A = false;   //Verifica si la tarjeta A es la correcta 
bool verifica_B = false;   //Verifica si la tarjeta B es la correcta
bool unavez = false;       //Solo permite ejecutarlo una vez (a menos que se intercambien las tarjetas y se vuelvan a colocar correctamente)

byte ssPins[] = {PIN_A, PIN_B};     

MFRC522 mfrc522[2];     



void setup()
{
    
  wdt_disable();  //Desactiva el watchdog mientras se configura, para que no se resetee
  wdt_enable(WDTO_8S);  //Configura el watchdog en 8 segundos

  Serial.begin(9600);
  SPI.begin();                                                             

  for (uint8_t reader = 0; reader < 2; reader++) {      
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN);
    Serial.print(F("Lector "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();
  }

  pinMode(Rele, OUTPUT);                     
  digitalWrite(Rele, LOW);             

}



void loop()
{

  wdt_reset(); //Actualiza el watchdog para que no produzca un reinicio

  if (mfrc522[0].PICC_IsNewCardPresent()){   //Se activa cuando una nueva tarjeta es puesta en el lector A (el 0)
    Serial.println("Lector A: ");  

    if(mfrc522[0].PICC_ReadCardSerial()){ //Selecciona una tarjeta nueva
      for(byte i=0; i<mfrc522[0].uid.size;i++){  //Bucle recorre todo el UID,
        if(mfrc522[0].uid.uidByte[i]<0x10){  //si el byte leído es menor a 0x10
          Serial.print(" 0");  //imprime espacio en blanco y numero cero,
        }else{  //si no,
          Serial.print(" ");  //imprime espacio en blanco
        }
        Serial.print(mfrc522[0].uid.uidByte[i], HEX);  //Imprime el byte del UID leído hexadecimal
        Lectura_A[i]=mfrc522[0].uid.uidByte[i];  //Almacena en array el byte del UID leido
        
        if(Lectura_A[i] != TARJETA_A[i]){   //Si el valor que se ha guardado al leer la tarjeta de A es distinto a la clave para A,
          verifica_A=false;  //la variable que verifica A vuelve a ser falsa
          unavez=false;  //y devuelve la variable unavez a falsa para que se pueda ejecutar el verificable
        }else{verifica_A=true;}  //Si no hay diferencias en la comprobación, la verificación de A es correcta y continúa  
    
      }

      Serial.println("\t");
      mfrc522[0].PICC_HaltA();  //Detiene la comunicación con la tarjeta

    }

  }

  if (mfrc522[1].PICC_IsNewCardPresent()){   //Se activa cuando una nueva tarjeta es puesta en el lector B (el 1)
    Serial.println("Lector B: "); 
    
    if(mfrc522[1].PICC_ReadCardSerial()){  //Selecciona una tarjeta nueva
      for(byte i=0; i<mfrc522[1].uid.size;i++){   //Bucle recorre todo el UID,
        if(mfrc522[1].uid.uidByte[i]<0x10){  //si el byte leído es menor a 0x10
          Serial.print(" 0");  //imprime espacio en blanco y numero cero,
        }else{   //si no,
          Serial.print(" ");   //imprime espacio en blanco
        }
        Serial.print(mfrc522[1].uid.uidByte[i], HEX);  //Imprime el byte del UID leído hexadecimal
        Lectura_B[i]=mfrc522[1].uid.uidByte[i]; //Almacena en array el byte del UID leido

        if(Lectura_B[i] != TARJETA_B[i]){ //Si el valor que se ha guardado al leer la tarjeta de B es distinto a la clave para B,
          verifica_B=false;    //la variable que verifica B vuelve a ser falsa
          unavez=false; //y devuelve la variable unavez a falsa para que se pueda ejecutar el verificable
        }else{verifica_B=true;}   //Si no hay diferencias en la comprobación, la verificación de B es correcta y continúa
 
      }
  
    Serial.println("\t");                                            
    mfrc522[1].PICC_HaltA();  //Detiene la comunicación con la tarjeta
    
    }
    
  }
  
  if(verifica_A==true && verifica_B==true && unavez==false){ //Si verifica que A y B son correctas y unavez es falsa (no se ha dado por correcto el código aún),
    Serial.println("CÓDIGO CORRECTO"); 
    digitalWrite(Rele, HIGH); //Activa el relé para que se desactive el electroimán
    for(int x=0; x<200; x++){ //bucle de espera para que el watchdog no reinicie
      wdt_reset();   //Actualiza el watchdog para que no produzca un reinicio
      delay(100);
    }
    digitalWrite(Rele, LOW);  //Desactiva el relé para que se active el electroimán
    unavez=true;   //Cambia unavez a verdadero puesto que ya ha mostrado el código una vez (se resetea cambiando tarjetas de sitio)
    }

}

:warning:
Código corregido

Tu publicación fue ** MOVIDA ** a su ubicación actual ya que es más adecuada.

¿Podría también tomarse unos minutos para Aprenda a usar el foro .

Vale, gracias. Es mi primera publicación y no me manejo muy bien en inglés :sweat_smile:

Moderador:
Justamente si escribes en español debes hacerlo en el foro en español.
Si publicas en el foro en inglés debes usar ingles y no español.

Si usas electroimanes debes alimentados obviamente con DC debes poner un diodo en antiparalelo. Diodo con cátodo al positivo del electroimán y ánodo al borne mas negativo del mismo electroimán.
Eso evitará problemas en la línea y posibles reinicios del arduino.

Analizaré tu código y luego te respondo.

1 Like

Hola, gracias por la respuesta.

El electroimán va a un relé que está conectado al pin 2 del arduino. Cuando el Arduino quiere trabajar, el electroimán se desactiva correctamente. Cuando se pilla, el electroimán se queda activo si se ha colgado antes de pasar las tarjetas y desactivado si se pilla después.

De todas formas, de alimentación no creo que sea, pues hace lo mismo aunque lo conecte por usb.

Insisto. Como alimentas el electroimán? Lo activas con un Relé. Y el electroimán que fuente usa?

Una fuente de 12V 0,5mAh. El electroimán me pide de 0,3 a 0,6mAh a 12V

Y cuando pasa esto, durante la acción del eletroiman o en un cambio de él.

Es realmente aleatorio. Por lo general, se pilla después de pasar las tarjetas. Pero hay veces que algún lector dejaba de funcionar antes de hacer nada o algún otro fallo del estilo. Es más, antes tenía 3 lectores (mismo código pero con uno más) y ahí sí que era un caos, algún lector dejaba de ir (unas veces uno, otras otro, sin mucho sentido).

Prueba este código a ver si funciona bien o repite los problemas.

#include <SPI.h>   //Incluye las librerías
#include <MFRC522.h> 
#include <avr/wdt.h>                                    

#define RST_PIN 9   //Define el pin que va a RST
#define PIN_A 10    //Define el pin que va a SDA del lector A
#define PIN_B 8   //Define el pin que va a SDA del lector B

#define Rele 2  //Rele normalmente cerrado conectado al pin 2 que activa(LOW)/desactiva(HIGH) un electroimán

byte TARJETA_A[4] = { 0x37, 0x01, 0x11, 0x3C };   //Código de la TARJETA_A
byte TARJETA_B[4] = { 0x8B, 0x7C, 0xD7, 0x10 };  //Código de la TARJETA_B
byte Lectura_A[4];
byte Lectura_B[4];

bool verifica_A   = false;   //Verifica si la tarjeta A es la correcta 
bool verifica_B   = false;   //Verifica si la tarjeta B es la correcta
bool unavez       = false;       //Solo permite ejecutarlo una vez (a menos que se intercambien las tarjetas y se vuelvan a colocar correctamente)
byte estado       = 0;

byte ssPins[] = { PIN_A, PIN_B };

MFRC522 mfrc522[2];



void setup() {

   //wdt_disable();  //Desactiva el watchdog mientras se configura, para que no se resetee
   //wdt_enable(WDTO_8S);  //Configura el watchdog en 8 segundos

   Serial.begin(9600);
   SPI.begin();

   for (uint8_t reader = 0; reader < 2; reader++) {
      mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN);
      Serial.print(F("Lector "));
      Serial.print(reader);
      Serial.print(F(": "));
      mfrc522[reader].PCD_DumpVersionToSerial();
   }
   pinMode(Rele, OUTPUT);
   digitalWrite(Rele, LOW);
}



void loop() {
   //wdt_reset(); //Actualiza el watchdog para que no produzca un reinicio

   if (mfrc522[0].PICC_IsNewCardPresent()) {   //Se activa cuando una nueva tarjeta es puesta en el lector A (el 0)
      Serial.println("Lector A: ");

      if (mfrc522[0].PICC_ReadCardSerial()) { //Selecciona una tarjeta nueva
         for (byte i = 0; i < mfrc522[0].uid.size;i++) {  //Bucle recorre todo el UID,
            if (mfrc522[0].uid.uidByte[i] < 0x10) {  //si el byte leído es menor a 0x10
               Serial.print(" 0");  //imprime espacio en blanco y numero cero,
            }
            else {  //si no,
               Serial.print(" ");  //imprime espacio en blanco
            }
            Serial.print(mfrc522[0].uid.uidByte[i], HEX);  //Imprime el byte del UID leído hexadecimal
            Lectura_A[i] = mfrc522[0].uid.uidByte[i];  //Almacena en array el byte del UID leido

            if (Lectura_A[i] != TARJETA_A[i]) {   //Si el valor que se ha guardado al leer la tarjeta de A es distinto a la clave para A,
               verifica_A = false;  //la variable que verifica A vuelve a ser falsa
               unavez = false;  //y devuelve la variable unavez a falsa para que se pueda ejecutar el verificable
            }
            else { verifica_A = true; }  //Si no hay diferencias en la comprobación, la verificación de A es correcta y continúa  
         }
         Serial.println("\t");
         mfrc522[0].PICC_HaltA();  //Detiene la comunicación con la tarjeta
      }
   }

   if (mfrc522[1].PICC_IsNewCardPresent()) {   //Se activa cuando una nueva tarjeta es puesta en el lector B (el 1)
      Serial.println("Lector B: ");

      if (mfrc522[1].PICC_ReadCardSerial()) {  //Selecciona una tarjeta nueva
         for (byte i = 0; i < mfrc522[1].uid.size;i++) {   //Bucle recorre todo el UID,
            if (mfrc522[1].uid.uidByte[i] < 0x10) {  //si el byte leído es menor a 0x10
               Serial.print(" 0");  //imprime espacio en blanco y numero cero,
            }
            else {   //si no,
               Serial.print(" ");   //imprime espacio en blanco
            }
            Serial.print(mfrc522[1].uid.uidByte[i], HEX);  //Imprime el byte del UID leído hexadecimal
            Lectura_B[i] = mfrc522[1].uid.uidByte[i]; //Almacena en array el byte del UID leido

            if (Lectura_B[i] != TARJETA_B[i]) { //Si el valor que se ha guardado al leer la tarjeta de B es distinto a la clave para B,
               verifica_B = false;    //la variable que verifica B vuelve a ser falsa
               unavez = false; //y devuelve la variable unavez a falsa para que se pueda ejecutar el verificable
            }
            else { 
               verifica_B = true; 
            }   //Si no hay diferencias en la comprobación, la verificación de B es correcta y continúa
         }

         Serial.println("\t");
         mfrc522[1].PICC_HaltA();  //Detiene la comunicación con la tarjeta
      }
   }

   //Si verifica que A y B son correctas y unavez es falsa (no se ha dado por correcto el código aún),
   if (verifica_A && verifica_B && unavez ) {
      switch(estado) {
      case 0:  Serial.println("CÓDIGO CORRECTO");
               digitalWrite(Rele, HIGH); //Activa el relé para que se desactive el electroimán
               estado = 1;
               contador = 0;
               t = millis();
               break;
      case 1:  if (millis() - t > 100UL) {
                  if (contador++ >= 200) {
                     estado = 2;
                  }
                  t = millis();
               }
               break;
      case 2: unavez == false;
              digitalWrite(Rele, LOW);
              break;
      }
   }
}

Este código pretende eliminar el super delay 200x100 = 20 segundos que metes para dejar el rele en 1, durante ese tiempo nada funciona.

EDITO: Como alimentas los lectores? Fuente de qué corriente?
Revisa esa parte.
Me parece que esta faltando energia a algun lector o al conjunto todo.

Muchas gracias por el código, ahora aguanta un poco más, pero después de 1h30m (apox) dejó de funcionar el lector A. Las luces de ambos estaban encendidas.

La fuente del Arduino es de 9v600mAh. La del electroimán es de 12v400mAh (te dije 0,5 pero me equivoqué). El electroimán funciona con normalidad, se enciende bien, con fuerza y sin altas temperaturas.

Los lectores van ambos al pin de 3.3v del Arduino UNO.

He añadido estas líneas de código para ver exactamente dónde se pilla. Ahora sé que es el relé pero no tengo ni la menor idea de cómo arreglarlo. Ahí es donde se reinicia.

if(verifica_A==true && verifica_B==true && unavez==false){                      //Si verifica que A y B son correctas y unavez es falsa (no se ha dado por correcto el código aún),
    Serial.println("CÓDIGO CORRECTO");                                            //imprime "Código correcto"        
    digitalWrite(Rele, HIGH);                                                     //Activa el relé para que deje de pasar corriente y se abra la cerradura electromagnética
    Serial.println("Relé desactivado");
    Serial.print("Espera: ");
    for(int x=0; x<100; x++){
      delay(100);
      if((x%10)==0){
        Serial.print(x/10);
        Serial.print("");
      }
      wdt_reset();                                                                //Actualiza el watchdog para que no produzca un reinicio
    }
    digitalWrite(Rele, LOW);                                                      //Desactiva el relé para que vuelva a pasar corriente y se cierre la cerradura electromagnética
    Serial.println(" ");
    Serial.println("Relé desactivado");
    unavez=true;                                                                  //Cambia unavez a verdadero puesto que ya ha mostrado el código una vez (se resetea cambiando tarjetas de sitio)
  }

Pero te lo he dicho. Debes poner un diodo en antiparalelo.
El rele se opone a la desconexión, genera un pico de tensión inversa. Ese pico de tensión inversa actua como una fuente de ruido que se propaga por todos lados.
Coloca un diodo como te dije varios post antes. Post#4 mira que manera de dar vueltas.
SI lo haces y aun continua entonces miraremos otra cosa, pero por ahora es el principal culpable porque siempre es el.

Y si te fijas yo quité todos los wathdog porque nada tienen que ver.

1 Like

El electroimán estaría en la parte de arriba (cables rojo y negro), la fuente es la que viene de la derecha y, obviamente, los otros 3 cables que van al relé son para el Arduino.

Entiendo que es así como se coloca. Pero no estoy muy seguro, los esquemas que veo por internet son un poco contradictorios. Lo conecté en base a tus explicaciones anteriores.

Por cierto, ya sé que parece que el cable que viene de fuente está mal y el que he puesto como positivo es negativo y viceversa. Pero es correcto, fue a la hora de soldarlos que los coloqué al revés, de ahí el color :sweat_smile:

Si está bien conectado, ese no es el problema pues me sigue dando el mismo fallo. De estar mal conectado, dímelo, porfa.

Esta mal conectado.
Te dije que lo pongas en bornes del electroimán y lo estas colocando en bornes del interruptor (relé), eso así no funciona como se espera.
image

El esquema que te pongo es el de un relé, así que no te confundas. Intento mostrarte eso como si fuera la bobina del electroimán y el transitor una llave (el interruptor NO de tu relé).

1 Like

Sigue sin funcionar.

Lo conecté primero entre los pines que van a la bobina y se pillaba al cabo de un tiempo, aunque iba muchísimo mejor. Pero buscando por el foro, encontré un hilo con un problema parecido (en el que de hecho fuiste tú el que le propuso mover el diodo).

Adjunto el esquema que encontré en el que me he basado (la única diferencia es que la alimentación de la bobina va al Arduino y no a la misma fuente de la cerradura, por lo demás es igual).

Al principio parece que quiere funcionar, pero al cabo de unos minutos se pilla de nuevo. He probado con varias cerraduras, por si el dato sirviera de algo.

¿Y no será falta de corriente para los lectores o exceso de ruido en los lectores? ten en cuenta también que los lectores generan un campo electromagnético importante para alimentar la antena RFID y dices que los alimentas desde la patilla de 3v3 del ESP¿?
El ESP está enjaulado? (jaula de Farady me refiero).

Saludos.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.