Arduino Musicplayer for my daughter

A while ago I wanted to buy a musicplayer for my daugther. The first idea was to buy one of these “pinky” plastic things made in east asia. While thinking about the lifetime of these  plastic players in a 2 years old child hand, I decided to look for alternatives. Then I found the famous hoerbert which is hand made in Germany, with responsible ingredients and really suitable for a child. The price is not cheap but really fair, as I know after building my version of a child capable music player. Inspired by the hoerbert I decided to build my own version called ABox because I want to have some changes:

  • run with an rechargeable pack instead of batteries
  • easy upload of songs with any format without the need of conversion
  • “stereo” Sound

For using standard audiofiles I needed to build a stereo musicplayer anyway. To have a good sound with a mono device, the music must be compressed to one channel. this means each file must be converted before uploading it to the players SD card.

Like most of my small diy projects i decided to use an arduino as base for the player. I combined it with adafruits mp3 shield and a self welded button panel. The 12 button panel works with 12 resistors which are bridged if a button is pressed. With this technique its possible to measure the voltage on one of the arduinos analog ports and to decide which button was pressed. A circuit plan can be found here or by searching for “arduino button keyboard resistor”. As you can see in the Images, I added two input resistors which helped to get better measurement values.

 

The concept of operation is easy: 10 Buttons represent a folder/playlist on the SD card, Button 11 jumps back, Button 12 jumps forward. If the AdaBox is switched off, it stores the actual played file on the sd card. If it’s switched on, it starts playing with the last file.

Here’s the code:

 
/*
* Software for the ABox - a Hoerbert inspired music player for children.
* Uses the Adafruit SD MP3 Player. The buttonboard is a 12 button board 
* which uses one of the analog ports and 1/4W 3,3K do divide the voltage
* if a button is pressed. For more infos search for "arduino button analog resitor"
* 
* Usage of the player: The SD Card must contain 10 Directories with music files. 
* Button 1-10 starts playing the music in the correspondent file. 
* Button 11 rewinds. 
* Button 12 plays the next musicfile
* of the directory.
*
* Feel free to use the software on your own risk. If you extend the software 
* i would be happy to get your code. Inform me at koelnerwasser.de
*
*/

#include 
#include 
#include 

//## user preferences
const char lastPlayedStorageFile[] = "LASTFILE.TXT";


//## programm variables
// buttonpad
//last pressed button
int actualButtonId = 99;
bool firstRun = true;

const int pinPadPin = A3;

// music dir/file
char actualMusicDir[5];
char* actualMusicFileName;
char actualMusicFileFullPath[20];
char lastSessionMusicFilePath[20];


const int maxFilesInDir = 50;

// list of played files for the rewind function
char listOfLastPlayedFilesInDir [maxFilesInDir][20];
int countOfEntryInLastPlayedArr = 0;

// volume
const int volumePotiPin = A2;



// Mp3 Board
#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// These are the pins used for the music maker shield
#define SHIELD_RESET  -1      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)
// These are common pins between breakout and shield
#define CARDCS 4     // Card chip select pin
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

// create MusicPlayer object
Adafruit_VS1053_FilePlayer musicPlayer =
  Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);



