Auteur Sujet: Annonces de gare avec RFID  (Lu 48148 fois)

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Annonces de gare avec RFID
« le: juin 30, 2019, 05:10:10 pm »
J'initie un projet  un de gestion des annonces de gare par RFID, indépendant de tout logiciel de pilotage, tant que faire se peut.

Je pars de l'article Annonces en gare avec la RFID.
J'adapte au matériel à ma disposition : lecteur RFID SPI, afficheur lcd I2C, DFPlayer, NanoV3
Cela m’embête de modifier chaque sketch quand la liste des trains évolue:  J’envisageais donc d’écrire dans le RFID, à l’aide d’un sketch particulier, ou d'une option du sketch:
- Le N° du train = .identifiant.
- Le nom du train = .nom
- Le type de train = .type  (Voyageur avec arrêt, Voyageur sans arrêt, Marchandise …)
Je travaille actuellement sur ce point précis.

Pour les trains entrant en gare:
A terme, le sketch surveillerait un certain nombre ( 10 ) d’adresses décodeurs Dcc afin de déterminer la provenance et la destination des trains et reconstituer l’annonce :
"Le train NrTrain en provenance de Provenance va entrer en gare Destination éloignez vous de la bordure du quai."

Les trains marchandise donneraient une autre annonce
"Attention, Destination au passage du train. Eloignez vous de la bordure du quai."

Certains wagons pourraient déclencher d’autres messages.

Le trigger est donc la détection du RFID qui déclenche la création du message correspondant.

Les adresses DCC à surveiller seraient gérées sous forme de CV
Les 3 premières adresses DCC permettrait de calculer la provenance (Un CV par 2^3=8 possibilité donnant le N° du MP3 correspondant)
Les 7 dernières adresses DCC permettrait de calculer la destination (Un CV par 2^4=16 possibilité donnant le N° du MP3 correspondant)
A moins que ce ne soit l'inverse ...

Pour les trains au départ:

Je cherche encore l'idée lumineuse: Quel trigger utiliser pour que cela fonctionne sans logiciel de pilotage ?
L'annonce est faite alors que le train est en position depuis un certain temps, qu'il est encore possible de modifier sa destination,

Je reste à l'écoute de vos suggestions.
Par ailleurs, je suis à la recherche de RFID autocollant de 19 mm x 12 mm : auriez vous un fournisseur à m’indiquer ?

Xavier

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3050
  • 100% Arduino et N
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #1 le: juin 30, 2019, 05:32:48 pm »
Bonjour,

On trouve ces étiquettes RFID en cherchant sur eBay « NTAG213 »

comme ceux-ci :
https://rover.ebay.com/rover/0/0/0?mpre=https%3A%2F%2Fwww.ebay.fr%2Fulk%2Fitm%2F272628279713
Cordialement,
Dominique

Didier44

  • Newbie
  • *
  • Messages: 43
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #2 le: juillet 02, 2019, 10:18:15 am »
Bonjour,

Tu as aussi ce fournisseur très complet en Italie que j'ai utilisé
https://www.shopnfc.com/fr/

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #3 le: août 04, 2019, 03:50:13 pm »
Une premiere partie ...

Préambule
Il existe de multiple sortes de RFID en fonction des besoins. En ce qui nous concerne, le cout, la facilité d'approvisionnement, la distance maximum de lecture me conduisent à utiliser des Tags MIFARE Classic 1K de NXP.
Les exemples fournis avec la bibliothèque ne permettent pas directement de lire et écrire dans la boucle du sketch. Ceci devrait vous aider a y parvenir!
Organisation de la mémoire d'un RFID
Les RFID utilisés disposent d'une mémoire organisée par blocs de 16 octets. J'utilise pour ma part les RFID les plus courant, qui possèdent 16 blocs (de 0 à 15).
Les blocs multiples de 4 (0, 4, 8 ...), sont réservés. Les autres blocs peuvent être utilisés pour y stocker vos données.
Attention : Pour lire ou écrire un RFID, il faut évidement qu'il soit présent à proximité du lecteur !
Lire un RFID
Les RFID utilisés disposent d'une mémoire organisée par blocs de 16 octets. On va donc lire l'ensemble du bloc pour n'afficher que les octets requis.
L'affichage se fera en Hexadécimal ou sous forme de caractère suivant les besoins.
Les étapes sont alors :
EtapeCommande
Autentificationstatus = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
Lecturestatus = mfrc522.MIFARE_Read(block, buffer, &size);
Chaque étape met a jour le status qui sera utilisé pour gérer les messages d'erreur
if (status != MFRC522::STATUS_OK) {…}L'instruction .GetStatusCodeName(status) donne le message d'erreur
Voici le sous-programme utilisé:

// ========================================================
// Lecture Block
// ========================================================
void Read_Block(byte block,int n1, int n2, int mode) {
  //  Serial.println();
  for (byte i = 0; i < MFRC522::MF_KEY_SIZE; ++i) {
    key.keyByte[i] = 0xFF;
  }
//  if (mfrc522.PICC_ReadCardSerial()) {
    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
    if (status == MFRC522::STATUS_OK) {
      status = mfrc522.MIFARE_Read(block, buffer, &size);
      if (status == MFRC522::STATUS_OK) {
        if (mode<2) {
          Serial.print(F("Data in block ")); Serial.print(block); Serial.print (F(": "));
        }
        TmpStr="";
        for (int p=n1; p<n2; p++) {
          if (mode==0) {
            Serial.print(buffer[p] < 0x10 ? " 0" : " ");
            Serial.print(buffer[p], HEX);
          }
          else if(mode%2==1) {
            if (buffer[p]>20) TmpStr+=(char)buffer[p];
            else TmpStr+="-";
          }
        }
        if(mode%2==1) Serial.print(TmpStr);
        Serial.println();
      }
    }
//  }
}

