Serrure Badge NFC - ajout et retrait d'utilisateurs ayant accès

Bonjour j'ai ce code ci-joint fonctionnel pour un projet de serrure électronique NFC j'utilise le shield NFC V2.1 de chez SEEED Studio : lien vers Gotronic avec la fiche technique

mon code:

#include <NfcAdapter.h>
#include <PN532/PN532/PN532.h>
#if 1
    #include <SPI.h>
    #include <PN532/PN532_SPI/PN532_SPI.h>


    PN532_SPI pn532spi(SPI, 10);
    NfcAdapter nfc = NfcAdapter(pn532spi);
#else

    #include <Wire.h>
    #include <PN532/PN532_I2C/PN532_I2C.h>


    PN532_I2C pn532_i2c(Wire);
    NfcAdapter nfc = NfcAdapter(pn532_i2c);
#endif

const byte Buzzer_PIN = 2;
const byte LedR_PIN = 3;
const byte LedV_PIN = 4;
const byte Serrure_PIN = 5;

unsigned long chrono = 0ul;
unsigned long chronoLED = 0ul;
const unsigned long TimeOutEtat = 7000ul;

int LedState = LOW;

boolean PremiereFoisRepos = false;
boolean PremiereFoisOuvert = false;
boolean PremiereFoisADD = false;
boolean PremiereFoisDEL = false;

enum {REPOS, ETATADD, ETATDEL, ETATOUVERT} EtatSysteme;

int CarteAdminADD = "EB 3F B7 FF";
int CarteAdminDEL = "5C 83 B5 FF";

int acces1 = "04 AF C7 0A 93 13 90";
int acces2 = "04 7B F 0A 93 13 94";





void setup() {
  pinMode (Buzzer_PIN, OUTPUT);
  pinMode (LedR_PIN, OUTPUT);
  pinMode (LedV_PIN, OUTPUT);
  pinMode (Serrure_PIN, OUTPUT);

  nfc.begin ();

  EtatSysteme = REPOS;

  Serial.begin (9600);

  tone (Buzzer_PIN, 900, 50);
  delay (100);
  tone (Buzzer_PIN, 900, 50);
  delay (50);

  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  SERIAL.println ("Serrure Atelier");
  Serial.println ("");
  Serial.println ("Setup & Serial OK");
  Serial.println ("Etat actuel = Initialisation finie");
  Serial.println ("");
}

void loop() {
  while (EtatSysteme == ETATOUVERT) {
    if (!PremiereFoisOuvert) {
      Serial.println ("Etat actuel = Ouverture ");
      PremiereFoisOuvert = true;
    }

    PremiereFoisRepos = false;

    Ouverture ();

    if (millis () - chrono >= TimeOutEtat) {
      TimeOut ();
      chrono = millis ();
    }
  }

  while (EtatSysteme == ETATADD) {
    if (!PremiereFoisADD) {
      Serial.println("Etat actuel = Etat Admin: ajout d'un utilisateur");
      PremiereFoisADD = true;
    }

    PremiereFoisRepos = false;

    BlinkLED();

    //ajouter un utilisateur autorisé

    if (millis () - chrono >= TimeOutEtat) {
      TimeOut ();
      chrono = millis ();
    }
  }

  while (EtatSysteme == ETATDEL) {
    if (!PremiereFoisDEL) {
      Serial.println("Etat actuel = Etat Admin: retrait d'un utilisateur");
      PremiereFoisDEL = true;
    }

    PremiereFoisRepos = false;

    BlinkLED();

    //retirer un utilisateur autorisé

    if (millis () - chrono >= TimeOutEtat) {
      TimeOut ();
      chrono = millis ();
    }
  }

  while (EtatSysteme == REPOS) {
    if (nfc.tagPresent ()) {
      NfcTag tag = nfc.read ();
      Serial.println ("BADGE/CARTE scanné et récupéré");
      Serial.println ("son UID est : ");
      Serial.print (tag.getUidString ());
      Serial.println ("");
      Serial.println ("");

      if (tag.getUidString () == CarteAdminADD) {
        tone (Buzzer_PIN, 2000, 50);
        chrono = millis ();
        EtatSysteme = ETATADD;
      }
      else if (tag.getUidString () == CarteAdminDEL) {
        tone (Buzzer_PIN, 2000, 50);
        chrono = millis ();
        EtatSysteme = ETATDEL;
      }
      else if (tag.getUidString () == acces1 || tag.getUidString () == acces2) {
        chrono = millis ();
        EtatSysteme = ETATOUVERT;
      }
      else{
        PremiereFoisRepos = false;
        Refus();
      }
    }
    
    else {
      Repos ();
    }
  }
}





