DFPlayer ... probleme de lecture

Quelle est la meilleure approche pour réaliser ceci :

  • ecoute en boucle d'une même séquence 004.mp3
  • passage à un autre 001.mp3 si appui sur un bouton
  • retour à la lecture de 004.mp3 au relachement du bouton

J'ai essayé avec un if .. declenchant 001.mp3 mais jamais je n'arrive pas à ecouter ni 001.mp3 ni 004.mp3

//-----------------------------------------------------------------------
//DFPlayer: Mini mp3 Player
//Library by: Angelo qiao: https://github.com/DFRobot/DFRobotDFPlayerMini
//-----------------------------------------------------------------------
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
//---------------------------------------------------
SoftwareSerial softwareSerial(10, 11);
DFRobotDFPlayerMini player;
//===========================================================
void setup() {
  pinMode(2, INPUT_PULLUP);

  //---------------------------------------------------
  softwareSerial.begin(9600);
  player.begin(softwareSerial);
}
//===========================================================
void loop() {
  if (digitalRead(2) == LOW) {
    player.play(1);
  }
  player.play(4);
}

Je ne connais pas ce module, il n'est pas nécessaire d'arrêter la chanson en cours, pour passer à la suivante?

Sinon ton code demande de jouer la chanson 4, lorsque le bouton n'est pas appuyé.
de jouer la chanson 1 puis tout de suite la chanson 4 lorsque le bouton est appuyé.
le tout en loupe, c'est à dire plusieurs dizaine de fois pas seconde, sauf si la fonction play est bloquante.

Pour résumer, tu demande uniquement que la chanson 4 soit joué, la chanson 1 est court-circuité, sauf si play est bloquant.

C'est bon .... ça marche comme ceci

//-----------------------------------------------------------------------
//DFPlayer: Mini mp3 Player
//Library by: Angelo qiao: https://github.com/DFRobot/DFRobotDFPlayerMini
//-----------------------------------------------------------------------
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
//---------------------------------------------------
SoftwareSerial softwareSerial(10, 11);
DFRobotDFPlayerMini player;
//===========================================================
void setup() {
  pinMode(2, INPUT_PULLUP);

  //---------------------------------------------------
  softwareSerial.begin(9600);
  player.begin(softwareSerial);
}
//===========================================================
void loop() {
  while (1)
  if(digitalRead(2) == HIGH) {
    player.play(4);
      break;
  }
  
  while (1)
  if(digitalRead(2) == LOW) {
    player.play(1);
      break;
}
}

Je te conseillerais de ne pas utiliser ce genre de syntaxe du while, c'est sujet à des erreurs.
Il est préférable je trouve de faire :slight_smile:

while (1) {
  if(digitalRead(2) == HIGH) {
    player.play(4);
      break;
  }
}

Bonjour jo_6466

Un moyen de savoir si un morceau est en cours de lecture est de lire, sur un port de l'Arduino, la pin BUSY
image
qui donne un LOW pendant la lecture.

Cordialement
jpbbricole

C’est dommage de bloquer la loop.

C’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement) et utiliser une bibliothèque bouton pour simplifier le code

Je n'ai pas compris

Les 2 while font des boucles d’attente active au sein de la loop, et donc la loop dure super
Longtemps . Ce serait un problème avec le watchdog sur ESP par exemple

La meilleure façon serait d'utiliser l'interruption alors?

Non, de ne pas faire d'attente active.
d'utiliser le fit que la fonction loop est appelé indéfiniement pour gérer ce que tu veux faire par des états.
Typiquement comme @J-M-L aime bien le rappeler, c'est une des fonctionnalité d'une machine à état.
Mais tu peux aussi le faire avec un code plus "traditionnel", mais moins lisisble.

En combinant toutes vos suggestions , notament celle de jpbbricole et sa remarque sur la pine "BUSY" , je suis arrivé à faire exactement tout ce que je souhaitais

  • lecture en boucle sans aucuns "blanc" du son 2
  • lecture en entier du son 1 dès une impulsion sur BP
  • retour à la lecture du son 2 en boucle dès la fin du son 1
void loop() {

  while (digitalRead(3) == LOW) {       // analyse de la pine "BUSY" du DFP ... LOW = une lecture en cours
    if (digitalRead(2) == LOW) {        // pression sur le bouton
      player.play(1);                   // lecture son 1
      while (digitalRead(2) == LOW) {}  // On attend le relâchement du bouton
    }
  }
  player.play(2);                       // lecture son 2
  delay(200);                           // necessaire sinon effet mitrailleuse
}

