Arduino Forum

International => Français => Topic started by: tomobilus on Jun 14, 2020, 05:15 pm

Title: créer Tableau de valeur qui varie
Post by: tomobilus on Jun 14, 2020, 05:15 pm
Bonjour cher Forum Arduino,

J'ai créé un bout de code pour un système de badges avec crédit qui fonctionne très bien actuellement.

Je n'arrive pas à simplifier le code en utilisant un tableau pour les crédits, afin de remplacer "credit_B1","credit_B2",...,"credit_B10" dans une seule variable.

Merci d'avance pour l'aide que vous pourrez m'apporter  :)

voici le bout de code :

Code: [Select]

//Déclaration des Librairies et PIN....

// Déclaration des constantes liées au délai
unsigned long previousMillis = 0;

// Déclaration des constantes liées au bouton et au crédit
int credit_min = 0;          // Variable crédit minimum
byte tagok = 0;               // Variable pour différencier les types de Badge
 
int credit_B1 = 5;              // Nombre de crédit Badge 1
int credit_B2 = 5;              // Nombre de crédit Badge 2
int credit_B3 = 5;              // Nombre de crédit Badge 3

//etc.... jusqu'à 10 badges différents....

//------------------------------------------------------------------------------------//
//------------------------------  DEFINITION DES VARIABLES  --------------------------//
//------------------------------------------------------------------------------------//

//Permet d'afficher les chiffres sur le 7 segment
const byte digit[11] = {
                    B11111100,  // 0
                    B01100000,  // 1
                    B11011010,  // 2
                    B11110010,  // 3
                    B01100110,  // 4
                    B10110110,  // 5
                    B10111110,  // 6
                    B11100000,  // 7
                    B11111110,  // 8
                    B11100110,  // 9
                    B00000000   // clean
                    };
                   
//---------------------------------------------------//
// Code des Badges
unsigned long sernum[13] = {0,            //poste 0 N° badge lue
                            1669386246,   //Badge 1
                            3009123561,   //Badge 2
                            3009327833,   //Badge 3
                            0,            //Badge 4
                            0,            //Badge 5
                            0,            //Badge 6
                            0,            //Badge 7
                            0,            //Badge 8
                            0,            //Badge 9
                            0,            //Badge 10
                            0,            //Badge 11
                            2778220336};  //Carte Master(12)

//------------------------------------------------------------------------------------//
//---------------------- INITIALISATION DE LA CARTE ET DES SORTIES -------------------//
//------------------------------------------------------------------------------------//
 
void setup()
{
  Serial.begin(9600);        // Initialiser communication avec le serial
//.......
  Serial.println("Présentez votre badge sur le lecteur ...");

 
//------------------------------------------------------------------------------------//
//--------------------------------  PROGRAMME  ---------------------------------------//
//------------------------------------------------------------------------------------//

void loop()
{       
  // Détecte la présence d'un badge devant le RFID
  if ( ! rfid.PICC_IsNewCardPresent()) {
    return; }

  // Lecture du badge pour réccupérer son UID
  if ( ! rfid.PICC_ReadCardSerial()) {
    return; }

  //Afficher l'UID sur le moniteur série
  Serial.print("UID Badge [");
  String content= "";

  for (byte i = 0; i < rfid.uid.size; i++)
    {  //Converti UID Binaire en Hexa
     content.concat(String(rfid.uid.uidByte[i], HEX));
    }
  //Compare le UID lu avec ceux du tableau de codes déjà enregistré
  sernum[0] = *((unsigned long *)rfid.uid.uidByte);
  Serial.print(sernum[0]);
  Serial.print("] ");
  tagok = 0;

  for  (byte i = 1; i < 12; i++) {
    if (sernum[0] == sernum[i]) tagok = 1; // badge reconnue dans le tableau
  }
  if (sernum[0] == sernum[12]) tagok = 255; // carte master reconnue
 
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII BADGE NON RECONNU  IIIIIIIIIIIIIIIIIIIIIIIIIIIIII//

  if (tagok == 0)
  {
    Serial.println("Bagge INCONNU");
    Serial.println();
    LED_Rouge();       //void pour allumer led rouge+Buzzer
  }
 
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII BADGE RECONNU IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//

  if (tagok == 1 )
  {         
    Serial.print("Badge OK");
    previousMillis = millis();                 //RESET le temps pour la boucle while
   
    //00000000000000000000000000000000  sernum[1]  00000000000000000000000000000000//   
 
    if (sernum[0] == sernum[1]) {        // Affiche Nom du Badge et Crédit sur Moniteur
      Serial.println(" - Badge 1 ");
      Serial.print("Credits= ");
      Serial.println(credit_B1);             // Affiche le crédit lié au badge 1
     
      byte chiffre = digit[credit_B1];    // Affiche Crédit restant du badge sur le 7 segment
      digitalWrite(latchPin, LOW);                 
      shiftOut(dataPin, clockPin, LSBFIRST, chiffre);
      digitalWrite(latchPin, HIGH);
      LED_Verte();              //void pour allumer led verte+Buzzer
     
      if (credit_B1==0) {     //Si credit vide alors erreur
        LED_Rouge();
      }
      else {
      // Attend appui sur le bouton pour décompter
      while ((sernum[0] == sernum[1]) && (millis() - previousMillis < 10000)) {
        if(digitalRead(bouton_play)==HIGH){
          if (credit_B1!=credit_min){
            credit_B1--;                             //si appui sur le bouton alors décompte crédit badge 1

      // Affiche Nouveau Crédit restant sur le badge   
      Serial.print("New credits= ");
      Serial.println(credit_B1);
     
      byte chiffreMoins = digit[credit_B1]; // Affiche New Crédit restant du badge sur le 7 segment
      digitalWrite(latchPin, LOW);                 
      shiftOut(dataPin, clockPin, LSBFIRST, chiffreMoins);
      digitalWrite(latchPin, HIGH);
      LED_Bleu();                          //void pour allumer led bleu+Buzzer
      break;     
          }   
     }
       if ((digitalRead(bouton_play)==LOW) && (millis() - previousMillis > 10000)){
        break;
    } } } }
   
    //00000000000000000000000000000000  sernum[2]  00000000000000000000000000000000//   
   
     //idem.....
   
    //00000000000000000000000000000000  sernum[3]  00000000000000000000000000000000//
   
     // idem.....
   
    //00000000000000000000000000000000  sernum[4]  00000000000000000000000000000000//
     //idem.....
     //etc......

//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII  CARTE MASTER  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//

  if (tagok == 255)
  {
    if (sernum[0] == sernum[12]) Serial.println("- Carte MASTER");


    //Allume LED VERTE puis BLEU + Double Buzzer son OK + ...

   }
   delay(2000);
   clean_7seg();     // on éteint le 7 segment
}
Title: Re: créer Tableau de valeur qui varie
Post by: iznobe on Jun 14, 2020, 06:05 pm
salut , pour creer un tableau avec 10 membres :
Code: [Select]
int credit_B[9] = {};

pour affecter une valeur au 5eme membre du tableau :
Code: [Select]
credit_B[4] = {254};
Title: Re: créer Tableau de valeur qui varie
Post by: hbachetti on Jun 14, 2020, 06:18 pm
Première remarque :
Code: [Select]

  String content= "";
  for (byte i = 0; i < rfid.uid.size; i++)
    {  //Converti UID Binaire en Hexa
     content.concat(String(rfid.uid.uidByte[i], HEX));
    }

Cette variable content ne sert  à rien, et l'utilisation de String peut amener des problèmes de fragmentation mémoire.

Ce code pourrait être factorisé bien au delà des variables crédit.
Regrouper les crédits dans un tableau n'apportera pas grand chose, attendu que tu ne parcours même pas la liste des N° de série pour trouver le N° du badge dans la liste.

En regroupant les N° de série et crédits dans une structure :

Code: [Select]

#define NACCOUNT      12

struct account
{
  unsigned long sernum;
  int credit;
};

struct account accountList[NACCOUNT] =
{
  2778220336, 0,  //Carte Master(0)
  1669386246, 5,  //Badge 1
  3009123561, 5,  //Badge 2
  3009327833, 5,  //Badge 3
  0, 0,           //Badge 4
  0, 0,           //Badge 5
  0, 0,           //Badge 6
  0, 0,           //Badge 7
  0, 0,           //Badge 8
  0, 0,           //Badge 9
  0, 0,           //Badge 10
  0, 0,           //Badge 11
};

// Ensuite on accède au N° de série par accountList[X].sernum, et au crédit par accountList[X].credit.
// Il ne reste plus qu'à parcourir le liste avec une boucle

for(int i = 0 ; i < NACCOUNT ; i++) {
  if (id == accountList[X].sernum) {
    // ici le N° est OK
    // le crédit : accountList[i].credit
  }
}


Tu vois l'idée ?

Stocker l'ID du badge lu dans sernum[0] n'est pas une bonne idée. Utilise plutôt une variable séparée.
Je collerais en 0 plutôt l'ID du master, ainsi si la liste s'allonge il ne change pas de place.

Ensuite je pense que tu es conscient qu'en cas de redémarrage les crédits repartent de leur valeur initiale. Il faudra bien les enregistrer quelque part : EEPROM par exemple.
Title: Re: créer Tableau de valeur qui varie
Post by: fdufnews on Jun 14, 2020, 06:19 pm
salut , pour creer un tableau avec 10 membres :
Code: [Select]
int credit_B[9] = {};
Heu, non!!
pour creer un tableau avec 10 membres :
Code: [Select]
int credit_B[10] = {};
par contre, l'index pour parcourir le tableau ira de 0 à 9 ;)
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jun 14, 2020, 06:36 pm
Merci beaucoup pour vos propositions :D

@hbachetti quelle excellente idée le tableau en 2 dimension avec les valeurs credit et sernum  8)
La formulation me plait, je vais essayer de l'adapter à ce que j'ai déjà fait...

Comme tu l'as si bien deviné, à termes je souhaite sauvegarder ce tableau sur la EEPROM. Que dois-je faire pour prévoir cela ?  :smiley-sweat:
Title: Re: créer Tableau de valeur qui varie
Post by: hbachetti on Jun 14, 2020, 06:42 pm
lecture avec EEPROM.get(), écriture avec EEPROM.put()

https://www.arduino.cc/en/Reference/EEPROM (https://www.arduino.cc/en/Reference/EEPROM)
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jun 14, 2020, 07:08 pm
Est ce que mon code est correct ?


Code: [Select]
void loop()
{       
  // Détecte la présence d'un badge devant le RFID
  if ( ! rfid.PICC_IsNewCardPresent()) {
    return; }
  // Lecture du badge pour réccupérer son UID
  if ( ! rfid.PICC_ReadCardSerial()) {
    return; }

  //Afficher l'UID sur le moniteur série

  for(int i = 0 ; i < NACCOUNT ; i++) {
    if (id == accountList[i].sernum) {
      Serial.print("Badge OK - ");
      //(UID Badge [........] )
      Serial.print("UID Badge [");Serial.print(accountList[i].sernum);Serial.println("] ");
      //(Credits : X)
      Serial.print("Credits= ");Serial.println(accountList[i].credit); 

      byte chiffre = digit[accountList[i].credit]];    // Affiche Crédit du badge X sur le 7 segment
      digitalWrite(latchPin, LOW);                 
      shiftOut(dataPin, clockPin, LSBFIRST, chiffre);
      digitalWrite(latchPin, HIGH);
      LED_Verte();              //Allume Led Verte+Buzzer
    }
    while (id == accountList[i].sernum) && (millis() - previousMillis < 10000)) { //délai avant break
        if(digitalRead(bouton_play)==HIGH){
          if (accountList[i].credit]!=credit_min){
            accountList[i].credit]--;                  //Décompte du crédit lié au badge X
            Serial.print("New credits= ");
            Serial.println(accountList[i].credit);
            byte chiffreMoins = digit[accountList[i].credit]]; // Affiche New Crédit restant du badge X sur le 7 segment
            digitalWrite(latchPin, LOW);                 
            shiftOut(dataPin, clockPin, LSBFIRST, chiffreMoins);
            digitalWrite(latchPin, HIGH);
            LED_Bleu();
            break
          }
         }
      else {
        if ((digitalRead(bouton_play)==LOW) && (millis() - previousMillis > 10000)){
        break;
        }
       }
      }
     }
