Arduino Uno e Shield MP3 Player Sparkfun
Que tal aposentar seu celular e ouvir suas músicas em MP3 direto no Arduino? OK, substituir o celular pode ser um pouco exagerado, mas você pode utilizar as funcionalidades do Shield MP3 Player Sparkfun e incrementar os seus projetos. Quer exemplos?
- Sistemas de identificação com avisos sonoros: Ao invés de enviar os dados para uma tela ou acender alguma lâmpada, o seu sistema de identificação pode “falar” o nome do usuário, recebê-lo com um “Bom dia”, “Bem vindo”, “Acesso liberado”, etc.
- Utilização em brinquedos: Interação ao apertar botões ou em conjunto com acelerômetro quando há movimentação do brinquedo
- Projetos de auxílio à pessoas com deficiência visual: um despertador que “fala” as horas, uma caixa de correio que avisa quando há correspondência, um sistema que emite um sinal sonoro quando alguém se aproxima. As possibilidades são infinitas.
O Shield MP3 Player Sparkfun
Com esse Shield MP3 Player Sparkfun você pode fazer tudo isso. Ele aceita arquivos nos formatos Ogg Vorbis, MP3, AAC, WMA e MIDI, possui uma saída para fone de ouvido padrão P2 (conector 3.5mm stéreo) e permite também a conexão de um alto-falante. Um conector para cartões microSD é o responsável pelo armazenamento dos arquivos de áudio.

Essa placa não vem com a barra de pinos soldada, assim você pode montar a configuração de sua preferência. Uma opção é soldar barras de pinos como essa abaixo, numa configuração “empilhável”:

Ou você pode soldar uma barra de pinos comum, utilizando apenas os pinos necessários para comunicação com o Arduino e funcionamento do shield MP3, que são os pinos mostrados na figura abaixo:

Os pinos marcados em azul (2, 3, 4, 6, 7 e 8) são os pinos utilizados pelo CI VS1053, “cérebro” da placa e responsável pelo tratamento do som. O pino em vermelho (9), é utilizado para comunicação com o cartão microSD, e os pinos em roxo (11, 12, 13), são utilizados pelos dois, que se comunicam com o Arduino via interface SPI.
E o que sobra? Pinos 0 e 1 (RX e TX – Comunicação serial), pinos digitais 5 e 10 (PWM) e os pinos analógicos de A0 a A5.
Legal! E como eu testo tudo isso?
Bom, a primeira coisa é você soldar a barra de pinos na configuração de sua preferência. Depois, você deve baixar o arquivo Sparkfun-MP3-Player-Shield-Arduino-Library-master.zip neste link.
Dentro desse arquivo, você tem as pastas SdFAT e SFEMP3Shield, que são as bibliotecas que devem ser extraídas e colocadas na pasta LIBRARIES dentro da IDE do seu Arduino.
Ligação MP3 Player Shield no Arduino
Se você vai usar a placa como “shield”, basta encaixá-la no Arduino e seguir o próximo passo. Se você for utilizar apenas os pinos básicos, sua ligação ficará assim:

