MP3 player continue from left off state

I'm trying to code and program a NANO linked to a mini DFPlayer to continue where it left off after power down / start up. Every time I start up the player, the first track starts at the beginning and no save points are set in the EEPROM. When some tracks are 2 hours long this can get quite tedious having to flick through the play list to reach the chosen track but even then it starts from the beginning of the long track when all I really want is to continue where it was left off prior to shutdown.

I've spend several days working with internal EEPRON to solve the problem to no avail.

Is there a way to lock the last (play point) in the EEPRON so when the player is powered down it resumes from where it left off when powered up? If so any guidence would be appreciated.

I've removed the EEPROM code as it was only cluttering up the working original.

Enclosed is the code:
#include <SoftwareSerial.h>
#include <IRremote.h>

define Start_Byte 0x7E

define Version_Byte 0xFF

define Command_Length 0x06

define End_Byte 0xEF

define Acknowledge 0x00

define pause_play 0xFF22DD

define next_song 0xFFC23D

define prev_song 0xFF02FD

define vol_inc 0xFF906F

define vol_dec 0xFFA857

define sound_equalizer 0xFFE01F

//-------------------------------------------------------//

SoftwareSerial mySerial(10,11);

const int receiver = A0;
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results dec; // create instance of 'decode_results'

int volume = 20;
int eqset = 0;
boolean Playing = false;

void setup ()
{
Serial.begin(9600);
Serial.println("IR Receiver Button Decode");

irrecv.enableIRIn(); // Start the receiver
mySerial.begin(9600);
delay(1000);
playFirst();
Playing = true;
}

void loop ()
{
if(irrecv.decode(&dec))
{
Serial.println(dec.value, HEX); // Here you can get your remote's buttons codes
if (dec.value==pause_play)
{
if(Playing)
{
pause();
Playing = false;
}
else
{
Playing = true;
play();
}
}
if (dec.value==next_song)
{
if(Playing)
{
next();
}
}
if (dec.value==prev_song)
{
if(Playing)
{
previous();
}
}
if(dec.value==vol_inc)
{
volumeINC();
}
if(dec.value==vol_dec)
{
volumeDEC();
}
if(dec.value==sound_equalizer)
{
equalizer();
}
irrecv.resume();
}
}

void playFirst()
{
exe_cmd(0x3F, 0, 0);
delay(100);
exe_cmd(0x06, 0, volume);
delay(100);
exe_cmd(0x11,0,1);
delay(100);
}

void pause()
{
exe_cmd(0x0E,0,0);
delay(100);
}

void play()
{
exe_cmd(0x0D,0,1);
delay(100);
}

void next()
{
exe_cmd(0x01,0,1);
delay(100);
}

void previous()
{
exe_cmd(0x02,0,1);
delay(100);
}

void volumeINC()
{
volume = volume+1;
if(volume == 31)
{
volume = 40;
}
exe_cmd(0x06, 0, volume);
delay(100);
}

void volumeDEC()
{
volume = volume-1;
if(volume == -1)
{
volume = 0;
}
exe_cmd(0x06, 0, volume);
delay(100);
}

void equalizer()
{
eqset = eqset+1;
if(eqset == 6)
{
eqset = 0;
}
exe_cmd(0x07, 0, eqset);
delay(100);
}

void exe_cmd(byte CMD, byte Par1, byte Par2)
{
word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2);
byte Command_line[10] = {Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge,
Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte};
for (byte x=0; x<10; x++)
{
mySerial.write(Command_line[x]);
}
}

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

You can not know the position within a track using a DFPlayer. There is no command for that. All you can do is record which track is playing

@billboflash In order to do what you want, I think you need the DFPlayer Pro. With the Mini, you can only know the track number that is playing, not how much of the track has been played.

The DFPlayer Pro has a function getCurTime() which may return the number of seconds that have been played on the current track. It also has a function setPlayTime() which looks like it can be used to start playback from a specific number of seconds into the track.

Thanks for the feedback guys.
I've just placed an order for the DFPlayer pro. Looks interesting. Glad I joined the forum or would never have heard about it.

