DfPlayer Répertoire MP3

Bonjour tous le monde :wave:

Je travail sur un projet avec un DfPlayer commandé par un Arduino pour commander la musique, le volume et la durée de la musique.

Le schéma est assé simple. un bus de dialogue entre l'Arduino et le DfPlayer (TX, RX et Busy pour la fin de la chanson) et deux potentiomètre pour géré le volume et la durée de la musique.

Nota : Par rapport au schéma le Busy est connecté à D8.

J'ai écris le code qui fonctionne à 99%

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(11, 10); // RX, TX

DFRobotDFPlayerMini myDFPlayer;

#define LED_PIN  13
#define BUSY_PIN 8
int busyState = 0;
int prevBusyState = 0;
int ValVolume =0;
unsigned long Duree = 0;
int AncienneDuree = 5;
int NbrDeChanson = 0;
int NumeroChanson = 1;
int  Debut = 0;
int ValDuree = 0;
unsigned long timer;

void setup()
{
  pinMode( LED_PIN, OUTPUT );
  pinMode( BUSY_PIN, INPUT_PULLUP );
  
  mySoftwareSerial.begin(9600);
  Serial.begin(9600); 

  Serial.println("Début");
  Serial.println(myDFPlayer.begin(mySoftwareSerial));
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    while(true){
      Serial.println("blocage");          // debug value
      delay(0); // Code to compatible with ESP8266 watch dog.
              }
     }

  // Nombre de chanson
  NbrDeChanson = myDFPlayer.readFileCountsInFolder(1);
  Serial.println("NbrDeChanson");
  Serial.println(NbrDeChanson);
  
  // initialisation timer
  timer = millis();
     
  // reglage du volume
  ValVolume = analogRead(A1)*30/1024;// Tension Durée
  myDFPlayer.volume (ValVolume);

  // Mesure Durée
  ValDuree = analogRead(A0)*6/1024;
  if (ValDuree == 0) {
      Duree = 5*60000;
    }
  if (ValDuree == 1) {
      Duree = 10*60000 ;
     }
  if (ValDuree == 2) {
      Duree = 15*60000 ;
    }
  if (ValDuree == 3) {
      Duree = 20*60000 ;
    }
  if (ValDuree == 4) {
      Duree = 30*60000 ;
    }
  if (ValDuree == 5) {
      Duree = 45*60000 ;
    }
   AncienneDuree = ValDuree ;

  // assume we need a delay to give the player time to start playing the initial track
  delay( 1000 );

  // initialise the BUSY states
  busyState = digitalRead( BUSY_PIN );
  //busyState = 1;
  prevBusyState = busyState;

  Aleatoire();
   
}

void loop()
{
  
  ValVolume = analogRead(A1)*30/1024;// Tension Volume
  myDFPlayer.volume (ValVolume);

  ValDuree = analogRead(A0)*6/1024;// Tension Durée

  if (ValDuree !=AncienneDuree) {
    if (ValDuree == 0) {
      myDFPlayer.playMp3Folder(5);
      Serial.println("5 minutes");
      Duree = 5*60000 ;
    }
    if (ValDuree == 1) {
      myDFPlayer.playMp3Folder(10);
      Serial.println("10 minutes");
      Duree = 10*60000 ;
     }
    if (ValDuree == 2) {
      myDFPlayer.playMp3Folder(15);
      Serial.println("15 minutes");
      Duree = 15*60000 ;
    }
    if (ValDuree == 3) {
      myDFPlayer.playMp3Folder(20);
      Serial.println("20 minutes");
      Duree = 20*60000 ;
    }
    if (ValDuree == 4) {
      myDFPlayer.playMp3Folder(30);
      Serial.println("30 minutes");
      Duree = 30*60000 ;
    }
    if (ValDuree == 5) {
      myDFPlayer.playMp3Folder(45);
      Serial.println("45 minutes");
      Duree = 45*60000 ;
    }
    AncienneDuree = ValDuree ;

    // Attendre que le texte se termine
    delay (1000);
    
    // Relancer la lecture
      Aleatoire();
  }

  // copy the state of the BUSY pin onto the UNO built-in LED
  busyState = digitalRead( BUSY_PIN );
  digitalWrite( LED_PIN, busyState );
  
  // has the player BUSY pin changed state?
   if ( busyState != prevBusyState ) {
    // state change - has the player stopped playing?
    if ( busyState == HIGH ) {
      Aleatoire(); 
    }
    prevBusyState = busyState;
  }
  
  Serial.println(millis());
  Serial.println(Duree);
  if (millis() - timer > Duree) {
     myDFPlayer.pause() ;
  }

 delay( 2000 );
}
void Aleatoire () {
    NumeroChanson = random(1,NbrDeChanson+1);
    Serial.println("Numéro chanson");
    Serial.println(NumeroChanson);
//    Serial.println(millis());
    if (millis() - timer > Duree) {
      myDFPlayer.pause() ;
    }
    else {
      myDFPlayer.playLargeFolder(1, NumeroChanson);
      delay(500);
      myDFPlayer.next();
      delay(500);
    }
}

