Reading Messages from DFPlayer using DFPlayerMini_Fast

Hi There,

I've been currently developing for the DFPlayer Mini in a PhD project and after doing some digging into these forums after some issues with sleep modes, I've found that the original library provided by the manufacturer isn't quite up to date.

Instead of throwing hardware at a software problem (by forgoing the sleep mode in favour of a high-side transistor switch to cut power when sleep was required), I have instead opted for using Power_Broker's excellent fast library.

However this has also caused some issues as my program employs significant use various specific commands within the original library. These however are either unavailable or not as simply accessed in the fast library and the example code (fast library) provided isn't as comprehensive as the examples in the original library.

To that end, I have taken the original "ReadValues" example code and modified it to reference the superior fast library. However, I have a few functions that I would like some advice on, to assist with my code's migration.

Is this a correct modification for the original .readType and .read commands?

printDetail(myDFPlayer.query(0x41), myDFPlayer.query(0x40)); //DFPlayerMini_Fast
//printDetail(myDFPlayer.readType(), myDFPlayer.read());     //DFRobotDFPlayerMini

And Is this a suitable replacement for checking .available in the fast library?

//if (myDFPlayer.available()) {      //DFRobotDFPlayerMini
  if (myDFPlayer.parseFeedback()) {  //DFPlayerMini_Fast

I quite like the original printDetail function in this that example code (since I can prompt my own debug of the unit) and I've found it a bit difficult to recreate it in the new library. Likewise, it also gives me the ability to check if the unit is sleeping by checking when myDFPlayer.read() = 2

Any advice would be excellent, I have also attached my version of the ReadValues.ino which has been modified to be fully compliant with Power_Broker's library and once the above issues are clarified, hopefully this can be a useful addition to the documentation.

Cheers

ReadValues_Fast.ino (8.51 KB)

Still trying to make my way forward with this library, i've found that .query doesn't allow for the passing of error codes (only providing a -1 for all errors) and instead requires the user to prompt a function called errorPrint to print possible errors. While this is good for a simple and easy print function, when we want to use errors for a condition, it hinders us as it obfuscates what the original function .read and .readType allowed us to do.

From my understanding, to get close to these functions we need to call .query(dfplayer::GET_STATUS_) then .parseFeedback(); and then use DFPlayerMini_Fast.recStack.paramLSB for conditions.

DFPlayerMini_Fast.query(dfplayer::GET_STATUS_);
DFPlayerMini_Fast.parseFeedback();
if (DFPlayerMini_Fast.recStack.paramLSB = 0x2)
{
 Serial.println(F("You are in sleep mode"));
}

Or something like

DFPlayerMini_Fast.query(dfplayer::GET_STATUS_);
DFPlayerMini_Fast.parseFeedback();
if (DFPlayerMini_Fast.recStack.paramLSB = 0x1)
{
 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);
}

There must be a better way to do this?

Thanks for the interest in the library. Here's how I would do it if I were you:

DFPlayerMini_Fast.query(dfplayer::GET_STATUS_);

if ((DFPlayerMini_Fast.recStack.commandValue == 0x40) && (DFPlayerMini_Fast.recStack.paramLSB == 0x8))
{
  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);
}

If 0x8 isn't the correct error code you're looking for, you can easily switch it out with the correct one. Two more things:

  • query() already calls parseFeedback()
  • printError() prints a description of whatever specific error has occurred during the last query (if an error happened at all)

Hope this helps!

Power_Broker:
Thanks for the interest in the library. Here's how I would do it if I were you:

DFPlayerMini_Fast.query(dfplayer::GET_STATUS_);

if ((DFPlayerMini_Fast.recStack.commandValue == 0x40) && (DFPlayerMini_Fast.recStack.paramLSB == 0x8))
{
  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);
}




If 0x8 isn't the correct error code you're looking for, you can easily switch it out with the correct one. Two more things:


- `query()` already calls `parseFeedback()`
- `printError()` prints a description of whatever specific error has occurred during the last query (if an error happened at all)