Title: Re: créer Tableau de valeur qui varie
Post by: hbachetti on Jun 14, 2020, 07:17 pm
Il est plutôt incomplet, mais semble en bonne voie.
Il manque en particulier une ligne essentielle:
  id = *((unsigned long *)rfid.uid.uidByte);
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jun 14, 2020, 07:51 pm
Oui en effet petit oubli non-négligeable  :smiley-lol:

Qu'entends-tu par incomplet ?

je viens de compléter certaines ligne...

Code: [Select]
Void Loop(){

// Détecte la présence d'un badge devant le RFID
  if ( ! rfid.PICC_IsNewCardPresent()) {
    return; }
  // Lecture du badge pour réccupérer son UID
  if ( ! rfid.PICC_ReadCardSerial()) {
    return; }
   
  id = *((unsigned long *)rfid.uid.uidByte);
  previousMillis = millis();

  //Afficher l'UID sur le moniteur série

  for(int i = 0 ; i < NACCOUNT ; i++) {
    if (id == accountList[i].sernum) {
      Serial.print("Badge OK - ");
      //(UID Badge [........] )
      Serial.print("UID Badge [");Serial.print(accountList[i].sernum);Serial.println("] ");
      //(Credits : X)
      Serial.print("Credits= ");Serial.println(accountList[i].credit);
     
      byte chiffre = digit[accountList[i].credit]];    // Affiche Crédit du badge X sur le 7 segment
      digitalWrite(latchPin, LOW);                 
      shiftOut(dataPin, clockPin, LSBFIRST, chiffre);
      digitalWrite(latchPin, HIGH);
      LED_Verte();   //Allume Led Verte+Buzzer
    }
    while (id == accountList[i].sernum) && (millis() - previousMillis < 10000)) {
        if(digitalRead(bouton_play)==HIGH){
          if (accountList[i].credit]!=credit_min){
            accountList[i].credit]--;
            Serial.print("New credits= ");
            Serial.println(accountList[i].credit);
            byte chiffreMoins = digit[accountList[i].credit]]; // Affiche New Crédit restant du badge X sur le 7 segment
            digitalWrite(latchPin, LOW);                 
            shiftOut(dataPin, clockPin, LSBFIRST, chiffreMoins);
            digitalWrite(latchPin, HIGH);
            LED_Bleu();  //Allume Led Bleu+Buzzer
            break
          }
         }
       else {
        if ((digitalRead(bouton_play)==LOW) && (millis() - previousMillis > 10000)){
        break;
        }
       }
      }
     }
   else if (id != accountList[i].sernum){
    Serial.println("Bagge INCONNU");
    LED_Rouge();  //Allume Led Rouge+Buzzer
   }
}
Title: Re: créer Tableau de valeur qui varie
Post by: hbachetti on Jun 14, 2020, 08:25 pm
Quote
Qu'entends-tu par incomplet ?
Incomplet car déclarations, setup(), fonctions annexes absents.

un conseil : plutôt que d'écrire un gros machin monolithique et tester ensuite, écris au fur à mesure, compile et teste. Si tu as le matériel bien entendu.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 07, 2020, 02:54 pm
Re-Bonjour,

J'ai finalisé le code, le système fonctionne parfaitement seulement à la prochaine coupure de courant tous les crédits seront réinitialisés, et ce n'est pas le but. :-\

Voici la structure que je souhaite sauvegarder :

Code: [Select]
#define NB_COMPTE  12             // Nombre de Badge défini

struct Params
{
  char nom[10];                   // numéro des chambres (ex:CHAMBRE 3)
  unsigned long sernum;           // UID Badge
  int credit;                     // Nombre de crédit sur les badges (par défaut 5 crédits)
};

// On accède au données par Utilisateur[X].nom,
// Utilisateur[X].sernum, et Utilisateur[X].credit.

struct Params Utilisateur[NB_COMPTE] = {
  "MASTER",      2778220336,    0,  // Carte Master
  "CHAMBRE 1",   1669386246,    5,  // Badge 1
  "CHAMBRE 2",   3009123561,    5,  // Badge 2
  "CHAMBRE 3",   3009327833,    5,  // Badge 3
  "CHAMBRE 4",   0,             0,  // Badge 4
  "CHAMBRE 5",   0,             0,  // Badge 5
  "CHAMBRE 6",   0,             0,  // Badge 6
  "CHAMBRE 7",   0,             0,  // Badge 7
  "CHAMBRE 8",   0,             0,  // Badge 8
  "CHAMBRE 9",   0,             0,  // Badge 9
  "CHAMBRE 10",  0,             0,  // Badge 10
  "CHAMBRE 11",  0,             0,  // Badge 11
 //Nom Chambre,  UID Badge,   Nombre de Crédit
};


Comment puis-je dire à mon système :
   - Recherche dans EEPROM "UID Badge"
   - Si valide alors récupère "nombre de crédit" du badge dans EEPROM
   - Si décompte alors écrit dans EEPROM "nouveau crédit" dans EEPROM