O próximo passo é você gravar alguns arquivos MP3 no cartão SD, que deve ter sido formatado previamente no formato FAT ou FAT32. Lembre-se que por ser formato FAT, os arquivos devem seguir o formato 8.3, ou seja. O nome do arquivo deve conter 8 caracteres, mais 3 caracteres para a extensão.
Assim, no exemplo que vamos utilizar, os nomes dos arquivos devem ser track001.MP3, track002.MP3, e assim sucessivamente.
Programa controle de músicas com Arduino
Carregue o programa abaixo, baseado no arquivo de exemplo que já vem na biblioteca SFEMP3Shield:
//Programa : Teste MP3 Player Sparkfun
//Autor : Arduino e Cia
//Baseador no programa original de
//author Bill Porter
//author Michael P. Flaga
#include <SPI.h>
//Bibliotecas para cartao SD
#include <SdFat.h>
#include <SdFatUtil.h>
//Biblioteca do MP3 Shield
#include <SFEMP3Shield.h>
SdFat sd;
SFEMP3Shield MP3player;
void setup() {
uint8_t result;
Serial.begin(115200);
Serial.print(F("F_CPU = "));
Serial.println(F_CPU);
Serial.print(F("Free RAM = "));
Serial.print(FreeRam(), DEC);
Serial.println(F(" Should be a base line of 1028, on ATmega328 when using INTx"));
//Inicializa o cartao SD
if(!sd.begin(SD_SEL, SPI_FULL_SPEED)) sd.initErrorHalt();
// depending upon your SdCard environment, SPI_HAVE_SPEED may work better.
if(!sd.chdir("/")) sd.errorHalt("sd.chdir");
//Inicializa o MP3 Player Shield
result = MP3player.begin();
//Verifica se ha erros na conexao
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to start MP3 player"));
}
#if defined(__BIOFEEDBACK_MEGA__) // or other reasons, of your choosing.
// Typically not used by most shields, hence commented out.
Serial.println(F("Applying ADMixer patch."));
if(MP3player.ADMixerLoad("admxster.053") == 0) {
Serial.println(F("Setting ADMixer Volume."));
MP3player.ADMixerVol(-3);
}
#endif
help();
}
void loop() {
MP3player.available();
if(Serial.available()) {
parse_menu(Serial.read()); // get command from serial input
}
delay(100);
}
uint32_t millis_prv;
void parse_menu(byte key_command) {
uint8_t result;
//Armazena o titulo da musica
char title[30];
//Armazena o nome do artista
char artist[30];
//Armazena o nome do album
char album[30];
Serial.print(F("Received command: "));
Serial.write(key_command);
Serial.println(F(" "));
//Caso s seja recebido, para a reproducao
if(key_command == 's') {
Serial.println(F("Stopping"));
MP3player.stopTrack();
//Caso um numero de 1 a 9 seja recebido,
//reproduz o arquivo MP3 correspondente
} else if(key_command >= '1' && key_command <= '9') {
//convert ascii numbers to real numbers
key_command = key_command - 48;
#if USE_MULTIPLE_CARDS
sd.chvol(); // assign desired sdcard's volume.
#endif
//Comando para o shield reproduzir a musica
result = MP3player.playTrack(key_command);
//Checa por erros na reproducao
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to play track"));
} else {
Serial.println(F("Playing:"));
MP3player.trackTitle((char*)&title);
MP3player.trackArtist((char*)&artist);
MP3player.trackAlbum((char*)&album);
//Imprime as informacoes sobre a musica reproduzida
Serial.write((byte*)&title, 30);
Serial.println();
Serial.print(F("by: "));
Serial.write((byte*)&artist, 30);
Serial.println();
Serial.print(F("Album: "));
Serial.write((byte*)&album, 30);
Serial.println();
}
//+/- altera volume da musica
} else if((key_command == '-') || (key_command == '+')) {
union twobyte mp3_vol;
mp3_vol.word = MP3player.getVolume();
if(key_command == '-') { // note dB is negative
// assume equal balance and use byte[1] for math
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
}
} else {
if(mp3_vol.byte[1] <= 2) { // range check
mp3_vol.byte[1] = 2;
} else {
mp3_vol.byte[1] -= 2;
}
}
// push byte[1] into both left and right assuming equal balance.
MP3player.setVolume(mp3_vol.byte[1], mp3_vol.byte[1]); // commit new volume
Serial.print(F("Volume changed to -"));
Serial.print(mp3_vol.byte[1]>>1, 1);
Serial.println(F("[dB]"));
//< ou > altera a velocidade de reproducao
} else if((key_command == '>') || (key_command == '<')) {
uint16_t playspeed = MP3player.getPlaySpeed();
// note playspeed of Zero is equal to ONE, normal speed.
if(key_command == '>') { // note dB is negative
// assume equal balance and use byte[1] for math
if(playspeed >= 254) { // range check
playspeed = 5;
} else {
playspeed += 1; // keep it simpler with whole dB's
}
} else {
if(playspeed == 0) { // range check
playspeed = 0;
} else {
playspeed -= 1;
}
}
MP3player.setPlaySpeed(playspeed); // commit new playspeed
Serial.print(F("playspeed to "));
Serial.println(playspeed, DEC);
/* Alterativly, you could call a track by it's file name by using playMP3(filename);
But you must stick to 8.1 filenames, only 8 characters long, and 3 for the extension */
} else if(key_command == 'f' || key_command == 'F') {
uint32_t offset = 0;
if (key_command == 'F') {
offset = 2000;
}
//create a string with the filename
char trackName[] = "track001.mp3";
#if USE_MULTIPLE_CARDS
sd.chvol(); // assign desired sdcard's volume.
#endif
//tell the MP3 Shield to play that file
result = MP3player.playMP3(trackName, offset);
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to play track"));
}
/* Display the file on the SdCard */
} else if(key_command == 'd') {
if(!MP3player.isPlaying()) {
// prevent root.ls when playing, something locks the dump. but keeps playing.
// yes, I have tried another unique instance with same results.
// something about SdFat and its 500byte cache.
Serial.println(F("Files found (name date time size):"));
sd.ls(LS_R | LS_DATE | LS_SIZE);
} else {
Serial.println(F("Busy Playing Files, try again later."));
}
/* Get and Display the Audio Information */
} else if(key_command == 'i') {
MP3player.getAudioInfo();
} else if(key_command == 'p') {
if( MP3player.getState() == playback) {
MP3player.pauseMusic();
Serial.println(F("Pausing"));
} else if( MP3player.getState() == paused_playback) {
MP3player.resumeMusic();
Serial.println(F("Resuming"));
} else {
Serial.println(F("Not Playing!"));
}
} else if(key_command == 't') {
int8_t teststate = MP3player.enableTestSineWave(126);
if(teststate == -1) {
Serial.println(F("Un-Available while playing music or chip in reset."));
} else if(teststate == 1) {
Serial.println(F("Enabling Test Sine Wave"));
} else if(teststate == 2) {
MP3player.disableTestSineWave();
Serial.println(F("Disabling Test Sine Wave"));
}
} else if(key_command == 'S') {
Serial.println(F("Current State of VS10xx is."));
Serial.print(F("isPlaying() = "));
Serial.println(MP3player.isPlaying());
Serial.print(F("getState() = "));
switch (MP3player.getState()) {
case uninitialized:
Serial.print(F("uninitialized"));
break;
case initialized:
Serial.print(F("initialized"));
break;
case deactivated:
Serial.print(F("deactivated"));
break;
case loading:
Serial.print(F("loading"));
break;
case ready:
Serial.print(F("ready"));
break;
case playback:
Serial.print(F("playback"));
break;
case paused_playback:
Serial.print(F("paused_playback"));
break;
case testing_memory:
Serial.print(F("testing_memory"));
break;
case testing_sinewave:
Serial.print(F("testing_sinewave"));
break;
}
Serial.println();
} else if(key_command == 'b') {
Serial.println(F("Playing Static MIDI file."));
MP3player.SendSingleMIDInote();
Serial.println(F("Ended Static MIDI file."));
#if !defined(__AVR_ATmega32U4__)
} else if(key_command == 'm') {
uint16_t teststate = MP3player.memoryTest();
if(teststate == -1) {
Serial.println(F("Un-Available while playing music or chip in reset."));
} else if(teststate == 2) {
teststate = MP3player.disableTestSineWave();
Serial.println(F("Un-Available while Sine Wave Test"));
} else {
Serial.print(F("Memory Test Results = "));
Serial.println(teststate, HEX);
Serial.println(F("Result should be 0x83FF."));
Serial.println(F("Reset is needed to recover to normal operation"));
}
} else if(key_command == 'e') {
uint8_t earspeaker = MP3player.getEarSpeaker();
if(earspeaker >= 3){
earspeaker = 0;
} else {
earspeaker++;
}
MP3player.setEarSpeaker(earspeaker); // commit new earspeaker
Serial.print(F("earspeaker to "));
Serial.println(earspeaker, DEC);
} else if(key_command == 'r') {
MP3player.resumeMusic(2000);
} else if(key_command == 'R') {
MP3player.stopTrack();
MP3player.vs_init();
Serial.println(F("Reseting VS10xx chip"));
} else if(key_command == 'g') {
int32_t offset_ms = 20000; // Note this is just an example, try your own number.
Serial.print(F("jumping to "));
Serial.print(offset_ms, DEC);
Serial.println(F("[milliseconds]"));
result = MP3player.skipTo(offset_ms);
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to skip track"));
}
} else if(key_command == 'k') {
int32_t offset_ms = -1000; // Note this is just an example, try your own number.
Serial.print(F("moving = "));
Serial.print(offset_ms, DEC);
Serial.println(F("[milliseconds]"));
result = MP3player.skip(offset_ms);
if(result != 0) {
Serial.print(F("Error code: "));
Serial.print(result);
Serial.println(F(" when trying to skip track"));
}
} else if(key_command == 'O') {
MP3player.end();
Serial.println(F("VS10xx placed into low power reset mode."));
} else if(key_command == 'o') {
MP3player.begin();
Serial.println(F("VS10xx restored from low power reset mode."));
} else if(key_command == 'D') {
uint16_t diff_state = MP3player.getDifferentialOutput();
Serial.print(F("Differential Mode "));
if(diff_state == 0) {
MP3player.setDifferentialOutput(1);
Serial.println(F("Enabled."));
} else {
MP3player.setDifferentialOutput(0);
Serial.println(F("Disabled."));
}
} else if(key_command == 'V') {
MP3player.setVUmeter(1);
Serial.println(F("Use \"No line ending\""));
Serial.print(F("VU meter = "));
Serial.println(MP3player.getVUmeter());
Serial.println(F("Hit Any key to stop."));
while(!Serial.available()) {
union twobyte vu;
vu.word = MP3player.getVUlevel();
Serial.print(F("VU: L = "));
Serial.print(vu.byte[1]);
Serial.print(F(" / R = "));
Serial.print(vu.byte[0]);
Serial.println(" dB");
delay(1000);
}
Serial.read();
MP3player.setVUmeter(0);
Serial.print(F("VU meter = "));
Serial.println(MP3player.getVUmeter());
} else if(key_command == 'T') {
uint16_t TrebleFrequency = MP3player.getTrebleFrequency();
Serial.print(F("Former TrebleFrequency = "));
Serial.println(TrebleFrequency, DEC);
if (TrebleFrequency >= 15000) { // Range is from 0 - 1500Hz
TrebleFrequency = 0;
} else {
TrebleFrequency += 1000;
}
MP3player.setTrebleFrequency(TrebleFrequency);
Serial.print(F("New TrebleFrequency = "));
Serial.println(MP3player.getTrebleFrequency(), DEC);
} else if(key_command == 'E') {
int8_t TrebleAmplitude = MP3player.getTrebleAmplitude();
Serial.print(F("Former TrebleAmplitude = "));
Serial.println(TrebleAmplitude, DEC);
if (TrebleAmplitude >= 7) { // Range is from -8 - 7dB
TrebleAmplitude = -8;
} else {
TrebleAmplitude++;
}
MP3player.setTrebleAmplitude(TrebleAmplitude);
Serial.print(F("New TrebleAmplitude = "));
Serial.println(MP3player.getTrebleAmplitude(), DEC);
} else if(key_command == 'B') {
uint16_t BassFrequency = MP3player.getBassFrequency();
Serial.print(F("Former BassFrequency = "));
Serial.println(BassFrequency, DEC);
if (BassFrequency >= 150) { // Range is from 20hz - 150hz
BassFrequency = 0;
} else {
BassFrequency += 10;
}
MP3player.setBassFrequency(BassFrequency);
Serial.print(F("New BassFrequency = "));
Serial.println(MP3player.getBassFrequency(), DEC);
} else if(key_command == 'C') {
uint16_t BassAmplitude = MP3player.getBassAmplitude();
Serial.print(F("Former BassAmplitude = "));
Serial.println(BassAmplitude, DEC);
if (BassAmplitude >= 15) { // Range is from 0 - 15dB
BassAmplitude = 0;
} else {
BassAmplitude++;
}
MP3player.setBassAmplitude(BassAmplitude);
Serial.print(F("New BassAmplitude = "));
Serial.println(MP3player.getBassAmplitude(), DEC);
} else if(key_command == 'M') {
uint16_t monostate = MP3player.getMonoMode();
Serial.print(F("Mono Mode "));
if(monostate == 0) {
MP3player.setMonoMode(1);
Serial.println(F("Enabled."));
} else {
MP3player.setMonoMode(0);
Serial.println(F("Disabled."));
}
#endif
} else if(key_command == 'h') {
help();
}
// print prompt after key stroke has been processed.
Serial.print(F("Time since last command: "));
Serial.println((float) (millis() - millis_prv)/1000, 2);
millis_prv = millis();
Serial.print(F("Enter s,1-9,+,-,>,<,f,F,d,i,p,t,S,b"));
#if !defined(__AVR_ATmega32U4__)
Serial.print(F(",m,e,r,R,g,k,O,o,D,V,B,C,T,E,M:"));
#endif
Serial.println(F(",h :"));
}
//Imprime o menu de opcoes
void help() {
Serial.println(F("Arduino SFEMP3Shield Library Example:"));
Serial.println(F(" courtesy of Bill Porter & Michael P. Flaga"));
Serial.println(F("COMMANDS:"));
Serial.println(F(" [1-9] to play a track"));
Serial.println(F(" [f] play track001.mp3 by filename example"));
Serial.println(F(" [F] same as [f] but with initial skip of 2 second"));
Serial.println(F(" [s] to stop playing"));
Serial.println(F(" [d] display directory of SdCard"));
Serial.println(F(" [+ or -] to change volume"));
Serial.println(F(" [> or <] to increment or decrement play speed by 1 factor"));
Serial.println(F(" [i] retrieve current audio information (partial list)"));
Serial.println(F(" [p] to pause."));
Serial.println(F(" [t] to toggle sine wave test"));
Serial.println(F(" [S] Show State of Device."));
Serial.println(F(" [b] Play a MIDI File Beep"));
#if !defined(__AVR_ATmega32U4__)
Serial.println(F(" [e] increment Spatial EarSpeaker, default is 0, wraps after 4"));
Serial.println(F(" [m] perform memory test. reset is needed after to recover."));
Serial.println(F(" [M] Toggle between Mono and Stereo Output."));
Serial.println(F(" [g] Skip to a predetermined offset of ms in current track."));
Serial.println(F(" [k] Skip a predetermined number of ms in current track."));
Serial.println(F(" [r] resumes play from 2s from begin of file"));
Serial.println(F(" [R] Resets and initializes VS10xx chip."));
Serial.println(F(" [O] turns OFF the VS10xx into low power reset."));
Serial.println(F(" [o] turns ON the VS10xx out of low power reset."));
Serial.println(F(" [D] to toggle SM_DIFF between inphase and differential output"));
Serial.println(F(" [V] Enable VU meter Test."));
Serial.println(F(" [B] Increament bass frequency by 10Hz"));
Serial.println(F(" [C] Increament bass amplitude by 1dB"));
Serial.println(F(" [T] Increament treble frequency by 1000Hz"));
Serial.println(F(" [E] Increament treble amplitude by 1dB"));
#endif
Serial.println(F(" [h] this help"));
}
Carregue o programa no Arduino e abra o Serial Monitor. Antes de mais nada, selecione a velocidade de comunicação para 115200, conforme destacado. Um menu de opções será exibido, e você pode selecionar as músicas, alterar o volume e a velocidade de reprodução, tudo através do serial monitor, bastando enviar os caracteres correspondentes:

Assim, pressione 1 para reproduzir o arquivo track001.mp3, 2 para reproduzir o arquivo track002.mp3, e assim por diante.
Esse é apenas um exemplo de utilização. Informações completas e detalhadas sobre esse shield você pode obter acessando diretamente o site do produto na Sparkfun, nesse link.
Gostou? Confira outros posts usando módulos MP3 aqui mesmo no Arduino e Cia!
Esse post é bem interessante, no entanto da forma como é mostrado torna-se impossível utilizar um display LCD para mostrar, por exemplo, que musica estaria tocando ?
Boa noite.
O que você pode fazer é utilizar a biblioteca Liquid Crystal e utilizar as portas do Arduino que ficaram livres para ligação do display.
Abraço !
Amigo, estou com um shield deste em um UNO, está funcionando perfeito, porém quando coloco uma bateria 9v não funciona, já troquei a bateria e nada… as luzes acendem mais não toca. Sabe o que pode ser?
Oi Alan,
Você está usando uma bateria de 9V "normal", certo ? Pelo jeito ela não tem potência suficiente para alimentar o Arduino e o shield. se possível, tente uma bateria de lítio, níquel-cádmio, etc.
Abraço!
Olá! Estou testando usar o sparkfun em meu projeto, mas ao tentar executar, depois de seguir os passos descritos no site,aparece no SerialMonitor a mensagem:
F_CPU = 16000000
Free RAM = 7173 Should be a base line of 1028, on ATmega328 when using INTx
Can't access SD card. Do not reformat.
SD errorCode: 0X2,0XFF
O que poderia fazer?
obs: o cartão que uso é de 4GB e estou utilizando um Arduino Mega
estou com o mesmo problema. Alguém sabe a solução?
Olá Arduino e Cia, eu estou fazendo um projeto com o Arduino e eu quero reproduzir uma música, a minha pergunta é, você pode selecionar a música que deseja ouvir (por meio de código óbvio)?
Oi José,
Consegue sim, tranquilamente.
Abraço!
Pra Funcionar no Mega 2560 R3 as conexões são a parte da placa ? se sim é so soldar os pinos de comunicação SD no ICSP do arduino mega ? já vi alguns sites falando + ainda tenho certeza se é o correto
Esta placa é muito usada para receber streamer de rádio,consegue disponibilizar algum exemplo prático ?
Oi Vinicius,
Vou tentar, mas acho que não tenho mais essa placa.. mas é uma boa sugestão de post.
Abraço!
Adilson