void TimeOut() {
  if (EtatSysteme != REPOS) {
    Serial.println ("Time Out !");
    EtatSysteme = REPOS;
  }
}

void Repos() {
  if (!PremiereFoisRepos){
    Serial.println ("Etat actuel = REPOS");
    Serial.println ("Attente : ");
    Serial.println ("");

    PremiereFoisRepos = true;
  }

  PremiereFoisOuvert = false;
  PremiereFoisADD = false;
  PremiereFoisDEL = false;

  digitalWrite (Buzzer_PIN, LOW);
  digitalWrite (LedR_PIN, LOW);
  digitalWrite (LedV_PIN, LOW);
  digitalWrite (Serrure_PIN, LOW);
}

void Ouverture() {
  digitalWrite (Serrure_PIN, HIGH);
  digitalWrite (LedV_PIN, HIGH);
  tone (Buzzer_PIN, 1100, 100);
  delay (100);
  tone (Buzzer_PIN, 1300, 50);
  delay (50);
}

void Refus() {
  Serial.println ("Refus d'acces: Utilisateur non reconnu");

  digitalWrite (LedR_PIN, HIGH);
  tone (Buzzer_PIN, 900, 100);
  delay (100);
  tone (Buzzer_PIN, 700, 50);
  delay (1000);
}

void BlinkLED() {
  if (millis() - chronoLED >= 250) {
    chronoLED = millis();

    if (LedState == LOW) LedState = HIGH;
    else LedState = LOW;
  }

  digitalWrite (LedR_PIN, LedState);
  digitalWrite (LedV_PIN, LedState);
}

j'aimerais qu'au passage devant le capteur NFC d'une carte dite "AdminADD", le programme puisse rajouter soit dans un tableau soit dans une liste de variable le prochain badge scanné (en attendant 7 secondes le scan du prochain badge). Ainsi ce nouveau badge pourrait déverrouiller la serrure

et inversement même système pour "AdminDEL", pour le retrait d'accès.

j'espère que c'est possible facilement je m'y connais moyennement, je me suis aider d'un tuto de J-M-L sur les machines fini ou à état, un grand merci à lui d'ailleurs.

j'ai mis en gros là ou je voyais les modifications en commentaire.
Merci beaucoup d'avance !

tu es sûre ?
je vois plusieurs chose qui ne doit pas passer la compilation.
Après, Je ne peux pas complétement tester, car je ne sais pas quel librairie tu utilises.

tout est relatif :slight_smile: , mais ce n'est pas insurmontable.
Il faut que tu rajoute déjà quelque chose qui gère ton tableau, list ou dictionnaire d'utilisateur.
Ensuite rajouter un état de scan et faire les actions que tu as défini.

Oui c'est fonctionnel, compilé, testé sur le temps cela marche vraiment bien.
J'espère que le programme n'est pas tout simplement tombé en marche (et pas en panne ^^) mais il ne me semble pas

comment faire un dictionnaire d'utilisateur incrémentable ? ou la gestion du tableau c'est ça que je ne sais pas faire

Ok, chez moi ça

int CarteAdminADD = "EB 3F B7 FF";
int CarteAdminDEL = "5C 83 B5 FF";

et ça

Serial.println ("");
  SERIAL.println ("Serrure Atelier");

ne compile pas

Je renvoie mon code au cas ou:

#include <NfcAdapter.h>
#include <PN532/PN532/PN532.h>
#if 1
    #include <SPI.h>
    #include <PN532/PN532_SPI/PN532_SPI.h>


    PN532_SPI pn532spi(SPI, 10);
    NfcAdapter nfc = NfcAdapter(pn532spi);
#else

    #include <Wire.h>
    #include <PN532/PN532_I2C/PN532_I2C.h>


    PN532_I2C pn532_i2c(Wire);
    NfcAdapter nfc = NfcAdapter(pn532_i2c);
#endif

const byte Buzzer_PIN = 2;
const byte LedR_PIN = 3;
const byte LedV_PIN = 4;
const byte Serrure_PIN = 5;