Merci encore pour l'aide que vous pourrez m'apporter :D
Title: Re: créer Tableau de valeur qui varie
Post by: fdufnews on Jul 07, 2020, 03:16 pm
Pour alors déjà, il y a un problème de dimensionnement de tableau
Code: [Select]
char nom[10];                   // numéro des chambres (ex:CHAMBRE 3)
alors que tu mets dedans
Code: [Select]
"CHAMBRE 10",  0,             0,  // Badge 10
Il faut penser que les chaines de caractères ont un terminateur que l'on ne voit pas mais qui occupe quand même un élément du tableau donc il faudrait écrire
Code: [Select]
char nom[11];                   // numéro des chambres (ex:CHAMBRE 3)
Title: Re: créer Tableau de valeur qui varie
Post by: fdufnews on Jul 07, 2020, 03:22 pm
Pour écrire et lire tes structures en EEPROM il faut regarder de ce coté:
EEPROMPut (https://www.arduino.cc/en/Reference/EEPROMPut)
EEPROMGet (https://www.arduino.cc/en/Reference/EEPROMGet)

Il y a même des exemples là: https://www.arduino.cc/en/Tutorial/EEPROMPut (https://www.arduino.cc/en/Tutorial/EEPROMPut)https://www.arduino.cc/en/Tutorial/EEPROMGet (https://www.arduino.cc/en/Tutorial/EEPROMGet)

ATTENTION à ne pas faire d'écritures inutiles sous peine de tuer l'EEPROM assez rapidement.
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 07, 2020, 03:28 pm
Il y a eu un projet similaire récemment ici (https://forum.arduino.cc/index.php?topic=658461.0) (un peu long à lire, mais tout y est je pense)
Title: Re: créer Tableau de valeur qui varie
Post by: biggil on Jul 07, 2020, 04:04 pm
Tu ne peux pas lire des éléments de tes données directement dans l'EEPROM.

l'EEPROM est juste une mémoire auxiliaire, elle n'est pas "en ligne" avec le processeur, pour lire/écrire dedans tu dois passer par les fonctions spéciales EEPROM.

Donc, pour sauver ton tableau (tout ton tableau) en EEPROM, tu le copies en EEPROM à l'adresse 0 (ou une autre adresse, c'est toi qui gère) avec la fonction qui va bien. Tu passes l'adresse du tableau et sa taille en octets ( utiliser sizeof() ).
C'est possible d'écrire seulement une partie, ou une donnée, mais c'est plus compliqué.
[EDIT] Y'a je crois une fonction intelligente qui n'écrit que les octets modifiés. Pour allonger la durée de vie de la prom.

[Edit]N'oublie pas de tester le codes de retour des fonctions, qui signalent un éventuelle erreur.
Si par exemple au démarrage tu n'arrives pas à lire l'EEPROM, il faut décider quoi faire.

Au démarrage après une coupure, il faut que tu déclares un tableau, avec rien dedans.
(ou utiliser le tableau existant, tel que compilé, s'il y en a un, pour remplacer ses valeurs).
Ensuite tu demandes de lire l'Eeprom à l'adresse 0, avec une autre fonction qui va bien, pour tant d'octets, et de poser le résultat à l'adresse du tableau.

Et voilà ! les données de l'EEPROM sont dans le tableau, utilise les normalement.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 21, 2020, 02:45 pm
Bonjour à tous  :)

Merci pour vos réponses, cela m'a donné autant de réponse que de nouveau problème  :smiley-sweat:

Il y a eu un projet similaire récemment ici (https://forum.arduino.cc/index.php?topic=658461.0) (un peu long à lire, mais tout y est je pense)
J'ai pris le temps de tout lire, mais la personne utilise une interface web pour stocker ses données... Alors que je souhaite utiliser uniquement l'EEPROM.
Il faut penser que les chaines de caractères ont un terminateur que l'on ne voit pas mais qui occupe quand même un élément du tableau donc il faudrait écrire
    char nom[11];                   // numéro des chambres (ex:CHAMBRE 3)
Merci pour la correction, c'est quelque chose que je ne connaissais pas  :D

J'ai essayé un petit code pour comprendre comment lire ma structure, mais malheureusement je n'arrive pas à changer de ligne...
Voici le code:
Code: [Select]
#include <EEPROM.h>

float f = 0.00f;   //Variable pour stocker les données lues depuis l'EEPROM.
int eeAddress = 0; //Adresse EEPROM à partir de laquelle commencer la lecture

struct Params {
  char nom[11];
  uint32_t sernum;
  byte credit;
};
///////////////////////////////  ECRIRE SUR EEPROM  ///////////////////////////////
void write_eeprom() {
  EEPROM.put(eeAddress, f);
  eeAddress += sizeof(float); // Déplacer l'adresse vers l'octet suivant après le float 'f'.

  struct Params Badge[12] = {
    //  nom         sernum       credit
    "MASTER",    2778220336,     0,  // Carte Master
    "CHAMBRE 1", 1669386246,     1,  // Badge 1
    "CHAMBRE 2", 3009123561,     2,  // Badge 2
    "CHAMBRE 3", 3009327833,     3,  // Badge 3
    "CHAMBRE 4", 0, 0,               // Badge 4
    "CHAMBRE 5", 0, 0,               // Badge 5
    "CHAMBRE 6", 0, 0,               // Badge 6
    "CHAMBRE 7", 0, 0,               // Badge 7
    "CHAMBRE 8", 0, 0,               // Badge 8
    "CHAMBRE 9", 0, 0,               // Badge 9
    "CHAMBRE 10", 0, 0,              // Badge 10
    "CHAMBRE 11", 0, 0,              // Badge 11
  };

  EEPROM.put(eeAddress, Badge);
  Serial.println("Données Enregistrés !");
}
////////////////////////////////  LIRE SUR EEPROM  ///////////////////////////////////
void read_eeprom() {
  int eeAddress = sizeof(float); // Déplacez l'adresse vers l'octet suivant après le float 'f'.
  Params Badge; // Variable pour stocker l'objet personnalisé lu depuis l'EEPROM.
  EEPROM.get(eeAddress, Badge);

  Serial.println("Lecture des données... ");
  Serial.println(Badge.nom);
  Serial.println(Badge.sernum);
  Serial.println(Badge.credit);
}
////////////////////////////////  SETUP  ///////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ; // attendez que le port série se connecte. Nécessaire uniquement pour le port USB natif
  }

  write_eeprom();
  delay (1000);
  read_eeprom();
}


void loop() {

}


Actuellement j'affiche :
Code: [Select]
Données Enregistrés !
Lecture des données...
MASTER
2778220336
0


et je souhaite pouvoir afficher par exemple :
Code: [Select]
Données Enregistrés !
Lecture des données...
CHAMBRE 3
3009327833
3


Je pensais qu'il fallait utiliser :

Serial.println(Badge[3].nom);  // Trouve "CHAMBRE 3"
ou
eeAddress = 3;
EEPROM.get(eeAddress, Badge.nom);


Je vous remercie de m'éclairer  :D
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 21, 2020, 03:15 pm
Tu t'es inspiré de l'exemple de la bibliothèque, mais tu n'en as pas compris la fonctionnement. Il stocke d'abord un float, puis une structure. Le eeAdress est là pour décaler le stockage de la structure après l'endroit où est stocké le float.

toi, tu n'as pas besoin de ça, tu veux juste stocker ton tableau de structure au début de l'EEPROM (en tout cas c'est ce que je suppsoe).
Donc pour stocker tu fais ça :

Code: [Select]
void write_eeprom() {

  struct Params Badge[12] = {
    //  nom         sernum       credit
    "MASTER",    2778220336,     0,  // Carte Master
    "CHAMBRE 1", 1669386246,     1,  // Badge 1
    "CHAMBRE 2", 3009123561,     2,  // Badge 2
    "CHAMBRE 3", 3009327833,     3,  // Badge 3
    "CHAMBRE 4", 0, 0,               // Badge 4
    "CHAMBRE 5", 0, 0,               // Badge 5
    "CHAMBRE 6", 0, 0,               // Badge 6
    "CHAMBRE 7", 0, 0,               // Badge 7
    "CHAMBRE 8", 0, 0,               // Badge 8
    "CHAMBRE 9", 0, 0,               // Badge 9
    "CHAMBRE 10", 0, 0,              // Badge 10
    "CHAMBRE 11", 0, 0,              // Badge 11
  };

  EEPROM.put(0, Badge);  // <-- on stocke à l'adresse 0
  Serial.println("Données Enregistrés !");
}


Pour lire la 3ème valeur, c'est plus compliqué, il faut savoir la taille d'une structure pour en sauter 2 :

Code: [Select]
void read_eeprom(int n) {
  int eeAddress = n * sizeof(Params); // Déplacez l'adresse vers l'octet suivant les n-1 premières données.
  Params Badge; // Variable pour stocker l'objet personnalisé lu depuis l'EEPROM.
  EEPROM.get(eeAddress, Badge);

  Serial.println("Lecture des données... ");
  Serial.println(Badge.nom);
  Serial.println(Badge.sernum);
  Serial.println(Badge.credit);
}


Ça donne ça :
Code: [Select]
#include <EEPROM.h>

float f = 0.00f;   //Variable pour stocker les données lues depuis l'EEPROM.
int eeAddress = 0; //Adresse EEPROM à partir de laquelle commencer la lecture

struct Params {
  char nom[11];
  uint32_t sernum;
  byte credit;
};
///////////////////////////////  ECRIRE SUR EEPROM  ///////////////////////////////
void write_eeprom() {

  struct Params Badge[12] = {
    //  nom         sernum       credit
    "MASTER",    2778220336,     0,  // Carte Master
    "CHAMBRE 1", 1669386246,     1,  // Badge 1
    "CHAMBRE 2", 3009123561,     2,  // Badge 2
    "CHAMBRE 3", 3009327833,     3,  // Badge 3
    "CHAMBRE 4", 0, 0,               // Badge 4
    "CHAMBRE 5", 0, 0,               // Badge 5
    "CHAMBRE 6", 0, 0,               // Badge 6
    "CHAMBRE 7", 0, 0,               // Badge 7
    "CHAMBRE 8", 0, 0,               // Badge 8
    "CHAMBRE 9", 0, 0,               // Badge 9
    "CHAMBRE 10", 0, 0,              // Badge 10
    "CHAMBRE 11", 0, 0,              // Badge 11
  };

  EEPROM.put(0, Badge);
  Serial.println("Données Enregistrés !");
}
////////////////////////////////  LIRE SUR EEPROM  ///////////////////////////////////
void read_eeprom(int n) {
  int eeAddress = n * sizeof(Params); // Déplacez l'adresse vers l'octet suivant les n-1 premières données.
  Params Badge; // Variable pour stocker l'objet personnalisé lu depuis l'EEPROM.
  EEPROM.get(eeAddress, Badge);

  Serial.println("Lecture des données... ");
  Serial.println(Badge.nom);
  Serial.println(Badge.sernum);
  Serial.println(Badge.credit);
}
////////////////////////////////  SETUP  ///////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  while (!Serial);

  write_eeprom();
  delay (1000);
  read_eeprom(3);
}


void loop() {

}

et ça affiche ça :
Quote
Données Enregistrés !
Lecture des données...
CHAMBRE 3
3009327833
3
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 21, 2020, 03:35 pm
Merci de ta réponse lesept 

J'y vois un peu plus clair déjà  :D

Dans le code que tu as remis, je pense que tu as oublié de supprimer "float f = 0.00f; "

En fait, je veux juste atteindre un élément précis d'une ligne pour pouvoir le lire et le modifier si besoin..

Par exemple:

- Lire le nombre de crédit de la CHAMBRE 3, appliquer un décompte et mettre à jour le crédit.
- Lire le UID du badge (sernum) et le remplacer par un nouveau

je suppose cela ne correspond plus...

Code: [Select]
int eeAddress = n * sizeof(Params);

Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 21, 2020, 04:38 pm
Si, c'est fait pour lire ou écrire à la bonne adresse. Voici un exemple pour changer le crédit de la chambre 3 :
Code: [Select]
#include <EEPROM.h>

int eeAddress = 0; //Adresse EEPROM à partir de laquelle commencer la lecture

struct Params {
  char nom[11];
  uint32_t sernum;
  byte credit;
};

struct Params Badge[12] = {
  //  nom         sernum       credit
  "MASTER",    2778220336,     0,  // Carte Master
  "CHAMBRE 1", 1669386246,     1,  // Badge 1
  "CHAMBRE 2", 3009123561,     2,  // Badge 2
  "CHAMBRE 3", 3009327833,     3,  // Badge 3
  "CHAMBRE 4", 0, 0,               // Badge 4
  "CHAMBRE 5", 0, 0,               // Badge 5
  "CHAMBRE 6", 0, 0,               // Badge 6
  "CHAMBRE 7", 0, 0,               // Badge 7
  "CHAMBRE 8", 0, 0,               // Badge 8
  "CHAMBRE 9", 0, 0,               // Badge 9
  "CHAMBRE 10", 0, 0,              // Badge 10
  "CHAMBRE 11", 0, 0,              // Badge 11
};

///////////////////////////////  ECRIRE SUR EEPROM  ///////////////////////////////
void init_eeprom() {
  EEPROM.put(0, Badge);
  Serial.println("Données Enregistrées !");
}
////////////////////////////////  LIRE SUR EEPROM  ///////////////////////////////////
void read_eeprom(int n) {
  int eeAddress = n * sizeof(Params); // Déplacez l'adresse vers l'octet suivant après le float 'f'.
  Params Badge;
  EEPROM.get(eeAddress, Badge);

  Serial.println("Lecture des données... ");
  Serial.println(Badge.nom);
  Serial.println(Badge.sernum);
  Serial.println(Badge.credit);
}

void write_eeprom(int n) {
  int eeAddress = n * sizeof(Params); // Déplacez l'adresse vers l'octet suivant après le float 'f'.
  EEPROM.put(eeAddress, Badge[n]);
}
////////////////////////////////  SETUP  ///////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  while (!Serial);

  init_eeprom();  // Première écriture
  read_eeprom(3); // Vérification des données chambre 3

  Badge[3].credit = 6;
  write_eeprom(3); // Modification des données chambre 3
  read_eeprom(3); // Vérification du changement
}

void loop() {

}
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 21, 2020, 06:00 pm
C'est super, ça marche nickel ! ;D

Si j'ai bien compris, le "void init_eeprom()" se fait seulement 1 fois lorsque je téléverse le programme ; il copie l'intégralité du tableau sur la EEPROM.

Juste une petite question : n'est-il pas préférable de mettre EEPROM.update() à la place EEPROM.put() ? Dans le but d'éviter trop d'écriture inutile..

EDIT: ça ne marche pas tant que ça finalement :/ les crédits ne se décompte pas de la mémoire EEPROM mais de la flash...

Code: [Select]
void loop() {
int credit_min = 0;

  if (digitalRead(bouton_play) == HIGH) {
    if (Badge[3].credit != credit_min) {
      Badge[3].credit--;
      Serial.print("New Credits= "); Serial.println(Badge[3].credit);

      write_eeprom(3); // Modification des données chambre 3
      read_eeprom(3); // Vérification du changement
      delay (2000);
    }
  }
}


Même en mettant la void init_eeprom()  en commentaire... À chaque fois que je reset c'est la valeur du tableau qui est reprise et non la nouvelle valeur du crédit après le décompte.

Je pense savoir d'où cela vient, c'est "Badge[3].credit " qui va directement chercher dans la structure et pas dans la mémoire EEPROM. Comment lire le crédit directement depuis la mémoire ?
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 21, 2020, 07:52 pm
Ce que je t'ai donné, c'est juste des exemples d'utilisation de l'EEPROM. Mais tu dois faire tes propres fonctions pour ton propre besoin.

La fonction init, est une sauvegarde de l'ensemble de ton tableau dans l'EEPROM. Tu peux l'appeler autrement. Je l'ai appelée init parce que dans ton exemple test, elle sert à initialiser l'EEPROM.

Les fonctions write_ et read_ vont mettre à jour et lire une structure dans ton tableau sauvé dans l'EEPROM.

