Nombre de visites :
9
 
Gare_2.jpg
Nombre de visites :
Compteur de visites
DFPlayer sans ARDUINO
Cette application est une prise de contact avec le module DFPlayer Mini.
Pas de télécommande.​
Pas de programme.
Juste quelques boutons poussoirs.

Date de création : 30/01/2022

Dernière modification : 30/01/2022

PRÉSENTATION du DFPlayer Mini
DFPlayer Mini de DFROBOT est un lecteur «.MP3» ou «.WAV».

Il comporte un amplificateur stéréo intégré pouvant délivrer directement jusqu'à 3 watts sur une enceinte d'impédence 4 à 8 ohms.

Une sortie est prévue pour attaquer un amplificateur externe.


Utilisé seul, le module DFPlayer Mini offre déjà de très nombreuses possibilités.

Liens utiles :
https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299
https://www.wikidebrouillard.org/wiki/Item:DFPlayer_Lecteur_MP3​
https://lesiteferroviaire.pagesperso-orange.fr/DF%20Player.htm​
 
PROJET
Dans cette application – je devrais plutôt dire «dans ce montage» – pas d'animation lumineuse ni de programme.
 
Uniquement du son.

Le montage proposé permet de diffuser jusqu'à 14 sons différents.
Chaque son est déclenché par un bouton poussoir différent.

Note : en réalité le DFPlayer utilisé seul peut diffuser beaucoup plus de sons différents, mais de façon séquentielle, ce qui ne correspond pas à l'utilisation «annonces en gare».


On peut trouver facilement sur le net des vidéos d'annonces en gare dont on peut extraire le son.

Pour cela j'ai utilisé AUDACITY.

Ce logiciel gratuit est génial !
Non seulement il permet d'enregistrer des sons en provenance d'un micro ou d'une vidéo, mais il offre de TRÈS nombreuses possibilités de modifier les sons et de les combiner.

Un vrai plaisir !

 
MATÉRIEL
MP3_Player.jpg
Platine_proto_edited.jpg
 
  • un module «DFPlayer Mini» 
 
 

 
  • une plaque de prototypage.
Celle qui est représentée ci-contre est la réplique d'un Breadboard de 420 points.

J'ai choisi cette solution parce qu'il est très facile de transposer sur ce type de platine le montage d'essai élaboré avec le breadboard.
 
  • x13 borniers à vis pour raccorder les boutons poussoirs et le HP ;
 
  • autant de boutons poussoirs que d'annonces ;
  • un HP ou une mini enceinte ;
  • une alimentation 5V DC ;
  • 18 résistances 1/4 watt ;
  • 1 carte «T» (micro SD).
Le DFPlayer n'est pas directement soudé sur la platine de prototypage.
Il est monté sur 2 connecteurs 8 pôles du type de ceux-ci...
Connecteur 8 poles.png
SCHÉMA
DFPlayer_14.png
 
On voit clairement sur ce schéma qu'on peut commander la lecture de 14 séquences sonores différentes.

Remarque sur les valeurs des résistances :
Au départ j'ai eu une petite inquiétude : les valeurs des résistances indiquées sur le schéma ci-dessus ne font pas toutes partie de la série E12.
En fait, on obtient tout de même un fonctionnement correct en choisissant dans la série E12 les valeurs les plus proches de celles du schéma.

Avec la série «220 k ; 100 k ; 56 k ; 33 k ; 27 k ; 15 k ; 10 k ; 5k6 ; 3k3 ; 0R», le montage fonctionne parfaitement bien.
 
CABLAGE SUR LA PLATINE DE PROTOTYPAGE
DFPlayer-annonces-03.jpg

En noir : les ponts pour GND (masse).
En orange : les ponts pour les liaisons avec «ADKEY_1» et «ADKEY_2».
En rouge : un tout petit pont qui n'a d'utilité que de repérer la borne «+5 V DC» du DFPlayer.

Les switchs seront connectés entre une des 14 bornes et une des 4 bornes GND (en haut à droite).

On notera les deux supports pour le DFPlayer.

Note 1 :
Pour l'alimentation 5 V DC j'ai utilisé un jack femelle 5.5 x 2.1 sur cordon.
Pratique, mais pas indispensable.

Note 2 :
Si on n'a que 4 sons différents à diffuser, il suffira de monter les borniers pour les sons 1 à 4.
Les borniers encadrés en rouge ne sont pas indispensables : voir ci-dessous dans «Remarques».

 
SÉQUENCES SONORES

Une fois mises au point – dans un logiciel comme AUDACITY par exemple – les séquences seront enregistrées sur la carte «T».
Elles seront numérotées :
  • 001.mp3 (ou .wav)
  • 002.mp3 ...
  • ...
  • 014.mp3

On peut éventuellement les nommer  :
  • 001_TGV_LYON_1.mp3
  • ...
... mais attention aux libellés trop longs.

Normalement, le switch du «Fichier n°1» (voir schéma) déclenche le son «001...mp3».

En fait je me suis rendu compte que le fichier «001_[quelque chose].mp3» était traité comme «Fichier n°1» seulement s'il avait été copié en premier sur la carte «T», et ainsi de suite...

Note : 
La notice indique que le DFPlayer est capable de traiter un très grand nombre de fichiers sons.
Ces fichiers n'ont pas de durée limite. En tout cas aucune durée susceptible de limiter les besoins de l'application.
Ils peuvent être en haute définition.

 
FONCTIONNEMENT

Ainsi utilisé, le DFPlayer est en commandes «manuelles».