Dans la carte SD j'ai deux répertoires. L'un (01) pour la musique et l'autre (MP3) contiens des fichiers son qui indique la durée (5 minutes, 10 minutes, ...)

Il fonctionne à 99% mais j'ai deux fonctionnement a peux prêt identique et inattendue.
1) Quant je fait un reset il y a une lecture du premier MP3 alors que je ne l'ai pas prévu dans mon code.
2) Quant je laisse tourné 10-20 minutes j'ai bien la musique du répertoire "01" en aléatoire. Mais a un moment j'ai un lecture d'un fichier son du répertoire MP3 sans que je le commande et cela bloque le DfPlayer.

Auriez-vous une idée ?

Si c’est un Nano ou similaire alors ces calculs faits sur des entiers débordent. Un int c’est Max 32767 sur ces petits arduino 8 bits.

Il faut passer les variable de temps en unsigned long et ne pas oublier de mettre UL pour forcer le calcul aussi en unsigned long

Duree = 5UL*60000UL; // avec la variable Duree en unsigned long

Idem pour les autres

Je ne connaissais pas merci pour l’info. Je test demain.

je ne sais pas si c'est votre souci, mais c'en est un en tout cas

Bonjour,

J'ai mis UL sur les gros nombres. Bien que c'est mieux comme ça mais cela n'a pas résolue le soucis.

J'ai changer de répertoire "MP3" --> "02" les fichiers qui me posent soucis.
Mais j'ai toujours le même problème.

J'ai trouvé que si j'augmente le délais (1000 -> 2000) après le changement de chanson je n'ai plus le problème au démarrage.