Dans tous les cas, une fois l'écriture effectuée, il faut clore le cryptage du RFID a l'aide de l'instruction .PCD_StopCrypto1()
Voici donc l'appel correspondant:
      Read_Block(Param[0].toInt(),Param[1].toInt(),Param[2].toInt(),0);
      mfrc522.PCD_StopCrypto1();      // Stop encryption on PCD
Ecrire dans un RFID
Pourquoi écrire dans un RFID?
Chaque RFID possède un numéro à priori unique: son identifiant. Lire cet identifiant est trés simple.   On peut ensuite utiliser un tableau contenant toutes les informations associées a cet identifiant. Il faudra cependant que ce tableau soit présent, identique, dans chacun des sketches, des arduinos qui pourront lire les RFID. Chaque fois qu'un nouvel RFID sera utilisé, il faudra mettre a jour tous ces tableaux!
En écrivant dans le RFID les informations communes, associées a ce RFID, elles deviennent disponible partout, sans besoin de copier de tableau.
Les RFID utilisés disposent d'une mémoire organisée par blocs de 16 octets. Tous ne sont pas utilisables, certains sont réservés!
Écriture d'un bloc :
La librairie permet d’écrire la totalité des 16 octets d'un bloc. Nous allons donc pouvoir y écrire une chaîne de 16 caractères maximum. Si la chaîne est moins longue, on la complétera par des espaces.
Les étapes sont alors :
EtapeCommande
Autentificationstatus = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
Ecriturestatus = mfrc522.MIFARE_Write(block, nbuffer, 16);
Chaque étape met a jour le status qui sera utilisé pour gérer les messages d'erreur
if (status != MFRC522::STATUS_OK) {…}L'instruction .GetStatusCodeName(status) donne le message d'erreur
Écriture d'un octet :
La librairie ne donne pas accès a un octet seul. Il faudra donc écrire le bloc complet en ne modifiant que l'octet désiré.
Voici le sous-programme utilisé:
// ========================================================
// Configuration RFID
// ========================================================
void ConfigureRFID(byte block, String s, byte v) {
  // Vidage du buffer
  byte nbuffer[16];
  for (int p=0;p<16;p++) {
    nbuffer[p]=' ';
  }
  if (String(s.charAt(0))=="#") {          // Configuration du nom
    for (int p=1;p<s.length();p++) {
      nbuffer[p-1]=s[p];
      Serial.print(nbuffer[p-1]);Serial.print(" ");
    }
    Serial.println("!");
  } else {          // Configuration du Nr et du type
    Read_Block(block,0,16,0);     // Recupere les valeurs initiales
    for (int p=0;p<16;p++) {
      nbuffer[p]=buffer[p];
      Serial.print(nbuffer[p]);Serial.print("-");
    }
    Serial.println("!");
    nbuffer[s.toInt()]=v;       // Change le CV concerné
  }
  Serial.println(F("Authenticating using key A..."));
  for (int p=0;p<16;p++) {
    Serial.print(nbuffer[p]);Serial.print(" ");
  }
  Serial.println("!");
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    for (int p=0;p<16;p++) {
      Serial.print(nbuffer[p]);Serial.print(" ");
    }
    Serial.println("!");
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    for (int p=0;p<16;p++) {
      Serial.print(nbuffer[p]);Serial.print(" ");
    }
    Serial.println("!");
    return;
  }
  else Serial.println(F("PCD_Authenticate() success: "));
  Serial.println();
  for (int p=0;p<16;p++) {
    Serial.print(nbuffer[p] < 0x10 ? " 0" : " ");
    Serial.print(nbuffer[p], HEX);
  }
  status = mfrc522.MIFARE_Write(block, nbuffer, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("MIFARE_Write() success: "));
}
Dans tous les cas, une fois l'écriture effectuée, il faut clore le cryptage du RFID a l'aide de l'instruction .PCD_StopCrypto1()
Voici donc l'appel correspondant :
    ConfigureRFID(Param[0].toInt(),Param[1], Param[2].toInt());
    mfrc522.PCD_StopCrypto1();      // Stop encryption on PCD

Ces premières fonctions vont me permettre d'enregistrer dans les RFID:
  • Le numero MP3 du train
  • Le type de train (Voyageur, Marchandise) ou de l’événement (Retard, Grève ...)
  • Le nom du train a des fins d'affichage

A suivre...
« Modifié: août 04, 2019, 03:57:07 pm par Barbadidoua »

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3050
  • 100% Arduino et N
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #4 le: août 04, 2019, 04:12:10 pm »
Bonjour Xavier,

Enfin quelqu’un qui bosse en Août ! Merci Xavier pour ces explications très claires.

Il est, en effet, utile de programmer quelques octets de la mémoire des tags pour simplifier les détections, les rendre plus utilisables.

Cordialement
Dominique
Cordialement,
Dominique

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1109
  • HO avec DCC++
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #5 le: août 05, 2019, 06:52:39 am »
Merci Xavier,

Tout ceci est très intéressant et très documenté qui permet d’aller encore un peu plus loin dans la connaissance et la mise en œuvre du RFID.

La solution de stocker des infos sur le TAG présente de nombreux avantages dans d’autres domaines également que la reconnaissance de trains ou les annonces en gare.

Sans que cela ne remette en cause ce que tu proposes, je suis personnellement dans une démarche différente et je profite de ce post pour l’évoquer et éventuellement développer si quelques-uns sont intéressés.