unsigned long chrono = 0ul;
unsigned long chronoLED = 0ul;
const unsigned long TimeOutEtat = 4000ul;

int LedState = LOW;

boolean PremiereFoisRepos = false;
boolean PremiereFoisOuvert = false;
boolean PremiereFoisBIPOuvert = false;
boolean PremiereFoisADD = false;
boolean PremiereFoisDEL = false;

enum {REPOS, ETATADD, ETATDEL, ETATOUVERT} EtatSysteme;

int CarteAdminADD = "EB 3F B7 FF";
int CarteAdminDEL = "5C 83 B5 FF";

int acces1 = "04 AF C7 0A 93 13 90";
int acces2 = "04 7B F 0A 93 13 94";





void setup() {
  pinMode (Buzzer_PIN, OUTPUT);
  pinMode (LedR_PIN, OUTPUT);
  pinMode (LedV_PIN, OUTPUT);
  pinMode (Serrure_PIN, OUTPUT);

  nfc.begin ();

  EtatSysteme = REPOS;

  Serial.begin (9600);

  tone (Buzzer_PIN, 900, 50);
  delay (100);
  tone (Buzzer_PIN, 900, 50);
  delay (50);

  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("");
  Serial.println ("Serrure Atelier - Technicentre Bischheim - TR - U63");
  Serial.println ("");
  Serial.println ("Setup & Serial OK");
  Serial.println ("Etat actuel = Initialisation finie");
  Serial.println ("");
}

void loop() {
  while (EtatSysteme == ETATOUVERT) {
    if (!PremiereFoisOuvert) {
      Serial.println ("Etat actuel = Ouverture ");
      PremiereFoisOuvert = true;
    }

    PremiereFoisRepos = false;

    Ouverture ();

    if (millis () - chrono >= TimeOutEtat) {
      TimeOut ();
      chrono = millis ();
    }
  }

  while (EtatSysteme == ETATADD) {
    if (!PremiereFoisADD) {
      Serial.println("Etat actuel = Etat Admin: ajout d'un utilisateur");
      PremiereFoisADD = true;
    }

    PremiereFoisRepos = false;

    BlinkLED();

    //ajouter un utilisateur autorisé

    if (millis () - chrono >= TimeOutEtat) {
      TimeOut ();
      chrono = millis ();
    }
  }

  while (EtatSysteme == ETATDEL) {
    if (!PremiereFoisDEL) {
      Serial.println("Etat actuel = Etat Admin: retrait d'un utilisateur");
      PremiereFoisDEL = true;
    }

    PremiereFoisRepos = false;

    BlinkLED();

    //retirer un utilisateur autorisé

    if (millis () - chrono >= TimeOutEtat) {
      TimeOut ();
      chrono = millis ();
    }
  }

  while (EtatSysteme == REPOS) {
    if (nfc.tagPresent ()) {
      NfcTag tag = nfc.read ();
      Serial.println ("BADGE/CARTE scanné et récupéré");
      Serial.println ("son UID est : ");
      Serial.print (tag.getUidString ());
      Serial.println ("");
      Serial.println ("");

      if (tag.getUidString () == CarteAdminADD) {
        tone (Buzzer_PIN, 2000, 50);
        chrono = millis ();
        EtatSysteme = ETATADD;
      }
      else if (tag.getUidString () == CarteAdminDEL) {
        tone (Buzzer_PIN, 2000, 50);
        chrono = millis ();
        EtatSysteme = ETATDEL;
      }
      else if (tag.getUidString () == acces1 || tag.getUidString () == acces2) {
        chrono = millis ();
        EtatSysteme = ETATOUVERT;
      }
      else{
        PremiereFoisRepos = false;
        Refus();
      }
    }
    
    else {
      Repos ();
    }
  }
}





void TimeOut() {
  if (EtatSysteme != REPOS) {
    Serial.println ("Time Out !");
    EtatSysteme = REPOS;
  }
}

void Repos() {
  if (!PremiereFoisRepos){
    Serial.println ("Etat actuel = REPOS");
    Serial.println ("Attente : ");
    Serial.println ("");

    PremiereFoisRepos = true;
  }

  PremiereFoisOuvert = false;
  PremiereFoisBIPOuvert = false;
  PremiereFoisADD = false;
  PremiereFoisDEL = false;

  digitalWrite (Buzzer_PIN, LOW);
  digitalWrite (LedR_PIN, LOW);
  digitalWrite (LedV_PIN, LOW);
  digitalWrite (Serrure_PIN, LOW);
}