Quote
Je pense savoir d'où cela vient, c'est "Badge[3].credit " qui va directement chercher dans la structure et pas dans la mémoire EEPROM. Comment lire le crédit directement depuis la mémoire ?
Ton fonctionnement doit être le suivant : tu utilises la mémoire RAM (le tableau Badge[]) lors des changements : il garde la vision courante des crédits et numéros de badges.

A certains moments (à définir : périodiquement, à chaque changement ?), tu sauves le contenu du tableau dans l'EEPROM. La fonction init te permet de faire ça.

Au lancement du code, après un crash ou une coupure d'alimentation, tu dois aller lire le contenu de l'EEPROM pour le stocker dans ton tableau : tu peux le faire comme ça :

Code: [Select]
void read_all_eeprom(int n) {
  for (int i=0; i<12;i++) {
    int eeAddress = i * sizeof(Params);
    EEPROM.get(eeAddress, Badge[i]);
    Serial.print("Case numéro  "); Serial.println(i);
    Serial.println(Badge[i].nom);
    Serial.println(Badge[i].sernum);
    Serial.println(Badge[i].credit);
  }
}

La question est de savoir s'il s'agit de la première exécution (auquel cas ton EEPROM est sûrement vide donc il ne faut pas lire dedans) ou pas (dans ce cas, tu peux lire). Pour ça, tu peux mettre à l'adresse 0 de l'EEPROM un "nombre magique" (il y a d'autres possibilités), disons 42.
Au lancement, tu lis ce qui se trouve à l'adresse 0 : si c'est 42 tu peux lire le tableau et le stocker en RAM, sinon, il ne faut pas lire.
Bien sûr, comme maintenant l'adresse 0 est prise, il faudra décaler tes adresses de stockage dans l'EEPROM de 1.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 21, 2020, 11:45 pm
Le "void read_all_eeprom()" c'est très pratique lors de la première initialisation pour voir toutes les données.

Seulement tant que la struct Params Badge [12] = {} existe en dur dans le code, l'enregistrement ne fonctionne pas... À chaque coupure de courant il me reprend la valeur initiale des crédits (celle qui se trouve dans ce tableau)... :smiley-confuse:

Voici le code entier:
Code: [Select]
#include <EEPROM.h>

int eeAddress = 0; //Adresse EEPROM à partir de laquelle commencer la lecture
int bouton_play = 2;         //pin bouton play
int credit_min = 0;

struct Params {
  char nom[11];
  uint32_t sernum;
  byte credit;
};

struct Params Badge[12] = {
  //  nom         sernum       credit
  "MASTER",    2778220336,     0,  // Carte Master
  "CHAMBRE 1", 1669386246,     1,  // Badge 1
  "CHAMBRE 2", 3009123561,     2,  // Badge 2
  "CHAMBRE 3", 3009327833,     3,  // Badge 3
  "CHAMBRE 4", 0, 0,               // Badge 4
  "CHAMBRE 5", 0, 0,               // Badge 5
  "CHAMBRE 6", 0, 0,               // Badge 6
  "CHAMBRE 7", 0, 0,               // Badge 7
  "CHAMBRE 8", 0, 0,               // Badge 8
  "CHAMBRE 9", 0, 0,               // Badge 9
  "CHAMBRE 10", 0, 0,              // Badge 10
  "CHAMBRE 11", 0, 0,              // Badge 11
};

///////////////////////////////  RECUP STRUCT BADGE  ///////////////////////////////
void read_all_eeprom() {
  for (int i = 0; i < 12; i++) {
    int eeAddress = i * sizeof(Params);
    EEPROM.get(eeAddress, Badge[i]);
    Serial.print("Badge N°"); Serial.println(i);
                              Serial.println(Badge[i].nom);
    Serial.print("UID: ");    Serial.println(Badge[i].sernum);
    Serial.print("Crédits= ");Serial.println(Badge[i].credit);
    Serial.println("-----------------");
  }
}
///////////////////////////////  SAUVE TOUT SUR EEPROM  ///////////////////////////////
void init_eeprom() {
  EEPROM.put(0, Badge);
  Serial.println("Données Enregistrées !");
}
////////////////////////////////  LIRE SUR EEPROM  ///////////////////////////////////
void read_eeprom(int n) {
  int eeAddress = n * sizeof(Params); // Déplacez l'adresse vers l'octet suivant après une ligne d'info
  Params Badge;
  EEPROM.get(eeAddress, Badge);
  Serial.println(Badge.nom);
  Serial.println(Badge.sernum);
  Serial.println(Badge.credit);
  Serial.println("-----------------");
}

void write_eeprom(int n) {
  int eeAddress = n * sizeof(Params); // Déplacez l'adresse vers l'octet suivant après le float 'f'.
  EEPROM.put(eeAddress, Badge[n]);
  Serial.println("La valeur a été modifié !");
}
////////////////////////////////  SETUP  ///////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  while (!Serial);
  pinMode(bouton_play, INPUT); // Indiquer BOUTON comme entrée
 
  //Initialisation du Tableau
  read_all_eeprom();
  init_eeprom();  // Première écriture

  Serial.println("Ready !");
}