J’ai découvert il y a quelques mois MySQL Connector qui, comme son nom le laisse deviner, est une bibliothèque qui permet de faire communiquer des Arduino (et ESP 8266, 32…) avec des bases SQL. Je l’ai testée et mis en œuvre. C’est assez simple et fonctionne vraiment très bien.

https://github.com/ChuckBell/MySQL_Connector_Arduino

Bien sûr, c’est plus lourd au niveau du soft et du hard (j’avais implanté la base SQL sur Raspberry) mais c’est la solution qui m’intéresse le plus car c’est comme cela que j’envisage la gestion globale de tout le réseau. Les infos ne sont donc plus ni dans une mémoire quelconque d’un Arduino ou d’un TAG mais dans une base centralisée. Tu parlais de mise à jour, c'est de ce point de vue l'idéal.

Ce que je dis là ne remet pas du tout en question l’intérêt de ta proposition mais vise à apporter de nouvelles pistes de réflexion pour qui serait intéressé.

Merci encore pour ta superbe contribution.

Christophe

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #6 le: août 05, 2019, 06:41:28 pm »
Bonjour Christophe,

C'est vrai que la base SQL est intéressante, dès lors que l'Arduino est connecté sur internet, pour une centrale Dcc++ par exemple. Je suivrai donc goulûment l'avancement de tes recherches.
En ce qui concerne ce projet, je souhaite qu'il reste non connecté et puisse fonctionner en autonomie: des Arduinos qui se parlent ok, mais entre eux et leurs périphériques seulement.

Amicalement,
Xavier

« Modifié: août 05, 2019, 06:47:12 pm par Barbadidoua »

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #7 le: août 05, 2019, 06:44:39 pm »
La suite ...
Communication entre 2 Arduinos (ou plus) par I2C
Préambule
Il existe de multiple façon de communiquer entre Arduino en fonction des besoins. L'utilisation d'un bus, associé au principe de maître-esclave permet de piloter des satellites depuis un point central.
Il existe de multiples bus. I2C, SPI, CAN … J'ai choisi le bus I2C disponible sur la plupart des Arduinos.
La bibliothèque Wire simplifie son utilisation même si elle limite les chaînes transmises à 32 caractères!
Les exemples fournis avec la bibliothèque ne permettent pas directement de lire et écrire dans la boucle du sketch. Ce document devrait vous aider à y parvenir!
Il faudra préalablement utiliser les définitions suivantes, communes aux 2 sketchs:
# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12
# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite
# define I2cMsgLength    60
Maitre
Le maître organise la communication. Il interroge à tour de rôle chaque esclave pour connaître leur besoin.
# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12
# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite
# define I2cMsgLength    60
Dans le Setup
Wire.begin();          

Voici le sous-programme utilisé:
// ========================================================
// Scan des esclaves I2C pour obtenir les messages
// ========================================================
void I2CGetMessages() {
  for (int i=10; i< 15;i++) {
    int j=0;
    int nr=0;
    char Message[I2cMsgLength];
    inStr="";
    //Serial.println(F(" recieved : "));
    Wire.requestFrom(i, I2cMsgLength);     // Demande 60 Octets à l'esclave I2C #i
    while (Wire.available()>0) {           // L'esclave peut envoyer moins d'octets
      Message[j] = Wire.read();            // reception d'un octet
      if (Message[j]>=0) {
        inStr+=Message[j];
      }
      j++;
    }
    // Traitement des messages recus
    if (inStr!="" && inStr.length()>3) {
      Serial.print(F(" recieved ("));
      Serial.print(inStr.length());
      Serial.print(F(") : "));
      Serial.println(inStr);
      if (inStr[2]=='P') {                 // Annonce arrivée des trains
        inStr = String(Dcc.getCV(CV_JINGLE)) + "_" + inStr.substring(3); // (ajout du jingle)
        Annonce(inStr); // Sequencage de l'annonce
      } else if (inStr[2]=='J') {          // Autre sons
        inStr.replace('_',' ');
      } else if (inStr[2]=='-') {          // Defaut
        inStr.replace('_',' ');
      }
    }
    delay(100);
  }
}
Il reste alors a traiter les messages reçus en fonction de ce que l’on souhaite faire.
Esclave
Chaque esclave est identifié de manière unique par son adresse. Les messages reçus sont traités par interruption:
# define I2C_SLAVE1_ADDRESS 11
# define I2C_SLAVE2_ADDRESS 12
# define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite
# define I2cMsgLength    60
Dans le Setup
Wire.begin(I2C_SLAVE_ADDRESS);
  Wire.onRequest(requestEvents);
  Wire.onReceive(receiveEvents);   

Le premier sous-programme utilisé: ne fait rien… et peut même être ignoré
// ========================================================
// Reception message I2C
// ========================================================
void receiveEvents(int numBytes)

  Serial.println(F("---> recieved events"));
  n = Wire.read();
  Serial.print(numBytes);
  Serial.println(F("bytes recieved"));
  Serial.print(F("recieved value : "));
  Serial.println(n);
}

Voici le second sous-programme utilisé: Il renvoie la chaîne Param[0] qui a été stoquée en attente de la demande du maître.
// ========================================================
// Réponse a un message reçu I2C
// ========================================================
void requestEvents()
{
  if (Param[0]!="") {
    Param[0].toCharArray(Message,60);
    Serial.print(F("sending value ("));
    Serial.print(String(Message).length());
    Serial.print(F(") : "));
    Serial.println(String(Message));
    Wire.write(Message);
    Serial.println();
    Param[0]="";
    Param[0].toCharArray(Message,60);
  } else {
    Wire.write("11-");
  }
}