void Ouverture() {
  digitalWrite (Serrure_PIN, HIGH);
  digitalWrite (LedV_PIN, HIGH);

  if (!PremiereFoisBIPOuvert) {
    tone (Buzzer_PIN, 1100, 100);
    delay (100);
    tone (Buzzer_PIN, 1300, 50);
    delay (50);
    PremiereFoisBIPOuvert = true;
  }
}

void Refus() {
  Serial.println ("Refus d'acces: Utilisateur non reconnu");

  digitalWrite (LedR_PIN, HIGH);
  tone (Buzzer_PIN, 900, 100);
  delay (100);
  tone (Buzzer_PIN, 500, 50);
  delay (1000);
}

void BlinkLED() {
  if (millis() - chronoLED >= 250) {
    chronoLED = millis();

    if (LedState == LOW) LedState = HIGH;
    else LedState = LOW;
  }

  digitalWrite (LedR_PIN, LedState);
  digitalWrite (LedV_PIN, LedState);
}

chez moi sur l'IDE Arduino ça fonctionne, je créé juste une variable int avec stoqué l'ID de mes Carte Admin

Car chez moi sur mon IDE Arduino et celui d'un ami à moi cela fonctionne

Le plus simple est d'utiliser une librairie qui te donne cette fonctionnalité.
Pour le tableau, il y a plusieurs façon de faire, la plus simple est de créer un tableau de tableau(tableau 2 dimensions, ex de 5 par 20 ).
c'est à dire que pour chaque utilisateur tu définir un tableau de caractère, avec un nombre de caractère maximum(ex 20).
puis tu définis un tableau pour le nombre d'utilisateur que tu pourras avoir au maximum(ex 5).
ll faudra aussi bien sûre un tableau pour tes 5 utilisateurs qui te permet aussi de sauver leur identifiant NFC

je vais me renseigner sur un dictionnaire d'utilisateur ça m'a l'air plus simple merci

C'est plus simple, je trouve aussi, mais peut être plus gourmand en mémoire et problématique en libération de mémoire.
Mais comme tu ne va surement pas ajouter/effacer des milliers d'utilisateurs, ce dernier point ne devrait pas être un problème.

je compte avoir 40-50 accès badge différents

Dans NfcTag.h je vois :

        String getUidString();

Si la méthode getUidString() retourne une String, il faudrait comparer avec une autre String, or tu compares avec un int.

mais pourquoi cela fonctionne t'il ? j'avais essayer en transformant le string en int avant la vérification, ou encore en stockant la valeur EB 3F B7 FF (par exemple) dans une sting mais ça ne fonctionnais pas d'où ce que j'ai écris qui fonctionne pourtant... Je ne comprend pas trop

C'est encore plus étrange avec ces deux variables sur 7 octets.
Tu as vraiment des badges avec des UID sur 7 bytes ?

Badges NFC et non RFID

avec mon shield NFC V2.1 de Chez SEEED Studio lien vers gotronic avec la fiche technique et la librairie
j'ai un code exemple "readNFC" et c'est l'ID renvoyé des badge NFC et non RFID et une fois mis dans le code cela fonctionne en réél avec mon système à coté en vrais

Si tu jettes un œil à la librairie :

String NfcTag::getUidString() retourne bien une String formatée avec des bytes en HEXA séparés par des espaces, donc tu devrais comparer avec des Strings.

String acces1 = "04 AF C7 0A 93 13 90";

mais je ne comprend pas pourquoi dans mon cas ça marche, si jamais j'utilisa la bibliothèque NfcAdaptater.h et non NfcTag.h je ne sais pas si cela marche

il faudra prévoir de conserver la liste en mémoire non volatile, sinon à la prochaine panne de courant toutes les modification des badges seront perdues.

quel Arduino utilisez vous ?

j'utilise celle ci

:sweat_smile:comment faire :cold_sweat:

Au sujet de ton problème de stockage de 50 UIDs, tu devrais utiliser l'EEPROM de l'ARDUINO.
Elle a une taille de 1K.
Comme tes UIDs sont sur sur 56 bits, tu peux les stocker dans des uint64_t et tu peux en mémoriser 128.

La question ne se pose pas. tag est un objet NfcTag, cette classe est décrite dans nfctag.h et nfctag.h est inclus dans NfcAdaptater.h.