MP3 Player shield

Ciao a tutti,volevo provare a fare un lettore MP3 con display e qualche pulsante di controllo ma ho un problema :roll_eyes: Nella libreria di sparkfun mostra diversi esempi di utilizzo ma con un formato del nome traccia in 8.3 ovvero 8 caratteri più l'estensione del file che in questo caso è MP3. Un link di riferimento https://www.sparkfun.com/products/10628 Mi chiedevo se qualcuno di voi mi potesse spiegare come e se si può risolvere questo problema. Vorrei fare in modo da scorrere i file all'interno della SD card e poter vedere a display il nome per intero(non 8.3) e poi successivamente una volta trovato il file di interesse avviare la riproduzione del brano. Basterebbe anche solo uno spunto sulla logica da usare Grazie a tutti,ciao

Per quella scheda ti dicono di usare la SdFatLib. Se vai sul sito di quella libreria si legge: "SdFat only supports short 8.3 file names"

Perciò puoi mettere sulla SD (formattata in FAT16 o FAT32) solo nomi di file corto. La libreria NON legge nomi di file lunghi. Il titolo completo potrebbe essere scritto dentro al file MP3 come Tag, ma non è semplice andare dentro al file a leggerlo.

Ciao e grazie della risposta :)

La libreria NON legge nomi di file lunghi.

Infatti ho visto che non li legge ed ho fatto una prova a leggere un file con nome Michele Zarr.... e lo leggo a display come michel->1.MP3 Per leggere all'interno del file il titolo,artista ed altre cosucce(a patto che vi siano scritte) è stata implementata la funzione quindi è possibile farlo sfruttando dei char....Un esempio

 char title[30]; // buffer to contain the extract the Title from the current filehandles
    char artist[30]; // buffer to contain the extract the artist name from the current filehandles
    char album[30]; // buffer to contain the extract the album name from the current filehandles
    uint32_t offset = 0;
    char trackName[] = "2.mp3";
    //start playing track 1
    MP3player.playMP3(trackName,offset);
    MP3player.trackTitle((char*)&title);
    MP3player.trackArtist((char*)&artist);
    MP3player.trackAlbum((char*)&album);

Il problema rimane il fatto che vorrei fosse possibile visualizzare nomi estesi ....... Ma se ,secondo te, volessi invece creare un file con nome più lungo di 8.3 riuscirei con la libreria oppure anche in scrittura ho delle limitazioni?? Perchè pensavo,in maniera contorta,di memorizzare il nome intero,rinominarlo come "1",mandarlo in riproduzione,leggere i tag all'interno visualizzandoli a display ed alla fine ripristinare il suo nome originale..... :roll_eyes:

Non mi è chiarissima l'ultima tua frase. Metti i file su SD chiamandoli 1.mp3, 2.mp3,etc. con i dati nei tag?

Secondo me la libreria è limitata ai nomi 8.3 in tutti i casi. Se tu scrivi da PC, che accetta i nomi lunghi, e poi la libreria legge file 8.3 non ci sono alternative. Il titolo/cantante può stare nel tag. Tieni conto che di solito i lettori MP3 visualizzano i dati del Tag (se presenti) e non il nome del file.

[

Non mi è chiarissima l'ultima tua frase. Metti i file su SD chiamandoli 1.mp3, 2.mp3,etc. con i dati nei tag?

Effettivamente rileggendo ho detto una fesseria ,se la lib legge nomi in 8.3 non posso fargli fare diversamente ]:) E' che vorrei fare in modo di non doversi preoccupare di modificare il nome del file (in formato 8.3) una volta messo sulla SD

In pratica il problema è: -metto un brano in SD il cui nome è Daniele Antonio.MP3 (quindi lungo più di 8) -se lo apro con la lib usando open next file il nome del file viene stampato in maniera differente,qualcosa tipo Daniele ->.MP3 -se ora mando in riproduzione Daniele ->.MP3 non son sicuro che parta......

potresti fare una funzione nella quale, a ogni cambiamento/modifica/inserimento di SD, rinomini i file in 8.3 mettendo però i nomi dei files in un tag sconosciuto dei files MP3(creatore mi pare che non lo legga nessuno). Però non so se si possa fare con quella libreria, non so se mi sono fatto capire. :drooling_face:

potresti fare una funzione nella quale, a ogni cambiamento/modifica/inserimento di SD, rinomini i file in 8.3 mettendo però i nomi dei files in un tag sconosciuto dei files MP3(creatore mi pare che non lo legga nessuno). Però non so se si possa fare con quella libreria, non so se mi sono fatto capire

Si ho capito cosa vuoi dire ma penso di aver capito come risolvere il problema.