void loop() {

  if (digitalRead(bouton_play) == HIGH) {
    if (Badge[3].credit != credit_min) {
      Badge[3].credit--;
      Serial.print("New Credits= "); Serial.println(Badge[3].credit);

      write_eeprom(3); // Modification des données chambre 3
      read_eeprom(3); // Vérification du changement

      delay (2000);
    }
  }
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 22, 2020, 09:28 am
Voila, j'ai fait ce que je t'ai décrit plus haut :
Code: [Select]
#include <EEPROM.h>

#define MAX_UTILS 12
int eeAddress = 0; //Adresse EEPROM à partir de laquelle commencer la lecture
const int bouton_play = 2;         //pin bouton play
const byte MAGIC = 42;
int credit_min = 0;

struct Params {
  char nom[11];
  uint32_t sernum;
  byte credit;
};
struct Params Badge[MAX_UTILS];

///////////////////////////////  RECUP STRUCT BADGE  ///////////////////////////////
void read_all_eeprom() {
  Serial.println("Lecture EEPROM et init tableau de badges");
  for (int i = 0; i < MAX_UTILS; i++) {
    int eeAddress = i * sizeof(Params) + 1;
    EEPROM.get(eeAddress, Badge[i]);
    Serial.print("Badge N°"); Serial.println(i);
    Serial.println(Badge[i].nom);
    Serial.print("UID: ");    Serial.println(Badge[i].sernum);
    Serial.print("Crédits= "); Serial.println(Badge[i].credit);
    Serial.println("-----------------");
  }
}
///////////////////////////////  SAUVE TOUT SUR EEPROM  ///////////////////////////////
void init_eeprom() {
  Serial.println("Initialisation de l'EEPROM");
  EEPROM.put(0, MAGIC);
  Params Badge[MAX_UTILS] = {
    //  nom         sernum       credit
    "MASTER",    2778220336,     0,  // Carte Master
    "CHAMBRE 1", 1669386246,     1,  // Badge 1
    "CHAMBRE 2", 3009123561,     2,  // Badge 2
    "CHAMBRE 3", 3009327833,     3,  // Badge 3
    "CHAMBRE 4", 0, 0,               // Badge 4
    "CHAMBRE 5", 0, 0,               // Badge 5
    "CHAMBRE 6", 0, 0,               // Badge 6
    "CHAMBRE 7", 0, 0,               // Badge 7
    "CHAMBRE 8", 0, 0,               // Badge 8
    "CHAMBRE 9", 0, 0,               // Badge 9
    "CHAMBRE 10", 0, 0,              // Badge 10
    "CHAMBRE 11", 0, 0,              // Badge 11
  };
  EEPROM.put(1, Badge);
  Serial.println("Données Enregistrées !");
}
////////////////////////////////  LIRE SUR EEPROM  ///////////////////////////////////
void read_eeprom(int n) {
  if (n >= MAX_UTILS) {
    Serial.print("Unable to read badge number ");
    Serial.println(n);
    return;
  }
  int eeAddress = n * sizeof(Params) + 1; // Déplacez l'adresse vers l'octet suivant après une ligne d'info
  Params Badge;
  EEPROM.get(eeAddress, Badge);
  Serial.println(Badge.nom);
  Serial.println(Badge.sernum);
  Serial.println(Badge.credit);
  Serial.println("-----------------");
}

void write_eeprom(int n) {
  if (n >= MAX_UTILS) {
    Serial.print("Unable to write badge number ");
    Serial.println(n);
    return;
  }
  int eeAddress = n * sizeof(Params) + 1; // Déplacez l'adresse vers l'octet suivant après le float 'f'.
  EEPROM.put(eeAddress, Badge[n]);
  Serial.println("La valeur a été modifiée !");
}
////////////////////////////////  SETUP  ///////////////////////////////////////////
void setup() {
  Serial.begin(115200);
  while (!Serial);
  pinMode(bouton_play, INPUT); // Indiquer BOUTON comme entrée

  //Initialisation du Tableau
  byte verif = 0;
  EEPROM.get(0, verif);
  if (verif == MAGIC) read_all_eeprom();  // lecture EEPROM
  else init_eeprom();  // Première écriture

  Serial.println("Ready !");
}

void loop() {

  if (digitalRead(bouton_play) == HIGH) {
    if (Badge[3].credit != credit_min) {
      Badge[3].credit--;
      Serial.print("New Credits= "); Serial.println(Badge[3].credit);

      write_eeprom(3); // Modification des données chambre 3
      read_eeprom(3); // Vérification du changement

      delay (2000);
    }
  }
}

A la première exécution, ça donne ça :
Quote
Initialisation de l'EEPROM
Données Enregistrées !
Ready !
Et à la seconde :
Quote
Lecture EEPROM et init tableau de badges
Badge N°0
MASTER
UID: 2778220336
Crédits= 0
-----------------
Badge N°1
CHAMBRE 1
UID: 1669386246
Crédits= 1
-----------------
Badge N°2
CHAMBRE 2
UID: 3009123561
Crédits= 2
-----------------
Badge N°3
CHAMBRE 3
UID: 3009327833
Crédits= 3
-----------------
Badge N°4
CHAMBRE 4
UID: 0
Crédits= 0
-----------------
Badge N°5
CHAMBRE 5
UID: 0
Crédits= 0
-----------------
Badge N°6
CHAMBRE 6
UID: 0
Crédits= 0
-----------------
Badge N°7
CHAMBRE 7
UID: 0
Crédits= 0
-----------------
Badge N°8
CHAMBRE 8
UID: 0
Crédits= 0
-----------------
Badge N°9
CHAMBRE 9
UID: 0
Crédits= 0
-----------------
Badge N°10
CHAMBRE 10
UID: 0
Crédits= 0
-----------------
Badge N°11
CHAMBRE 11
UID: 0
Crédits= 0
-----------------
Ready !
Si tu veux réinitialiser l'EEPROM, il suffit de changer 42 en autre chose dans le code ici:
Code: [Select]
const byte MAGIC = 42;
A l'exécution suivante, il trouvera 42 dans l'EEPROM, mais le comparera à la nouvelle valeur et comme ce sera différent, il refera l'initialisation.

Je n'ai pas câblé le bouton, donc je n'ai pas pu tout vérifier : est-ce que ça fonctionne comme il faut lorsque tu appuies sur le bouton ?
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 22, 2020, 08:06 pm
C'est parfait, ça marche nickel. Merci Beaucoup !  :D
Je l'ai associé à l'ensemble de mon système.

Cependant, je viens de me poser une question ; si par exemple, le locataire de la chambre 3 perd son badge...

Est ce qu'il est possible que la carte Master puisse remplacer le badge 3 perdu par un nouveau avec un système de compteur pour sélectionner le badge 3 grâce au bouton ? Dans le but, d'éviter de retoucher au code à chaque fois qu'il y a une perte...
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 22, 2020, 08:49 pm
Il faut écrire les lignes de code pour faire ça... Tout est possible.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 23, 2020, 04:26 pm
J'ai tenté quelque chose...  :(

Mais je ne comprends pas pourquoi le bouton_play (qui sert à sélectionner la bonne ligne, ex : Badge 11) ne fonctionne pas pendant le fonctionnement du "programMode"

Actuellement le "programMode" s'active et se désactive nickel, mais entre temps les fonction de la void badge_master() sont illisibles...

Voici le bout de code:

Code: [Select]
///////////////////////////////////////// LIT UID BADGE ///////////////////////////////////
uint8_t getID() {
  // Getting ready for Reading PICCs
  if ( ! rfid.PICC_IsNewCardPresent()) {
    return 0;
  }
  if ( ! rfid.PICC_ReadCardSerial()) {
    return 0;
  }
  serNumLu = *((uint32_t *)rfid.uid.uidByte);
  Serial.println(); date_heure();
  //Affiche le serNumLu sur le moniteur série (UID Badge [........])
  Serial.print("UID Badge ["); Serial.print(serNumLu); Serial.println("] ");
  tagok = 0;
  rfid.PICC_HaltA(); // Arrête de lire
  return 1;
}
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII   LOOP   IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//
void loop() {
  do {
    successRead = getID();  // définit successRead à 1 lorsque nous lisons dans le lecteur, sinon 0

    for (int i = 0 ; i < nbUser ; i++) {
      if (serNumLu == Badge[i].sernum) tagok = 1;    // badge reconnue dans le tableau
    }
    if (serNumLu == Badge[0].sernum) tagok = 255;  // carte master reconnue

  }
  while (!successRead);   //le programme n'ira pas plus loin si vous n'obtenez pas une lecture réussie
  if (tagok == 1 ) {
    badge_ok();
  }
  if (programMode) {
    if (tagok == 255) {
      Serial.println(F("========================="));
      Serial.println(F("ARRET MODE PROGRAM"));
      Serial.println(F("========================="));
      tone(BUZZER, 1200, 100);
      digitalWrite(LED_B, LOW);
      programMode = false;
      return;
    }
  }
  else {
    if (tagok == 255) {
      programMode = true;
      Serial.println(F("========================="));
      Serial.println(F("MODE PROGRAM ACTIF"));
      Serial.println(F("========================="));
      badge_master();
    }
    else {
      if (tagok == 0 ) {
        badge_erreur();
      }
    }
  }
  delay(2000);
  clean_7seg();     // on éteint le 7 segment
}
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII  CARTE MASTER  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//
void badge_master() {
  digitalWrite(LED_B, HIGH);
  tone(BUZZER, 1200, 100);                            //Allume Led bleu+Buzzer
  if (digitalRead(bouton_play) == HIGH) {
    for (int i = 0 ; i < nbUser ; i++) {
      i++;
      Serial.print(i);
      delay(500);
      // Affiche chiffre "compteur" sur 7 segement
      byte compteur = digit[i];
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, compteur);
      digitalWrite(latchPin, HIGH);

      // Se préparer à lire les Badges
      if ( ! rfid.PICC_IsNewCardPresent()) {
      }
      if ( ! rfid.PICC_ReadCardSerial()) {
      }
      serNumLu = *((uint32_t *)rfid.uid.uidByte);
      LED_Verte();                                     //allume LED Verte et buzzer ok
      //Affiche le serNumLu sur le moniteur série (UID Badge [........])
      Serial.print("UID Badge ["); Serial.print(serNumLu); Serial.println("] ");
      rfid.PICC_HaltA(); // Arrête de lire
     
      serNumLu = Badge[i].sernum;
      //Affiche le serNumLu sur le moniteur série (UID Badge [........])
      Serial.println("Lecture du nouveau Badge...");
      Serial.print("UID Badge ["); Serial.print(Badge[i].sernum); Serial.println("] ");
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
  }
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 24, 2020, 11:09 am
C'est pas facile car le code n'est pas complet.
Que veux-tu dire par
Quote
les fonction de la void badge_master() sont illisibles
Qu'est-ce qu'une fonction illisible ?

Tu peux remplacer ceci
Code: [Select]
    for (int i = 0 ; i < nbUser ; i++) {
      if (serNumLu == Badge[i].sernum) tagok = 1;    // badge reconnue dans le tableau
    }
    if (serNumLu == Badge[0].sernum) tagok = 255;  // carte master reconnue
par cela
Code: [Select]
    if (serNumLu == Badge[0].sernum) tagok = 255;  // carte master reconnue
    else for (int i = 1 ; i < nbUser ; i++) {
      if (serNumLu == Badge[i].sernum) tagok = 1;    // badge reconnue dans le tableau
    }

Mais à la fin de la boucle, tu sais seulement qu'un badge a été reconnu, tu ne sais pas lequel. Tu devrais faire ça :
Code: [Select]
      if (serNumLu == Badge[i].sernum) { tagok = 1; break; }  // badge reconnue dans le tableau
Le break stoppe la boucle et la variable i contient le numéro du badge reconnu.

Dans la suite, tu peux changer ton code comme suit (pour éviter un return dans la loop):
Code: [Select]
  if (tagok == 255) {
    if (programMode) {
      Serial.println(F("========================="));
      Serial.println(F("ARRET MODE PROGRAM"));
      Serial.println(F("========================="));
      tone(BUZZER, 1200, 100);
      digitalWrite(LED_B, LOW);
      programMode = false;
    } else {
      programMode = true;
      Serial.println(F("========================="));
      Serial.println(F("MODE PROGRAM ACTIF"));
      Serial.println(F("========================="));
      badge_master();
    }
  } else if (tagok == 0 ) badge_erreur();

Tu es conscient que tu ne traites pas les autres tags pour l'instant ?

Dans badge_master, ajoute un delay(30) pour annuler l'effet des rebonds du bouton.
Ca c'est bizarre :
Code: [Select]
    for (int i = 0 ; i < nbUser ; i++) {
      i++;
      Serial.print(i);
Pourquoi un i++ dans la boucle ?
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 30, 2020, 07:14 pm
Bonjour lesept  :)

Je te remercie énormément pour l'aide que tu m'apportes  :D

Les modifications de codes que tu as écrits fonctionnent nickel et c'est plus logique dans la lecture.  :)

le i++; c'est une erreur de ma part  :smiley-sweat:

Pour le void badge_master() je ne comprends pas pourquoi je n'affiche pas le résultat du compteur  "i" (le chiffre sur le 7segment) suite à l'appui sur le bouton_play...
Et quand je scan un autre badge que la carte Master (qu'il soit connu ou non), il ne lit pas dans la void badge_master() mais dans la void loop().

L'objectif :

1) scan Badge Master --> ProgramMode ON
2) select d'un chiffre correspondant à une chambre par l'appui successif du bouton_play (ex: N°3, après 3 appui sur bouton_play)
3) scan nouveau badge inconnu
4) enregistre le UID du nouveau badge dans l'EEPROM à la place de celui de la chambre 3
5) scan Badge Master --> ProgramMode OFF

J'en suis là pour le code après correction:
Code: [Select]
///////////////////////////////////////// LIT UID BADGE ///////////////////////////////////
uint8_t getID() {
  // Getting ready for Reading PICCs
  if ( ! rfid.PICC_IsNewCardPresent()) {
    return 0;
  }
  if ( ! rfid.PICC_ReadCardSerial()) {
    return 0;
  }
  serNumLu = *((uint32_t *)rfid.uid.uidByte);
  Serial.println(); date_heure();
  //Affiche le serNumLu sur le moniteur série (UID Badge [........])
  Serial.print("UID Badge ["); Serial.print(serNumLu); Serial.println("] ");
  tagok = 0;
  rfid.PICC_HaltA(); // Arrête de lire
  return 1;
}
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII   LOOP   IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//
void loop() {
  do {
    successRead = getID();  // définit successRead à 1 lorsque nous lisons dans le lecteur, sinon 0

    if (serNumLu == Badge[0].sernum) tagok = 255;  // carte master reconnue
    else for (int i = 1 ; i < nbUser ; i++) {
        if (serNumLu == Badge[i].sernum) { tagok = 1; break; }  // badge reconnue dans le tableau
      }
  }
  while (!successRead);   //le programme n'ira pas plus loin si vous n'obtenez pas une lecture réussie
  if (tagok == 1 ) {
    badge_ok();
  }
  if (tagok == 255) {
    if (programMode) {
      Serial.println(F("========================="));
      Serial.println(F("ARRET MODE PROGRAM"));
      Serial.println(F("========================="));
      tone(BUZZER, 1200, 100);
      digitalWrite(LED_B, LOW);
      programMode = false;
    } else {
      programMode = true;
      Serial.println(F("========================="));
      Serial.println(F("MODE PROGRAM ACTIF"));
      Serial.println(F("========================="));
      badge_master();
    }
  } else if (tagok == 0 ) badge_erreur();
 
  delay(2000);
  clean_7seg();     // on éteint le 7 segment
}
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII  CARTE MASTER  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//
void badge_master() {
  digitalWrite(LED_B, HIGH);
  tone(BUZZER, 1200, 100);                            //Allume Led bleu+Buzzer
  if (digitalRead(bouton_play) == HIGH) {
    for (int i = 0 ; i < nbUser ; i++) {
      Serial.print(i);
      delay(30);
      // Affiche chiffre "compteur" sur 7 segement
      byte compteur = digit[i];
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, compteur);
      digitalWrite(latchPin, HIGH);

      // Se préparer à lire les Badges
      if ( ! rfid.PICC_IsNewCardPresent()) {
      }
      if ( ! rfid.PICC_ReadCardSerial()) {
      }
      serNumLu = *((uint32_t *)rfid.uid.uidByte);
      LED_Verte();                                     //allume LED Verte et buzzer ok
      //Affiche le serNumLu sur le moniteur série (UID Badge [........])
      Serial.print("UID Badge ["); Serial.print(serNumLu); Serial.println("] ");
      rfid.PICC_HaltA(); // Arrête de lire

      serNumLu = Badge[i].sernum;
      //Affiche le serNumLu sur le moniteur série (UID Badge [........])
      Serial.println("Lecture du nouveau Badge...");
      Serial.print("UID Badge ["); Serial.print(Badge[i].sernum); Serial.println("] ");
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
  }
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 30, 2020, 09:49 pm
Ton code est encore incomplet. La variable digit je ne sais pas ce que c'est ni comment elle est définie.

Je verrai demain pour le code. Cependant j'ai une question pour le point 2). Comment l'arduino sait-il que tu as fini d'appuyer sur le bouton ?

Il faut décider d'une temporisation au bout de laquelle, si le bouton n'est pas enfoncé, ça veut dire que le numéro de la chambre est choisi, et qu'on peut passer à l'étape suivante. Ok ?
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 31, 2020, 01:03 am
Je t'ai mis le code complet en PJ

Pour le 2) la temporisation c'est une bonne idée. :)   