Voici donc comment stoker le message à envoyer , quand cela est nécessaire:
      Serial.print(F("Message : "));
      Serial.println(Param[0]);
      Param[0]="11P"+Param[0];

Je m’aperçois que ’ai codé en dur l’adresse de l’esclave: j’ai honte mais je me soigne!
Je corrigerai dans le programme final ;) peut-être  :o

A suivre...

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1109
  • HO avec DCC++
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #8 le: août 05, 2019, 10:19:21 pm »
Non non, pas du tout, la base SQL n'a pas besoin d'être connectée à internet. Un réseau local suffit.

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #9 le: août 05, 2019, 10:37:23 pm »
Tout a fait, pardon, j'ai pensé Ethernet et tapé Internet.

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #10 le: août 08, 2019, 07:18:27 pm »
Préambule
Avec un arduino, il existe de nombreuses solutions pour jouer de la musique ou faire une annonce. Il existe un module peu cher et simple d’utilisation, le DFPlayer mini, qui pour quelques euros, permet de jouer le fichier MP3 désiré.
Découpage des annonces
On aurait pu avoir un fichier MP3 par annonce… C’est pas très flexible. Alors on va découper les annonces en morceaux que assemblera au dernier moment.
Comment découper une annonce telle que «Le train 7512 en provenance de Lyon va entrer en gare voie C. Éloignez vous de la bordure du quai»?
Les éléments variables sont:
  • le numéro du train
  • la provenance
  • la destination
On découpera donc comme suit:
  • «Le train»
  • 7512
  • «en provenance de»
  • Lyon
  • «va entrer en gare»
  • voie C
  • «Éloignez vous de la bordure du quai»
On replacera chaque élément variable par sa valeur le moment voulu. On ajoutera le jingle en début d’annonce.
On fera de même pour chaque type de message.
Audacity, un logiciel gratuit permet de découper les fichiers MP3, de standardiser leur niveaux.
Provenance et destinations
Comment savoir d’où vient un train, où il va… Il suffit de suivre les rails, donc de connaître la position des appareils de voie situés sur le parcours.
Nous avons de la chance, transformer un Arduino en décodeur d’accessoire est relativement simple, grâce à la bibliothèque NMRA et quelques composants électroniques. On peut ainsi surveiller un nombre limité d’adresses choisies afin de déterminer  provenance et destination.
Cette bibliothèque permet de lire et d’écrire dans l’Eprom des CVs: la bonne aubaine!
Il faut definir les CV et leur valeur par défaut (Un seul est decrit ici: le volume!):
// ========================================================
// Structures DCC
// ========================================================
struct CVPair
{
  uint16_t  CV;
  uint8_t   Value;
};

#define CV_VOLUME               15

CVPair FactoryDefaultCVs [] =
{
  {CV_VOLUME,5},                // Volume Son MP3
}

Pour lire un CV:
   int v=Dcc.getCV(i)

Pour ecrire un CV:
   Dcc.setCV(Param[0].toInt(),Param[1].toInt());

Pour reinitialiser les CV:
// ========================================================
// Reset CV
// ========================================================
void ResetCV() {
  Serial.print(Msg_ResetCV);
  for (int j=0; j < sizeof(FactoryDefaultCVs)/sizeof(CVPair); j++ ) {
    Serial.print(FactoryDefaultCVs[j].CV);
    Serial.print(F(" = "));
    Serial.println(FactoryDefaultCVs[j].Value);
    Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
  }
}

Le suivi des aiguillages est effectué par «MAM-RFID» qui dispose ainsi de tous les éléments pour créer les messages d’annonce.
Voici le sous-programme utilisé:
// ========================================================
// Dcc Accessory Turnout message treatment
// ========================================================

void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower )
{
  DccMsg=Addr;
  DccMsg+=",";
  DccMsg+=Direction;
  DccMsg+=",";
  DccMsg+=OutputPower;
  if (LastDccMsg!=DccMsg) {
    LastDccMsg=DccMsg;
//#ifdef Debug >>>>>>>>>>>>>>>>>>>>>>>>
      Serial.print("notifyDccAccTurnoutOutput: ") ;
      Serial.print(Addr,DEC) ;
      Serial.print(',');
      Serial.print(Direction,DEC) ;
      Serial.print(',');
      Serial.println(OutputPower, HEX) ;
//#endif <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    byte data;
    int address=Addr;
    boolean enable=(Direction==1) ? 1: 0;
    boolean activate=(OutputPower==1) ? 1: 0;
    bool Upd=false;
   
    switch (Mode) {
      case 0:                                      // Update Turnout state, if in the list
        // If address is one of the expected (Aiguillage[])
        // update its direction (Trn[])
        for (int i=0; i<20; i++) {
          if (address=Dcc.getCV(CV_TRN_ADD + i)) {
            if (Trn[i]!=enable) {
              Trn[i]=enable;
              Serial.print(address);
              Serial.print(F(" -> "));
              Serial.println(Trn[i]);
              Upd=true;
            }
          }
        }
        if (Upd) ShowTurnOutState();              // Display turnout known states
        break;
      case 1:                                      // Display received accessory address and state
        digitalWrite(DccAckPin,true);
        tmpDccAddress=address;
        msg = "Detecte Dcc : ";
        msg += String(tmpDccAddress);
        Serial.println(msg);
        msg = "! ou SW2 = Sauve Adresse Dcc ";     //Cmd_SaveDcc;
        msg += String(tmpDccAddress);
        Serial.println(msg);
        digitalWrite(DccAckPin,false);
        break;
    }
  }
}

