Le montage proposé dans cet article va permettre de donner une touche réaliste à votre réseau de trains miniatures. Lorsqu’un train s’approche de la gare, une annonce au haut-parleur prévient les voyageurs de la provenance et de la destination du train lorsqu’il s’arrête pour prendre des voyageurs ou bien encore de s’écarter du bord du quai si le train ne fait que traverser la gare. Bien évidemment, l’annonce est différente en fonction de chaque train. Le montage, valable aussi bien pour un réseau analogique que numérique, ne nécessite que quelques composants bon marché. Voyons comment faire…
Annonces en gare avec la RFID
.
Par : ,
,
DIFFICULTÉ :★★☆
La reconnaissance des trains
L’annonce en gare est personnalisée pour les différents trains, ce qui implique qu’ils doivent être reconnus en amont de la gare. Pour ce faire, nous allons placer sous la voie un lecteur RFID (taille 3 cm x 6 cm) et équiper chaque locomotive d’un TAG qui, en passant sur le lecteur, va permettre son identification. C’est simple, ces composants se trouvent facilement sur internet, faible coût de montage, des bibliothèques spécialisées existent pour les utiliser, cela fait du code en moins à écrire et à tester. Mais qu’est-ce au juste que la RFID ?
La RFID, comment ça marche ?
La Radio Frequency Identification ou radio identification en français se compose de deux éléments complémentaires, le lecteur (figure 1) et le TAG (figure 2). Les TAG, pour les dispositifs les plus simples comme utilisés ici, ne disposent d’aucune alimentation électrique qui leur soit propre. Ils disposent simplement d’une antenne d’émission/réception et d’une puce où sont stockées les informations. Cette mémoire est généralement de petite capacité de l’ordre de quelques dizaines d’octets à 8 Ko.
Le lecteur RFID est aussi un émetteur d’énergie électromagnétique. En même temps qu’il envoie un signal d’interrogation, il fournit l’énergie nécessaire au TAG pour s’activer. Le lecteur va ainsi recevoir les données envoyées par le TAG (taille 19 mm x 12 mm).
Le lecteur en tant que tel ne sait rien faire de ces données. Dans notre cas, c’est un Arduino relié au lecteur et communicant en I2C qui va traiter ces données et permettre la lecture d’un fichier sonore spécifique pour chaque locomotive.
Le matériel nécessaire
Voici la liste du matériel nécessaire pour réaliser ce montage :
- Carte Arduino Uno ou Nano
- Lecteur RFID RC522 en version I2C v1.1 (le signal émis a une fréquence de 13,56 MHz)
- Des tags autocollants pour chacune des locomotives (adhésif, verre [1])
- Lecteur DFPlayer Mini
- Carte micro SD
- Une paire de mini-enceintes alimentées de PC ou un petit haut-parleur
- Quelques résistances et une petite diode (1N914, 1N4148, etc.)
Au total, le prix de revient de ce montage sera inférieur à 20 € clone Arduino compris. Prévoyez aussi quelques câbles et un peu de soudure (il y en aura très peu à faire).
Une alimentation récupérée sur un PC hors d’usage (figure 3) permet de disposer de toutes les tensions pour ce type de montage, 3,3v, 5v et 12v, tension qu’il sera plus sage d’abaisser à 9 V avec un régulateur (7809 par exemple) si on veut alimenter l’Arduino avec.
Pour les enceintes, nous utilisons des enceintes amplifiées de PC alimentées en 5v (figure 4).
La figure 5 montre l’ensemble du montage sur la planche avec en premier plan le module son que nous avons monté sur un PCB pour faciliter le câblage et auquel nous avons ajouté une DEL comme témoin d’alimentation.
Les annonces en gare
Pour effectuer une annonce en gare, il suffit de lire un fichier son stocké sur une carte micro SD et l’envoyer sur un petit haut-parleur. Il doit y avoir autant d’annonces (donc de fichiers son) que de trains différents roulant sur votre réseau. Bien évidemment, les trains de marchandises qui ne s’arrêtent pas en gare constituent une seule et même catégorie. L’annonce correspondante ne fait que prévenir les usagers de s’écarter de la bordure du quai. Les fichiers son doivent être au format MP3 et il est facile de trouver de tels fichiers sonores sur le net, ou bien de les enregistrer soi-même et les convertir ensuite. Voici un petit exemple de fichier sonore constituant une annonce (époque contemporaine comme vous le remarquerez !).
Pour lire le fichier son MP3 contenu sur la carte micro SD, on utilise le DFPlayer Mini alimenté en 5 V par la carte Arduino, il se raccorde sur elle très simplement comme nous le verrons par la suite.
Comment relier le module RFID à la carte Arduino ?
La figure 6 montre comment relier un module RFID RC522 I2C à une carte Arduino. Attention : le module s’alimente en 3,3 V et non en 5 V. Cette alimentation de 3,3 V est prise sur la carte Arduino elle-même ou sur une alimentation extérieure, mais il ne faut pas se tromper avec le 5 V délivré aussi par la carte Arduino.
IMPERATIF : ne pas oublier de raccorder les résistances (2,2 kΩ) sur les entrées SDA et SCL et le 3,3 V.
La broche SDA de la carte RC522 I2C sera reliée à la broche A4 (SDA) de l’Arduino alors que la broche SCL sera reliée à la broche A5 (SCL) de l’Arduino. En raison des différentiels de tension entre la carte RC522 I2C (3,3V) et Arduino(5V) exposés ci-dessus, on prendra soin d’abaisser la tension entre les broches des deux cartes soit avec des résistances de 2,2 kΩ, soit un convertisseur de tension à base de transistors (figure 7).
Comment relier le module DFPlayer Mini à la carte Arduino ?
La figure 8 montre comment relier le module DFPlayer Mini à une carte Arduino Uno. Le son est reproduit sur un petit haut-parleur de moins de 3 W (limitation du DFPlayer Mini) qui ne reproduit pas la stéréo. Nous verrons plus loin (figure 11) comment utiliser une paire de mini-enceintes pour ceux qui en disposent, ce qui permet la stéréo, une amplification du son et une meilleure qualité sonore ; c’est ce montage que nous conseillons.
Installation du lecteur RFID sous la voie
Le lecteur RFID doit être installé sous la voie, à l’endroit exact où il faut reconnaître quel train est en approche. Il faut prévoir une certaine distance entre le lecteur et la gare de manière à laisser le temps à l’annonce d’être lue. De plus, il est nécessaire de creuser légèrement la plateforme de voies pour y glisser le détecteur de manière à ce que l’épaisseur de ce dernier ne crée pas un soulèvement de la voie. Ceci peut se faire avec une défonceuse dont la profondeur de passe est réglée en conséquence. Le ballastage peut ensuite faire disparaître le lecteur RFID (insérer un morceau de carte plastique de 0,5 mm d’épaisseur). La figure 9 montre un exemple d’installation.
Installation des tags autocollants sous les machines
Chaque locomotive est équipée d’un tag autocollant de 19 mm x 12 mm référence NXP Ntags 213. Faire attention à l’endroit où il est installé, éviter les parties métalliques et éviter l’installation sous le moteur. A l’échelle N, lorsque la place sous la loco ne permet pas de coller le tag, celui-ci peut être collé sous un wagon. La figure 10 montre ce tag.
Bien évidemment, lorsque vous recevez vos tags et que vous les installez sous vos locomotives, vous ne connaissez pas encore leur numéro d’identification. Le programme que nous donnons en fin d’article possède un mode DEBUG qui permet d’afficher n’importe quel tag qui passe sur le lecteur, ce qui permet de faire la corrélation entre le numéro d’identification et la locomotive sous laquelle est fixé le tag et ainsi de modifier le tableau locosTab du programme.
Montage complet
La figure 11 montre comment relier tous les éléments du montage à la carte Arduino Uno. Il est nécessaire de respecter ce montage si vous ne voulez pas avoir à adapter le programme fourni avec cet article.
Les fichiers son
Les fichiers sons doivent être au format mp3, numérotés :
0001.mp3
0002.mp3
0003.mp3
…
et placés dans un dossier nommé mp3 au premier niveau de votre carte micro SD. Le nom de la carte (ici AUDIO) n’a pas d’importance (figure 12).
La numérotation des fichiers (figure 13) correspond aux fichiers à lire au moment du passage d’une locomotive tel que nous pourrons le voir dans le code dans la dernière colonne du tableau des locomotives. Notez qu’un même fichier peut être lu pour deux locomotives différentes.
Explication du programme
Le programme utilise quatre bibliothèques qui doivent être installées dans votre IDE et qui sont :
- SoftwareSerial et Wire font partie de l’application Arduino, vous n’avez donc pas besoin de les installer.
- DFRobotDFPlayerMini qui permet de lire un fichier MP3 de la micro carte SD et de le jouer sur le haut-parleur. Pour l’installer, il suffit d’utiliser le gestionnaire de bibliothèque de l’IDE et faire une recherche avec le nom DFRobotDFPayerMini. La version 1.0.5 est celle en cours lors de la rédaction de cet article.
- MFRC522_I2C qui permet d’utiliser le lecteur de tag. Le gestionnaire de bibliothèque ne vous proposera que la bibliothèque pour les lecteurs de tags utilisant l’interface SPI, pas I2C. Le mieux est donc d’utiliser le fichier ZIP MFRC522-I2C-Library-master fourni ci-dessous pour installer cette bibliothèque.
/*
RC522 I2C Module annonces gare
www.locoduino.org - fev 2019, vers : v 0.6
MFRC522.cpp - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS I2C BY AROZCAN
arozcan @ https://github.com/arozcan/MFRC522-I2C-Library
MFRC522.cpp - Based on ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI Library BY COOQROBOT
miguelbalboa @ https://github.com/miguelbalboa/rfid
Mapping @ http://www.locoduino.org/local/cache-vignettes/L610xH886/rc522_annonces_gare_0-87805.jpg?1552162449
Si vous utilisez une carte Arduino Mega, SDA est sur le connecteur 20 et SCL sur le connecteur 21.
*/
//#define DEBUG // Ne pas oublier de commenter en production
//-------------------------------- Module son -----------------------------------//
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h" // https://github.com/DFRobot/DFRobotDFPlayerMini
const uint8_t soundVolume = 20; // Sur 30 volume maxi
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
// Plus d'infos sur DFPlayer : https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram
//-------------------------------- RC522 -----------------------------------//
#include <Wire.h>
#include "MFRC522_I2C.h" // https://github.com/arozcan/MFRC522-I2C-Library
const uint8_t rstPin = 6; // Pin for RST
MFRC522 mfrc522(0x28, rstPin); // MFRC522 instance.
Les bibliothèques étant installées dans votre IDE, voyons comment fonctionne ce programme.
Tout d’abord, vous voyez que les broches 10 et 11 sont affectées au RX et au TX pour la communication avec le module son.
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
Ensuite, on affecte à la broche 6 le RST du module RFID dont l’adresse est 0x28. Cette valeur est à changer si votre lecteur RFID opère avec une autre adresse I2C. Si vous ne connaissez pas cette adresse, vous pouvez utiliser le programme i2c-scanner donné dans l’article Bibliothèque Wire : I2C pour rechercher l’adresse de votre lecteur.
const uint8_t rstPin = 6; // Pin for RST
MFRC522 mfrc522(0x28, rstPin); // MFRC522 instance.
//-------------------------- Variable globales -----------------------------//
const long rc522tempo = 1 * 10UL; // rc522tempo entre 2 lectures => 1 * 10UL = 10/1000 sec
long prev;
String uidOld;
const uint8_t nbreLocos = 3; //Remplacer par le nbs de machines. Doit etre < 255
/*
* Structure permettant de décrire une locomotive
*/
typedef struct {
uint8_t index;
char * tagRFID;
char * nom;
char * identifiant;
} Locomotive;
const Locomotive locosTab[nbreLocos] = {
{0, "04263722665D81", "YC 6400 ", 0001},
{1, "04463722665D81", "Renault VH", 0002},
{2, "04726922665D80", "CC-7126 ", 0003}
};
Déclaration des variables globales et initialisation de certaines d’entre elles.
const long rc522tempo = 1 * 10UL; // rc522tempo entre 2 lectures => 1 * 10UL = 10/1000 sec
est une variable qui détermine le laps de temps souhaité entre deux lectures de tags. Nous l’avons ici réglée à 1/100 ème de seconde et obtenons ainsi des résultats satisfaisants
long prev;
String uidOld;
prev et uidOld définissent deux variables d’état dont nous reparlerons plus loin dans le programme.
const uint8_t nbreLocos = 3; //Remplacer par le nbs de machines. Doit etre < 255
nbreLocos est le nombre de locomotives équipées de tags. Elle détermine la taille du tableau ci-dessous.
Pour gérer les tags associés à chaque locomotives, nous créons une structure que nous appelons Locomotive.
Le premier membre de cette structure correspond au numéro de la ligne, le second à l’UID de votre tag. Nous verrons plus loin comment trouver cette valeur. Notez que vous pouvez tout à fait associer un même fichier son à plusieurs locomotives (tags). Le troisième membre de cette structure correspond au nom de votre locomotive qui s’affichera dans le moniteur série de l’IDE au passage d’un tag. Enfin, le dernier membre correspond au nom du fichier son à lire au passage de la locomotive sur le lecteur.
A partir de cette structure, nous créons un tableau d’instances (objets) dont la taille est égale à nbreLocos soit 3 dans notre exemple.
typedef struct {
uint8_t index;
char * tagRFID;
char * nom;
char * identifiant;
} Locomotive;
const Locomotive locosTab[nbreLocos] = {
{0, "04263722665D81", "YC 6400 ", 0001},
{1, "04463722665D81", "Renault VH", 0002},
{2, "04726922665D80", "CC-7126 ", 0003}
};
Dans le setup, nous avons l’initialisation des deux modules et le lancement de diagnostics vous permettant de savoir à travers du moniteur série de l’IDE si tout est bien installé.
//-------------------------------- setup -----------------------------------//
void setup() {
Serial.begin(115200); // Initialize serial communications with the PC
// SoftwareSerial
mySoftwareSerial.begin(9600); // Initialize mySoftwareSerial
Serial.print(F("\nDFRobot DFPlayer Mini Demo\n"));
Serial.print(F("Initializing DFPlayer ... (May take 3~5 seconds)\n"));
if (!myDFPlayer.begin(mySoftwareSerial)) { // Use softwareSerial to communicate with mp3.
Serial.print(F("Unable to begin:\n"));
Serial.print(F("1.Please recheck the connection!\n"));
Serial.print(F("2.Please insert the SD card!\n"));
}
Serial.print(F("DFPlayer Mini online.\n"));
myDFPlayer.volume(soundVolume); //Set volume value. From 0 to 30
Wire.begin(); // Initialize I2C
mfrc522.PCD_Init(); // Initialize MFRC522
mfrc522_printDetail(); // Show details of PCD - MFRC522 Card Reader details
Serial.print(F("\n"));
}
Dans le loop, nous appelons deux fonctions :
void loop() {
mfrc522update(); // MAJ du RC522
//Print the detail message from DFPlayer to handle different errors and states.
if (myDFPlayer.available()) {
DFRobotDFPlayerMini_printDetail(myDFPlayer.readType(), myDFPlayer.read());
}
}
DFRobotDFPlayerMini_printDetail() permet d’afficher dans le moniteur série de l’IDE des diagnostics. C’est une fonction très puissante et nous vous invitons, surtout en phase de mise au point, à vous y reporter car elle risque de vous faire économiser des recherches qui peuvent se révéler fastidieuses autrement.
L’autre fonction est mfrc522update(). Voyons tout d’abord l’ensemble du code avant de l’examiner en détail.
void mfrc522update() {
while ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
delay(50);
}
if (millis() > prev + rc522tempo ) { // Verifie que la rc522tempo est depassee
String uidNew;
for (uint8_t i = 0; i < mfrc522.uid.size ; i++) {
uidNew += mfrc522.uid.uidByte[i] < 0x10 ? "0" : "";
uidNew += String(mfrc522.uid.uidByte[i], HEX);
}
uidNew.toUpperCase(); // On met toutes les lettres du tag en majuscules
#ifdef DEBUG
Serial.println(uidNew); // Permet de lire n'importe quel tag passe sur le lecteur
// et d'afficher son UID
#endif
if (uidNew != uidOld) { // Le tag est il different ?
for (uint8_t i = 0; i < nbreLocos ; i++) { // Recherche dans le tableau des locos
if (uidNew == locosTab[i].tagRFID) {
#ifdef DEBUG
Serial.print(F("Train : \t"));
Serial.print(locosTab[i].nom);
Serial.print(F("\n"));
#endif
myDFPlayer.playMp3Folder(locosTab[i].identifiant);
uidOld = uidNew; // On met a jour la variable uidOld
i = nbreLocos; // Une loco a ete trouvee, on quitte la boucle de recherche
}
}
}
prev = millis(); // On affecte a la variable prev l'heure courante
}
}
Dans cette fonction mfrc522update() nous avons tout d’abord une boucle qui teste si un tag est présenté devant le lecteur ou si un tag a été lu.
void mfrc522update() {
while ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
delay(50);
}
L’execution du programme est bloquée ici. Si l’une des deux conditions est remplie, le programme peut alors se poursuivre.
if (millis() > prev + rc522tempo ) { // Verifie que la rc522tempo est depassee
String uidNew;
for (uint8_t i = 0; i < mfrc522.uid.size ; i++) {
uidNew += mfrc522.uid.uidByte[i] < 0x10 ? "0" : "";
uidNew += String(mfrc522.uid.uidByte[i], HEX);
}
uidNew.toUpperCase(); // On met toutes les lettres du tag en majuscules
On teste tout d’abord que la tempo fixée entre deux lectures est dépassée. Si c’est le cas, on définit une String uidNew qui servira à enregistrer la valeur du tag qui se présente en lecture.
Dans une boucle for, nous allons ensuite lire un à un les différents caractères renvoyés par le tag et ce, autant de fois qu’il y a de caractères dans l’uid du tag (mfrc522.uid.size). La longueur de l’uid est variable car les valeurs inférieures à 0x10 (hexadécimal) ne comportent qu’un seul caractère au lieu de deux dans le cas contraire. C’est aussi la raison pour laquelle nous allons ajouter un zéro (alphanumérique) pour ces caractères à la ligne suivante avec une expression ternaire : uidNew += mfrc522.uid.uidByte[i] < 0x10 ? "0" : "";
uidNew += permet d’incrémenter progressivement la variable "texte" uidNew.
Il nous reste encore une petite étape pour le "décryptage" de la valeur du tag que nous venons de recevoir. En effet, les lettres contenues dans l’identifiant peuvent être en minuscules, ex : 0x1e. La classe String avec sa fonction toUpperCase() permet de convertir tous les caractères minuscules en majuscules. uidNew.toUpperCase() ;
Dans la suite du programme, nous avons ajouté une petite fonctionnalité bien pratique : le mode DEBUG qui vous permet de lire tous vos tags et ainsi de constituer votre propre tableau locosTab.
#ifdef DEBUG
Serial.println(uidNew); // Permet de lire n'importe quel tag passe sur le lecteur
// et d'afficher son UID
#endif
A condition que vous ayez "décommenté" la ligne 16
//#define DEBUG // Ne pas oublier de commenter en production
il vous sera possible d’afficher dans le moniteur série de l’IDE la valeur de n’importe quel tag passé devant le lecteur. Ceci vous sera en particulier bien pratique pour connaître par exemple l’identifiant de nouveaux tags.
if (uidNew != uidOld) { // Le tag est il different ?
for (uint8_t i = 0; i < nbreLocos ; i++) { // Recherche dans le tableau des locos
if (uidNew == locosTab[i].tagRFID) {
Dans la suite du programme, nous allons tester si cette valeur uidNew ainsi lue est différente de la valeur précédemment lue : uidOld.
Souvenez vous, en début de programme, nous avons définit la variable uidOld mais sans lui affecter de valeur. A la première lecture de tag, la valeur de uidNew est donc forcement différente de celle de uidOld. La condition sera donc vraie. Nous verrons après comment on change la valeur de uidOld.
La boucle for suivante va nous conduire à parcourir le tableau locosTab, jusqu’à ce que nous y trouvions (ou pas) une locomotive qui porte la même valeur de tag.
Pour ce faire, nous allons tester si uidNew est une valeur contenue dans une des lignes du tableau dans la colonne 1 :
if (uidNew == locosTab[i].tagRFID)
Si aucune valeur n’est trouvée, nous allons parcourir tout le tableau et sortir de la boucle sans qu’il ne se soit passé quoique ce soit.
Si au contraire, la même valeur que uidNew a été trouvée dans le tableau, alors on entre dans la condition.
#ifdef DEBUG
Serial.print(F("Train : \t"));
Serial.print(locosTab[i].nom);
Serial.print(F("\n"));
#endif
myDFPlayer.playMp3Folder(locosTab[i].identifiant);
Si DEBUG est décommenté ligne 16, on va pouvoir afficher dans le moniteur série de l’IDE le nom du train contenu dans la colonne 2 du tableau, ce qui permet de contrôler que le fichier mp3 qui est ensuite joué correspond bien au train.
uidOld = uidNew; // On met a jour la variable uidOld
break; // Une loco a ete trouvee, on quitte la boucle de recherche
Nous allons ensuite affecter à la variable uidOld la valeur qui vient d’être lue uidNew pour éviter d’exécuter une nouvelle fois la fonction si le même tag est lu.
Enfin, la locomotive ayant été trouvée dans le tableau, nous quittons la boucle for avec l’instruction break.
Puis l’on affecte l’heure courante à la variable prev pour un nouveau calcul de temporisation.
prev = millis(); // On affecte a la variable prev l'heure courante
Le sketch en anglais et sa version en français (commentaires et messages) sont téléchargeables avec le lien ci-dessous ainsi que les fichiers son en mp3 qui ont servis pour cet exemple auxquels nous avons ajouté quelques exemples de klaxons de locomotives :
Mise en œuvre
Voici une petite vidéo qui montre l’implantation des composants et le déclenchement des lectures quand les locomotives passent sur le lecteur (une DEL bleue sur le module sonore s’allume lors de la lecture). Ne nous tenez pas rigueur de l’inadéquation des messages avec les locomotives !
Conclusion
Voici un petit aperçu de ce qu’il est possible de réaliser avec la reconnaissance et l’identification d’une locomotive, d’un convoi mais aussi des différents wagons qui composent un train.
Ainsi, selon la locomotive concernée, il est envisageable de commuter différents aiguillages pour conduire le convoi sur le quai souhaité. Il est également envisageable d’envoyer des commandes en DCC, exemple : activer un klaxon dans la locomotive, réduire la vitesse ou passer en mode manœuvre.
Dans le projet présenté ici, nous aurions pu aussi développer facilement un écran d’affichage OLED avec les trains à l’arrivée sur le principe de ce que Gilbert nous avait présenté pour la gare d’Aurillac, mais avec ici un affichage interactif.
On peut aussi imaginer des projets beaucoup plus complexes : la création d’une butte de triage où les aiguilles seraient commutées en fonction de chaque wagon ou encore, comme le réalise actuellement Marcel (Catplus sur le forum), une base de données de la position de chaque wagon sur le réseau. Tous les lecteurs du réseau étant reliés entre eux par un bus CAN. Dans son cas, cela concernera plus de deux cents wagons !
Voilà une technologie qui est aujourd’hui fiable et abordable et qui peut largement enrichir l’interactivité sur votre réseau.
Comme d’habitude, n’hésitez pas à poser toutes vos questions auxquels nous nous efforcerons de répondre dans les meilleurs délais.
[1] Ces tags sont généralement utilisés pour identifier des animaux. Pour faire une recherche sur internet, tapez "Animal verre tube tag RFID" et bien choisir ceux travaillant à 13,56 MHz pour être compatibles avec le lecteur RC522.