Je pensais qu'on pouvait scanner un nouveau badge pendant que le chiffre voulu était apparent sur le 7 segment... :-\
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 31, 2020, 11:39 am
Voila, j'ai modifié la fonction master :
Code: [Select]
/*
  1) scan Badge Master --> ProgramMode ON
  2) select d'un chiffre correspondant à une chambre par l'appui successif du bouton_play (ex: N°3, après 3 appui sur bouton_play)
  3) scan nouveau badge inconnu
  4) enregistre le UID du nouveau badge dans l'EEPROM à la place de celui de la chambre 3
  5) scan Badge Master --> ProgramMode OFF
*/
void badge_master() {
  digitalWrite(LED_B, HIGH);
  tone(BUZZER, 1200, 100);  //Allume Led bleu+Buzzer
  // select d'un chiffre correspondant à une chambre par l'appui successif du bouton_play
  // (ex: N°3, après 3 appui sur bouton_play)
  byte roomNumber = 0;
  Serial.println("Appuyez sur le bouton pour selectionner la chambre");
  const unsigned long tempo = 3000ul; // temporisation : fin d'appui bouton
  unsigned long wait = millis();
  while (millis() - wait < tempo) {
    if (digitalRead(bouton_play) == HIGH) {
      delay (30);  // debounce
      ++ roomNumber;
      if (roomNumber > nbUser + 1) roomNumber = 1;
      Serial.print ("Chambre numéro :");
      Serial.println(roomNumber);
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, roomNumber);
      digitalWrite(latchPin, HIGH);

      wait = millis();
    }
  }
  if (roomNumber == 0) {
    Serial.println ("Aucune chambre selectionnee !");
    return;
  }

  // scan nouveau badge inconnu
  if (! rfid.PICC_IsNewCardPresent());
  if (! rfid.PICC_ReadCardSerial());
  serNumLu = *((uint32_t *)rfid.uid.uidByte);
  LED_Verte();                                     //allume LED Verte et buzzer ok
  //Affiche le serNumLu sur le moniteur série (UID Badge [........])
  Serial.print("UID Badge ["); Serial.print(serNumLu); Serial.println("] ");
  rfid.PICC_HaltA(); // Arrête de lire

  //  enregistre le UID du nouveau badge
  // dans l'EEPROM à la place de celui de la chambre sélectionnée
  Badge[roomNumber].sernum = serNumLu;
  //Affiche le serNumLu sur le moniteur série (UID Badge [........])
  Serial.println("Lecture du nouveau Badge...");
  Serial.print("UID Badge ["); Serial.print(Badge[roomNumber].sernum); Serial.println("] ");
  write_eeprom(roomNumber);   // Modification des données sur l'EEPROM
  read_eeprom(roomNumber);    // Vérification du changement
}


Par contre, n'ayant jamais utilisé d'afficheur 7 segments, je ne sais pas si ce que j'ai mis pour afficher est correct. Ce sont les lignes
Code: [Select]
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, roomNumber);
      digitalWrite(latchPin, HIGH);

J'ai mis une tempo de 3 secondes pour savoir la fin des appuis sur le bouton. Ça peut se modifier si c'est trop long.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 31, 2020, 06:07 pm
C'est super ce que tu m'as donné :D

J'ai réalisé quelques modifications sur la durée qui été un peu courte :)

Pour l'affichage sur le 7 segment tu avais oublié une bricole, je l'ai corrigé.

Code: [Select]

      // Affiche le numéro de la chambre sur le 7 segment
      byte chiffre = digit[roomNumber];  //<== SUR CETTE LIGNE
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, chiffre);
      digitalWrite(latchPin, HIGH);
      wait = millis();


Je viens de penser que j'ai oublié une fonction.. Durant le Mode Program, je selectionne toujours mon numéro de chambre avec le bouton et je scan un badge.
Seulement, si l'UID du badge scanné est le même que celui dans l'eeprom, j'aimerais qui me mette les crédits du numéro de badge à 5.

Exemple de résultat sur le moniteur série:
Quote
Date : 31/7/2020 17H44min 15Sec
UID Badge [3009340601]
Badge OK - CHAMBRE 11
Credits= 0

Date : 31/7/2020 17H47min 20Sec
UID Badge [2778220336]
=========================
MODE PROGRAM ACTIF
=========================
Appuyez sur le bouton pour selectionner la chambre
Chambre numéro :1
Chambre numéro :2
Chambre numéro :3
Chambre numéro :4
Chambre numéro :5
Chambre numéro :6
Chambre numéro :7
Chambre numéro :8
Chambre numéro :9
Chambre numéro :10
Chambre numéro :11

Lecture du Badge...
UID Badge [3009340601]
Badge connu
-----------------
CHAMBRE 11
3009340601
0
-----------------
Crédits réinitialisé !
La valeur modifiée dans l'EEPROM
-----------------
CHAMBRE 11
3009340601
5
-----------------
Date : 31/7/2020 17H44min 30Sec
UID Badge [2778220336]
=========================
ARRET MODE PROGRAM
=========================

Que dois-je ajouter ?

Code: [Select]
void badge_master() {
  digitalWrite(LED_B, HIGH);
  tone(BUZZER, 1200, 100);  //Allume Led bleu+Buzzer
  // select d'un chiffre correspondant à une chambre par l'appui successif du bouton_play
  // (ex: N°3, après 3 appui sur bouton_play)
  byte roomNumber = 0;
  Serial.println("Appuyez sur le bouton pour selectionner la chambre");
  const unsigned long tempo = 4000ul; // temporisation : fin d'appui bouton
  unsigned long wait = millis();
  while (millis() - wait < tempo) {
    if (digitalRead(bouton_play) == HIGH) {
      delay (500);  // debounce
      ++ roomNumber;
      if (roomNumber > nbUser + 1) roomNumber = 1;
      Serial.print ("Chambre numéro :");
      Serial.println(roomNumber);
      // Affiche le numéro de la chambre sur le 7 segment
      byte chiffre = digit[roomNumber];
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, chiffre);
      digitalWrite(latchPin, HIGH);
      wait = millis();
    }
  }
  if (roomNumber == 0) {
    Serial.println ("Aucune chambre selectionnee !");
    LED_Rouge();
    return;
  }

  // scan nouveau badge inconnu
  if (! rfid.PICC_IsNewCardPresent());
  if (! rfid.PICC_ReadCardSerial());
  serNumLu = *((uint32_t *)rfid.uid.uidByte);
  LED_Verte();                                     //allume LED Verte et buzzer ok
  rfid.PICC_HaltA(); // Arrête de lire

  //  enregistre le UID du nouveau badge
  // dans l'EEPROM à la place de celui de la chambre sélectionnée
  Badge[roomNumber].sernum = serNumLu;
  //Affiche le serNumLu sur le moniteur série (UID Badge [........])
  Serial.println("Lecture du nouveau Badge...");
  Serial.print("UID Badge ["); Serial.print(Badge[roomNumber].sernum); Serial.println("] ");
  write_eeprom(roomNumber);   // Modification des données sur l'EEPROM
  read_eeprom(roomNumber);    // Vérification du changement
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Jul 31, 2020, 07:45 pm
Après la fin de la lecture (après le halt) tu compares
Code: [Select]
if (Badge[roomNumber].sernum == serNumLu) {
  Badge[roomNumber].credit = 5;
} else {
  Badge[roomNumber].sernum = serNumLu;
}

Ensuite tu mets les lignes d'affichage sur la console et le 7 segments

... à tester ...
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Jul 31, 2020, 11:56 pm
Tout marche du feu de Dieu ! tu es au top Lesept :D :D

Tu commence à connaître mon penchant pour les petits plus ^^

Pour finir, je souhaiterais réaliser un reset de tous crédits des badges au 1er jour de chaque mois (ex: 01/xx/20xx) afin qu'ils reviennent tous à 5 crédits.

Tu as s'en doute remarqué que j'avais pour cela rajouté un module DS3231 et que j'utilisais la library <Wire.h>

Sachant que toutes mes variables de temps sont dans cette void :

Code: [Select]
void date_heure() {
  //Affiche date et heure lors du badge sur le moniteur série
  dt = clock.getDateTime();
  //Exemple --> Date : 2/5/2020 16H 15min 31Sec
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 01, 2020, 10:25 am
Je vais te laisser faire celui-là.

Le principe ici est de tester que le jour vaut 1 et qu'il est exactement 0:00:00.

Si la condition est vraie, alors tu mets 5 crédits partout (boucle for) et tu ajoutes un delay (1000) pour faire en sorte que la condition devienne fausse, afin d'éviter de refaire ça plusieurs fois.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 01, 2020, 07:11 pm
Merci pour tes indications :)

J'ai essayé de bricoler quelque chose, mais je ne vois pas pourquoi ça ne se lance pas... :smiley-confuse:
(j'ai volontairement changé l'heure et les minutes pour accélérer le processus de test) :)