`      myDFPlayer.playLargeFolder(1, NumeroChanson);
      myDFPlayer.next();
      delay(2000);

Je ne comprend pas pourquoi cela résout le problème car dans le reste du programme je ne dialogue pas avec le DfPlayer. Peux être que l'Ardunio est n'a pas encore finis de dialogué. :thinking:

Mais j'ai encore le fichier 0015.MP3 dans le répertorie 2 qui s'active tout les 10-15 minutes. Alors que le seule moment ou je l'active il y a un texte qui s'affiche dans le terminal.

    if (ValDuree == 2) {
      myDFPlayer.playLargeFolder(2, 15);
      Serial.println("15 minutes");

Lorsque qu'il s'active je n'ai pas de texte dans le terminale.

J'ai un truc qui est peux être normal. J'utilise l'instruction Random pour choisir la chanson suivante. Ok cela me donne un nombre aléatoire. Mais c'est toujours la même séquence de chanson.

J'ai remit en forme le programme pour qu'il soit plus propre.

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(11, 10); // RX, TX

DFRobotDFPlayerMini myDFPlayer;

#define LED_PIN  13
#define BUSY_PIN 8
int busyState = 0;
int prevBusyState = 0;
int ValVolume =0;
unsigned long Duree = 0;
int AncienneDuree = 5;
int NbrDeChanson = 0;
int NumeroChanson = 1;
int  Debut = 0;
int ValDuree = 5;
unsigned long timer;
float toto = 0;

void setup()
{
  pinMode( LED_PIN, OUTPUT );
  pinMode( BUSY_PIN, INPUT_PULLUP );
  
  mySoftwareSerial.begin(9600);
  Serial.begin(9600); 

  Serial.println("Début");
  Serial.println(myDFPlayer.begin(mySoftwareSerial));
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    while(true){
      Serial.println("blocage");          // debug value
      delay(0); // Code to compatible with ESP8266 watch dog.
              }
     }

  // Nombre de chanson
  NbrDeChanson = myDFPlayer.readFileCountsInFolder(1);
  Serial.println("NbrDeChanson");
  Serial.println(NbrDeChanson);
  
  // initialisation timer
  timer = millis();
     
  // reglage du volume
  ValVolume = int(analogRead(A1)*30/1024);// Tension Durée
  myDFPlayer.volume (ValVolume);

  // Mesure Durée
  ValDuree = int(analogRead(A0)*6/1024);
  if (ValDuree == 0) {
      Duree = 5UL*60000UL;
    }
  if (ValDuree == 1) {
      Duree = 10UL*60000UL ;
     }
  if (ValDuree == 2) {
      Duree = 15UL*60000UL ;
    }
  if (ValDuree == 3) {
      Duree = 20UL*60000UL ;
    }
  if (ValDuree == 4) {
      Duree = 30UL*60000UL ;
    }
  if (ValDuree == 5) {
      Duree = 45UL*60000UL ;
    }
   AncienneDuree = ValDuree ;
  
  // assume we need a delay to give the player time to start playing the initial track
  delay( 1000 );

  // initialise the BUSY states
  busyState = HIGH;
  prevBusyState = busyState;

  // intialisation numéro de chanson aléatoire
  randomSeed(analogRead(A0));
}

void loop()
{
  
  ValVolume = analogRead(A1)*30/1024;// Tension Volume
  myDFPlayer.volume (ValVolume);

  ValDuree = analogRead(A0)*6/1024;// Tension Durée

   if (ValDuree !=AncienneDuree) {
    if (ValDuree == 0) {
      myDFPlayer.playLargeFolder(2, 5);
      Serial.println("5 minutes");
      Duree = 5UL*60000UL ;
    }
    if (ValDuree == 1) {
      myDFPlayer.playLargeFolder(2, 10);
      Serial.println("10 minutes");
      Duree = 10UL*60000UL ;
     }
    if (ValDuree == 2) {
      myDFPlayer.playLargeFolder(2, 15);
      Serial.println("15 minutes");
      Duree = 15UL*60000UL ;
    }
    if (ValDuree == 3) {
      myDFPlayer.playLargeFolder(2, 20);
      Serial.println("20 minutes");
      Duree = 20UL*60000UL ;
    }
    if (ValDuree == 4) {
      myDFPlayer.playLargeFolder(02, 30);
      Serial.println("30 minutes");
      Duree = 30UL*60000UL ;
    }
    if (ValDuree == 5) {
      myDFPlayer.playLargeFolder(2, 45);
      Serial.println("45 minutes");
      Duree = 45UL*60000UL ;
    }
    AncienneDuree = ValDuree ;

    // Attendre que le texte se termine
    delay (1000);
  }

  // copy the state of the BUSY pin onto the UNO built-in LED
  busyState = digitalRead( BUSY_PIN );
  digitalWrite( LED_PIN, busyState );
  
  // Si la chanson est finis on passe à la suivante
  if ( busyState == HIGH ) {
    if (millis() - timer > Duree) {
      myDFPlayer.pause();
    }
    else {
      NumeroChanson = random(1,NbrDeChanson+1);
      Serial.println("Numéro chanson");
      Serial.println(NumeroChanson);
      myDFPlayer.playLargeFolder(1, NumeroChanson);
      myDFPlayer.next();
      delay(2000);
    }
  }
  
  //Serial.println(millis());
  //Serial.println(Duree);
  if (millis() - timer > Duree) {
     myDFPlayer.pause() ;
  }

 delay(1000);
}

J'ai le MP3 15 minutes toute les 14 minutes. Etrange étrange :thinking:

vous ne remettez jamais à jour la variable timer ? (fait une seule fois dans le setup)

Non, elle n'est initialisé que dans le setup. Pourquoi ?

Nota après réflexion j'aurais pue me passer de la variable Timer vue que l'instruction milles() commence à 0.

qu'attendez vous du test if (millis() - timer > Duree) dans ce code ? c'est uniquement une seule fois à l'origine ?

Il y a deux fois le test avec le timer.

Le premier arrête la musique. Après Bussy passe à 1 donc il en faut un deuxième pour éviter de relancer la lecture d’u morceau.

OK donc l'idée c'est bien d'arrêter toute musique au bout du temps défini - c'est ça ?

une machine à états serait plus lisible (cf mon tuto éventuellement)

Oui, après un temps défini j’arrête la
Musique.

Le temps est définis par un potentiomètre. J’ai créé 6 niveaux pour 6 temps différents.

Je vais regarder votre poste. Mais à première vue je n’ai que deux état différent. Donc plutôt simple au premier abord.

oui ce serait juste pour simplifier la structure du code et le rendre plus lisible
ça permettrait aussi de définir ce que vous voulez faire une fois que la musique est terminée (si vous ne voulez pas rebooter)

Oui, vous avez raison. J'ai simplifié mon code pour ne mettre en pause qu'une seule fois dans mon code

  if (millis() > Duree) {
     myDFPlayer.pause() ;
  }
  else if ( busyState == HIGH )
   {  NumeroChanson = random(1,NbrDeChanson+1);
      Serial.println("Numéro chanson");
      Serial.println(NumeroChanson);
      myDFPlayer.playLargeFolder(1, NumeroChanson);
      myDFPlayer.next();
      delay(2000);

Comme cela l'arrêteriez est beaucoup plus propre.

J'ai toujours le MP3 15 minutes mais avec une période différente. Avant c'était tous 14 minutes. Là, je l'ai eu 3 minutes et 7 minutes.

Je vais essayé d'augmenter le temps après le changement de chanson.

je ne connais pas la bibliothèque que vous utilisez, donnez un peu de temps entre 2 commandes successives au module pour qu'il ait le temps de traiter ce qui arrive

J'utilise la fonction Random elle me fournis un numéro aléatoire de chanson mais c'est toujours la même série de chanson.

Je pense que cela vient que mon code est très linéaire. J'ai vue que l'on pouvait utilisé l'instruction randomSeed pour utilisé une entrée analogique en plus dans le calcule du nombre aléatoire.

Je pensais rajouter un NE555 en astable est relier la capa du NE sur une entrée analogique.

Quand penses-tu ?

randomSeed(analogRead(A0)); vous fera commencer la série "aléatoire" à différents endroits si A0 est vraiment "flottante" ➜ mettez un petit bout de fil dans A0 pour faire antenne si vous voulez augmenter la variabilité éventuellement

J’ai un truc étrange. Si je fait un reset la chanson se lance mais si je fais une mise sous-tension (connecté l’usb) la chanson ne se lance pas.

J’ai rajouté dans le setup le fait de lancer une chanson mais cela ne change rien.

Je pense mettre un RC sur l’entrée reset de l’Arduino.

Le module MP3 n'a peut-être pas encore démarré.
Place un delay() dans le setup() pour laisser le temps de démarrer au module MP3