Attendre retrait du tag RFID avant reprise du loop

Bonjour (ça faisait longtemps !),

J’ai un petit problème, mais je suis sûr que vous allez me trouver la solution en moins de 2 secondes. Je sens que c’est pas compliqué ! Mais pas moyen de trouver la solution seul…

Voilà ma situation : j’ai un lecteur RFID qui actionne une gâche électrique quand le bon tag RFID est présenté. Mais vu que, me semble-t-il, il ne faut pas laisser les gâches électriques sous tension trop longtemps (vous confirmez ?), j’ai mis un delay(10000) pour que la gâche se referme au bout de 10s.
Sauf que, vu que le tag RFID qui active le mécanisme se pose sur le lecteur, la gâche est de nouveau mise sous tension à chaque loop ce qui donne : “tag détecté => ouverture gache => 10s => fermeture gâche => ouverture gâche => 10s etc…” Alors que je souhaiterais que, tant que le tag est posé sur le lecteur, l’ouverture de la gâche ne se ré-enclenche pas.
Là-aussi j’ai essayé quelque chose : lorsque mon tag est détecté, je passe une variable “valid=0” à “valid=1” et j’inclus “valid=0” aux conditions pour que la gâche s’ouvre. Jusque là ça fonctionne.
Mais ce n’est pas fini puisque il faudrait que je puisse de nouveau ouvrir ma gâche une fois qu’elle s’est refermée. Pour ça, il me faudrait remettre la variable “valid” à 0 quand le tag est retiré du lecteur.
C’est cette dernière action que je ne parviens pas à réaliser.
Vous pouvez m’aider ? (siouplé)

Mon code :

//RFID Solenoid Lock

#include <SPI.h>
#include <MFRC522.h>
 
#define SS_PIN 3
#define RST_PIN 8
#define RELAY A0 //relay pin
#define ACCESS_DELAY 2000
#define DENIED_DELAY 1000
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
int valid = 0;
 
void setup() 
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();          // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  pinMode(RELAY, OUTPUT);
  digitalWrite(RELAY, LOW);
  Serial.println("Put your card to the reader...");
  Serial.println();

}
void loop() 
{
  String readRFID = "";
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "11 C4 25 D9" && valid == 0) //change here the UID of the card/cards that you want to give access
  {
    Serial.println("Authorized access");
    Serial.println();
    delay(500);
    digitalWrite(RELAY, HIGH);
    delay(10000);
    digitalWrite(RELAY, LOW);
    valid = 1;
    Serial.println("valid=1");

  }
   
}

}

Je ne connais pas trop ces lecteurs, mais ici

  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }

tu détectes qu'il n'y a pas de tag sur lecteur, non ?

Je t'avoue que je ne maîtrise pas non plus cette bibliothèque. J'ai beaucoup pompé sur des codes trouvés ci et là.
Mais à mon avis, ça détecte si un nouveau tag est présenté devant le lecteur.
De plus, le problème n'est pas tant de savoir comment lui faire détecter l'absence der tag, mais plus de le faire en ajoutant une "durée de détection" car sinon, une micro-perte de signal va me mettre le bazar. Il faudrait qu'il y ait une condition "absence de tag pendant 2 secondes".

FoNeTiK47:
Je t'avoue que je ne maîtrise pas non plus cette bibliothèque. J'ai beaucoup pompé sur des codes trouvés ci et là.
Mais à mon avis, ça détecte si un nouveau tag est présenté devant le lecteur.
De plus, le problème n'est pas tant de savoir comment lui faire détecter l'absence der tag, mais plus de le faire en ajoutant une "durée de détection" car sinon, une micro-perte de signal va me mettre le bazar. Il faudrait qu'il y ait une condition "absence de tag pendant 2 secondes".

Bonsoir
si j'ai bien compris ton problème
il suffit de remplacer dans ton programme

Serial.println("Authorized access");
par
Serial.println("Authorized access");
mfrc522.PICC_HaltA(); // Halt PICC

Alors , tel quel, ça ne fonctionne pas. Mais sinon, tu peux m'expliquer ce que tu espérais avec ce Halt ? A quoi ça sert ? Je peux peut-être l'adapter...

Je reprends mon message #1, je pense que c'est dans ce bloc, qui ne contient pour l'instant qu'un return, qu'il faut remettre ton drapeau à 0

Je fais le test dans quelques minutes mais à mon avis, ça ne va pas marcher. Quand je regardais ce qu'il se passait sur ma liaison série, je voyais que le lecteur RFID perdait l'info du tag pendant quelques fractions de secondes. Même si le tag restait posé immobile sur le lecteur. Ça risque de fausser l'état de mon flag.