void setup() {
  //Serial.begin(9600);

  Serial.println("Adafruit VS1053 Library Test");

  // initialise the music player
  if (! musicPlayer.begin()) {
    Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    while (1);
  }
  Serial.println(F("VS1053 found"));

  // generate Testtone
  // musicPlayer.sineTest(0x44, 500);

  // we need bass, bass
  // bass values
  byte bassAmp = 9; // value should be 0-15
  byte bassFrq = 9; // value should be 0-150

  // treble values
  byte trebAmp = 1; // value should be 0-15
  byte trebFrq = 1;

  // convert values into ushort for cpu command
  unsigned short bassCalced = ((trebAmp  & 0x0f) << 12)
                              | ((trebFrq  & 0x0f) <<  8)
                              | ((bassAmp  & 0x0f) <<  4)
                              | ((bassFrq  & 0x0f) << 0); // process bass cpu command musicPlayer.sciWrite(0x02, bassCalced); if (!SD.begin(CARDCS)) { Serial.println(F("SD failed, or not present")); while (1); // don't do anything more } Serial.println("SD OK!"); // list files // printDirectory(SD.open("/"), 0); // define interrupt - Pininterrupt if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) Serial.println(F("DREQ pin is not an interrupt pin")); } void loop() { // Set volume // lower numbers == louder volume! int volume = getVolumeValue(); musicPlayer.setVolume(volume, volume); File actualDirPointer; File actualFilePointer; // ## inital start: nothing pressed, read stored last used file and play it ## if (firstRun) { // read last played file readLastSessionFilenameFromSd(); if (sizeof(lastSessionMusicFilePath) > 0) {
      //Serial.print(dumpCharArray(lastSessionMusicFilePath,sizeof(lastSessionMusicFilePath)));

      if (SD.exists(lastSessionMusicFilePath)) {
        Serial.println(F("Found LastPlayed Musicfile of Last Session on SD, try to initalize variables for playing it"));
        // extract dir
        char *ptrOfSlashOccurence = strchr(lastSessionMusicFilePath, '/');

        // set dir and file pointer to the correct dir
        if (ptrOfSlashOccurence) {
          // extract dir and file string
          int indexOfSlash = ptrOfSlashOccurence - lastSessionMusicFilePath;
          strncpy(actualMusicDir, lastSessionMusicFilePath, indexOfSlash + 1);
          char lastSessionMusicFileName[15];
          strncpy(lastSessionMusicFileName, lastSessionMusicFilePath + indexOfSlash + 1, sizeof(lastSessionMusicFilePath));

          // set filepointer
          actualFilePointer = SD.open(lastSessionMusicFilePath);
          // set dirpointer
          actualDirPointer = SD.open(actualMusicDir);

          // forward dir pointer to lastSessionMusicFilePath
          int breaker = 0;
          File toCompare;
          while (breaker < maxFilesInDir) {
            breaker++;
            toCompare = actualDirPointer.openNextFile();
            if (strcmp(toCompare.name(), lastSessionMusicFileName)  == 0 ) {
              toCompare.close();
              break;
            }
            toCompare.close();
          }
          if (breaker < 50) { Serial.println(F("Initalize of variables for playing lastSession Music File successful")); firstRun = false; goto lastSessionStart; } } } } Serial.println(F("Did not found the file on sd or unable to init the variables")); firstRun = false; } // jumpPoint: playlistelected goto playlistSelected: // ## main entry ## if (checkButton()) { // check if a playlist was selected if (actualButtonId > 0 && actualButtonId < 11) { // open the dir sprintf (actualMusicDir, "%i/", actualButtonId); actualDirPointer = SD.open(actualMusicDir); Serial.print(F("Actual Dir: ")); Serial.println(actualMusicDir); // play selected playlist until no more files to play while (true) { // jumpPoint: forward goto forward: // reset actual buttonId for detect a new buttonPress // - the selected value is not longer needed actualButtonId = 99; // get file from directory handle actualFilePointer = actualDirPointer.openNextFile(); if (!actualFilePointer) { Serial.println(F("Last File of dir reached.. Starting at the beginning of the actual dir")); actualDirPointer.rewindDirectory(); actualFilePointer = actualDirPointer.openNextFile(); } Serial.print(F("Actual File: ")); Serial.println(actualFilePointer.name()); //Ignore underscore prefix "._ " Files of OSX which are delivered by openNextFile() if (strchr(actualFilePointer.name(), '_')) { int indexOfUnderScore = strchr(actualFilePointer.name(), '_') - actualFilePointer.name(); if (indexOfUnderScore == 0) { Serial.println(F("Filename starts with underscore, ignoring it because its a OSX Filesystem file")); actualFilePointer = actualDirPointer.openNextFile(); if (!actualFilePointer) { Serial.println(F("Last File of dir reached.. Starting at the beginning of the actual dir")); actualDirPointer.rewindDirectory(); actualFilePointer = actualDirPointer.openNextFile(); } } } // jumpPoint: start with last session file lastSessionStart: // no file found if (!actualFilePointer) { Serial.println(F("No Files/Dir found goto playlistSelected")); goto playlistSelected; } // build filename to play actualMusicFileName = actualFilePointer.name(); sprintf (actualMusicFileFullPath, "%s%s", actualMusicDir, actualMusicFileName); Serial.print(F("Created full Filepath: ")); Serial.println(actualMusicFileFullPath); // store last played filename, for use as initial file after restarting the system // store before playing because SD Lib cant not read and write at one time.. saveFilenameOnSd(actualMusicFileFullPath); // store it for the rewind function sprintf (listOfLastPlayedFilesInDir[countOfEntryInLastPlayedArr], "%s", actualMusicFileName); countOfEntryInLastPlayedArr++; // play //dumpCharArray(actualMusicFileFullPath,sizeof(actualMusicFileFullPath)); if (! musicPlayer.startPlayingFile(actualMusicFileFullPath)) { Serial.println(F("Could not open file")); musicPlayer.reset(); goto forward; } else { Serial.print(F("Started playing:")); Serial.println(actualMusicFileFullPath); } // ## check button pressed button while playing ## while (musicPlayer.playingMusic) { // set volume while playing int volume = getVolumeValue(); musicPlayer.setVolume(volume, volume); // check for changed playlist, forward or stop if (checkButton()) { actualFilePointer.close(); //Serial.print(F("Actual Button ID:")); //Serial.println(actualButtonId); // backward if(actualButtonId == 12){ Serial.println(F("Backward pressed")); musicPlayer.stopPlaying(); musicPlayer.softReset(); actualDirPointer.rewindDirectory(); delay(300); goto forward; } // forward else if (actualButtonId == 11) { Serial.println(F("Forward pressed")); musicPlayer.stopPlaying(); musicPlayer.softReset(); actualFilePointer.close(); delay(300); goto forward; } // playlist else if (actualButtonId > 0 && actualButtonId < 11 ) { musicPlayer.stopPlaying(); musicPlayer.softReset(); actualFilePointer.close(); Serial.println(F("Playlist selected")); delay(300); countOfEntryInLastPlayedArr = 0; goto playlistSelected; } } //delay(300); } musicPlayer.reset(); actualFilePointer.close(); } } } } // FUNKTION get value of the volume poti int getVolumeValue() { // read PotiData int vol = analogRead(volumePotiPin) ; // 0-1023 // Serial.println("poti Value:"); // Serial.println(v); // value correction vol = vol / 15; // limit max volume 0 => max vol
  if (vol < 30) {
    vol = 30;
  }
  // Serial.println("Volume Value:");
  // Serial.println(v);
  return vol;

}

