Adafruit VS1053 (mp3) library for music maker shield ported?

@zeroyellow thank you for all your help so far. I have adjusted my wiring to be like yours. You included an excerpt of your code but I can seem to find a way to get it to work with what I have. Would you mind including a little more? All I’m trying to do is play a simple MP3.

@zeroyellow, part of the problem with using the VS1053 library is that is has a lot of “options” to use:

***** Two interrupt options! *****
musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); //Timer interrupt
This option uses SparkIntervalTimer (timer2) with 1ms interrupt
intervals.

musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); // DREQ int
This option uses a pin interrupt. No timers required! But DREQ
must be on an interrupt pin. For Spark Core, those are pins:
D0, D1, D2, D3, D4 A0, A1, A3, A4, A5, A6, A7

!!! This method is preferred !!!

In both cases, the interrupt service routine calls feeder() which in turns calls feedBuffer(). This function reads a buffer full of data (32 bytes) from the SD card then writes it out to the VS1503. With hardware SPI, these reads and writes do not overlap and will not conflict, primarily since hardware SPI operations block until they are complete. Unless you are using SPI for other peripherals, there will not be any conflicts. If you ARE using other SPI devices, you will need to disable interrupts during your SPI transactions to avoid conflicts with the VS1503 interrupts.

The player_simple example is setup for hardware SPI and DREQ interrupts. I updated the file to include a SPARK specific pin assignment section. In this scenario, the Core hardware SPI pins are used and DREQ is put on an interrupt capable pin.

One area I could not explore in the port is the SPI clock setting in the VS1053 begin() function. It is presently set to SPI_CLOCK_DIV128. For Arduino, that gives an SPI clock of 125KHz. From the specs and the Adafruit schematics, it looks as if the maximum SPI clock speed is 1.5MHz! For the Core, that requires a setting of SPI_CLOCK_DIV32. So it may be worth exploring this as the SPI clock affects both the VS1053 and the SD card.

Looking at the entire library and the examples, both the VS1053 and the SD begin() functions set the SPI clock to different values. The SD code, which is called after the VS1053 begin() code, sets the clock to DIV8, which is too high for the VS1053. A quick fix for this issue is to do a SPI.setClockDivider(SPI_CLOCK_DIV32) after the SD.begin() call to reset the SPI speed to work with both the VS1053 and the SD (albeit at a slower speed). You will need to experiment with this to see what the highest SPI clock speed you can use for the VS1053. Keep me posted. :smile:

You might want to try my fork which you can find at

It already include die SPI-clock divider which works at least for me using MP3s - I’m having troubles playing WAV-files though - but the VS1053 does only support a couple of WAV codecs, bitlengths etc. - maybe that’s the problem.

I’ve also added a new sample called sparkplayer.ino -

If you are using the WebIDE , I’ve also added the VS1053 library to the WebIDE moments ago …

1 Like

@McTristan, your library still has the issue that SD.begin will set the SPI to DIV8, overriding the DIV256 of the VS1053 begin(). A quick fix is to change the SPI.setClockDivider() in S2dCard.cpp line 232 to DIV256. I would also try setting it to DIV32 since the VS1053 should be able to handle a 1.5MHz SPI clock.

1 Like

Thanx peekay123 - I’ve changed it though it seems to work also with the DIV8 setting …

Unfortunately it seems I can’t reimport the library into the WebIDE once I’ve published it - what a pitty :confused:

Edit: Deleted the library and reimported it - DIV256 seems to work just fine - will also try DIV32 and then publish again …

2 Likes

It is kind of weird … I have a couple of mp3 files which the player does not like to play in the background… I can play long songs usually without any problems and lighten up a couple of LEDs from the main loop - no problem. But for particular mp3s it seems something is blocking the mainloop until the mp3 finished playing.

It seems to happen always with the same files and I can’t figure out what it is …the length does not seem to be important as longer mp3s do also work while others (but always the same others) do not …

This one won’t play in the background (or the main loop is kind of blocked):
https://drive.google.com/file/d/0B94OULS6inTJUmxJUF9QWUduR3c/view?usp=sharing

This one will play just fine in the background (LEDs are blinking - all other things are going normal):

https://drive.google.com/file/d/0B94OULS6inTJLUhIUXhQdm8xdkE/view?usp=sharing

I’ve even removed all additional calls from the main loop but it even seems subscribed events, external function calls (i.e. over the cloud) won’t be processed at all… it’s completely blocking but playing music …

this happens on two different core at the same time (don’t ask :stuck_out_tongue: ) so it is no coincidence …

@McTristan I had a strange blocking problem as well. The core would intermittently hang for 20 seconds or more, although it didn’t seem specific to certain files. I fixed it in the end by disabling interrupts at the end of my loop function and re-enabling them at the start. It might not be the same problem you’re seeing but perhaps worth a try.

void loop(){
    // reenable interrupts so we can play the audio
    interrupts();

    // do your stuff here
    ...

    // disable interrupts while the spark is talking to the cloud because othewise it can hang for quite a while
    noInterrupts();
}

I have these blockings you mention also from time to time, good to know there is a workaround… However, the blocking I have seems to be dependent on certain songs…
Strange…

I’ve tried the suggested fix but it does not help me with my specific problem - the whole core is still blocking while playing particular files (that’s also the reasons I haven’t yet published the library again) :confused:

Got it - it’s the bitrate - 128 kbit seems to be too high ,

Could it be, that this is a problem with the reading from the SD card ? Like, it is not fast enough to load it and blocks the whole core ??

@McTristan

I’m trying to get the VS1053 working but I’m having a bit of trouble. I imported your library and flashed sparkplayer.ino. I believe I have all the connections correct, but it’s still not working. Could you elaborate on how I can go about setting up a simple play of one mp3 file?