Vous avez remarqué qu’il y avait deux modes:
Le mode 0 est le mode de fonctionnement normal.
Le mode 1 permet d’afficher toutes les adresses d’accessoires vues par le décodeur: on pourra alors utiliser les adresses detectées pour initialiser les CV des adresses DCC à suivre!

Reste alors à associer a chacun le bon fichier MP3, que l’on enregistrera elles aussi sous forme de CV.
Voici le sous-programme utilisé:
// ========================================================
// Affiche l'etat des aiguillages surveilles
// ainsi que les MP3 de provenance et de destination
// ========================================================
void ShowTurnOutState() {
  String tmp="";
  Serial.println(F("===="));
  for (int i=9;i>=0;i--) {
    if (Trn[i]) tmp+="1"; else tmp+="0";
  }
  Serial.println(tmp);
  // Calcul Provenance
  Provenance=0; // =tmp[2]+2*(tmp[1]+2*Trn[0]);
  for (int i=2;i>=0;i--) {
    Provenance=2*Provenance;
    if (Trn[i]==true) Provenance+=1;
  }
  Serial.print(F("Provenance  : "));
  Serial.print(Provenance);
  Serial.print(F(" CV "));
  Serial.print(CV_MP3_PROV+Provenance);
  Prv=Dcc.getCV(CV_MP3_PROV+Provenance);
  Serial.print(F(" = "));
  Serial.println(Prv);
  // Calcul Destination
  Destination=0; //=Trn[6]+2*(Trn[5]+2*(Trn[4]+2*(Trn[3]+2*(Trn[2]+2*(Trn[1]+2*Trn[0])))));
  for (int i=9;i>2;i--) {
    Destination=2*Destination;
    if (Trn[i]==true) Destination+=1;
  } 
  Serial.print(F("Destination : "));
  Serial.print(Destination);
  Serial.print(F(" CV "));
  Serial.print(CV_MP3_DEST+Destination);
  Dst=Dcc.getCV(CV_MP3_DEST+Destination);
  Serial.print(F(" = "));
  Serial.println(Dst);
}

Le tableau Trn contient la position de chacun des appareils de voie surveillés.
Composer le message d’annonce
Les différents morceaux sont disponible. Il faut les assembler dans le bon ordre.
Voici le sous-programme utilisé:
// ========================================================
// Creation de l'annonce en DCC
// ========================================================
void MakeAnnonce(int train, int t) {
  String s;
  // Calcul Provenance
  Provenance=0; // =tmp[2]+2*(tmp[1]+2*Trn[0]);
  for (int i=2;i>=0;i--) {
    Provenance=2*Provenance;
    if (Trn[i]==true) Provenance+=1;
  }
  Prv=Dcc.getCV(CV_MP3_PROV+Provenance);
  // Calcul Destination
  Destination=0; //=Trn[6]+2*(Trn[5]+2*(Trn[4]+2*(Trn[3]+2*(Trn[2]+2*(Trn[1]+2*Trn[0])))));
  for (int i=9;i>2;i--) {
    Destination=2*Destination;
    if (Trn[i]==true) Destination+=1;
  } 
  Dst=Dcc.getCV(CV_MP3_DEST+Destination);

  if (train!=0) {                     // Le train est connu
    if (t==0) {
      Serial.print(F("Le train "));                              // Creation de l'annonce en fonction des éléments
      Serial.print(train);
      Serial.print(F(" En provenance de "));
      Serial.print(Prv);
      Serial.print(F(" va entrer en gare "));
      Serial.print(Dst);
      Serial.println(F(" Eloignez vous de la bordure des quais"));
      s = "P" + String(Dcc.getCV(CV_LETRAIN)) + "_" + String(train)                                   // Le Train N°
        + "_" + String(Dcc.getCV(CV_PROVENANCE)) + "_" + String(Dcc.getCV(CV_MP3_PROV+Provenance))    // en provenance de
        + "_" + String(Dcc.getCV(CV_VA_ENTRER)) + "_" + String(Dcc.getCV(CV_MP3_DEST+Destination))    // va entrer en gare Voie
        + "_" + String(Dcc.getCV(CV_ELOIGNEZ_VOUS));   
    } else if (t==1) {
      Serial.print(Dst);
      Serial.println(F(" attention au passage d'un train"));         
      s = "P" + String(Dcc.getCV(CV_MP3_DEST+Destination))        // Voie
        + "_" + String(Dcc.getCV(CV_PASSAGE));                    // attention au passage d'un train
    } else if (t==2) {
      Serial.print(F("Attention "));
      Serial.print(F(" le train "));
      Serial.print(train);
      Serial.print(F(" En provenance de "));
      Serial.print(Prv);
      Serial.println(F(" est annonce avec un retard de 10 minutes"));
      s = "P" + String(Dcc.getCV(CV_JINGLE))                     // Jingle
        + "_" + String(train)                                     // Le Train N°
        + "_4_" + String(Dcc.getCV(CV_MP3_PROV+Provenance))       // en provenance de
        + "_11_";                                                 // est annonce avec un retard de 10 minutes     
    } else {
     Serial.println(F("Suite a un mouvement de grève ... "));
      s = "P37_";                                                // Suite a un mouvement de grève ...
    }
  } else {                        // Le Train est inconnu
    long randNumber = random(110,130);
    if (randNumber==109){         // Greve
      s = "P7";                                                 // Par suite d'un mouvement de Greve
    } else {                      // Train sans arrêt
      s = "P7_" + String(Dcc.getCV(CV_MP3_DEST+Destination))     // Attention Voie
        + "_6";                                                  // eloignez vous ...
    }
  }
   Param[0]="11"+s;       // mise a disposition de l'annonce pour les requetes I2C
}