Autre question
Je voudrais que le choix du son 1 soit aléatoire et choisi entre 2 et 5
J'ai essayé la fonction N= random (2,5) mais je remarque que N prend les valeurs 3,4 mais jamais 2 et 5
Pourquoi?

Bonsoir jo_6466

Peut-être une piste ici.

Cordialement
jpbbricole

Dans le setup, peut-on lancer la lecture d'une séquence sonore que l'on ne voudrait voir executer qu'une seule fois à la mise sous tension?
J'ai essayé mais cela ne marche pas

Bonjour jo_6466

Mets ton essai en ligne (le programme en entier) entre les balises :wink:

Cordialement
jpbbricole

J'ai trouvé
Si dans le setup, je ne mets pas la ligne delay(1000) après la ligne lecture player.play(1) cela ne marche pas ... avec delay ça fonctionne

//-----------------------------------------------------------------------
//DFPlayer: Mini mp3 Player
//Library by: Angelo qiao: https://github.com/DFRobot/DFRobotDFPlayerMini

//Son1 = allumage
//sons2à17 = combats
//-----------------------------------------------------------------------
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
//---------------------------------------------------
SoftwareSerial softwareSerial(10, 11);
DFRobotDFPlayerMini player;

long N = 0;
//===========================================================
void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  Serial.begin(115200);
  softwareSerial.begin(9600);
  player.begin(softwareSerial);
  //player.enableLoop();

  player.play(1); //son 1x au demarrage
  delay(1000);
}
//===========================================================
void loop() {

  player.play(20); 

  digitalWrite(5, HIGH);
  delay(200);
  digitalWrite(6, HIGH);
  delay(200);
  digitalWrite(7, HIGH);
  delay(200);
  digitalWrite(8, HIGH);
  delay(200);

  while (digitalRead(3) == LOW) {  // analyse de la pine "BUSY" du DFP ... LOW = une lecture en cours
    if (digitalRead(2) == LOW) {
      N = random(2, 18);  // pression sur le bouton
      player.play(N);     // lecture sons combats
      delay(100);

      for (int i = 0; i <= 5; i++) {

        digitalWrite(5, HIGH);
        digitalWrite(6, HIGH);
        digitalWrite(7, HIGH);
        digitalWrite(8, HIGH);
        delay(100);

        digitalWrite(8, LOW);
        digitalWrite(7, LOW);
        digitalWrite(6, LOW);
        digitalWrite(5, LOW);
        delay(100);
      }
    }
    while (digitalRead(2) == LOW) {}  // On attend le relâchement du bouton
  }
}

Bonjour jo_6466

Tu peux aussi attendre la fin du MP3 en faisant une fonction pour ça:

void attenteFinMp3()
{
	while (digitalRead(3) == LOW){};     // Tant que BUSY est LOW
}

Que tu appelles ainsi:

	player.play(1); //son 1x au demarrage
	attenteFinMp3();
	//delay(1000);

Ce n'est pas essayé en vrai :wink:

Cordialement
jpbbricole

En placant player.play(1) et attenteFinMp3 dans le setup : marche pas
Mais en ajoutant un delay(100) entre les deux ça marche

Arghhh .. non probleme dans la loop ...plus moyen de choisir le son par le bouton-poussoir

si vous regardez le code (sans le delay)

  ...
  player.play(1); //son 1x au demarrage
}
//===========================================================
void loop() {
  player.play(20);

à la fin du setup vous lancez la chanson N° 1. La fonction play() est non bloquante, donc tout de suite après le code rentre dans la loop et là vous demandez de jouer la chanson N° 20, juste donc quelques microsecondes plus tard ➜ votre DFPlayer n'a même pas eu le temps de commencer à jouer (il doit sans doute être toujours en train de recevoir la commande transmise en software serial donc la pin busy n'a sans doute pas eu le temps de s'activer non plus) qu'il reçoit un contre ordre... c'est pour cela sans doute que ça ne fonctionne pas

La valeur du delay compte
Si je mets 200ms , je n'entendrai que 200ms de son
comme le son a moins de 1sec .. en faisant delay(1000) il sera complet