Thank you

Hmm … Let me try it:

// This #include statement was automatically added by the Spark IDE.
#include "Adafruit_VS1053/Adafruit_VS1053.h"

// This #include statement was automatically added by the Spark IDE.
#include "Adafruit_VS1053/SD.h"

// define the pins used
#define BREAKOUT_MOSI A5      // Output data, to VS1053/SD card
#define BREAKOUT_MISO A4      // Input data, from VS1053/SD card
#define BREAKOUT_CLK A3       // SPI Clock, shared with SD card
// Connect CLK, MISO and MOSI to hardware SPI pins. 
// See http://arduino.cc/en/Reference/SPI "Connections"

// These are the pins used for the breakout example

#define BREAKOUT_CS     A2//10     // VS1053 chip select pin (output)
#define BREAKOUT_RESET  D6//9      // VS1053 reset pin (output)
#define BREAKOUT_DCS    D2//8      // VS1053 Data/command select pin (output)
#define STANDARD_VOLUME_LEVEL 0
    
Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(BREAKOUT_MOSI, BREAKOUT_MISO, BREAKOUT_CLK, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, BREAKOUT_CARDCS);

int currentVolume = STANDARD_VOLUME_LEVEL;

void setup() {
    SD.begin(BREAKOUT_MOSI, BREAKOUT_MISO, BREAKOUT_CLK, BREAKOUT_CARDCS);
  
    if (! musicPlayer.begin()) { // initialise the music player
      Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    } else {
      Serial.println(F("VS1053 found"));
    }
    
    musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
  //  musicPlayer.sineTest(0x44, 500);    // Make a tone to indicate VS1053 is working

}

void loop() {
   
}

int playSong(String command)
{
    char filename[255]; // Or something long enough to hold the longest file name you will ever use.
    command.toCharArray(filename, sizeof(filename));
   
    musicPlayer.setVolume(currentVolume,currentVolume);
    
    musicPlayer.stopPlaying();
    musicPlayer.startPlayingFile(filename);
    
    return 1;
}

You just call the playSong method - make sure you are not doing in the main loop without a delay or such thing as it will play the song in the background - I’m mainly using spark cloud events for playing sounds and this works well … I have also multiple VS1053 modules and they all work fine …

2 Likes

sorry to have dropped out of the conversation. Seems like you have this al worked out: very nice! Will work on sound based projects soon again, so very greatfull for the community running with my initial request.

Rolf

2 Likes

Thanks for the help. I’m still having trouble. Here’s the code.

    // This #include statement was automatically added by the Spark IDE.
#include "Adafruit_VS1053/Adafruit_VS1053.h"

// This #include statement was automatically added by the Spark IDE.
#include "Adafruit_VS1053/SD.h"

// define the pins used
#define BREAKOUT_MOSI A5      // Output data, to VS1053/SD card
#define BREAKOUT_MISO A4      // Input data, from VS1053/SD card
#define BREAKOUT_CLK A3       // SPI Clock, shared with SD card
// Connect CLK, MISO and MOSI to hardware SPI pins. 
// See http://arduino.cc/en/Reference/SPI "Connections"

// These are the pins used for the breakout example

#define BREAKOUT_CS     A2//10     // VS1053 chip select pin (output)
#define BREAKOUT_RESET  D6//9      // VS1053 reset pin (output)
#define BREAKOUT_DCS    D2//8      // VS1053 Data/command select pin (output)
#define STANDARD_VOLUME_LEVEL 40
// These are common pins between breakout and shield
#define BREAKOUT_CARDCS D3     // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ D0                 // VS1053 Data request, ideally an Interrupt pin

bool played_once = false;

Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(BREAKOUT_MOSI, BREAKOUT_MISO, BREAKOUT_CLK, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, BREAKOUT_CARDCS);

int currentVolume = STANDARD_VOLUME_LEVEL;

void setup() {
    SD.begin(BREAKOUT_MOSI, BREAKOUT_MISO, BREAKOUT_CLK, BREAKOUT_CARDCS);

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

    musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
    musicPlayer.sineTest(0x44, 500);    // Make a tone to indicate VS1053 is working

}

void loop() {
    delay(5000);
    if (played_once == false){
        playSong("track001.mp3");
        played_once = true;
    }

}

int playSong(String command)
{
    char filename[255]; // Or something long enough to hold the longest file name you will ever use.
    command.toCharArray(filename, sizeof(filename));

    musicPlayer.setVolume(currentVolume,currentVolume);
    musicPlayer.stopPlaying();
    musicPlayer.startPlayingFile(filename);

    return 1;
}

I’m new to the spark core, am I calling the function correctly? The VS1053 is functioning and plays the test tone on start.

Are you sure you have the sd card cabling correct? if the test tone is working it seems your problem is with the sd card access.

I was just about to edit my post.

I looked at the wiring and I’m a little confused as far as the XDCS and SDCS and which pins in the code belong to those VS1053 connections.

#define BREAKOUT_DCS    D2//8      // VS1053 Data/command select pin (output)
#define STANDARD_VOLUME_LEVEL 40
// These are common pins between breakout and shield
#define BREAKOUT_CARDCS D3     // Card chip select pin

DCS goes to XDCS and CARDCS goes to SDCS?

EDIT: That was the problem. Now its working but the audio is stuttering.

which bitrate are you playing? I can’t play mp3 with a higher bitrate than 64 Kbit/s without stuttering :confused:

235 Kbit/s.

I’ll try to play a lower bitrate file and report back. Thanks again!

Converted the MP3 to 64Kbit/s and plays perfectly, thanks!

I honestly don’t think it’s the VS1053 module which prevents higher bitrates - somehow the SD card access seems to be very, very slow …