On retrouve ici la variable Param[0], prête à être envoyée à «MAM-Gare» pour y être joué.

Tous les éléments sont là ...

La suite vous permettra de charger les 2 sketches, les MP3 que j'ai utilisé, et vous indiquera comment mettre en œuvre l'ensemble, le modifier en fonction de vos besoins.

A bientôt.
« Modifié: août 08, 2019, 07:25:03 pm par Barbadidoua »

bobyAndCo

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1109
  • HO avec DCC++
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #11 le: août 09, 2019, 09:07:48 am »
Très beau travail, bonne analyse et bonnes solutions. Je pense que cela mériterait de faire un article de fond.

Cela commence à faire un ensemble très complet avec aussi une certaine complexité (je n'ai pas dit compliqué !) Il est peut être intéressant à cette occasion de proposer une solution avec une base SQL comme déjà évoqué. Je pourrai t'aider sur ce point si tu le souhaites.

Encore bravo

Christophe

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3050
  • 100% Arduino et N
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #12 le: août 09, 2019, 11:30:15 am »
Je pensais à la même chose : il y a une belle matière pour un article, et nous pouvons t’aider pour le peaufiner
Amicalement
Dominique
Cordialement,
Dominique

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #13 le: août 09, 2019, 10:28:38 pm »
Bonsoir,

Je vous remercie pour l’intérêt que vous portez a ce sujet. Si vous le permettez, je vais d'abord achever le dernier chapitre avant de penser article et évolutions.
J'ai d'ailleurs certaines évolutions qui commencent à faire jour en mon for intérieur: je les évoquerai en fin du prochain épisode.

Amicalement,
Xavier (qui espère trouver un moment la semaine prochaine pour la suite)
« Modifié: août 29, 2019, 08:46:25 am par Barbadidoua »

Barbadidoua

  • Newbie
  • *
  • Messages: 14
    • Voir le profil
Re : Annonces de gare avec RFID
« Réponse #14 le: août 26, 2019, 03:35:53 pm »
Hardware
J’ai plusieurs fois indiqué MAM. De quoi s’agit-il?
MAM signifie Module d’Animation Modéliste. Vous trouverez de plus amples informations ici, sur le site de son concepteur Philippe Chavatte, avec qui j’ai travaillé pour tester ce montage. Il regroupe les fonctions suivantes sur un même PCB et permet de nombreuses variantes à découvrir ou à créer.
  • Décodeur accessoire DCC
  • Sonorisation (DFPlayer avec ou sans amplification complémentaire)
  • I2C (Afficheur lcd …)
  • Commandes de servomoteurs ( 8 )
  • Amplificateur collecteur ouvert ( 8 )
  • Boutons poussoirs (unitaires ou multiples) / interrupteurs
  • OU 4 entrées (occupation des voies)
  • Alimentation à partir du DCC ou de 12V extérieur
Téléchargements
Le sktech MAM-ReadRFID à charger sur l'arduino nano de MAM pour former MAM-ReadRFID (De nombreuses fonctionnalité de MAM n'étant pas utilisées, il sera peut-être préférable de ne pas utiliser MAM)
Le sktech MAM-Gare  à charger sur l'arduino nano de MAM pour former MAM-Gare
Les MP3 : Ils sont donnés à titre d’exemple mais vous pourrez les remplacer par ceux qui vous conviennent. (J’utilise Audacity pour découper, ajuster, standardiser mes enregistrements MP3)
Ils seront copiés sur la carte micro SD du DFPlayer.  Ils seront placés dans le répertoire \MP3. Leur nom devra impérativement commencer par un nombre à 4 chiffres qui sera chargé dans les CV, le Rfid.
Notez que le fichier correspondant doit exister dans la carte SD du DfPlayer, faute de quoi, il ne pourra être joué.

Arbitrairement j’ai regroupé les fichiers par intérêt, comme suit:
BaseType
0-39(40) Général annonces
50-69(20) Quais
70-89(20) Gares
90-139(50) Trains
150-179(30) Animaux
170-199(20) Véhicules
200-255(55) Ambiance

Commandes
Pour paramétrer, tester mes programmes j’ai choisi d’utiliser l’USB et le moniteur de l’IDE.
De toute façon, il vous faudra charger les sketch: L’IDE est là pour vous permettre de la faire simplement. De plus il met à votre disposition le moniteur, ce qui vous permet de dialoguer avec vos sketches: voir les messages d’erreur, le déroulement du programme, mais aussi passer des commandes pour paramétrer et simuler le fonctionnement!
Paramétrage
Le paramétrage permet d’adapter le fonctionnement du sketch à vos besoins. Il se fait comme pour les décodeurs DCC sous forme de CV ou de variables sauvées en Eeprom (récupérables au démarrage du montage)

Les valeurs de CV par défaut sont automatiquement initialisée quand le CV témoin (volume ou Numéro esclave) vaut 255, c’est à dire quand l’Arduino est neuf (Toutes les valeurs de l’EEPROM sont alors à 255).
Pour remettre tous les CV par défaut, il suffit donc d’affecter la valeur 255 au CV témoin (voir plus loin) puis de faire un Reset du module. (La commande R en fait autant, comme on le verra par la suite).

Le paramétrage des sketches se fait par USB. Les commandes peuvent être envoyées par :
  • Le Moniteur de l'IDE Arduino  (115200 Bauds, 8 bits, NL et CR)
Il est aussi possible de tester le fonctionnement du sketch grâce à ces commandes.
Lors de son initialisation, le sketch chargé dans l'Arduino
  • Indique son nom et sa version (@)
  • Liste les commandes qu'il reconnaît (&)
  • Liste ses paramètres et leur valeur (?)