Guardando bene dall’esempio allegato alla libreria dello shield mi sono soffermato in questo passaggio…

 else if(key_command == 'l') {
    if(!MP3player.isPlaying()) {
      Serial.println(F("Music Files found :"));
      SdFile file;
      char filename[13];
      sd.chdir("/",true);
      uint16_t count = 1;
      while (file.openNext(sd.vwd(),O_READ))
      {
        file.getFilename(filename);
        if ( isFnMusic(filename) ) {
          SerialPrintPaddedNumber(count, 5 );
          Serial.print(F(": "));
          Serial.println(filename);
          count++;
        }
        file.close();
      }
      Serial.println(F("Enter Index of File to play"));

    } else {
      Serial.println(F("Busy Playing Files, try again later."));
    }

…ed ho capito che ogni volta che si alimenta il circuito fa una lettura di tutti i file nella SD e li numera partendo dal numero 00001
a partire dal primo fino all’ultimo.
Ora eliminando ciò che riguarda la stampa in serial monitor non riesco ad interpretare ciò che è scritto e cioè quale variabile assegna il numero in sequenza alle tracce :roll_eyes:
Riuscite per favore a spiegarmi queste righe di codice??

EDIT

quì c’è la void SerialPrintPaddedNumber

void SerialPrintPaddedNumber(int16_t value, int8_t digits ) {
  int currentMax = 10;
  for (byte i=1; i<digits; i++){
    if (value < currentMax) {
      Serial.print("0");
    }
    currentMax *= 10;
  }
  Serial.print(value);
}

Rieccomi,dopo un po di studio ulteriore,sono riuscito a fare qualcosina

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>
SdFat sd;
SdFile file;
SFEMP3Shield MP3player;
char filename[13];         // char in cui metto il nome del file
byte conta =0;             //variabile che uso per memorizzare il numero di file che ho riprodotto 
byte traccia=0;            //variabile che uso per raggiungere il numero di traccia da riprodurre
byte n_brani=0;            //variabile che uso per memorizzare quanti brani ci sono in tutto nella SD
char title[20];            // buffer che contiene il titolo del file
char artist[20];           // buffer che contiene l'artista del file
char album[20];            // buffer che contiene l'album del file 
 

void setup() {
  Serial.begin(9600);                          //inizializzo la seriale
  sd.begin(SD_SEL, SPI_HALF_SPEED);            //inposto la velocità SPI
  MP3player.begin();                           //inizializzo l'MP3 
  sd.chdir("/",true);
  while(file.openNext(sd.vwd(),O_READ)){        //entro nella sd card e conto quanti file ci sono(uscirà dal while quando sono finiti)
     n_brani++;                                 //memorizzo il numero totale 
     file.close();                              //chiudo
    }
  Serial.print("brani trovati in SD card  :");  //stampo a monitor 
  Serial.println(n_brani);                      //quanti brani ci sono
}

/////Nel loop si crea una riproduzione automatica a partire dalla prima traccia fino all'ultima e si richiedono i dati dai tag_MP3 dopo la 
/////riproduzione visualizzandoli in serial monitor.........


void loop(){
  if(!MP3player.isPlaying()) {                 //controllo se è in riproduzione
    sd.chdir("/",true);
   while(file.openNext(sd.vwd(),O_READ)){      //entro nella sd ed apro il primo file 
     file.getFilename(filename);               //memorizzo il nome del file
     traccia++;                                //do un numero di traccia
     file.close();                             //chiudo il file
     if(traccia>conta){                        //se non è già stato riprodotto
     MP3player.playMP3(filename);              //riproduco ed esco dal ciclo bloccante while
     break;
     }
  }
  conta++;                                     //aumento il numero di brano riprodotto
  Serial.print("traccia in esecuzione :  ");   //stampo a monitor questultimo
  Serial.println(conta);
  MP3player.trackTitle((char*)&title);         //richiedo i dati scritti nei tag del file e li stampo a monitor
  MP3player.trackArtist((char*)&artist);
  MP3player.trackAlbum((char*)&album);
  Serial.write((byte*)&title, 20);
  Serial.println();
  Serial.print(F("by:  "));
  Serial.write((byte*)&artist, 20);
  Serial.println();
  Serial.print(F("Album:  "));
  Serial.write((byte*)&album, 20);
  Serial.println();
  traccia=0;                                  //azzero il contatore della traccia aperta per poter arrivare a quella successiva a quella appena riprodotta
  }
  if(conta==n_brani){                         //se i brani riprodotti hanno lo stesso numero di quelli presenti in SD 
    conta=0;                                  //azzero conta per poter ricominciare da capo  
  }
}

Con questo codice faccio una riproduzione in sequenza dal primo brano fino all’ultimo presente nella SD card…
Il problema che avevo era quello di non riuscire a capire come aprire un file senza conoscere il nome della traccia ed anche se conoscevo il nome traccia mi preoccupava la limitazione della lunghezza del nome di 8 caratteri più 3 per l’estensione.
Di fatto invece il problema non c’è nel senso che se il nome traccia è più lungo dello standard(8.3) il nome viene accorciato in lettura in questo modo : file originale = MARIOROSSI.MP3 diventa MARIOR->1.MP3…a questo punto se viene memorizzato come tale in un Char,quando decido di riprodurre la traccia con il nome file,usando sempre lo stesso concetto di riduzione del nome ,effettivamente trova la traccia …Quindi per il momento il problema è risolto ma non ritengo chiuso il topic perchè ,a lavoro ultimato, condividerò il lavoro fatto.
Ciao,Tony :wink:

Ciao a tutti,ho fatto un po di aggiornamenti al codice…
Ora ho 2 pulsanti per il volume(+,-),1 x play,1 x stop,2 x traccia avanti,traccia indietro ed un pulsante per la riproduzione automatica,dovrò fare ancora delle sistemazioni e dovrò aggiungere il controllo dei toni (bassi,alti) più un ultimo pulsante ON/OFF,dovrò usare un pin per l’accensione dell’amplificatore esterno(remote) ed altre cosucce tra cui un display 40x4…
Sicuramente userò un ATMega2560 sulla scheda definitiva perchè con un 328 c’è poca memoria e non si riesce a fare tutto questo.
Il passo successivo sarà quello di fare una app su android per fare un telecomando sfruttando il bluetooth…

#include <MemoryFree.h>
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h> 
#include <SFEMP3Shield.h>
SdFat sd;
SdFile file;
SFEMP3Shield MP3player;
char filename[13];         // char in cui metto il nome del file
byte conta =0;             //variabile che uso per memorizzare il numero di file che ho riprodotto 
byte traccia=0;            //variabile che uso per raggiungere il numero di traccia da riprodurre
byte n_brani=0;            //variabile che uso per memorizzare quanti brani ci sono in tutto nella SD
char title[20];            // buffer che contiene il titolo del file
char artist[20];           // buffer che contiene l'artista del file
char album[20];            // buffer che contiene l'album del file 
boolean state_r_auto=false;


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////


int analogico=0;
#define play 0
#define alt 1
#define traccia_in 2
#define traccia_av 3
#define r_auto 4
#define alza 5
#define abbassa 6
#define toni 7
#define ON 8
#define no_pulsante 9
#define DEBOUNCE_TIME  200 
int pulsante=0;
boolean debounce;
unsigned long previous_time;



//////////////////////////////////////////////////////////////////////////////////////////////////////////////



void setup() {
  
  Serial.begin(9600);                          //inizializzo la seriale
  debounce=false;
  sd.begin(SD_SEL, SPI_HALF_SPEED);            //inposto la velocità SPI
  MP3player.begin();                           //inizializzo l'MP3 
  sd.chdir("/",true);
  while(file.openNext(sd.vwd(),O_READ)){        //entro nella sd card e conto quanti file ci sono(uscirà dal while quando sono finiti)
     n_brani++;                                 //memorizzo il numero totale 
     file.close();                              //chiudo
    }
  Serial.print("brani trovati in SD card  :");  //stampo a monitor 
  Serial.println(n_brani);                      //quanti brani ci sono
 
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

union twobyte mp3_vol; // create key_command existing variable that can be both word and double byte of left and right.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop(){ 
 if(debounce) {
    pulsante = no_pulsante;
    if(millis() > previous_time + DEBOUNCE_TIME) debounce = false;
  } else  pulsante= read_buttons();
  
  // if a button is pressed, start debounce time
  if(pulsante != no_pulsante) {
    
    previous_time = millis();
    debounce = true;  
  } 
 switch(pulsante){
 case ON:
// Serial.println ("ON/Off");
 break;
 case alza:
 mp3_vol.word = MP3player.getVolume(); // returns a double uint8_t of Left and Right packed into int16_t
 if(mp3_vol.byte[1] <= 2) { // range check
        mp3_vol.byte[1] = 2;
      } else {
        mp3_vol.byte[1] -= 2;
      }   
 MP3player.setVolume(mp3_vol.byte[1], mp3_vol.byte[1]);
 break;
 case abbassa:
 mp3_vol.word = MP3player.getVolume(); 
 if(mp3_vol.byte[1] >= 254) { // range check
        mp3_vol.byte[1] = 254;
      } else {
        mp3_vol.byte[1] += 2; // keep it simpler with whole dB's
      } 
 MP3player.setVolume(mp3_vol.byte[1], mp3_vol.byte[1]); 
 break;
 case toni:
 Serial.println ("toni");
 break;
 case r_auto:
 if(state_r_auto==false){state_r_auto=true;}
 else {state_r_auto=false;}
 break;
 case traccia_av:
 MP3player.stopTrack();
 if(state_r_auto==false){conta++;traccia_av_in();}
 else{rip_auto();}
 break;
 case traccia_in:
 conta--;
 MP3player.stopTrack();
 if(state_r_auto==false){traccia_av_in();}
 else{conta--;rip_auto();}
 break;
 case alt:
 MP3player.stopTrack();
 state_r_auto=false;
 conta=0;
 break;
 case play:
 rip_auto();
 break;
 }
 if(state_r_auto)rip_auto();
 Serial.println(state_r_auto);
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////


void rip_auto(){
  
  if(!MP3player.isPlaying()) {                 //controllo se è in riproduzione
    sd.chdir("/",true);
   while(file.openNext(sd.vwd(),O_READ)){      //entro nella sd ed apro il primo file 
     file.getFilename(filename);               //memorizzo il nome del file
     traccia++;                                //do un numero di traccia
     file.close();                             //chiudo il file
     if(traccia>conta){                        //se non è già stato riprodotto
     MP3player.playMP3(filename);              //riproduco ed esco dal ciclo bloccante while
     break;
     }
  }
  conta++;                                     //aumento il numero di brano riprodotto
  //Serial.print("traccia in esecuzione :  ");   //stampo a monitor questultimo
  //Serial.println(conta);
//  MP3player.trackTitle((char*)&title);         //richiedo i dati scritti nei tag del file e li stampo a monitor
//  MP3player.trackArtist((char*)&artist);
//  MP3player.trackAlbum((char*)&album);
//  Serial.write((byte*)&title, 20);
//  Serial.println();
//  Serial.print(F("by:  "));
//  Serial.write((byte*)&artist, 20);
//  Serial.println();
//  Serial.print(F("Album:  "));
//  Serial.write((byte*)&album, 20);
//  Serial.println();
  traccia=0;                                  //azzero il contatore della traccia aperta per poter arrivare a quella successiva a quella appena riprodotta
  }
  if(conta==n_brani){                         //se i brani riprodotti hanno lo stesso numero di quelli presenti in SD 
    conta=0;                                  //azzero conta per poter ricominciare da capo  
  }
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void traccia_av_in(){
  
  if(!MP3player.isPlaying()) {                 //controllo se è in riproduzione
    sd.chdir("/",true);
   while(file.openNext(sd.vwd(),O_READ)){      //entro nella sd ed apro il primo file 
     file.getFilename(filename);               //memorizzo il nome del file
     traccia++;                                //do un numero di traccia
     file.close();                             //chiudo il file
     if(traccia>conta){                        //se non è già stato riprodotto
     MP3player.playMP3(filename);              //riproduco ed esco dal ciclo bloccante while
     break;
     }
  }
  traccia=0;                                  //azzero il contatore della traccia aperta per poter arrivare a quella successiva a quella appena riprodotta
  }
  if(conta==n_brani){                         //se i brani riprodotti hanno lo stesso numero di quelli presenti in SD 
    conta=0;                                  //azzero conta per poter ricominciare da capo  
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int read_buttons(){
  
  analogico=analogRead(0);
  if(analogico<50)   {return ON;}
  if(analogico<150)  {return alza;}
  if(analogico<300)  {return abbassa;}
  if(analogico<400)  {return toni;}
  if(analogico<500)  {return r_auto;}
  if(analogico<600)  {return traccia_av;}
  if(analogico<700)  {return traccia_in;}
  if(analogico<800)  {return alt;}
  if(analogico<900)  {return play;} 
  if(analogico>1000) return no_pulsante;
}

Per il momento è tutto,ciao.
Tony

I don't speak italian but I understand you try to make a mp3 reader and search how to overcome the 8.3 limitation of SdFat library. I had the same problem building my web radio listener/mp3 reader. I can now read files by their long names using SdFat library. May be a look at those posts can help you: http://forum.arduino.cc/index.php?topic=171663.0 (in english) and http://forum.arduino.cc/index.php?topic=171663.0 (in french) or there: http://larocola.net/?c=larocola2

But now I want to LaRocola be able to act as a FTP server so that I can modify the content of the SD card without removing it. For doing that I need to [u]create[/u] files by their long names. I think than that would be very difficult to modify SdFat to get that result. So I am looking for an other solution using only 8.3 names and manage a additional file in each folder with the list of the files in the folder with their respective short and long names.

If you are interested I can write in french or spanish