Hope this helps!

Hi Power_Broker,
Thanks for the advice, I missed the parseFeedback call when looking through the library files so that's great that we don't need to call that function too!

Regarding the conditions, I'm glad that I was thinking along correct lines and admittingly I was struggling to realise how the 0x40 value could be utilised (in the original data sheet, it says that 0x40 returns an error and re-requests transmission), hence I thought we had to send the module 0x40 for it to return the error code. However after your reply I can now see that we don't need to send 0x40 but it just helps identify the received hex code as an error. After looking at the printError function in light of this, makes a lot more sense!

An additional aside however, I have found that the error code for the SD card either not being installed or damaged is not flagging the intended 0x8 but is instead flagging an error of 0x1 (module busy), quite strange, I wonder if this is a hardware issue, have you seen similar behaviour? Regardless, I modified the code to error check across the whole error range, which should help with this issue.

  myDFPlayer.query(dfplayer::GET_STATUS_);
  Serial.println (myDFPlayer.recStack.paramLSB);
  if ((myDFPlayer.recStack.commandValue == 0x40) && ((myDFPlayer.recStack.paramLSB > 0x0) && (myDFPlayer.recStack.paramLSB <= 0x8)))
  {
   Serial.println(F("Unable to begin:"));
   if (myDFPlayer.recStack.paramLSB == 0x8)
   {
   Serial.println(F("1.Please recheck the connection!"));
   Serial.println(F("2.Please insert the SD card!"));
   }else
   {
    DFPlayerMini_Fast.printError();
   }
   while(true);
  }

Regarding the prior library's use of .available(), I now believe it is using this to call their error checking function every time the arduino and module have a period of no communication. Hence, I am going to instead call the get_status query using a millis condition rather than that method.

Error code issue appears to be worse than first thought, it appears that every error I receive is being given the 0x1 identifier (module busy). This includes putting the module into sleep mode (with sleep mode causing a 0x1 rather than 0x2 message to be received.

Has this behaviour been seen by anyone else?

Two things:

  • I don't have much experience with error codes, however I have gotten an error code of 0x6 before
  • Sleep mode doesn't actually save much power. It mainly causes the player to stop playing and prevent the processing of commands that can start a track

Power_Broker:
Two things:

  • I don't have much experience with error codes, however I have gotten an error code of 0x6 before
  • Sleep mode doesn't actually save much power. It mainly causes the player to stop playing and prevent the processing of commands that can start a track

So in that regard then, regardless of library, sleep mode on the DFPlayer module isn't useful for applications that require reductions in power consumption. That's a shame as I was hoping to avoid using high-side transistor switching on the v+ lines of the DFPlayer mini, but needs be must.

Since I sent the last message, I have discovered that not all DFPlayers are equal with error codes between what appear to be same models, actually being slightly different:

Microsoft Word - MP3-TF-16P V1.0_en.doc (amperka.ru)

In the error section of both documents, it details that 7E FF 06 40 00 00 01 xx xx EF can either indicate "A frame data are not all received" or on another datasheet "Module busy(this info is returned when the initialization
is not done)"

Still though, this is a bit of a shame when it comes to conditions that want to detect if the module is sleeping and do something.

Yeah, I only recently learned that not all DFPlayers are created equal and the lack of standardization between them is frustrating. The sleep mode not actually saving power is also something I recently discovered. Then again, what should we expect from Chinese electronics, lol

Power_Broker:
Yeah, I only recently learned that not all DFPlayers are created equal and the lack of standardization between them is frustrating. The sleep mode not actually saving power is also something I recently discovered. Then again, what should we expect from Chinese electronics, lol

I know, such as life :), cheers for the assistance regardless! Following on from the high-side switching plan, there is a quite good post from @TomGeorge in the post can't active DFPlayer with a transistor - Page 4 (arduino.cc) that has a solution that seems fairly good with the addition of a resistor on the tx line.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.