// FUNKTION File listing helper
void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      //Serial.println("**nomorefiles**");
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) { Serial.print('\t'); } Serial.print(entry.name()); if (entry.isDirectory()) { Serial.println("/"); printDirectory(entry, numTabs + 1); } else { // files have sizes, directories do not Serial.print("\t\t"); Serial.println(entry.size(), DEC); } entry.close(); } } // FUNKTION check button boolean checkButton() { int buttonTmp = readPressedButtonId(); if (buttonTmp > 0 && buttonTmp < 13) { if (actualButtonId != buttonTmp) { actualButtonId = buttonTmp; return true; } else { return false; } } } // FUNKTION read Keypad int readPressedButtonId() { long button = 0; long voltage = 501; voltage = analogRead(pinPadPin); /* String dbg = "Volt aktuell: "; dbg += voltage; Serial.println(dbg); */ if (voltage > 850) {
    button = 12;
  }
  else if (voltage > 790) {
    button = 1;
  }
  else if (voltage > 710) {
    button = 2;
  }
  else if (voltage > 640) {
    button = 3;
  }
  else if (voltage > 560) {
    button = 4;
  }
  else if (voltage > 540) {
    button = 5;
  }
  else if (voltage > 490) {
    button = 99;
  }
  else if (voltage > 460) {
    button = 10;
  }
  else if (voltage > 420) {
    button = 9;
  }
  else if (voltage > 360) {
    button = 8;
  }
  else if (voltage > 300) {
    button = 7;
  }
  else if (voltage > 220) {
    button = 6;
  }
  else if (voltage > 120) {
    button = 11;
  }

  /*
  dbg = "Knopf: ";
  dbg += button;
  dbg += " gedrueckt";
  Serial.println(dbg);
  */

  return button;
}

// FUNKTION safe given filename into a file  on the sd card
void saveFilenameOnSd(char* fileNameToStore) {

  File fileToWrite = SD.open(lastPlayedStorageFile, FILE_WRITE);

  if (fileToWrite) {
    fileToWrite.seek(0);
    fileToWrite.println(fileNameToStore);

    // close the file:
    fileToWrite.close();
    Serial.print(F("Saved given Filename to SD Card:"));
    Serial.println(fileNameToStore);
  } else {
    // if the file didn't open, print an error:
    Serial.print(F("SaveFilenameOnSd: error opening File:"));
    Serial.println(lastPlayedStorageFile);
  }
}


// FUNKTION read last played filename stored in file from sd card
void readLastSessionFilenameFromSd() {

  File fileToRead = SD.open(lastPlayedStorageFile);

  if (fileToRead) {

    int i = 0;
    int maxRead = sizeof(lastSessionMusicFilePath);
    while (fileToRead.available() && i < maxRead - 1) {
      lastSessionMusicFilePath[i] = fileToRead.read();

      // change ascii 13 from fileend to string end
      if (lastSessionMusicFilePath[i] == '\r') {
        lastSessionMusicFilePath[i] = '\0';
        break;
      }
      i++;
    }

    // close the file:
    fileToRead.close();
    Serial.print(F("Read saved Filename from SD Card:"));
    Serial.println(lastSessionMusicFilePath);

  } else {
    // if the file didn't open, print an error:
    Serial.print(F("getSavedFilenameFromSd: error opening File:"));
    Serial.println(lastPlayedStorageFile);
  }
}

