Go Down

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

tomobilus

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

lesept

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.
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

tomobilus

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

lesept

Tu peux ôter le else et le do et leurs accolades
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

tomobilus

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:

lesept

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...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

tomobilus

#51
Aug 02, 2020, 08:37 pm Last Edit: Aug 02, 2020, 09:01 pm by tomobilus
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;
  }
}

lesept

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 pas de badge :
    • si une seconde est passée, il met dt à l'heure.
    • si on est le premier du mois à minuit, tous les crédits passent à 5.
    • autre cas : rien à faire
  • Si un badge est passé :
    • c'est un badge client : ...
    • c'est le badge master : ...

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...
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

tomobilus

#53
Aug 02, 2020, 11:18 pm Last Edit: Aug 03, 2020, 12:24 am by tomobilus
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
}

5_cylindres

#54
Aug 03, 2020, 12:23 am Last Edit: Aug 03, 2020, 12:36 am by 5_cylindres
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 !)
"Le Maître te montrera le puits et te fournira le seau, mais il n'ira pas puiser l'eau à ta place" (Jigorō Kanō)

tomobilus

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

lesept

Tout le plaisir est pour moi...



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 !
A force d'essayer on finit par réussir... Donc, plus ça rate, plus on a de chances que ça marche (proverbe Sharduinok).

tomobilus

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

Go Up