(Résolu) Problème incrémentation DFPlayer mini mp3

Bonjour à toutes et tous,
je rencontre un problème d'incrémentation sur le moniteur série.
Matériel DFPlayermp3mini, carte adruino Uno et Liquid Crystal I2C
Les bibliothèques qui vont avec.
4 poussoirs qui font : play, stop et next et previous

Je m'explique :
lorsque je lance un fichier DFPLayer, avec un bouton poussoir en PullUp, cela lance le fichier correctement. Pas de soucis.
A la fin de la lecture le moniteur n'affiche pas le message de fin : "Number:1 Play Finished!"
Par contre si je lance le même fichier et que je relance (alors que celui ci est en mode lecture) alors là il m'affiche à la fin de la lecture, le message : "Number:1 Play Finished!"

Et parfois dans la navigation entre les boutons (next, previous play stop) je me retrouve avec le moniteur série qui affiche :
Play :
-1
Stop :
-1
Next :
-1
Etc....

Voici le code.
Je ne sais pas d'oùu vient ce beug...
Merci de votre aide...

#include <DFRobotDFPlayerMini.h>
#include <LiquidCrystal_I2C.h>
#include "SoftwareSerial.h"
SoftwareSerial mySerial(10, 11);

# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]

# define ACTIVATED LOW

int VarPotentioValeur = 0; // Variable où on stock la valeur du potentiomètre
const byte PinButtonPlay = 4;
const byte PinButtonStop = 5;
const byte PinButtonPrevious = 6;
const byte PinButtonNext = 7;

boolean isPlaying = false;

// Create the LCD object
LiquidCrystal_I2C myLcd(0x27, 16, 2);
DFRobotDFPlayerMini myDFPlayer;

void setup () {
  
myLcd.begin(16, 2);  
myLcd.init();
myLcd.backlight();

mySerial.begin (9600);
Serial.begin(115200);
delay(1000);
//playFirst();
isPlaying = true;//

Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  
  if (!myDFPlayer.begin(mySerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true){
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));
  
pinMode(PinButtonPlay, INPUT_PULLUP);
digitalWrite(PinButtonPlay,HIGH);
pinMode(PinButtonStop, INPUT_PULLUP);
digitalWrite(PinButtonStop, HIGH);
pinMode(PinButtonPrevious, INPUT_PULLUP);
digitalWrite(PinButtonPrevious,HIGH);
pinMode(PinButtonNext, INPUT_PULLUP);
digitalWrite(PinButtonNext,HIGH);

myDFPlayer.volume(10);  //Set volume value. From 0 to 30
  
}


void loop () { 
// Set volume to maximum (0 to 30).
  myDFPlayer.volume(map(analogRead(A0), 0, 1023, 0, 30));
  myLcd.setCursor(10, 0);
  myLcd.print("VOL:");
 
  if (myDFPlayer.readVolume() < 10)
    myLcd.print(String ("0") + myDFPlayer.readVolume());
  else
    myLcd.print(myDFPlayer.readVolume());

if (digitalRead(PinButtonStop) == ACTIVATED)
  {
    if(isPlaying)
    {
      Stop();
      isPlaying = false;
    }else
    {
      isPlaying = true;
      Play();    
    }
  }

  if (digitalRead(PinButtonPlay) == ACTIVATED)
  {
    if(isPlaying)
    {
      Play();
      isPlaying = false;
    }else
    {
      isPlaying = true;
      Play(); 
    }
  }
    
 if (digitalRead(PinButtonNext) == ACTIVATED)
  {
    if(isPlaying)
    {
      PlayNext();
    }
    }

    if (digitalRead(PinButtonPrevious) == ACTIVATED)
  {
    if(isPlaying)
    {
      PlayPrevious();
    }
  }


if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
    }
    
}

void printDetail(uint8_t type, int value){
  switch (type) {
    
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }  
} 