Le paramétrage des RFID se fait à l’aide du sketch MAM-ReadRfid, permettant de modifier pour  chaque RFID les informations permettant de reconnaître le train ou l’événement correspondant: ces informations, utilisées par ce même sketch, permettent de ne pas modifier la configuration de chaque décodeur lors de l’introduction, la modification ou la suppression d’un train.
Mode ligne de commande
Toutes les commandes que j’utilise sont toutes formatées de la même manière:
Un préfixe sur 1 caractère (non sensible à la casse) immédiatement suivit de paramètres séparés par des espaces.
Elles sont décrites ci dessous dans le tableau Générique quand elle s'appliquent à tous les sketches, ou dans le tableau correspondant au sketch quand elles lui sont dédiées.
CommandeFonction Générique MAM
?AideListe des commandes disponibles
&ListeListe des valeurs des paramètres
@Identification SketchIdentification du sketch chargé
ex: MAM-Gare V0
{a vSet CVProgrammation CV :Adresse (0-255) Valeur(0-15)
{1 255 permet de réinitialiser les CV
}aGet CVLecture CV : Adresse (0-255)
} affiche toutes les CV via USB
VvVolumeNiveau sonore DfPlayer (0-30)
JjJoueJoue fichier MP3 identifié par son N°(1-255)
ZStopStop le MP3 en cours.