void dumpCharArray(char* charArrayToDump, int lengt) {

  for (int i = 0; i < lengt; i++)
  {
    Serial.print(F("["));
    Serial.print(i);
    Serial.print(F("] is {"));
    Serial.print(charArrayToDump[i]);
    Serial.print(F("} which has an ascii value of "));
    Serial.println(charArrayToDump[i], DEC);
  }
  Serial.println();
}






 

Download the code and the library here: ABox.zip

I ordered the parts at reichelt.de, here is the partlist (without the Arduino..):

OrderNumber Description Price
1/4W 3,3K
Kohleschichtwiderstand 1/4W, 5%, 3,3 K-Ohm
14
0,46 Euro
PO6M-LIN 22K
Drehpoti. linear, 6mm, mono 22 k-Ohm
2
2,90 Euro
KAPPE 1D08
Kappe, rund, rot für Taster 3F…
3
0,75 Euro
KAPPE 1D06
Kappe, rund, weiß für Taster 3F…
4
1,00 Euro
KAPPE 1D04
Kappe, rund, gelb für Taster 3F…
3
0,75 Euro
TASTER 3FTL6
Multimec Taster ohne Beleucht., Printanschluss
12
11,52 Euro
KAPPE 1D00
Kappe, rund, blau für Taster 3F…
3
0,75 Euro
H25PS160
Punkt-Streifenrasterplati. Hartpapier, 160x100mm
3
5,85 Euro
VIS FR 10HM-8
VISATON Breitbandlautsprecher, 10cm
2
11,20 Euro
AKKU-PACK PP1
Akku-Pack, NiMh, 7,2 Volt, 1,1 Ah, 6 Zellen
1
10,75 Euro