La très grande richesse de possibilités a conduit le constructeur à prévoir plusieurs options pour chaque fonction.

C'est ce qui apparaît sur le schéma rappelé ci-dessous.
Par exemple, les entrées «5» et «6» sur ADKEY_1 ont 2 fonctions :
  • «Piste suivante» si on fait un appui bref ;
  • «Volume +» si on fait un appui long.
Délicat, mais ça fonctionne.

De même sur les touches «Fichier 1» à «Fichier 14» (mais ce n'est pas indiqué sur le schéma) :
  • un appui bref fait jouer le son une seule fois ;
  • un appui à peine plus long fait jouer le son en boucle !
DFPlayer_14.png
REMARQUES
Borniers encadrés en rouge sur l'image du montage :
Ils correspondent aux 6 entrées de fonctions sur ADKEY_1 (résistances de 15k à 200k).
On peut s'en passer.
Volume sonore :
3 watts, c'est déjà beaucoup.
Le volume sonore pour cette application a besoin d'être réglé à un certain niveau, une fois pour toute.
Il n'est donc pas indispensable d'avoir accès aux commandes «Volume +» et «Volume -» qui sont d'ailleurs assez délicates à maîtriser manuellement.
D'autre part, le rendu sonore dépend énormément du modèle de HP ou d'enceinte utilisé.
Deux solutions pour ajuster le volume des sons :
  • soit on agit sur le fichier son lui-même, par approches successives, en utilisant par exemple AUDACITY ;
  • soit on intercale, en série avec le HP, une résistance dont la valeur sera ajustée entre 10 et 50 ohms. 
Cette dernière solution est très efficace et très simple à mettre en œuvre.
Déclenchement des sons :
Un appui bref sur un poussoir déclenche la diffusion du son correspondant.
Pendant la diffusion du son, un nouvel appui bref sur un autre poussoir démarre instantanément la diffusion du nouveau son !
En fait, le DFPlayer possède une borne «BUSY» qui permet de savoir qu'un son est en cours de diffusion, mais le traitement de cette information ne peut être gérée que par programmation.

 
CONCLUSIONS

Le montage ci-dessus a la vertu d'être extrêmement simple et de donner un résultat très plaisant.

Il sera privilégié chaque fois que :
  • l'application ne dépasse pas la limite de 14 fichiers sons différents ;
  • il n'y a pas de couplage avec une animation lumineuse synchronisée ;
  • on ne désire qu'une commande manuelle.

Avec ce même montage, rien qu'en changeant les séquences sonores, on pourrait donc diffuser :
  • des sifflets et des klaxons de locomotives ;
  • des ambiances sonores de gares ou de triages ;
  • des sons de fête foraine ;
  • des sons de basse-cour et de ferme ;
  • ...





 
 
20210207_152651.jpg
Nombre de visites :
Compteur de visites
CATTLE DOCK
  • une seule séquence sonore ;
  • pas d'animation lumineuse ;
  • télécommande infrarouge.

Date de création : 30/01/2022

Dernière modification : 30/01/2022

Download_1.png
Téléchargement
POURQUOI UNE TÉLÉCOMMANDE ?

Pour cette application, on peut se contenter du même montage que pour le projet «Annonces en gare» :
  • une seule séquence sonore ;
  • déclenchement par bouton poussoir.
Cependant...​
En mode manuel :​
  • dès qu'on doit commander plus de 2 ou 3 fonctions pour une animation, l'utilisation des poussoirs et leur câblage deviennent un problème : il faut fabriquer et câbler un panneau de commande, encombrant et inesthétique, qu'on ne sait pas où installer proprement ;
  • il faut installer autant de panneaux de commande que d'animations ;
  • déclencher une action nécessite d'être à proximité immédiate des poussoirs concernés ;
Grâce à la télécommande :
  • on s'affranchit de la fabrication, de l'installation et du câblage des panneaux de commande ;
  • on accède à d'autres fonctions du DFPlayer : les commandes possibles ne se bornent pas à «marche/arrêt» ;
  • la portée de la télécommande dépasse facilement 5 mètres ;
  • un récepteur infrarouge du type VS1838B coûte bien moins cher que deux poussoirs ;
  • le VS1838B peut facilement être dissimulé dans le décor ;
  • toutes les animations seront télécommandées avec un seul boitier de télécommande ;
    On en trouve de très corrects à moins de 4 € sur le net.
Pour toutes mes animations, j'utilise une télécommande SONY TV (ou compatible).
Rien n'empêche d'utiliser d'autres marques de télécommandes (moyennant quelques modifications du programme).
J'utilise aussi mon smartphone avec une des très nombreuses applications de télécommande.
PRÉSENTATION DU PROJET
Actuellement il y a déjà 5 animations «sons et lumières» sur mon réseau, ce qui nécessite un nombre important de codes.
J'ai donc pris l'option d'utiliser des codes à 2 digits.
Pour l'application «Cattle dock», ce sont les codes 60 à 69, ainsi que les touches «Vol+», «Vol-» et «POWER» associées à la touche «6».
J'aurais pu me contenter de :
  • un code pour démarrer la séquence sonore ;
  • un code pour l'arrêter avant qu'elle se termine naturellement ;
... mais il faut bien s'amuser un peu. J'ai donc profité des possibilités du DFPlayer et de l'ARDUINO pour programmer un ensemble de commandes plus fourni.
Pour démarrer :
  • touches «6» puis «POWER» pour démarrer la séquence avec un volume sonore égal à 10 (faible).
    (Le volume de l'ampli intégré du DFPlayer peut être réglé entre 0 et 30).
  • codes «60» pour démarrer la séquence avec le volume 12 ;
  • ... ;
  • codes «65» pour démarrer la séquence avec le volume 27.
 
Une fois que la séquence est en route :
  • touches «6» puis «Vol+» pour augmenter le volume de 2 crans ;
  • touches «6» puis «Vol-» pour diminuer le volume de 2 crans ;
  • code «62» pour activer le réglage «jazz» de l'amplificateur du DFPlayer, afin d'obtenir une tonalité plus aigue ;
  • touche «6» puis touche «POWER» pour stopper la séquence sonore avant son déroulement complet.
... plus quelques petites choses...
Cela peut paraître excessif, mais c'est l'occasion de se familiariser avec les commandes inaccessible manuellement.
MATÉRIEL
 
  • x1 platine de prototypage  420 points ;
  • x1 DFPlayer Mini ;
  • x1 carte «T» (micro SD) ;
  • x1 ARDUINO Nano (*) ;
  • X1 récepteur infrarouge VS1838B ;
  • x1 télécommande SONY TV compatible ;
  • x3 résistances 1/4 watt ;
  • x1 bornier à vis pour la sortie HP ;
  • connecteurs supports pour le DFPlayer et l'ARDUINO Nano ;
  • x1 HP ou mini-enceinte ;
  • x1 bloc d'alimentation 5 V DC ;
(*) un ARDUINO Nano et un DFPlayer montés sur une une platine de prototypage donne un montage bien moins encombrant qu'un ARDUINO UNO + un shield + un DFPlayer monté sur le shield.
VS1838B_2-300x300.png
LIENS UTILES
SCHÉMA
Schema_1.png
VS1838 (équipé de ses 2 résistances)

Il est relié à l'ARDUINO par 3 fils :
  • le + 5 V DC ;
  • la masse (GND) ;
  • le signal.

DFPlayer
 
  • il reçoit les commandes sur son entrée «Rx».
  • cette entrée «Rx» est reliée à la pin «12» par une résistance de 1k (indispensable).
  • la pin «12» de l'ARDUINO joue le rôle de «Tx» pour le DFPlayer.
     
PLATINE DE PROTOTYPAGE
cattle-dock-02_edited.jpg
Montage complet.

Tout tient sur la platine de prototypage.
cattle-dock-01_edited.jpg
Vue sur l'ensemble des ponts de liaison.

En rouge ⇒ Vcc (5 V DC) 
En noir ⇒ GND

Bloc de connexion bleu ⇒ HP

L'alimentation 5 V DC sera raccordée sur les pastilles «-1» et «+1» (ou «-4» et «+4» si on ne veut pas gêner la connexion avec le HP).
cattle-dock-04.jpg
Vue sur le VS1838B et son connecteur.

Bien respecter l'ordre des connexions.
(La couleur des fils nous aide).
 
Breadboard.png
Pour aider, voici le Breadboard qui a servi à mettre au point le câblage de la platine de prototypage.

En gris : les emplacements
  • de l'ARDUINO NANO ;
  • du DFPlayer ;
  • du connecteur pour le VS1838.
  • du HP ;

Note :
Sur les photos de la platine figurent 2 résistances (en A11 et B12) et 2 ponts (en B24 et B27), ainsi qu'un connecteur de wrapping (en C10-C13).
Ce sont des éléments qui sont utilisés pour une autre application avec animation lumineuse.
Ils n'est donc pas nécessaire de les installer dans le cas présent.



 
LE CODE C++
Petit préambule :

J'ai déjà installé 5 animations sur mon réseau (quand on aime, on ne compte pas ! )
Chaque animation mobilise de 3 à 20 commandes infrarouges (comme par exemple dans l'application qui diffuse des sifflets et klaxons de locos).


Des codes IR à un seul digit ne suffisent pas.

J'ai donc pris l'option d'utiliser des codes à 2 digits.
⇒ chaque animation se voit attribuer une décade ;
⇒ on dispose ainsi à 100 codes (si on inclut les codes «00» à «09»), et même d'avantage si on utilise (environ 200 codes) si on utilise toutes les touches de la télécommande.

Par exemple, la présente application «CATTLE DOCK» fonctionne avec les codes «60» à «69», «6 + VolUp», «6 + VolDown» et «6 + POWER».


 
Smiley-Prof-1.png

Le programme n'est pas d'une très grande complexité.
confused-smiley.png

Oui ! Mais il fait quand même plus de 340 lignes !
ordi.gif

Pas d'angoisse !
Il y a plein de lignes vides et de lignes de commentaires...
Le code de ce programme n'est effectivement pas très complexe.
Ce n'est pas non plus de la programmation «de haut vol», le but étant que chacun puisse éventuellement le modifier pour l'adapter à ses besoins.

 

#include et déclarations de variables
 
#include <IRremote.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h> 
// Bibliothèque à télécharger.

SoftwareSerial mySoftwareSerial(11,12); // la broche «11» de l'ARDUINO est utilisée
             //comme «Rx» pour communiquer avec la broche «Tx» du DFPlayer
             // la broche «12» de l'ARDUINO est utilisée comme «Tx» pour
             //communiquer avec la broche «Rx» du DFPlayer.
             // Note : la liaison «Rx ARDUINO» --> «Tx DFPlayer» n'est pas
             // utilisée dans ce programme.
                                        
DFRobotDFPlayerMini myDFPlayer;      
  // Déclare une instance pour le DFPlayer.

int IRpin = 2;                          // Entrée du capteur IR
IRrecv irrecv(IRpin);
decode_results results;

const int  Touche_9 = 272 ; 
const int  Touche_8 = 3600 ;
const int  Touche_7 = 1552 ;
const int  Touche_6 = 2576 ;
const int  Touche_5 = 528 ;
const int  Touche_4 = 3088 ;
const int  Touche_3 = 1040 ;
const int  Touche_2 = 2064 ;
const int  Touche_1 = 16 ;
const int  Touche_0 = 2320 ;

//const int  Touche_Up = 1904 ;  Ces touches ne sont pas utilisées dans ce programme.
//const int  Touche_Down = 3952 ;
//const int  Touche_Left = 2800 ;
//const int  Touche_Right = 752 ;
const int  Touche_VolUp = 1168 ;
const int  Touche_VolDown = 3216 ;

//const int  Touche_CH_Up = 144 ;
//const int  Touche_CH_Down = 2192 ;
const int  Touche_POWER = 2704 ;
//const int  Touche_Menu = 112 ;

La bibliothèque «DFRobotDFPlayerMini» doit être téléchargée est installée.
(Elle figure dans le fichier .zip).

J'ai déclaré toutes les touches du modèle de télécommande SONY TV que j'utilise.
Les touches non utilisées dans le programme sont passées en commentaires.

Ainsi, pour les programmes de mes autres animations, je n'ai pas besoin de rechercher les codes.
Il suffit de recopier ce bloc et de «libérer» uniquement les touches utilisées.



 
void loop()
 
void loop() est réduite à sa plus simple expression :
 
void loop() 
  { 
  Serial.println("-------------------------") ;
  Serial.println("Attente du code démarrage") ;
   
  irrecv.resume();          // Receive the next value  
    
  myDFPlayer.play(Numero_du_son() );
  Attente_fin_du_son() ;
  
     
  }

Seules les 3 lignes en gras sont vraiment importantes.
Les lignes «Serial.print...» sont des éléments de contrôle sur le moniteur, bien utiles pendant la mise au point.
 

Que fait cette boucle «void loop()» ?
  • «irrecev.resume() ; » prépare l'ARDUINO à recevoir un code infrarouge
  • «myDFPlayer.play(Numero_du_son() ; » commande au DFPlayer de jouer le son dont le numéro est renvoyé par la fonction personnelle «Numero_du_son()»
  • lorsque la séquence sonore a démarré, la fonction personnelle «Attente_fin_du_son() ; » attend que la diffusion du son soit terminée ou qu'une commande de modification du son soit envoyée.
    Par exemple pour augmenter ou diminuer le volume, ou pour stopper le son prématurément.

Remarque importante pour comprendre la relation «ARDUINO <==> DFPlayer» :

Aucune des commandes destinée au DFPlayer n'est bloquante :
  • dès qu'une commande a été envoyée par la liaison série, c'est le DFPlayer qui exécute l'ordre de façon autonome ;
  • ⇒ ARDUINO est donc libéré pour faire autre chose.
 
 

 
void setup()
 
void setup() 
  {
  irrecv.enableIRIn();                    // initialise la réception infrarouge.

  mySoftwareSerial.begin(9600);           // pour communiquer avec le DFPlayer
  myDFPlayer.begin(mySoftwareSerial);
 
  //  ----EQUALIZER : PARAMETRAGES POSSIBLES
  //  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  //  myDFPlayer.EQ(DFPLAYER_EQ_POP);
  //  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
  myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
  //  myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
  //  myDFPlayer.EQ(DFPLAYER_EQ_BASS);
 
  Serial.begin(9600);                     // Pour communiquer avec le moniteur
  pinMode(13, OUTPUT);                    // LED de contrôle de la réception d'un code.
  }

La ligne «myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);» est intéressante.
DFPlayer possède un equalizer avec des réglages de tonalité sonore pré-établis.

«EQ_JAZZ» permet de renforcer les aigus, par rapport au mode «EQ_NORMAL» ⇒ utile quand le HP ou l'enceinte est planquée sous la table du réseau ou dans une montagne en polystyrène extrudé !

 

Fonction personnelle «Numero_du_son()»
 
int Numero_du_son()
   {      
    int Numero = 1 ;
    int Premier_chiffre = 99 ;   // initialise les 2 digits à une valeur
                                 // qui n'existe pas.
    int Deuxieme_chiffre = 99 ;  // Ainsi, une mauvaise réception accidentelle ou la
                                 // réception d'un code non valide sera traduite par
                                 // le code «99» qui est un code non valide.
    
    Premier_chiffre = Interception_du_premier_code_IR_SONY() ;
    Deuxieme_chiffre = Interception_du_deuxieme_code_IR_SONY() ;

    
   // Décade 6 
   if (Premier_chiffre == Touche_6) 
     {
        if (Deuxieme_chiffre == Touche_POWER)   {Numero = 1 ; myDFPlayer.volume(10); }
        if (Deuxieme_chiffre == Touche_0)       {Numero = 1 ; myDFPlayer.volume(12); } 
        if (Deuxieme_chiffre == Touche_1)       {Numero = 1 ; myDFPlayer.volume(15); } 
        if (Deuxieme_chiffre == Touche_2)       {Numero = 1 ; myDFPlayer.volume(18); } 
        if (Deuxieme_chiffre == Touche_3)       {Numero = 1 ; myDFPlayer.volume(21); } 
        if (Deuxieme_chiffre == Touche_4)       {Numero = 1 ; myDFPlayer.volume(24); } 
        if (Deuxieme_chiffre == Touche_5)       {Numero = 1 ; myDFPlayer.volume(27); }
        if (Deuxieme_chiffre == Touche_6)       {loop() ; }     
        if (Deuxieme_chiffre == Touche_7)       {loop() ; }     
        if (Deuxieme_chiffre == Touche_8)       {loop() ; }        
        if (Deuxieme_chiffre == Touche_9)       {loop() ; }
        else if (Deuxieme_chiffre == 99)        {loop() ; }
      }
      return Numero ;
  // «Numero» est la valeur de la fonction «int Numero_du_son()».
   }
ordi.gif

Pourquoi ce commentaire :
«// Décade 6» ?
Smiley-Prof-1.png

Tout simplement parce qu'il pourrait y en avoir une de plus...

«// Décade 6» laisse supposer qu'il pourrait y avoir une autre «décade» en plus.

Effectivement.
Par simple addition d'un autre groupe «if (Premier_chiffre == ...) » on peut traiter 10 codes de plus, et même 20 codes de plus si on utilise toutes les touches de la télécommande).
C'est le cas dans l'application qui diffuse des sons de sifflets et de klaxons de locomotives et qui fera l'objet d'un autre article.
 

Le principe de cette fonction est le suivant :
  • on récupère successivement le deux chiffres du code  grâce aux deux fonctions personnelles :
    Premier_chiffre = Interception_du_premier_code_IR_SONY() ;
   Deuxieme_chiffre = Interception_du_deuxieme_code_IR_SONY() ;
  • on traite tous les codes valides, et seulement eux, dans le test
    «if (Premier_chiffre == Touche_6) { ... } »
     
  • si le code est valide :
    – «Numero» prend la valeur «1». C'est la valeur qui sera retournée par la fonction «Numero_du_son()» ;
    – l'instruction «myDFPlayer.volume(xx) ; » transmet au DFPlayer le niveau sonore désiré.
 
(dans le cas présent, comme il n'y a qu'une seule séquence sonore, le numéro du son est forcément «1»).​
  • si le code n'est pas valide (mauvaise saisie ou mauvaise réception), le test impose l'instruction «loop()».
Cette astuce est intéressante :
En effet, si le code à 2 digits est incorrect, que faut-il faire ?
Recommencer la saisie... ou, plus exactement, revenir à la situation de départ, c'est-à-dire tout simplement redémarrer le programme.
C'est ce que réalise l'instruction «loop()» : elle renvoie directement à «void loop() », c'est à dire au début de la boucle principale du programme, ce que ne peut pas faire une instruction «return» qui, elle, se contente de revenir à l'instruction qui suit la fonction appelée.
Les codes «6 + POWER» et les codes «60» à «65» sont les codes de démarrage du programme.
Ils permettent de démarrer la diffusion du son avec un niveau sonore au choix, de 10 à 27.
Les codes «66» à «69» sont en réserve. Dans le cas présent ils se contentent de redémarrer le programme.


 

Fonction personnelle «Interception_du_premier_code_IR_SONY()»
 
int Interception_du_premier_code_IR_SONY() 
    {
    int Code_touche_obtenu = 999 ;
    irrecv.resume() ;
    

            while (!(irrecv.decode(&results)))    // Attend indéfiniment (sans rien
                                                  // faire) la réception du 2e code.
                  {

                  // boucle d'attente de la réception d'un code IR (valide ou pas).
                  delay(100) ;
                  }
             Code_touche_obtenu = results.value ;
// le code reçu est stocké 
                                                  // dans «Code_touche_obtenu»                           Serial.print("Code touche obtenu = ") ;
                  Serial.println(Code_touche_obtenu) ;   

             delay(600) ;
 // Délai avant la saisie du 2e code.
                           // Nécessaire pour avoir le temps de relâcher la touche.

             irrecv.resume() ;   // prépare à la réception IR suivante.
                                       
             return Code_touche_obtenu ;            
}  

Rien de particulier.
Tout est expliqué dans les commentaires.

Les deux instructions surlignées en jaune sont facultatives.
Cependant, elles sont TRES utiles pour connaître le code de chacune des touches de la télécommande.

 

Fonction personnelle «Interception_du_deuxieme_code_IR_SONY()»
 
int Interception_du_premier_code_IR_SONY() 
    {
    int Code_touche_obtenu = 999 ;
    irrecv.resume() ;
    

            while (!(irrecv.decode(&results)))    // Attend indéfiniment (sans rien
                                                  // faire) la réception du 2e code.
                  {

                  // boucle d'attente de la réception d'un code IR (valide ou pas).
                  delay(100) ;
                  }
             Code_touche_obtenu = results.value ;
// le code reçu est stocké 
                                                  // dans «Code_touche_obtenu»                           Serial.print("Code touche obtenu = ") ;
                  Serial.println(Code_touche_obtenu) ;   

             delay(1000) ;
 // Délai avant la saisie du 2e code.

             results.value = 0 ; // ... sinon, à la prochaine saisie (ordre suivant)
                                 // «results.value» contient déjà un code valide.


             irrecv.resume() ;   // prépare à la réception IR suivante.
                                       
             return Code_touche_obtenu ;            
}  

Rien de particulier.
Tout est expliqué dans les commentaires.
Elle ne diffère de la fonction «int Interception_du_premier_code_IR_SONY()» que par la durée de la temporisation.
 

Fonction personnelle «Attente_fin_du_son()»
 
C'est la troisième et dernière instruction du programme principal.
 
void Attente_fin_du_son() 
{

  // La pin «BUSY» est reliée à la pin «5» sur l'ARDUINO.
  
  delay(1000);
// ... pour être sûr que la lecture du son a commencé, 
               //donc que BUSY est à «LOW».
  while (digitalRead(5) == LOW) 
      {

      // attend un éventuel code de modification du son ou le code d'arrêt,
      // tant que le son est en cours de lecture.
      Modification_du_son() ;
      }
}

La diffusion du son est commencée.
Tant que le son est en cours de diffusion, le programme tourne à l'intérieur de la boucle «while(...)» dans l'attente d'un éventuel code de modification du son ou du code d'arrêt .

 

Fonction personnelle «Modification_du_son()»
 
int Modification_du_son()
   {

// Cette fonction utilise les mêmes codes que la fonction «Numero_du_son()».
// Cette fonction est appelée pendant que le programme attend la fin de la diffusion
//   du son, donc elle ne fait que modifier le son, mais ne relance pas le programme.

    int Premier_chiffre = 99 ;
    int Deuxieme_chiffre = 99 ;
    Premier_chiffre = Interception_du_premier_code_IR_SONY() ;
    Deuxieme_chiffre = Interception_du_deuxieme_code_IR_SONY() ;
    

    // Décade 6
    if (Premier_chiffre == Touche_6) 
      {
      if (Deuxieme_chiffre == Touche_POWER)       {myDFPlayer.stop(); loop() ; }     
      
      // ... et pour s'amuser un peu...
      if (Deuxieme_chiffre == Touche_VolUp)
          {
          myDFPlayer.volumeUp();
          myDFPlayer.volumeUp();
          }     
      if (Deuxieme_chiffre == Touche_VolDown)
          {
          myDFPlayer.volumeDown();
          myDFPlayer.volumeDown();
          }  

      if (Deuxieme_chiffre == Touche_0)          {myDFPlayer.volume(12); }      
      if (Deuxieme_chiffre == Touche_1)          {myDFPlayer.volume(18); }
      if (Deuxieme_chiffre == Touche_2)          {myDFPlayer.EQ(DFPLAYER_EQ_JAZZ); }
      if (Deuxieme_chiffre == Touche_3)          {myDFPlayer.EQ(DFPLAYER_EQ_POP); } 
      if (Deuxieme_chiffre == Touche_4)          {myDFPlayer.advertise(1); }        
      if (Deuxieme_chiffre == Touche_5)          {myDFPlayer.advertise(2); }
      if (Deuxieme_chiffre == Touche_6)          {myDFPlayer.advertise(3); }     
      if (Deuxieme_chiffre == Touche_7)          {myDFPlayer.advertise(4); }     
      if (Deuxieme_chiffre == Touche_8)          {myDFPlayer.advertise(5); }        
      if (Deuxieme_chiffre == Touche_9)          {myDFPlayer.stop(); loop() ; }

      // par contre, ce qui suit est indispensable :
      else if (Deuxieme_chiffre == 99)           {return ; }
      }  
   }

Cette fonction, elle aussi, fait appel aux deux fonctions d'interception du premier et deuxième code IR.

Seul le traitement du code de la 2e touche est différent :
  • la touche «POWER» provoque l'arrêt du son et le retour au début du programme ;
  • les touches «VolUp» et «VolDown» provoquent l'augmentation ou la diminution du volume sonore par pas par 2 crans à la fois. (Oui, je sais, répéter 2 fois la même commande n'est pas très élégant, mais dans ce cas là c'est plus court et plus lisible que d'utiliser une boucle de répétition).
  • les touches «0» et «1» imposent un volume sonore déterminé ;
  • les touches «2» et «3» permettent de choisir un autre réglage de l'equalizer ;
  • la touche «9» a le même effet que la touche «POWER» (mais on pourrait lui affecter un autre rôle) ;
  • en l'absence de code valide, la fonction se termine sans rien faire et sera relancée par la fonction «Attente_fin_du_son() ; »

Particularité intéressante et amusante : «advertise» :
 
La fonction «myDFPlayer.advertise(n° du son) ; » permet au DFPlayer d'interrompre la diffusion de la séquence sonore principale pour diffuser provisoirement un autre son.
Dès que ce dernier est terminé, la séquence principale reprend.
 
C'est ce que je me suis amusé à programmer avec les touches «4» à «8».
Dans mon cas, ces 5 touches déclenchent de sifflets de locomotives.
Remarque importante :
Pour que la fonction «advertise» fonctionne, il faut respecter 2 conditions :
  • les sons auxiliaires déclenchés par «myDFPlayer.advertise(n° du son) ; » doivent être IMPÉRATIVEMENT enregistrés sur la carte «T» dans un répertoire nommé «ADVERT» (en respectant les majuscules) ;
  • les sons doivent IMPÉRATIVEMENT être nommés «0001.mp3», «0002.mp3»... «0005.mp3» ou «0001.wav», etc., c'est-à-dire sur 4 chiffres, et rien d'autre derrière les chiffres. 
... sinon le programme ne trouve pas les fichiers sons.
 
 
ordi.gif

Finalement, ce programme n'est pas si impressionnant que cela.

Quand on a retiré tous les commentaires et toutes les lignes vides,
il ne reste que environ 130 lignes de vrai code!







 
 
Steam_whistle.jpg
Nombre de visites :
Compteur de visites
SIFLETS et KLAXONS
  • 20 séquences sonores ;
  • pas d'animation lumineuse ;
  • télécommande infrarouge.

Date de création : 01/02/2022

Dernière modification : 02/02/2022

PRÉSENTATION DU PROJET
Ce projet est quasiment identique au projet précédent «Cattle Dock».
Au lieu d'une seule séquence sonore, il y en a 20.
Il faut traiter 20 codes de commandes, et c'est tout.
SCHÉMA - MATÉRIEL - PLATINE DE PROTOTYPAGE
IDENTIQUES à ceux du projet précédent «Cattle Dock».

 
LE CODE C++
Ce projet est quasiment identique au projet précédent «Cattle Dock».

Au lieu d'une seule séquence sonore, il y en a 20.
Il faut traiter 20 codes de commandes.
Pour cela on utilise les 10 touches numériques, et c'est tout.
 

#include et déclarations de variables
 
#include <IRremote.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h> 
// Bibliothèque à télécharger.

SoftwareSerial mySoftwareSerial(11,12); // la broche «11» de l'ARDUINO est utilisée
             //comme «Rx» pour communiquer avec la broche «Tx» du DFPlayer
             // la broche «12» de l'ARDUINO est utilisée comme «Tx» pour
             //communiquer avec la broche «Rx» du DFPlayer.
             // Note : la liaison «Rx ARDUINO» --> «Tx DFPlayer» n'est pas
             // utilisée dans ce programme.
                                        
DFRobotDFPlayerMini myDFPlayer;      
  // Déclare une instance pour le DFPlayer.

int IRpin = 2;                          // Entrée du capteur IR
IRrecv irrecv(IRpin);
decode_results results;

const int  Touche_9 = 272 ; 
const int  Touche_8 = 3600 ;
const int  Touche_7 = 1552 ;
const int  Touche_6 = 2576 ;
const int  Touche_5 = 528 ;
const int  Touche_4 = 3088 ;
const int  Touche_3 = 1040 ;
const int  Touche_2 = 2064 ;
const int  Touche_1 = 16 ;
const int  Touche_0 = 2320 ;

//const int  Touche_Up = 1904 ;  Ces touches ne sont pas utilisées dans ce programme.
//const int  Touche_Down = 3952 ;
//const int  Touche_Left = 2800 ;
//const int  Touche_Right = 752 ;
//const int  Touche_VolUp = 1168 ;
//const int  Touche_VolDown = 3216 ;
//const int  Touche_CH_Up = 144 ;
//const int  Touche_CH_Down = 2192 ;
//const int  Touche_POWER = 2704 ;
//const int  Touche_Menu = 112 ;

void loop()
 
void loop() 
  { 
  Serial.println("-------------------------") ;
  Serial.println("Attente du code démarrage") ;
   
  irrecv.resume();          // Receive the next value  
    
 myDFPlayer.volume(25);    // valeurs acceptables : 0 à 30

  myDFPlayer.play(Numero_du_son() );
  Attente_fin_du_son() ;
  
     
  }

Un seule ajout : «myDFPlayer.volume(25); », pour fixer le volume sonore au niveau «25».
 

void setup()
 

Strictement identique à celui du projet «Cattle Dock».
 
void setup() 
  {
  irrecv.enableIRIn();                    // initialise la réception infrarouge.

  mySoftwareSerial.begin(9600);           // pour communiquer avec le DFPlayer
  myDFPlayer.begin(mySoftwareSerial);
 
  //  ----EQUALIZER : PARAMETRAGES POSSIBLES
  //  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  //  myDFPlayer.EQ(DFPLAYER_EQ_POP);
  //  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
  myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
  //  myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
  //  myDFPlayer.EQ(DFPLAYER_EQ_BASS);
 
  Serial.begin(9600);                     // Pour communiquer avec le moniteur
  pinMode(13, OUTPUT);                    // LED de contrôle de la réception d'un code.
  }


Fonction personnelle «Numero_du_son()»
 

Ah ! Là, il y a du changement...

On a besoin de traiter 20 codes, donc on a besoin de 2 décades : la «30» et la «40».

 
int Numero_du_son()
   {
   myDFPlayer.volume(15);
// Volume atténué pour le son «21».
                         // Chaque son ci-dessous se voit affecté un volume individuel.
   int Numero = 21 ;   
 // En cas de code invalide, c'est le son 21 qui est joué.

   // PRINCIPE DE LA FONCTION «Numero_du_son» :

   //    -- on récupère successivement le deux chiffres du code ;
   //    ⇒ ces codes sont peut-être invalides : faux code, mauvaise réception
   //      ou réception accidentelle du code destiné à un autre récepteur ;
   //    -- on force a priori le n° du son à «21» ;
   //    -- on traite tous les cas valides, et seulement eux :
   //    ⇒ un numero de son correct est choisi ;
   //    ⇒ si effectivement le code est valide,
   //       alors ce numéro vient remplacer le n° «21» ;
   //    -- si l'un ou l'autre des codes saisis est in correct,
   //       alors «Numero» vaut toujours 21 puisqu'il n'a pas été remplacé.
   //    ⇒ le son «21» est diffusé, signifiant ainsi que les codes reçus
   //       n'étaient pas valides.
                        
   //    Note 1 : pour le son «21» on pourrait utiliser un son très faible
   //             ou un bip ou un silence de quelques secondes.

   //    Note 2 : Après le n° du son, on peut ajouter un correctif du volume
   //             ⇒ chaque son peut bénéficier d'un volume qui lui est propre.
   //             (c'est une commande directement envoyée au DFPlayer).
    
    int Premier_chiffre = Interception_du_premier_code_IR_SONY() ;
    int Deuxieme_chiffre = Interception_du_deuxieme_code_IR_SONY() ;
    

   // Décade 3 -------------------------------------- 
   if (Premier_chiffre == Touche_3) 
     {
        if (Deuxieme_chiffre == Touche_0)      {Numero = 10 ; myDFPlayer.volume(25); } 
        if (Deuxieme_chiffre == Touche_1)      {Numero = 1 ; myDFPlayer.volume(25); }  
        if (Deuxieme_chiffre == Touche_2)      {Numero = 2 ; myDFPlayer.volume(25); }           if (Deuxieme_chiffre == Touche_3)      {Numero = 3 ; myDFPlayer.volume(25); }  
        if (Deuxieme_chiffre == Touche_4)      {Numero = 4 ; myDFPlayer.volume(25); }  
        if (Deuxieme_chiffre == Touche_5)      {Numero = 5 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_6)      {Numero = 6 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_7)      {Numero = 7 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_8)      {Numero = 8 ; myDFPlayer.volume(25); } 
        if (Deuxieme_chiffre == Touche_9)      {Numero = 9 ; myDFPlayer.volume(25); }
      }  



      // Décade 4 --------------------------------------
      if (Premier_chiffre == Touche_4) 
      {
        if (Deuxieme_chiffre == Touche_0)      {Numero = 20 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_1)      {Numero = 11 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_2)      {Numero = 12 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_3)      {Numero = 13 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_4)      {Numero = 14 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_5)      {Numero = 15 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_6)      {Numero = 16 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_7)      {Numero = 17 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_8)      {Numero = 18 ; myDFPlayer.volume(25); }
        if (Deuxieme_chiffre == Touche_9)      {Numero = 19 ; myDFPlayer.volume(25); } 
      }    
      return Numero ;
   }



Fonction personnelle «Interception_du_premier_code_IR_SONY()»
 

Strictement identique à celui du projet «Cattle Dock».
 
int Interception_du_premier_code_IR_SONY() 
    {
    int Code_touche_obtenu = 999 ;
    irrecv.resume() ;
    

            while (!(irrecv.decode(&results)))    // Attend indéfiniment (sans rien
                                                  // faire) la réception du 2e code.
                  {

                  // boucle d'attente de la réception d'un code IR (valide ou pas).
                  delay(100) ;
                  }
             Code_touche_obtenu = results.value ;
// le code reçu est stocké 
                                                  // dans «Code_touche_obtenu»                           Serial.print("Code touche obtenu = ") ;
                  Serial.println(Code_touche_obtenu) ;   

             delay(600) ;
 // Délai avant la saisie du 2e code.
                           // Nécessaire pour avoir le temps de relâcher la touche.

             irrecv.resume() ;   // prépare à la réception IR suivante.
                                       
             return Code_touche_obtenu ;            
}  



Fonction personnelle «Interception_du_deuxieme_code_IR_SONY()»
 

Strictement identique à celui du projet «Cattle Dock».
 
int Interception_du_premier_code_IR_SONY() 
    {
    int Code_touche_obtenu = 999 ;
    irrecv.resume() ;
    

            while (!(irrecv.decode(&results)))    // Attend indéfiniment (sans rien
                                                  // faire) la réception du 2e code.
                  {

                  // boucle d'attente de la réception d'un code IR (valide ou pas).
                  delay(100) ;
                  }
             Code_touche_obtenu = results.value ;
// le code reçu est stocké 
                                                  // dans «Code_touche_obtenu»                           Serial.print("Code touche obtenu = ") ;
                  Serial.println(Code_touche_obtenu) ;   

             delay(1000) ;
 // Délai avant la saisie du 2e code.

             results.value = 0 ; // ... sinon, à la prochaine saisie (ordre suivant)
                                 // «results.value» contient déjà un code valide.


             irrecv.resume() ;   // prépare à la réception IR suivante.
                                       
             return Code_touche_obtenu ;            
}  


Fonction personnelle «Attente_fin_du_son()»
 


Petite modification : l'appel à la fonction «Modification_du_son()» est supprimé.

En effet, dans le projet «Cattle Dock», cette fonction permettait de saisir un code pour :
  • modifier le son (volume, tonalité...) ;
  • stopper la diffusion du son ;
  • revenir au début du programme.

Or, dans le cas présent, ces commandes n'ont pas lieu d'être puisque le volume des sons ne peut pas être modifié (faute de temps), et qu'il n'y a aucun intérêt à les stopper vu leurs courtes durées.

Le programme revient automatiquement au début de «void loop()» à la fin naturelle de la diffusion du son.
void Attente_fin_du_son() 
{

  // La pin «BUSY» est reliée à la pin «5» sur l'ARDUINO.
  
  delay(500);
// ... pour être sûr que la lecture du son a commencé, 
               //donc que BUSY est à «LOW».
  while (digitalRead(5) == LOW) 
      {

      // attend tant que le son est en cours de lecture.
      }
}

 
Petit détail pour terminer...
 
Le son des sifflets des Bigboy sont assez caverneux. Ils contiennent pas mal de graves.
D'autre part je me suis amusé, pour certains, à leur donner un effet de réverbération pour leur donner un effet spatial plus important.
Pour traduire correctement les sons j'ai donc utilisé 2 enceintes de 4 ohms montées en série et disposées sous le réseau, à environ 3 mètres de distance l'une de l'autre (pour encadrer la gare).
Le résultat est remarquable.
Looney_tunes.png

That's all Folks !
 

Réalisations avec DFPlayer Mini