CommandeFonction MAM ReadRfid & MAM GaresMAM
RReset CVRemet les CV du décodeur à leur valeur initiale.
Tn vTurnoutTest le changement de position de l’aiguillage suivi n en position v  en absence de DCC
An tAnnonceTest une annonce en absence de RFID (on indique le N° du train et son type)
#Affiche données RFIDAffiche le contenu du RFID devant le lecteur sous forme hexadécimale.
GGet RFID CVG<Bloc> <N° 1er CV dans le bloc> <Nombre de CV>
Affichage des CV du RFID devant le lecteur sous forme hexadécimale.
SSet RFID CVS<Bloc> <N° CV dans le bloc> <Valeur du CV>
S<Bloc> #<Valeur de la chaîne>
Définit le ou les CV du RFID devant le lecteur
Les chaînes ont 16 caractères maximum!
DDéfinit DCCD<n> <Adresse DCC>
Définit l'adresse DCC à suivre en position n
Ces commandes peuvent être utilisées à tout moment pour paramétrer, tester le fonctionnement du montage.
Paramétrage des fichiers MP3 utilisés
Les fichiers MP3 utilisés sont enregistrés dans la carte micro SD du DFPlayer monté sur MAM-Gare.
Chaque des fichiers correspond à un CV: voir tableau ci dessus.
On utilisera  la commande {a v pour modifier ces numéros de fichiers.

Les parties fixes des messages ne sont pas gérées par des CV mais fixées par le sketch
Paramétrage des Gares de provenance et des voies de destination
Je vous propose de commencer par imprimer le tableau suivant et le compléter à la main avec:
Le N° du fichier MP3 correspondant, dans les cases Gare et Voie.
Les adresses DCC des aiguillages, dans les cases adresses Aiguillage
Voir image en bas de page

Vous utiliserez ces informations pour modifier les CV correspondants à l'aide de la commande {a v

Si un CV vaut 255, la gare ou la voie correspondant ne sont pas définis.
Paramétrage des aiguillages surveillés
Ce paramétrage est à faire pour chacune des entrées de gare, chacune étant équipée d'un lecteur RFID associée à MAM-ReadRFID.
Si vous demandez la liste des paramètres à l'aide de la commande &, les adresses surveillées s'affichent sous la forme suivante:

Dcc surveilles (0 à 9)
100 105 111 112 115 145 146 147 148 149

On utilisera  la commande Dn a pour définir l'adresse a en position n(de 0 à 9).

Les adresses des aiguillages sont définies sur 9 bits, comme pour tous les décodeurs d’accessoire.
Les CV 30 à 49 contiennent les adresses des adresses DCC à surveiller. On aurait pu utiliser  la commande {a v pour modifier ces adresses mais la commande Dn a est plus simple!
Une adresse complète tient sur 9 bits, soit 512 combinaisons ou adresses.
Voir image en bas de page

Une fois les CV configurés, le moniteur affichera, à chaque commande accessoire reconnue,  les informations utiles pour associer les fichiers MP3 correspondants aux provenances et destinations.

Vous pouvez aussi utiliser la commande Tx y pour simuler la position de l'aiguillage x en position y
Le moniteur série indique alors:Set Turnout x à y
Position des différents aiguillages surveillés10010100
N° MP3, CV correspondant = Valeur du CVProvenance  : 4 CV 184 = 255
N° MP3, CV correspondant = Valeur du CVDestination : 18 CV 68 = 50








Test du montage
Les étapes suivantes devraient vous permettre de tester votre montage. Suivez les dans l'ordre, et faite le pour chaque entrée de gare (sauf le paramétrage des RFID).
Paramétrage des RFID
Le Paramétrage des RFID s'effectue sur le module MAM à l'aide du sketch MAM-ReadRFID
Placer le RFID sur le lecteur.
La commandes USB Sb n v permet de modifier la valeur du bit n du bloc b avec la valeur v
Nom de la locomotive
S2 #«Nom du train» ou «Nom du train» est une chaîne alphanumérique de maximum 16 caractères
"S2 #ABJ4"  2=Block #ABJ4=char[16]  1=NA
N° du MP3
S1 0 v ou v sera une valeur décimale de 0 à 255
"S1 0 116"    1=Block 0=CV  116=valeur du CV
Type de train
S1 1 v
v=0 pour les trains omnibus
v=1 pour les trains sans arrêt (marchandise)
v=2 pour les grèves
v=3 pour les retards
"S1 1 1"        1=Block 1=CV  1  =valeur du CV
Vérification des CV RFID
La vérification se fait avec la commande USB Gb n m
G2 #nom   pour le nom du train
G1 0 1   pour le N° du MP3 (en hexadécimal)
G1 1 2   pour le type de train
Vous pouvez aussi obtenir ces informations plus simplement...
Placer le RFID sur le lecteur. Vous obtiendrez sur le moniteur série  de l'IDE:
Retirer le RFID du lecteur. Vous obtiendrez sur le moniteur série  de l'IDE:
Vérifier les CV de MAM-Gare
Utilisez le moniteur série de MAM-Gare avec la commande }a
CV
Volume15
Adresse 1er esclave I2C16
Nombre d'esclaves17
MP3 Jingle SNCF100
MP3101 à 104
120 et 121
Modifiez si nécessaire ces CV avec la commande {a v
Vérifier les CV de MAM-ReadRFID
Utilisez le moniteur série de MAM-ReadRFID avec la commande }a
CV
Adresse esclave16
Adresses DCC des appareils de voie surveillés30 à 49
Numéro MP3 standard annonces200 à 260
Numéro MP3 de provenance180 à 188
Numéro MP3 de destination50 à 177
Modifiez si nécessaire ces CV avec la commande {a v
Paramétrage du volume
Le DfPlayer est monté sur le moniteur série de MAM-Gare. Utilisez  le moniteur série de MAM-Gare avec la commande Vv permet d'ajuster le volume sonore de 0 à 30 maximum
Pour une modification permanente, modifiez le CV 15 avec la commande {15 v
Simuler un message en provenance de MAM-ReadRFID
Sur le moniteur série de MAM-Gare entrez la commande suivante:
"J3_97_4_70_5_51_6"
Vous devez alors entendre le message suivant:
"Le train 8250 En provenance de Arvant va entrer en gare Voie B. Éloignez vous de la bordure des quais"
Le moniteur série indique alors:
Joue Annonce :1_3_97_4_70_5_51_6
Play 1 ?  Done
Play 3 ?  Done
Play 97 ?  Done
Play 4 ?  Done
Play 70 ?  Done
Play 5 ?  Done
Play 51 ?  Done
Play 6 ?  Done
Tester la communication entre MAM-ReadRFID et MAM-Gare
Connecter Mam-ReadRFID et MAM-Gare en I2C (GND-SCL-SDA)
Sur MAM-ReadRFID Utiliser le moniteur pour simuler le message a envoyer
"M3_97_4_70_5_51_6"
En réponse, vous obtiendrez:
Message : 3_97_4_70_5_51_6
sending value (20) : 11P3_97_4_70_5_51_6
Sur le moniteur série de MAM_Gare vous devriez voir arriver et exécuter la commande identique à la simulation précédente:
recieved (20) : 11P3_97_4_70_5_51_6
P
Annonce :1_3_97_4_70_5_51_6
Play 1 ?  Done
Play 3 ?  Done
Play 97 ?  Done
Play 4 ?  Done
Play 70 ?  Done
Play 5 ?  Done
Vous devriez aussi entendre le même message.
"Le train 8250 En provenance de Arvant va entrer en gare Voie B. Éloignez vous de la bordure des quais"
Test de la chaîne RFID-DFPlayer
On peut maintenant utiliser les RFID programmés précédemment.
En plaçant le RFID sur le lecteur couplé à MAM-ReadRFID on doit immédiatement voir apparaître sur le moniteur série associé les informations de ce RFID:
Rfid :769A6B51
Nr   90
Type 0
32 32 32 32 32 32 32 32 32 32 32 32 32 32
232TC           
Le train 90 En provenance de 70 va entrer en gare 50 Eloignez vous de la bordure des quais
769A6B51 retire
Simulation des changements d'aiguillages surveillés
Sur le moniteur série de MAM-ReadRFID entrez la commande suivante:
Tn v
Ou n indique le numéro d'ordre de l'appareil de voie surveillé et v indique sa position.
Vous verrez immédiatement sur ce moniteur série l'état actuel des 8 adresses surveillées ainsi que les CVs de destination et de provenance suivis de leur valeur c'est à dire au N° de MP3 servant à constituer l'annonce:
====
0010010110
Provenance  : 6 CV 186 = 70
Destination : 18 CV 68 = 50

Vous pouvez alors modifier ces Cvs si nécessaire.
N'oubliez pas que vous pouvez entendre le MP3 correspondant en utilisant la commande Jj sur MAM_Gare




Vous êtes désormais prêt à connecter le signal DCC sur MAM-ReadRFID afin qu'il utilise la position des appareils de voie pour constituer ses messages.

Utilisez le moniteur série de MAM-ReadRFID pour verifier l'état des appareils de voie, au moins dans un premier temps, avant de passer à un second MAM-ReadRFID correspondant à une autre entrée de la gare.




Un module SceNic regroupant différents projets Arduino est en cours de construction:
  • Annonces Gare RFID
  • Passage à niveau SAL (avec signaux lumineux et cloche)
  • Simulation Jour Nuit accelérée, éclairage publique et cloche du village
  • Appareils de voie par Servomoteur
  • Signaux mécaniques rotatifs
  • Deteleur Kadee/Microtrain
Je posterai une vidéo dès que possible. 
« Modifié: août 26, 2019, 05:20:41 pm par Barbadidoua »