OK the new DFplayer pro arrived and was hooked up to my Arduino Nano.
I used the example file provided in the DFRobot _DF1201S-master folder downloaded from the site. Everything works except the music starts from the beginning of the last track played after shutdown.

Here is a section of the code in the example file markd833 was referring to.

The only question I have right now is. What do I put in the ()); if that is all I need to make it work as requested in the original post?

  Serial.print("The time length the current song has played:");
  //Get the time length the current song has played 
  Serial.println(DF1201S.getCurTime());
  
  Serial.print("The total length of the currently-playing song: ");
  //Get the total length of the currently-playing song 
  Serial.println(DF1201S.getTotalTime());

Appreciate any and all help.

The library isn't clear what is being returned when you call getCurTime(). The source comment says:

Get the time length the current song has played

You can probably figure this out by querying the device when the current song is playing, but I'd hazard a guess that as the returned value is a uint16, then it's likely to be the number of seconds into the song.

The setPlayTime() function is somewhat clearer on its parameter:

Let the currently-playing song start playing from a particular time point

The parameter is a uint16 called second, so I'd say that is the number of seconds into the track to resume playback. So if you wanted to start playing from 1min 30sec, then you would pass 90.

You would need to experiment with the module to figure out when to call the setPlayTime() function. You might need the track to be playing first, or you might just need the track to be selected, and calling setPlayTime() starts playback of the currently selected track from the number of seconds into the track you've passed as a parameter to the function.

You will have to query the timestamp of the currently playing track every X milliseconds and write that out to EEPROM. Be aware, the EEPROM does not have an infinite amount of writes so updating very quickly can wear out your EEPROM.

unsigned long lastUpdate;
const unsigned long updateInterval = 10000UL;  // update every 10 seconds
void loop() {
  if ( millis() - lastUpdate >= updateInterval ) {
    lastUpdate = millis();
    uint16_t playTime = DF1201S.getCurTime();
    // update EERPOM with current track and time
  }
...

And in setup(), you will need to read those values back and start the correct track at the correct time.

Note that the pro version also has fastforward/reverse so it would be easy to have buttons on your nano to skip ahead/back 10 seconds or whatever.

Hey thanks for the replies.
This is starting to look a little overwhelming after only just becoming associated with Arduino's and coding.
I get some of what you are saying but much is over my head, leaves me in a fog.

I was hoping for some kind of deal where the memory was logged prior to shutdown after the command 'turnoff' was executed in the code, then continue onward at restart. A timestamp made at that point if you will.

The idea came from a set of P47 headphones I own that played mp3 files and resumed from left off. Almost perfect. Only problem is the chip inside the headphones has no data available online to know the pin out, function, etc. I tried to emulate that with an Arduino and several players but was never successful. Also the Arduino would have allowed my to use IR remote as an option.

From what blh says. Yeah I can see my eeprom going south in a short time with multiple updates.

Mark. I'll take a closer look at it tomorrow and see if anything from your reply has any effect.

Thanks again.

If you power down through a button, then you do not need to update the timestamp very often at all. I was assuming the power just got turned off at any given moment...

That indeed would be easy, except for that the fact that you do not have such a function in your code

@Bob
Nor would I even know how to start making / writing that function (power down) if indeed where possible.

@blh64
Yeah sorry for not being too specific about that. I have an old boombox that ticks all the boxes as far as lcd screen, remote / button control, graphic eq etc. The only thing it lacks is the ability to retain last position on a played track. Like many players out there it starts from the beginning when switched on. Great if a track is 4 mins long......not so great when they are 2 hrs long and you have listened to an hour already.

I kinda find it surprising this subject is not too common with mp3 players as many suffer from the same problem or worse start from the first song on the list. Couldn't find anything when I searched online.

First, you need to know what code your IR remote sends for "power off"
Then, you need your sketch to react to that code by storing the current track and time in the EEPROM. It doesn't sound like the arduino itself will be powered off?

Then, do the same thing for "power on" code.
react to that by reading track & time and starting to play...