void Play()
{
  execute_CMD(0x0D, 0, 1);
  delay(500);
  displayFileName();
  Serial.println ("Play:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}

void Stop()
{
  execute_CMD(0x16, 0, 0);
  delay(500);
  displayFileName();
  Serial.println ("Stop:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}
void PlayNext()
{
  execute_CMD(0x01, 0, 1);
  delay(500);
  displayFileName();
  Serial.println ("Next:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}

void PlayPrevious()
{
  execute_CMD(0x02, 0, 1);
  delay(500);
  displayFileName();
  Serial.println ("Previous:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
  
}


void displayFileName()
{
  myLcd.clear();
  myLcd.setCursor(0,0);
  myLcd.print("Track :");
  myLcd.setCursor(0,1);
 
int fileNumber = myDFPlayer.readCurrentFileNumber();
  switch (fileNumber)
  {
    case 1:
      myLcd.print("1.mp3");
      break;
    case 2:
      myLcd.print("2.mp3");
      break;
    case 3:
      myLcd.print("3.mp3");
      break;
    case 4:
      myLcd.print("4.mp3");
      break;
    case 5:
      myLcd.print("5.mp3");
      break;
    default:
      break;
  }
  
}

void execute_CMD(byte CMD, byte Par1, byte Par2)
// Excecute the command and parameters
{
// Calculate the checksum (2 bytes)
word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
// Build the command line
byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte};
//Send the command line to the module
for (byte k=0; k<10; k++)
{
mySerial.write( Command_line[k]);
}
}

si je lance deux fois "play", je reçois le message de fin de lecture. sinon , rien.
Est-ce que ce serait la fonction pullup ?

Capture d’écran 2021-12-10 à 18.26.15

J'ai lu en diagonale et c'est bizarre ce code

  if (digitalRead(PinButtonPlay) == ACTIVATED)
  {
    if (isPlaying)
    {
      Play();
      isPlaying = false;
    } else
    {
      isPlaying = true;
      Play();
    }
  }

que doit faire réellement ce bouton Play ?

@J-M-L il doit faire : play.
Si le bouton est appuyé : play.
Si il jouait : il fait rien.
S'il ne jouait pas : play.

Merci de ton aide.

et donc ça expliquerait cela ??

if (isPlaying)
    {
      Play();
      isPlaying = false;
    }

pas compris...

@J-M-L :joy::joy::joy:

Bon admettons que j'ai pas comprite comment on fait play.

Ce que je voudrais faire :

Bouton play j'appuie : play
Bouton stop : stop.
Bouton Next : next
Bouton Previous : Previous.

Et

Bouton play/stop : j'appuie play et si je rappuie : stop.

Merci de l'aide.

donc on dirait

si isPlaying alors stop et mémoriser isPlaying à faux
sinon play et mémoriser isPlaying à vrai

là vous écrivez

si isPlaying alors Play et mémoriser isPlaying à faux
sinon play et mémoriser isPlaying à vrai

@J-M-L merci je testerai ça lundi... Merki.
As-tu une idée pour le fait du moniteur série évoqué plus haut ?

vous aviez dit

il me semble que justement le code dont on parlait n'était pas bon et s'appliquait à ce cas

➜ testez déjà avec la correction

1 Like

@J-M-L code testé : cela ne fonctionne toujours pas.

j'ai testé un code super simple:

if (digitalRead(PinButtonPlay) == LOW)

    {
      Play();
    }
    
if (digitalRead(PinButtonStop) == LOW)
  {
    {
      Stop();
    }
  }

voici ce que j'ai en moniteur série si j'appuie sur le poussoir 1 seule fois :
Capture d’écran 2021-12-13 à 08.47.41
dans ce cas : le fichier est lu jusqu'au bout et s'arrête.

voici ce que j'ai en moniteur série si j'appuie sur le poussoir 2 fois (la deuxième pendant que le fichier tourne encore) :
Capture d’écran 2021-12-13 à 08.48.17

dans ce cas : le fichier est lu jusqu'au bout et s'arrête mais le moniteur série affiche la fin de la lecture, pas dans le premier cas.

que veut dire la variable isPlaying ? pourquoi est-elle mise à true dans le setup() sans lancement de mp3 ?

pourquoi mettre HIGH vos pins qui sont en INPUT_PULLUP?

  pinMode(PinButtonPlay, INPUT_PULLUP);
  digitalWrite(PinButtonPlay, HIGH);
  pinMode(PinButtonStop, INPUT_PULLUP);
  digitalWrite(PinButtonStop, HIGH);
  pinMode(PinButtonPrevious, INPUT_PULLUP);
  digitalWrite(PinButtonPrevious, HIGH);
  pinMode(PinButtonNext, INPUT_PULLUP);
  digitalWrite(PinButtonNext, HIGH);

Quelle bibliothèque LCD utilisez vous (lien). C'est rare d'avoir à faire à la fois begin() et init()

  lcdScreen.begin(16, 2);
  lcdScreen.init();

en plus de la déclaration

LiquidCrystal_I2C lcdScreen(0x27, 16, 2);

comment gérez vous le rebond des boutons et l'appui (si on tient appuyé à la prochaine loop le bouton est encore vu appuyé) ➜ pour simplifier votre gestion des boutons, éventuellement utilisez la librairie de @bricoleau ou alors la librairie OneButton de Matthias Hertel.

sinon essayez déjà cela - approche en supposant que le bouton ne sera pas lu 2 fois (en gros vous avez 1/2 seconde de delay pour relâcher le bouton)

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <LiquidCrystal_I2C.h>

SoftwareSerial mp3Serial(10, 11);
DFRobotDFPlayerMini myDFPlayer;
LiquidCrystal_I2C lcdScreen(0x27, 16, 2);

# define ACTIVATED LOW

int VarPotentioValeur = 0; // Variable où on stock la valeur du potentiomètre
const byte PinButtonPlay = 4;
const byte PinButtonStop = 5;
const byte PinButtonPrevious = 6;
const byte PinButtonNext = 7;

boolean isPlaying = false;

void setup () {
  pinMode(PinButtonPlay, INPUT_PULLUP);
  pinMode(PinButtonStop, INPUT_PULLUP);
  pinMode(PinButtonPrevious, INPUT_PULLUP);
  pinMode(PinButtonNext, INPUT_PULLUP);

  lcdScreen.begin();
  lcdScreen.backlight();

  mp3Serial.begin(9600);
  Serial.begin(115200);   Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mp3Serial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) yield(); // Code to compatible with ESP8266 watch dog.
  }

  myDFPlayer.volume(10);  //Set volume value. From 0 to 30
  Serial.println(F("DFPlayer Mini online."));
}


void loop () {
  // Set volume to maximum (0 to 30).
  myDFPlayer.volume(map(analogRead(A0), 0, 1023, 0, 30));
  lcdScreen.setCursor(10, 0);
  lcdScreen.print("VOL:");

  if (myDFPlayer.readVolume() < 10) lcdScreen.write('0');
  lcdScreen.print(myDFPlayer.readVolume());

  if (digitalRead(PinButtonStop) == ACTIVATED) {
    stopMP3();
    isPlaying = false;
  }

  if (digitalRead(PinButtonPlay) == ACTIVATED) {
    playMP3();
    isPlaying = true;
  }

  if (isPlaying && digitalRead(PinButtonNext) == ACTIVATED) {
    `playNextMP3`();
  }

  if (isPlaying && digitalRead(PinButtonPrevious) == ACTIVATED) {
    playPreviousMP3();
  }

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value) {
  switch (type) {

    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerUSBInserted:
      Serial.println("USB Inserted!");
      break;
    case DFPlayerUSBRemoved:
      Serial.println("USB Removed!");
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      isPlaying = false;
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

void playMP3() {
  execute_CMD(0x0D, 0, 1);
  delay(500);
  displayFileName();
  Serial.println ("Play:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}

void stopMP3() {
  execute_CMD(0x16, 0, 0);
  delay(500);
  displayFileName();
  Serial.println ("Stop:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}

void playNextMP3() {
  execute_CMD(0x01, 0, 1);
  delay(500);
  displayFileName();
  Serial.println ("Next:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}

void playPreviousMP3() {
  execute_CMD(0x02, 0, 1);
  delay(500);
  displayFileName();
  Serial.println ("Previous:");
  Serial.println (myDFPlayer.readCurrentFileNumber());
}

void displayFileName() {
  lcdScreen.clear();
  lcdScreen.setCursor(0, 0);
  lcdScreen.print("Track :");
  lcdScreen.setCursor(0, 1);

  int fileNumber = myDFPlayer.readCurrentFileNumber();
  lcdScreen.print(fileNumber);
  lcdScreen.print(F(".mp3"));
}

void execute_CMD(byte CMD, byte Par1, byte Par2) {

# define Start_Byte 0x7E
# define Version_Byte 0xFF
# define Command_Length 0x06
# define End_Byte 0xEF
# define Acknowledge 0x00 //Returns info with command 0x41 [0x01: info, 0x00: no info]
  // Excecute the command and parameters
  // Calculate the checksum (2 bytes)
  word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
  // Build the command line
  byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
                            Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte
                          };
  //Send the command line to the module
  mp3Serial.write( Command_line, sizeof Command_line);
}

code tapé ici sur la base de votre code, non testé...

il faut sans doute regarder plus précisément quand remettre isPlaying = false en fonction des messages du module.

Merci je vais retester tout cela.
Je te répondrai quand je serai sur l'ordi et devant l'Arduino.
Pour lastuce de @la librairie de bricoleau impossible de la télécharger.....

le lien en haut ne fonctionne pas mais en bas vous avez un zip

ya une erreur que je n'arrive pas à corriger dans ton code....

exit status 1
no matching function for call to 'LiquidCrystal_I2C::begin()'

et si j'enlève :

 lcdScreen.init();

l'écran LCD n'affiche que le volume mais seul.

je l'ai enlevée car je veux juste que le lecteur démarre sans lancer de musique.

oui, c'est mieux en ACTIVATED.
j'ai mis INPUT_PULLUP pour éviter de mettre une resistance

j'utilise celle-ci

je gère les rebonds avec la function PULLUP.

merci pour votre aide

Je suppose que c'est le firmware de la puce, dans le premier cas c'est un arrêt normal et ne rapporte pas, le second cas est un arrêt forcé et rapporte. Cependant, vous pouvez obtenir cette information en lisant la broche Busy du dfplayer, lorsqu'il ne joue pas, vous aurez une logique. Connectez cette broche à l'arduino, la lecture de cette broche peut être très utile pour prendre certaines décisions, par exemple vous pourriez supprimer la variable isPlaying.

@gonpezzi merci pour cette info précise....
comment écrirais-tu pour récupérer les infos de la pin 16 et l'afficher dans le moniteur série ?

alors je précise que malgré tout ce désordre mets en vrille le dfplayer et ce dernier n'est plus contrôlable et doit être redémarré...donc je ne sais pas si c'est une solution durable...
merci encore

Je suppose qu'à la broche 16 vous avez connecté la broche busy du dfplayer, par exemple :

If (digitalRead (16) == LOW) {
Serial.println ("EN JOUANT");
}
If (digitalRead (16) == HIGH) {
Serial.println (" STAND-BY");
}

Au final ça va sortir, n'hésitez pas si tôt, dites juste que je n'utilise pas ces commandes complexes
par exemple pour aller à la chanson précédente que je n'utilise pas

texecute_CMD(0x02, 0, 1);

je viens d'utiliser

myDFPlayer.previous();

Et puisque vous incluez la fonction void printDetail(), profitez-en, par exemple dans le case :

 case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;

Vous pouvez ajouter :

 case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      myDFPlayer.randomAll();
      break;

Vous avez encore beaucoup à essayer pour vous décourager si vite.

non, laissez juste INPUT_PULLUP, rien de plus.

ça dépend de la bibliothèque retenue pour le LCD. avec celle que vous avez il faut

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcdScreen(0x27, 16, 2);
void setup()
{
  lcd.init();                      // initialize the lcd 
  lcdScreen.backlight();

mais pas de begin()

je viens d'essayer cela , ok pour ça. merci à vous

la broche 16 est la pin 16 du dfplayer qui est la broche BUSY.
je la connecte à la broche 3 de mon arduino par exemple ?