Arf, je me suis planté en vous recopiant mon code, c’est pas celui que j’utilise.
Voilà le bon :

// DEFINES
// Provides debugging information over serial connection if defined
#define DEBUG

// LIBRARIES
// Standard SPI library comes bundled with the Arduino IDE
#include <SPI.h>
// Download and install from https://github.com/miguelbalboa/rfid
#include <MFRC522.h>

// CONSTANTS
int valid =0;
// The number of RFID readers
const byte numReaders = 2;
// Each reader has a unique Slave Select pin
const byte ssPins[] = {3, 4,};
// They'll share the same reset pin
const byte resetPin = 8;
// This pin will be driven LOW to release a lock when puzzle is solved
const byte lockPin = A0;
// The sequence of NFC tag IDs required to solve the puzzle
const String correctIDs[] = {"11c425d9", "89c124d9"};

// GLOBALS
// Initialise an array of MFRC522 instances representing each reader
MFRC522 mfrc522[numReaders];
// The tag IDs currently detected by each reader
String currentIDs[numReaders];


/**
 * Initialisation
 */
void setup() {

  #ifdef DEBUG
  // Initialise serial communications channel with the PC
  Serial.begin(9600);
  Serial.println(F("Serial communication started"));
  #endif
  
  // Set the lock pin as output and secure the lock
  pinMode(lockPin, OUTPUT);
  digitalWrite(lockPin, LOW);
  
  // Initialise the SPI bus
  SPI.begin();

  for (uint8_t i=0; i<numReaders; i++) {
  
    // Initialise the reader
    // Note that SPI pins on the reader must always be connected to certain
    // Arduino pins (on an Uno, MOSI=> pin11, MISO=> pin12, SCK=>pin13)
    // The Slave Select (SS) pin and reset pin can be assigned to any pin
    mfrc522[i].PCD_Init(ssPins[i], resetPin);
    
    // Set the gain to max - not sure this makes any difference...
    // mfrc522[i].PCD_SetAntennaGain(MFRC522::PCD_RxGain::RxGain_max);
    
	#ifdef DEBUG
    // Dump some debug information to the serial monitor
    Serial.print(F("Reader #"));
    Serial.print(i);
    Serial.print(F(" initialised on pin "));
    Serial.print(String(ssPins[i]));
    Serial.print(F(". Antenna strength: "));
    Serial.print(mfrc522[i].PCD_GetAntennaGain());
    Serial.print(F(". Version : "));
    mfrc522[i].PCD_DumpVersionToSerial();
	#endif
    
    // Slight delay before activating next reader
    delay(100);
  }
  
  #ifdef DEBUG
  Serial.println(F("--- END SETUP ---"));
  #endif
}

/**
 * Main loop
 */
void loop() {

  // Assume that the puzzle has been solved
  boolean puzzleSolved = true;

  // Assume that the tags have not changed since last reading
  boolean changedValue = false;

  // Loop through each reader
  for (uint8_t i=0; i<numReaders; i++) {

    // Initialise the sensor
    mfrc522[i].PCD_Init();
    
    // String to hold the ID detected by each sensor
    String readRFID = "";
    
    // If the sensor detects a tag and is able to read it
    if(mfrc522[i].PICC_IsNewCardPresent() && mfrc522[i].PICC_ReadCardSerial()) {
      // Extract the ID from the tag
      readRFID = dump_byte_array(mfrc522[i].uid.uidByte, mfrc522[i].uid.size);
    }
    
    // If the current reading is different from the last known reading
    if(readRFID != currentIDs[i]){
      // Set the flag to show that the puzzle state has changed
      changedValue = true;
      // Update the stored value for this sensor
      currentIDs[i] = readRFID;
    }
    
    // If the reading fails to match the correct ID for this sensor 
    if(currentIDs[i] != correctIDs[i]) {
      // The puzzle has not been solved
      puzzleSolved = false;
    }

    // Halt PICC
    mfrc522[i].PICC_HaltA();
    // Stop encryption on PCD
    mfrc522[i].PCD_StopCrypto1(); 
  }

  #ifdef DEBUG
  // If the changedValue flag has been set, at least one sensor has changed
  if(changedValue){
    // Dump to serial the current state of all sensors
    for (uint8_t i=0; i<numReaders; i++) {
      Serial.print(F("Reader #"));
      Serial.print(String(i));
      Serial.print(F(" on Pin #"));
      Serial.print(String((ssPins[i])));
      Serial.print(F(" detected tag: "));
      Serial.println(currentIDs[i]);
    }
    Serial.println(F("---"));
  }
  #endif

  // If the puzzleSolved flag is set, all sensors detected the correct ID
  if(puzzleSolved && valid ==0){
    onSolve();
  }
 
  // Add a short delay before next polling sensors
  //delay(100); 
}

