Go Down

Topic: créer Tableau de valeur qui varie (Read 1 time) previous topic - next topic

tomobilus

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
}

iznobe

#1
Jun 14, 2020, 06:05 pm Last Edit: Jun 14, 2020, 06:08 pm by iznobe
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};
mini serveur domotique : https://forum.arduino.cc/index.php?topic=493039.0

hbachetti

#2
Jun 14, 2020, 06:18 pm Last Edit: Jun 14, 2020, 06:20 pm by hbachetti
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.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

fdufnews

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 ;)

tomobilus

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:

hbachetti

Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

tomobilus

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;
        }
       }
      }
     }

hbachetti

#7
Jun 14, 2020, 07:17 pm Last Edit: Jun 14, 2020, 07:18 pm by hbachetti
Il est plutôt incomplet, mais semble en bonne voie.
Il manque en particulier une ligne essentielle:
  id = *((unsigned long *)rfid.uid.uidByte);
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

tomobilus

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
   }
}

hbachetti

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.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

tomobilus

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

fdufnews

#11
Jul 07, 2020, 03:16 pm Last Edit: Jul 07, 2020, 03:17 pm by fdufnews
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)

fdufnews

#12
Jul 07, 2020, 03:22 pm Last Edit: Jul 07, 2020, 03:27 pm by fdufnews
Pour écrire et lire tes structures en EEPROM il faut regarder de ce coté:
EEPROMPut
EEPROMGet

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

ATTENTION à ne pas faire d'écritures inutiles sous peine de tuer l'EEPROM assez rapidement.

lesept

Il y a eu un projet similaire récemment ici (un peu long à lire, mais tout y est je pense)
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

biggil

#14
Jul 07, 2020, 04:04 pm Last Edit: Jul 07, 2020, 05:40 pm by biggil
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.
Aide toi, le compilateur t'aidera

Go Up