Code: [Select]
void loop() {
  if ((dt.day = 1) && (dt.hour = 19) && (dt.minute = 7) && (dt.second = 0)) {
    int count = nbUser - 1;
    while (count != nbUser) {
      for (int i = 1 ; i < count ; i++) {
        Badge[count].credit = 5;
        Serial.println(Badge[count].nom);
        Serial.print("Crédits= "); Serial.println(Badge[count].credit);
        write_eeprom(count);   // Modification des données sur l'EEPROM
        read_eeprom(count);    // Vérification du changement
        delay (1000);
        }
      }
  } else {
    do {
      ...... // Attend lecture d'un Badge à scanner
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 01, 2020, 07:51 pm
Les conditions, c'est == :)

Enlève le while qui ne sert à rien ainsi que la variable count, tu fais juste un for de 1 à nbusers

Et le delay va après la boucle for, c'est juste pour passer à 0 heures 1 seconde et éviter que la condition du if soit réalisée plusieurs fois
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 01, 2020, 11:43 pm
il y a un beug dans la matrix... :smiley-sweat:

Il ne se passe toujours rien malgré tes corrections... :smiley-confuse:

Code: [Select]
void loop() {
if ((dt.day == 1) && (dt.hour == 23) && (dt.minute == 40) && (dt.second == 0)) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[nbUser].credit = 5;
      Serial.println(Badge[nbUser].nom);
      Serial.print("Crédits= "); Serial.println(Badge[nbUser].credit);
      write_eeprom(nbUser);   // Modification des données sur l'EEPROM
      read_eeprom(nbUser);    // Vérification du changement
    }
    delay (1000);
  } else {
    do {
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 12:26 am
Ajoute ceci avant ton if pour vérifier que tu entres ou non dans le if
Code: [Select]

  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 11:06 am
j'ai essayé avec ce que tu m'as dit, ça n'a pas été d'un grand succès :smiley-sweat:

J'obtiens un résultat en enlevant "dt.second" et après avoir scan un badge...

Quote
Présentez votre badge sur le lecteur ...

Date : 2/8/2020 10H58min 35Sec

Date : 2/8/2020 10H58min 43Sec
UID Badge [3009386505]
Badge OK - CHAMBRE 11
Credits= 2
Date : 2/8/2020 10H59min 18Sec

⸮
;⸮<%_
Crédits= 5
Impossible d'écrire le badge N° 12
Impossible de lire le badge numéro 12
⸮
;⸮<%_
Crédits= 5
Impossible d'écrire le badge N° 12
Impossible de lire le badge numéro 12
⸮
;⸮<%_
Crédits= 5
Impossible d'écrire le badge N° 12
Impossible de lire le badge numéro 12
⸮
;⸮<%_
le code :

Code: [Select]
void loop() {
  dt = clock.getDateTime();
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");

  if ((dt.day == 2) && (dt.hour == 10) && (dt.minute == 59) /*&& (dt.second == 0)*/) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[nbUser].credit = 5;
      Serial.println(Badge[nbUser].nom);
      Serial.print("Crédits= "); Serial.println(Badge[nbUser].credit);
      write_eeprom(nbUser);   // Modification des données sur l'EEPROM
      read_eeprom(nbUser);    // Vérification du changement
    }
    delay (1000);
  } else {
    do {
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 12:15 pm
Dans la boucle for, il faut changer Badge[nbUser] en Badge[ i ]
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 01:21 pm
Oh qu'elle erreur bête...  :smiley-sweat:

Alors le fonctionnement marche MAIS...

La réinitialisation s'est déclenché après avoir fait un scan d'un badge et une fois qu'on fait apparaître dt = clock.getDateTime(); au début de la Loop. (j'ai volontairement enlevé dt.second dans mon test pour être sur que cela s'exécute)

J'en ai déduit que la fonction reset crédit ne se lance que s'il y a un affichage de dt = clock.getDateTime(); toutes les secondes, afin de comparer avec les valeur du "if" demandé.
Quote
if ((dt.day == 2) && (dt.hour == 13) && (dt.minute == 7) && (dt.second == 0)) {
Du coup comment faire pour que la void date_heure() se lance toutes les seconde, pendant que les autres fonctions de scan badge tourne ?

Code: [Select]
void date_heure() {
  //Affiche date et heure lors du badge sur le moniteur série
  dt = clock.getDateTime();
  //Exemple --> Date : 2/5/2020 16H 15min 31Sec
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");
}

Code: [Select]
void loop() {
  date_heure();
  if ((dt.day == 2) && (dt.hour == 13) && (dt.minute == 7) && (dt.second == 0)) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[i].credit = 5;
      Serial.println(Badge[i].nom);
      Serial.print("Crédits= "); Serial.println(Badge[i].credit);
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
    delay (1000);
  } else {
    do {
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 01:39 pm
Quote
Du coup comment faire pour que la void date_heure() se lance toutes les seconde, pendant que les autres fonctions de scan badge tourne ?
C'est simple. Tu utilises millis() pour mesurer une seconde. Lorsque la seconde est passée, tu appelles ta fonction date_heure() 
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 02:06 pm
D'accord... J'ai aucune idée de comment intégrer cela... :smiley-confuse:

j'imagine que c'est quelque chose comme cela :

Quote
unsigned long previousMillis = 0;
previousMillis = millis();

(millis() - previousMillis < 1000)
Mais comment et à quel endroit je dois l'insérer...

Code: [Select]
void loop() {
  date_heure();
  if ((dt.day == 2) && (dt.hour == 13) && (dt.minute == 7) && (dt.second == 0)) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[i].credit = 4;
      Serial.println(Badge[i].nom);
      Serial.print("Crédits= "); Serial.println(Badge[i].credit);
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
    delay (1000);
  } else {
    do {
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 03:54 pm
Ça dépend de ce que tu veux faire.

Plus un code devient compliqué, plus il y a de possibilités, et plus il est important de bien spécifier ce qu'on veut faire. Si tout est bien spécifié, le code vient naturellement, et il n'est pas nécessaire d'y apporter des modifications par la suite...

Si je comprends bien, ce que tu veux c'est mettre à jour la variable dt chaque seconde ?

Mais cette partie ne doit pas être bloquante car le code peut faire autre chose en même temps. Exact ?

C'est la fonction date_heure qui fait la mise à jour. Si elle ne sert qu'à ça et ne sera jamais appelée par ton code pour autre chose que cette mise à jour chaque seconde, autant mettre millis dans la fonction.
Sinon, il faut le mettre à l'appel de la fonction.

Que choisis-tu ?
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 03:58 pm
C'est exactement ça, tu as bien cerné le problème :)

la void date_heure() ne sera appelé qu'uniquement pour reset les crédits tous les début de mois
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 04:16 pm
OK, alors :

Code: [Select]
void date_heure() {
  static unsigned long chrono = millis();
  if (millis() - chrono < 1000ul) return;
  chrono = millis();
  //Affiche date et heure lors du badge sur le moniteur série
  dt = clock.getDateTime();
  //Exemple --> Date : 2/5/2020 16H 15min 31Sec
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");
}

Pas besoin de changer l'appel à la fonction : ça devrait t'afficher l'heure et mettre à jour dt chaque seconde.
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 04:36 pm
Alors ça a marché 1 fois je ne sais pas comment (en bidouillant, en badgeant,...) mais depuis ça ne marche pas. :smiley-confuse:

J'ai l'impression que ça vient des conditions, qui ne sont pas bonne dans la loop...

Code: [Select]
void loop() {
  date_heure();    //Vérifie chaque seconde l'heure s'il faut reset les crédits des badges
   else {
    do {   //lecture des badges

//---------------------------------------------------//
void date_heure() {
  static unsigned long chrono = millis();
  if (millis() - chrono < 1000ul) return;
  chrono = millis();

  //Affiche date et heure lors du badge sur le moniteur série
  dt = clock.getDateTime();
 
  //Exemple --> Date : 2/5/2020 16H 15min 31Sec
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");

  if ((dt.day == 2) && (dt.hour == 16) && (dt.minute == 29) && (dt.second == 0)) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[i].credit = 2;
      Serial.println(Badge[i].nom);
      Serial.print("Crédits= "); Serial.println(Badge[i].credit);
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
    delay (1000);
  }
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 05:08 pm
Tu peux ôter le else et le do et leurs accolades
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 05:59 pm
J'ai ôté le else{ mais sans le do{ le programme de lecture des badges ne fonctionne pas...

Ne faudrait-il pas faire un schéma comme ceci ?

Code: [Select]
void loop() {
  date_heure();

while (date_heure){
do {      //lecture des badges...


J'ai essayé de faire ça, mais la void date_heure() ne peux pas s'insérer dans la condition while...  :smiley-confuse:
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 07:17 pm
Plus un code devient compliqué, plus il y a de possibilités, et plus il est important de bien spécifier ce qu'on veut faire. Si tout est bien spécifié, le code vient naturellement, et il n'est pas nécessaire d'y apporter des modifications par la suite...
Exprime clairement ce que doit faire la loop. Moi je ne sais pas encore...
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 08:37 pm
Oh pardon, à force d'avoir la tête dans le projet, j'en ai oublié mes bonnes manières... :smiley-confuse:

Le projet : Monnayeur RFID pour machine à laver pour une collocation de 11 chambres

Accessoires : Arduino Nano, RFID, Afficheur simple 7 segments couplé à un multiplex 74hc595 , Buzzer, Relais, LED RGB, Module RTC horloge et un bouton pour play.

Utilisations : Limiter l'accès à la machine à laver par le biais d'un badge pour chaqu'un des locataires. Dont 5 crédits par badge ; soit une utilisation de 5 fois/mois/chambre.

La personne remplit la machine avec son linge sale, choisit le programme voulu et pour lancer la machine à laver, il faut que :....

Fonction de la Loop :
- Cas le plus favorable : le locataire scan son badge. Il est reconnu dans la base de donnée : LED_Verte(), Buzzer OK, le nombre de crédit lié au badge est affiché sur le 7 segment. Il lui reste des crédits il peut alors appuyer sur le bouton qui va lui décompter 1 crédit et enclencher le relais qui va à son tour lancer le programme de la machine à laver. FIN DE LOOP

- Cas défavorable :le locataire scan son badge. Il est reconnu dans la base de donnée : LED_Verte(), Buzzer OK, le nombre de crédit lié au badge est affiché sur le 7 segment. Il ne lui reste aucun crédits : LED_Rouge(), Buzzer ERREUR. Il ne peut pas appuyer sur le bouton. FIN DE LOOP

- Cas le plus défavorable : le locataire ou l'admin scan son badge. Il n'est pas reconnu dans la base de donnée : LED_Rouge(), Buzzer ERREUR. FIN DE LOOP

- Fonction Master 1 : L'admin scan son badge. LED_Bleu(), Buzzer Admin. Il ne fait aucune action pendant 5 sec. LED_Rouge(), Buzzer ERREUR. LED_Verte() Relais actif. FIN programMode

- Fonction Master 2 : L'admin scan son badge. LED_Bleu(), Buzzer Admin. Il appui plusieurs fois sur le bouton play pour sélectionner un numéro qui s'affiche sur le 7 segment. (Le chiffre correspond à une chambre, il fait 5 appuis : Chambre 5). Il a 5 sec pour placer un badge sur le lecteur RFID. Le badge sélectionné correspond déjà au badge de la chambre 5 : les crédits du badge sont réinitialisés à 5 crédits. FIN programMode

- Fonction Master 3 : L'admin scan son badge. LED_Bleu(), Buzzer Admin. Il appui plusieurs fois sur le bouton play pour sélectionner un numéro qui s'affiche sur le 7 segment. (Le chiffre correspond à une chambre, il fait 5 appuis : Chambre 5). Il a 5 sec pour placer un badge sur le lecteur RFID. Le badge sélectionné ne correspond pas au badge de la chambre 5 : l'UID du nouveau badge scanné est remplacé par l'ancien UID de la chambre 5. Les anciens crédits sont concervés pour être attribué au nouveau badge. FIN programMode

- Mode Reset crédits Auto : Tous les 1er du mois, une boucle vérifie la date et l'heure pour réinitialiser tous les crédits de toutes les chambres afin de les remettre à 5 crédits.

Toutes les données sont stockées dans l'EEPROM et actualisées au fur et à mesure des actions. :)

Code: [Select]
void loop() {
  date_heure();
  do {
    successRead = getID();  // définit successRead à 1 lorsque nous lisons dans le lecteur, sinon 0

    if (serNumLu == Badge[0].sernum) tagok = 255;  // carte master reconnue
    else for (int i = 1 ; i < nbUser ; i++) {
        if (serNumLu == Badge[i].sernum) {
          tagok = 1;  // badge reconnue dans le tableau
          break;
        }
      }
  }

  while (!successRead);   //le programme n'ira pas plus loin si vous n'obtenez pas une lecture réussie
  if (tagok == 1 ) {
    badge_ok();
  }
  if (tagok == 255) {
    if (programMode) {
      programMode_OFF();
    } else {
      programMode_ON();
      badge_master();
    }
  } else if (tagok == 0 ) badge_erreur();

  delay(2000);
  clean_7seg();     // on éteint le 7 segment
}
//IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII  CARTE MASTER  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII//
void badge_master() {
  digitalWrite(LED_B, HIGH);
  tone(BUZZER, 1200, 100);  //Allume Led bleu+Buzzer
  // select d'un chiffre correspondant à une chambre par l'appui successif du bouton_play
  // (ex: N°3, après 3 appui sur bouton_play)
  byte roomNumber = 0;
  Serial.println("Appuyez sur le bouton pour selectionner la chambre");
  const unsigned long tempo = 4500ul; // temporisation : fin d'appui bouton
  unsigned long wait = millis();
  while (millis() - wait < tempo) {
    if (digitalRead(bouton_play) == HIGH) {
      delay (300);  // debounce
      ++ roomNumber;
      if (roomNumber > nbUser + 1) roomNumber = 1;
      Serial.print ("Chambre numéro :");
      Serial.println(roomNumber);
      // Affiche le numéro de la chambre sur le 7 segment
      byte chiffre = digit[roomNumber];
      digitalWrite(latchPin, LOW);
      shiftOut(dataPin, clockPin, LSBFIRST, chiffre);
      digitalWrite(latchPin, HIGH);
      wait = millis();
    }
  }
  if (roomNumber == 0) {
    Serial.println ("Aucune chambre selectionnee !");
    LED_Rouge();
    programMode_OFF();
    LED_Verte();
    relais_actif();
    return;
  }

  // scan nouveau badge inconnu
  if (! rfid.PICC_IsNewCardPresent());
  if (! rfid.PICC_ReadCardSerial());
  serNumLu = *((uint32_t *)rfid.uid.uidByte);
  rfid.PICC_HaltA(); // Arrête de lire

  // compare UID badge, si identique alors reset credit
  if (Badge[roomNumber].sernum == serNumLu) {
    successWrite_credit();
    Serial.println("Badge connu");
    Serial.print("UID Badge ["); Serial.print(Badge[roomNumber].sernum); Serial.println("] ");
    Badge[roomNumber].credit = 5;
    Serial.println("Credits Réinitialisé...");
    Serial.print("Crédits= "); Serial.println(Badge[roomNumber].credit);
    write_eeprom(roomNumber);   // Modification des données sur l'EEPROM
    read_eeprom(roomNumber);    // Vérification du changement
    programMode_OFF();
    return;
  } else {
    //  enregistre le UID du nouveau badge
    // dans l'EEPROM à la place de celui de la chambre sélectionnée
    Badge[roomNumber].sernum = serNumLu;
    successWrite_UID();
    //Affiche le serNumLu sur le moniteur série (UID Badge [........])
    Serial.println("Lecture du nouveau Badge...");
    Serial.print("UID Badge ["); Serial.print(Badge[roomNumber].sernum); Serial.println("] ");
    write_eeprom(roomNumber);   // Modification des données sur l'EEPROM
    read_eeprom(roomNumber);    // Vérification du changement
    programMode_OFF();
    return;
  }
}
//////////////////////////////////// VERIFIE DATE POUR RESET CREDITS /////////////////////////////////
void date_heure() {
  static unsigned long chrono = millis();
  if (millis() - chrono < 1000ul) return;
  chrono = millis();
  //Affiche date et heure lors du badge sur le moniteur série
  dt = clock.getDateTime();

  //Exemple --> Date : 2/5/2020 16H 15min 31Sec
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");

  if ((dt.day == 2) && (dt.hour == 17) && (dt.minute == 33) && (dt.second == 0)) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[i].credit = 2;
      Serial.println(Badge[i].nom);
      Serial.print("Crédits= "); Serial.println(Badge[i].credit);
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
    delay (1000);
    return;
  }
}
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 02, 2020, 10:18 pm
Très bien, c'est beaucoup plus clair. Je vais te redemander un exercice similaire : réécrire ça mais cette fois ci du point de vue de l'arduino. Lui, il ne sait pas que quelqu'un est dans la pièce. Lorsqu'un badge est passé sur le lecteur, il ne sait pas de quel badge il s'agit, il doit le chercher lui-même.

Ça commencera par ça :
L'arduino vérifie si un badge est passé sur le lecteur.

Si tu fais ça clairement, l'écriture de la loop se fera toute seule. On pourra même la faire avec des fonctions pour la rendre le plus simple possible.

Ça revient un peu à décrire une machine d'états...
(https://lh3.googleusercontent.com/proxy/68ttRBr5JJeBMVJ-LopKaZr1RE97UkfWo2Z3_73x4sSDGT5mEZZyuOag5qaoJLHEXaae1yxob58LzEKiUW-zkkg2fxNEECNdgS8D0lcQCqaKK8fFUymg5eXwvw)
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 02, 2020, 11:18 pm
Avec tous ces exos, on se croirait de retour à l'école... Je vais finir par vous appeler Professeur  :P

Ça me plaît ces petites réflexions structurées !  :D

J'ai pondu quelque chose qui correspond au déroulé que vous m'avez indiqué. Ça marche plutôt bien !  :D  
Pouvez-vous me dire s'il y a des choses à améliorer corriger ?

EDIT : J'avais une erreur, que je viens de modifier (un else { transformé en else if{ sinon ça ne passait pas) :smiley-sweat:

Voici le code:
Code: [Select]
///////////////////////////////////////// LIT UID BADGE ///////////////////////////////////
uint8_t getID() {
  // Getting ready for Reading PICCs
  if ( ! rfid.PICC_IsNewCardPresent()) {
    return 0;
  }
  if ( ! rfid.PICC_ReadCardSerial()) {
    return 0;
  }
  serNumLu = *((uint32_t *)rfid.uid.uidByte);
  Serial.println();
  //Affiche le serNumLu sur le moniteur série (UID Badge [........])
  Serial.print("UID Badge ["); Serial.print(serNumLu); Serial.println("] ");
  tagok = 0;
  rfid.PICC_HaltA(); // Arrête de lire
  return 1;
}

//////////////////////////////////// VERIFIE DATE & HEURE  /////////////////////////////////
void date_heure() {
  static unsigned long chrono = millis();
  if (millis() - chrono < 1000ul) return;
  chrono = millis();
  //Affiche date et heure lors du badge sur le moniteur série
  dt = clock.getDateTime();

  //Exemple --> Date : 2/5/2020 16H 15min 31Sec
  Serial.print("Date : ");
  Serial.print(dt.day);    Serial.print("/");
  Serial.print(dt.month);  Serial.print("/");
  Serial.print(dt.year);   Serial.print(" ");
  Serial.print(dt.hour);   Serial.print("H");
  Serial.print(dt.minute); Serial.print("min ");
  Serial.print(dt.second); Serial.println("Sec");
}

//////////////////////////////////// RESET CREDITS /////////////////////////////////
void reset_credit() {
  if ((dt.day == 1) && (dt.hour == 0) && (dt.minute == 0) && (dt.second == 0)) {
    for (int i = 1 ; i < nbUser ; i++) {
      Badge[i].credit = 5;
      Serial.println(Badge[i].nom);
      Serial.print("Crédits= "); Serial.println(Badge[i].credit);
      write_eeprom(i);   // Modification des données sur l'EEPROM
      read_eeprom(i);    // Vérification du changement
    }
    delay (1000);
    return;
  }
}

/////////////////////////////////////// VOID LOOP ////////////////////////////////////
void loop() {
  successRead = getID();    // Définit successRead à 1 lorsque nous lisons dans le lecteur, sinon 0

if (serNumLu == Badge[0].sernum) tagok = 255;  // carte master reconnue
    else for (int i = 1 ; i < nbUser ; i++) {
        if (serNumLu == Badge[i].sernum) {
          tagok = 1;  // badge reconnue dans le tableau
          break;
        }
      }
  if (successRead != 1) {   // Pas de badge présent sur le lecteur
    date_heure();           // Affiche Date & Heure toutes les secondes
    reset_credit();         // Si 1er du mois, Reset crédits
    return;                // Rien à faire
  }
  else if (successRead == 1) { // Badge présent sur le lecteur
    if (tagok == 1 ) {      // Badge connu
      badge_ok();
    }
    if (tagok == 255) {     // Badge Master
      if (programMode) {
        programMode_OFF();
      } else {
        programMode_ON();
        badge_master();
      }
    } else if (tagok == 0 ) { // Badge non connu
      badge_erreur();
    }
  }
  delay(2000);
  clean_7seg();     // on éteint le 7 segment
}
Title: Re: créer Tableau de valeur qui varie
Post by: 5_cylindres on Aug 03, 2020, 12:23 am
Avec tous ces exos, on se croirait de retour à l'école... Je vais finir par vous appeler Professeur  :P
Ça me plaît ces petites réflexions structurées !
c'est (à mon sens) le but d'un (de ce) forum, et pas de faire le boulot à la place des autres.

la démarche de le sept est excellente !
c'est en travaillant toi-même que tu progresseras : profite de la leçon
(qu'est-ce que j'aimerais tomber sur de bons tutos en français pour combler mes propres lacunes !)
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 03, 2020, 12:35 am
c'est (à mon sens) le but d'un (de ce) forum, et pas de faire le boulot à la place des autres.

la démarche de le sept est excellente !
c'est en travaillant toi-même que tu progressera : profite de la leçon
Je suis tout à fait d'accord avec toi :D

Et puis c'est tellement satisfaisant d'arriver à construire quelque chose soi-même, certes un peu beaucoup aidé mais dans la finalité on comprend, on progresse.

Je remercierai jamais assez le professeur lesept et le reste du forum pour m'avoir épaulé tout au long de ce projet  :smiley-mr-green:

J'ai adoré cet apprentissage/perfectionnement méthodique, pas à pas. Il n'y a rien de mieux pour comprendre comment sont faites les choses et pouvoir à son tour les utiliser à sa guise. :)

Il me reste plus qu'à assembler, souder le tout. Imprimer en 3D un petit boitier sympa et voir dans la pratique s'il ne manque rien dans le programme ou faire des correctifs.  :smiley-cool:

À très vite pour de nouveau projet :D
Title: Re: créer Tableau de valeur qui varie
Post by: lesept on Aug 03, 2020, 10:36 am
Tout le plaisir est pour moi...

(https://fr.web.img6.acsta.net/videothumbnails/19/07/25/16/46/2693131.jpg)


Je pense que tu devrais ôter le delay(2000) à la fin de la loop, car ça bloque le code et ça risque de faire louper un passage de badge.
Si c'est juste pour laisser le 7 segments allumé un moment, et que ça ne risque rien du côté lecteur, alors laisse-le...

Bonne continuation !
Title: Re: créer Tableau de valeur qui varie
Post by: tomobilus on Aug 03, 2020, 10:52 am
Merci encore :D

Le delay (2000) est fait exprès, c'est pour laisser l'afficheur 7 segment allumé quelques secondes avec les nouveaux crédits sur le badge.

Donc si j'en crois votre expérience, le prochain projet pourrait-être "comment braquer une banque ?" :P

Très bonne continuation à vous et au plaisir ;)