/**
 * Called when correct puzzle solution has been entered
 */
void onSolve(){

  #ifdef DEBUG
  // Print debugging message
  Serial.println(F("Puzzle Solved!"));
  #endif
  
  // Release the lock
  digitalWrite(lockPin, HIGH);
  delay(3000);
  digitalWrite(lockPin, LOW); 
  valid=1; 

  while(true) {
    delay(1000);
  }
  
}

/**
 * Helper function to return a string ID from byte array
 */
String dump_byte_array(byte *buffer, byte bufferSize) {
  String read_rfid = "";
  for (byte i=0; i<bufferSize; i++) {
    read_rfid = read_rfid + String(buffer[i], HEX);
  }
  return read_rfid;
}

Vous voyez un endroit où je pourrais mettre un “valid=0;” pour réautoriser l’ouverture de ma gâche ?

lesept ==> J’ai essayé de mettre mon “valid=0” ici :

// If the sensor detects a tag and is able to read it
    if(mfrc522[i].PICC_IsNewCardPresent() && mfrc522[i].PICC_ReadCardSerial()) {
      // Extract the ID from the tag
      readRFID = dump_byte_array(mfrc522[i].uid.uidByte, mfrc522[i].uid.size);
      valid=0;
    }

Ca ne fonctionne pas : ma gâche s’ouvre et se referme en boucle alors que mes tags sont présents en permanence sur les lecteurs.

Petite question : à votre avis, à quoi sert le while(true) {
delay(1000);
} dans ma boucle onSolve() ?

Bon, j'ai trouvé la solution à mon problème !
Je pense que l'un de mes 2 lecteurs RFID ne fonctionne pas bien. Je m'explique. Quand je regarde un peu ce qu'il se passe sur mon moniteur série, j'observe que l'un des 2 lecteurs oscille en permanence entre tag reconnu et tag absent (alors que le tag ne bouge pas) :

18:51:44.767 -> Reader #0 on Pin #3 detected tag: 11c425d9
18:51:45.321 -> Reader #1 on Pin #4 detected tag: 
18:51:45.355 -> ---
18:51:45.355 -> Reader #0 on Pin #3 detected tag: 11c425d9
18:51:45.528 -> Reader #1 on Pin #4 detected tag: 89c124d9
18:51:45.562 -> ---
18:51:45.562 -> Reader #0 on Pin #3 detected tag: 11c425d9
18:51:46.290 -> Reader #1 on Pin #4 detected tag: 
18:51:46.360 -> ---
18:51:46.360 -> Reader #0 on Pin #3 detected tag: 11c425d9
18:51:46.499 -> Reader #1 on Pin #4 detected tag: 89c124d9

Je pense que c'est ça qui fait que mon valid est remis à 0 même si le tag n'est pas enlevé.
C'est de la bidouille mais pour pallier à ce bug, j'ai modifié le code :

   if(currentIDs[i] != correctIDs[i]) {
      // The puzzle has not been solved
      puzzleSolved = false;
      valid=0;

J'ai remplacé les i par des 0 de manière à ce qu'il ne se base que sur le lecteur stable pour savoir si il doit passer le valid à 0. Seul inconvénient : le fait d'enlever l'autre tag (celui du lecteur défaillant) ne reset pas mon mécanisme. Mais bon, c'est un moindre mal !

Merci pour vos conseils toujours bienveillants. :wink:

vous avez mis des adaptateurs de tension pour passer en 3.3V ? Les mfrc522 y sont parfois sensibles

Notez que dans le GitHub ils mentionnent

Before buy

Please notice that there are many sellers (ebay, aliexpress, …) who sell mfrc522 boards. The quality of these boards are extremely different. Some are soldered with wrong/low quality capacitors or fake/defect mfrc522.

Please consider buying several devices from different suppliers. So the chance of getting a working device is higher.

If you got a bad board and you can tell us how to detect those boards (silk, chip description, …), please share your knowledge.

Et si votre lecteur ressemble à cela, il y en a de toutes les sortes, certains fonctionnent mieux que d’autres en fonction du vendeur…J’en ai eu 1 sur 5 merdique dans mes achats
RFID.png
Dans la librairie il y a un exemple de lecteurs multiples, c’est celui là que vous avez pris comme source d’inspiration ?