48 thoughts on “Arduino Musicplayer for my daughter

  1. Hallo der Code will nicht so richtig, da die includes fehlen und zwischendurch ein paar Zeilen auskommentiert sind.

    Das bringt der Compiler als Fehler:

    music4kids.ino:17:10: error: #include expects “FILENAME” or
    music4kids.ino:19:10: error: #include expects “FILENAME” or
    music4kids.ino:20:10: error: #include expects “FILENAME” or
    music4kids:25: error: variable or field ‘printDirectory’ declared void
    music4kids:25: error: ‘File’ was not declared in this scope
    music4kids:25: error: expected primary-expression before ‘int’
    music4kids:63: error: ‘Adafruit_VS1053_FilePlayer’ does not name a type
    music4kids.ino: In function ‘void setup()’:
    music4kids:74: error: ‘musicPlayer’ was not declared in this scope
    music4kids:99: error: ‘SD’ was not declared in this scope
    music4kids:113: error: ‘actualFilePointer’ was not declared in this scope
    music4kids:115: error: ‘actualDirPointer’ was not declared in this scope
    music4kids:119: error: ‘File’ was not declared in this scope
    music4kids:119: error: expected `;’ before ‘toCompare’
    music4kids:122: error: ‘toCompare’ was not declared in this scope
    music4kids:129: error: label ‘lastSessionStart’ used but not defined
    music4kids.ino: At global scope:
    music4kids:129: error: expected constructor, destructor, or type conversion before ‘.’ token
    music4kids:129: error: expected unqualified-id before ‘)’ token
    music4kids:129: error: expected constructor, destructor, or type conversion before ‘=’ token
    music4kids:129: error: expected declaration before ‘}’ token

    Ich habe die Bibliothek heruntergeladen und eingebunden:
    // include SPI, MP3 and SD libraries
    #include
    #include
    #include

    Dann kommt die folgende Fehlermeldung:
    music4kids.ino: In function ‘void setup()’:
    music4kids:115: error: ‘actualFilePointer’ was not declared in this scope
    music4kids:117: error: ‘actualDirPointer’ was not declared in this scope
    music4kids:131: error: label ‘lastSessionStart’ used but not defined
    music4kids.ino: At global scope:
    music4kids:131: error: expected constructor, destructor, or type conversion before ‘.’ token
    music4kids:131: error: expected unqualified-id before ‘)’ token
    music4kids:131: error: expected constructor, destructor, or type conversion before ‘=’ token
    music4kids:131: error: expected declaration before ‘}’ token

  2. Includes 2. versuch SPI.h, Adafruit_VS1053.h und SD.h wurden vom Kommentarfeld abgeschnitten – Fehler in WordPress?

    #include
    #include
    #include

  3. Hi aktuell werden noch 2 Fehler gefunden:
    // list of played files for the rewind function
    char listOfLastPlayedFilesInDir [maxFilesInDir][20];
    Lösung:
    –>char listOfLastPlayedFilesInDir [80]

    // store it for the rewind function
    sprintf (listOfLastPlayedFilesInDir[countOfEntryInLastPlayedArr], “%s”, actualMusicFileName);

    error: invalid conversion from ‘char’ to ‘char*’
    error: initializing argument 1 of ‘int sprintf(char*, const char*, …)’

  4. Hallo Simon,
    ja schön – gib Bescheid wenn es funktioniert.
    Über ein paar Infos/Bilder vom fertigen Player
    würde ich mich freuen.

    Viele Grüße,
    Daniel

  5. Hi bei diesem Part komm ich nicht weiter – was genau hast du damit vor?
    Zudem wollte ich noch wissen wo du die holzkiste bestellt hast?
    Merci
    // store it for the rewind function
    sprintf (listOfLastPlayedFilesInDir[countOfEntryInLastPlayedArr], “%s”, actualMusicFileName);

    error: invalid conversion from ‘char’ to ‘char*’
    error: initializing argument 1 of ‘int sprintf(char*, const char*, …)’

  6. Hallo Simon,
    dort wird der gerade zu spielende Dateiname in einem Array abgelegt um beim drücken des “Rewind” Buttons den Dateinamen wiederverwenden zu können bzw. zu wissen was zuletzt gespielt wurde.

    Die Kiste ist aus dem Baumarkt. Es so eine Buchenkiste die eigentlich oben offen, mit 2 Griffmulden versehen und dafür gedacht ist in ein Regal gestellt zu werden-. Ich habe die ziemlich missbraucht..

  7. Hi danke für die infos.

    Bekommst du auch die Fehlermeldung zu dem sprintf zu dem rewind array?

  8. Eigentlich nicht – ich probiere es heute Abend
    nochmal mit der neueren Arduinoversion aus.
    Ansonsten kommentier doch erstmal alles was mit dem Array zu tun hat aus. Solange Du nicht Button 11 drückst passiert da nichts weiter.

  9. Hi Daniel,

    bei mir kompiliert der Code nun auch ohne Probleme. Allerdings läuft das Programm nicht auf dem Arduino – hab Serial Debug aktiviert aber keine Anzeige im Serial Monitor.
    Zum Testen meiner Verkabelung hab ich die Arduino Examples für das MP3 Board geteset – damit funktioniert es einwandfrei. Hast du den Code mal auf deinem “Music4Kids” getestet?

    Eine Frage noch zum Button 99 – wie kommst du auf den entsprechenden Spannungswert für den Button?

    Danke
    Grüße Simon

  10. Hi,

    ich finden dein Projekt und die Umsetzung sehr gelungen. Ich möchte auch gerne einen Player bauen und bin auf der Suche nach einer geeigneten Box.

    Hast du vielleicht eine Empfehlung für mich?

  11. Hi ich habe nochmal geschaut,

    sobald ich diesen Code einfüge startet der uC nicht mehr richtig.
    // store last played filename, for use as initial file after restarting the system
    // store before playing because SD Lib cant not read and write at one time..
    saveFilenameOnSd(actualMusicFileFullPath);
    // store it for the rewind function
    sprintf (listOfLastPlayedFilesInDir[countOfEntryInLastPlayedArr], “%s”, actualMusicFileName);
    countOfEntryInLastPlayedArr++;

  12. Hallo Simon,
    sorry das ich mich jetzt erst melde, hatte viel zu tun. Funktioniert es jetzt?
    Die Spannungswerte habe ich gemessen, bzw. ausprobiert.

    Der Code läuft so auf dem Player meiner Tochter.

    Viele Grüße,
    Daniel

  13. Hi Daniel,

    I am trying to build a very similar player using a regular Arduino R3, but when compiling / uploading your code, I get a message that it uses 99% of the available dynamic memory and as a result things do not work (it does not even output the “Adafruit VS1053 Library Test” text.

    Can you tell me which exact board you are using?

    Thanks!
    Gianfranco

  14. Hallo Robert,
    sorry für die späte Antwort, ich hatte viel zu tun. Zu Deiner Frage: Die box ist eine Buchen Holzkiste aus dem Baumarkt (so eine eine einfache Aufbewahrungskiste z.B. für Spielsachen)

    Viele Grüße,
    Daniel

  15. Thanks Daniel for the quick response. I am using the exact same board and shield, so am not sure why the code does not work for me. The only reason I can think of is that the Adafruit library for the Music Maker has changed since you put together your player and is perhaps less efficient using memory. I downloaded the libraries last week. Could you send me a copy of the library which you are using?

    In the mean time I also ordered an Arduino Mega board which has more memory, will let you know if that ends up working, but I would still like to learn why the Uno is not working.

    Another question: what speaker covers did you buy, or did you make them?

    Kind regards,
    Gianfranco

  16. Hello Gianfranco,
    i do not think that the Adafruit library produces the problems. The size of mine is 4kb. Anyway I included a download link in the post, providing a zip containing the library and my latest code version.

    I build the speaker covers by my own, using the hole core as negative stenzil and a hand sawn piece of wood as positive stenzil. I included a gallery in the post containing pictures where you can see how i did id. I used a hand operated press to press the metal into the matrix. I think it would be possible to do this with
    two C-clamps.

    Greetings,
    Daniel

  17. Thanks again Daniel, really appreciate you taking the time to help out. Sorry, I did not realise there was an entire photo gallery, I should have seen how you produced the speaker covers. I now also see which speakers you used and will probably end up ordering the exact same ones, since the Adafruit ones I am using now are not exactly the best sounding ones, although they are very affordable.

    As for the code / library, I will try out your files tomorrow with the Original Uno, but I just confirmed that your code works fine on the Sunfounder Mega (after having soldered the ICSP jumpers as per the Adafruit instructions).

    I am also adding in the Adafruit NFC reader, which will allow my daughter to select an unlimited number of playlists (directories with MP3’s in this case) by simply holding an NFC card near the box. Not sure yet if I will keep the buttons as an additional shortcut for up to 10 playlists.

    I will send you some pictures and the code once the project is done, which will probably take a few more weeks.

    Kind regards,
    Gianfranco

  18. Hallo Gianfranco,
    i just added the additional pictures yesterday evening 😉

    Interesting idea to associate the playlists with RFID tags. Hope to hear about this. One thing to remember while using a due or additional add on boards: battery lifetime will not increase..

    Greetings, Daniel

  19. Hi

    Kannst du genauere Angaben zu der Holz Box machen. War die schon zusammen und du hast die wieder zerlegt? Bei welchem Baumarkt hast du dir gekauft Masse etc. Was hat du mit der offenen Seite gemacht?

    Danke
    Gruss
    Patrick

  20. Hallo Daniel,

    kannst du mit mal erklären was uf dem Schema 1,2,3 ist? also was ist A3 was ist Gnd und was ist 5V.
    Danke

  21. Hallo Peter,
    wenn ich richtig Zähle habe sogar 14 Wiederstände verbaut.. Wenn ich ich richtig erinnere waren die Messwerte mit den Eingangswiederständen besser. Ich habe noch 3 Bilder in die Galerie eingefügt auf denen man den Aufbau erkennen kann.
    Hier die Belegung:
    1= Messausgang bei mir auf A3 gelegt
    2= +
    3= GND

    Alle Wiederstände haben 3,3 Ohm

    Grüße,
    Daniel

  22. Hallo Daniel,
    danke für Deine Antwort. Ich denke mal du hast Dich verschrieben und meinst 3,3KOhm Widerstände (anhand des Codes auf deinen Bildern).

    Wenn ich es nach der Variante aufbaue :
    http://www.directupload.net/file/d/4388/7rj8hg4f_png.htm
    dann habe ich 0V im normal zustand an A3. (ohne taster)
    if (voltage > 200) {
    button = 12;
    }
    else if (voltage > 2390) {
    button = 1;
    }
    else if (voltage > 1572) {
    button = 2;
    }
    else if (voltage > 1164) {
    button = 3;
    }
    else if (voltage > 919) {
    button = 4;
    }
    else if (voltage > 727) {
    button = 5;
    }
    else if (voltage > 0) {
    button = 99;
    }
    else if (voltage > 349) {
    button = 10;
    }
    else if (voltage > 408) {
    button = 9;
    }
    else if (voltage > 472) {
    button = 8;
    }
    else if (voltage > 545) {
    button = 7;
    }
    else if (voltage > 637) {
    button = 6;
    }
    else if (voltage > 286) {
    button = 11;
    }
    Gehe ich richtig davon aus, dass button 99 = 0 ist? oder wie bist du auf den Wert gekommen?

    oder würdest du das Ganze nach dieser Schaltung aufbauen?
    http://www.directupload.net/file/d/4388/ksiv4ke8_png.htm

    Du hast ja den Player ja in Betrieb. Hast du keine Probleme mit dem Akku? Das heisst wenn die Spannung tiefer wird. Könnte ma nicht auch einen Bereich definieren z.B.
    else if (voltage > 342-355) {
    button = 10;

    Wenn ich “Serial.begin(9600);” aktiviere komme ich bis SD OK.
    Müssen die Ordner gewisse Namen haben? Wie lange dürfen die einzelnen Tracks sein (Namen)?

  23. Hello Peter,
    you have to play a bit wit the value which is delivered by the pressed button and change the value “button” to the one you need in your coding.
    You don#t have problems if the battery deliver a lower voltage as you use the power delivered by the arduino. He contains a power regulation which deliver 5V or stop the arduino.

    Greetings Daniel

  24. Hallo Daniel,

    Die Werte habe ich angepasst. Ich habe alle Knöpfe gemässen und eingetragen.
    Wenn ich am PC über USB angeschlossen bin habe ich ca 4.8V und das arduino läuft. Wenn ich es dann von der PowerBank betreibe habe ich 5V. So sind die gemessenen Werte ganz anders.
    Jedoch auch wenn ich es am PC betreibe und die Werte eintrage die ich messe funktioniert es nicht. Wie muss die SD Karte aufgebaut sein? Ordername? Trackname?
    Ist es egal, wenn ich Knopf 99 mit 0V definiere? 0V habe ich wenn nichts betätigt ist.

    Wenn ich das ganze kompiliere kommt immer die Meldung (Version 1.6.2):
    Der Sketch verwendet 19.970 Bytes (61%) des Programmspeicherplatzes. Das Maximum sind 32.256 Bytes.
    Globale Variablen verwenden 2.022 Bytes (98%) des dynamischen Speichers, 26 Bytes für lokale Variablen verbleiben. Das Maximum sind 2.048 Bytes.
    Wenig Speicher verfügbar, es können Stabilitätsprobleme auftreten.

  25. Hi Peter,
    get easy! Play a bit, Code a bit – the ABox of my daughter is running since i build it.. And she loves it.
    There is only one thing which i would improve: It would be better if the Sd is accessible without removing a screw…

    Greetings Daniel

  26. Hallo Daniel,
    Ich habe das gleiche Problem wie Simon:

    “Simon on November 27, 2015 at 0:22 said:

    Hi ich habe nochmal geschaut,

    sobald ich diesen Code einfüge startet der uC nicht mehr richtig.
    // store last played filename, for use as initial file after restarting the system
    // store before playing because SD Lib cant not read and write at one time..
    saveFilenameOnSd(actualMusicFileFullPath);
    // store it for the rewind function
    sprintf (listOfLastPlayedFilesInDir[countOfEntryInLastPlayedArr], “%s”, actualMusicFileName);
    countOfEntryInLastPlayedArr++;”

    Kannst du nicht den Code der auf deinem Player läuft nochmals hochladen und sagen mit welcher Version von Arduino du es gemacht hast?

    Danke dir
    Peter

  27. Hello Peter,
    did you used the download version of the code (download link “aBox.zip”) or the version which is displayed in the post? The code included in the zip is the latest version which runs on the arduino of my daughter.

    Seems to be a problem with the used sd lib? Try to comment out only the method saveFilenameOnSD
    (..). Later take a look at the method and try to only comment out the write to sd card command. If the arduino works then try to use another sd lib. Maybe your sd controller (located on the sd shield) works with another sd libary..

    If you need help with debuging code, please provide detailed information. As i want to provide the knowledge not only for german speakers, please write your comments in english.

    Greetings, Daniel.

  28. Hi Daniel,
    yes i use the code from the Zip File.
    The problems make this line:
    printf (listOfLastPlayedFilesInDir [countOfEntryInLastPlayedArr], “% s”, actual music
    I dont think its a problem whit the lib.

    Greets
    Peter

  29. Hallo Daniel,
    ich habe folgendes Problem:

    “Knopf: 1 gedrueckt
    Volt aktuell: 467
    Knopf: 1 gedrueckt
    Volt aktuell: 467
    Knopf: 1 gedrueckt
    Volt aktuell: 467
    Knopf: 1 gedrueckt
    Volt aktuell: 467
    Knopf: 1 gedrueckt
    Volt aktuell: 466
    Knopf: 2 gedrueckt
    Actual Dir: 2/
    Actual File: TRACK3.MP3
    Created full Filepath: 2/TRACK3.MP3
    Saved given Filename to SD Card:2/TRACK3.MP3

    Für Knopf 2 habe ich 353 hinterlegt.

    oder

    “Knopf: 1 gedrueckt
    Volt aktuell: 101
    Knopf: 1 gedrueckt
    Volt aktuell: 102
    Knopf: 1 gedrueckt
    Volt aktuell: 94
    Knopf: 0 gedrueckt
    Volt aktuell: 94”

    komischerweise geht er dann immer einen “Knopf” zurück, obwohl die Spannung an A3 gar nicht gemessen wird. Hast du eine Idee?
    Für was ist der Knopf 99?

    Hast du Aufbauplan von deiner Schaltung?

    @ Peter, ich hatte die gleichen Probleme wie Du. Es liegt am UNO R3. Bei mit lief das Programm darauf auch nicht. Habe jetzt noch ein Mega, da geht es mit den richtigen ICSP brücken.

  30. Hi Daniel,

    cooles Projekt und tolles Design!
    Sind die Akkus dann eigentlich aufladbar indem man ein USB-Kabel an das Radio anschließt oder muss man die ausbauen wenn sie leer sind? Ist die Lautstärke ausreichend?

    Gruß

    Daniel

  31. Hallo Daniel,
    Danke für das Kompliment. Ja, die Akkus werden über den USB Stecker aufgeladen. Man kann natürlich auch einen anderen Stecker/Buchse nehmen, ich hatte diesen halt gerade da. Die Lautstärke und Akkulaufzeit sind ausreichend, ich habe die Lautstärke sogar gedrosselt. Einziger Nachteil ist, das man zum einspielen neuer Lieder den Deckel öffnen und die SD-Karte in den PC stecken muss. Würde ich es nochmal bauen, würde ich jetzt vlt. einen Raspi nehmen um das ganze per WLAN/FTP managen zu können. Zudem braucht man dann nur noch einen kleinen Verstärker. Jetzt (Kind ist älter) wäre auch ein Display nicht schlecht. Inzwischen habe ich auch ein System gesehen, das ca. 70€ kostet und die Auswahl der Stücke mittels Figuren ermöglicht die auf das Gerät gestellt werden. Das ganze mit Ladestation und ausreichendem Mono Klang. Für das Geld ist der Selbstbau nur aus Spass an der Freude lohnenswert..

    Viele Grüße,
    Daniel

  32. Hallo Daniel,

    bin eifrig am Nachbauen.:)
    Da ich es auf den Bildern nicht eindeutig erkennen kann: Wie hast du das Akkupack mit den anderen Komponenten verdrahtet? Auf einem der Anfangsbilder ist noch der Tamiya-Stecker zu sehen, aber dann hast du das ja irgendwie an den Kippschalter und den USB-Anschluss gebracht?

    Danke für die Rückmeldung.

    Gruß

    Marcus

  33. Hallo Marcus,
    den Tamiya-Stecker habe ich abgeknipst, der USB Stecker ist nur als Stecker verwendet, da ich nichts anderes da hatte (geht also auch jeder andere 2polige Stecker)… Also die beiden Pole des Akkus über den USB nach aussen geführt. Die Masse(-) dann weiter mit dem Arduino verbunden. + weiter an den Schalter und von da weiter an den Arduino.
    Zum Laden dann ein passendes Ladegerät mit einem passenden USB Stecker “aufpimpen” (auf Polung achten), den Schalter “Aus” schalten und der Akku lädt. Ladegerät ab, Schalter an: Arduino bekommt Strom..

    Viel Spass beim Basteln,
    Daniel

  34. nutzt du das verlinkte music maker Board oder das mit integriertem 3W Verstärker?

  35. Hi Daniel,

    thank you for sharing your project.
    I was also interested in the hoerbert original but in my opinion it is much to expensive.
    So it decided to rebuild your version.
    I ordered most of the parts on Aliexpress so it is much more cheap than your build. <25€ without case
    But i have had some strange issues which took me approx 2 months to build up a functional prototype.
    The biggest one was that the programm always as freezing when using the potentiometer more than a millimeter.
    I checked erverthing wireing , power supply, The arduino, the potentiometer.
    When is used the potentiometer in a seperate sketch it worked like a charm.
    After studing the datasheet of the ATMEGA 328 i had a clue.
    There ae not 8 ADCs inside, only one whith a 8 port multiplexer.
    Switching from one input pin to another needs a bit time to get stable.
    So you have to to a reading with no use and after it you can read again and use the value:

    Example:
    analogRead(pinPadPin);
    delay(100);
    voltage = analogRead(pinPadPin);

    For the Keypad i used 1k Resistors and a 1M Pullup resistor.
    This brings very streight forward readings. Nothing pressed has now the highest reading.

    Much fun for all others which try to build this player.

    Maybe someone can improve the code to start playing from a exact stored position not from the beginning of a track.

    Regards

    Thomas

  36. I am new to circuitry and I would very much to make this my first diy project. I can see the parts list, but I don’t know what they do or how to put them together. Which part is the on/off switch and which is the volume control knob?

    Where can I see what to connect to what?

  37. Hi Daniel,

    do you drive the speakers with the integrated 3W amp from the mp3 shield or did you use a separate amp? Are your kids satisfied with the achieved volume or would you build it differently next time?

    Thanks, Bho

Leave a Reply

Your email address will not be published. Required fields are marked *