Skip to content

Instantly share code, notes, and snippets.

@hz37
Created October 14, 2018 11:25
Show Gist options
  • Save hz37/ed35f715b928f03d8fa2d522fc05ce58 to your computer and use it in GitHub Desktop.
Save hz37/ed35f715b928f03d8fa2d522fc05ce58 to your computer and use it in GitHub Desktop.
Arduino Uno using asynchronous music playing in the background while handling button presses using Adafruit shield
// *********************************************************************
// Merry-go-round using Arduino Uno en Adafruit VS1053 shield.
// H.Zimmerman, 13-10-2018, Weesp.
// Code based on Adafruit examples:
// https://github.com/adafruit/Adafruit_VS1053_Library
// *********************************************************************
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
// *********************************************************************
// Switch debug and release modes.
// #define DEBUGGING
// There is no VS1053 reset pin.
#define SHIELD_RESET -1
// VS1053 Data request.
#define DREQ 3
// Card chip select pin.
#define CARDCS 4
// VS1053 Data/command select pin (output).
#define SHIELD_DCS 6
// VS1053 chip select pin (output).
#define SHIELD_CS 7
// Def volume at startup.
#define DEF_VOLUME 40
// Max song.
#define MAX_SONG 44
// *********************************************************************
// Instance of Adafruit_VS1053_FilePlayer.
Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer
(
SHIELD_RESET,
SHIELD_CS,
SHIELD_DCS,
DREQ,
CARDCS
);
// Global vars, bad practice but easy in this case.
uint16_t song = 0;
char songBuffer[8];
uint16_t volume = 0;
// *********************************************************************
void setup()
{
#ifdef DEBUGGING
Serial.begin(9600);
Serial.println("Draaimolen start.");
#endif
// Initialise the music player shield.
if (!musicPlayer.begin())
{
#ifdef DEBUGGING
Serial.println(F("musicPlayer.begin() error."));
#endif
while(true);
}
#ifdef DEBUGGING
Serial.println(F("VS1053 found"));
#endif
if (!SD.begin(CARDCS))
{
#ifdef DEBUGGING
Serial.println(F("SD failed, or not present"));
#endif
while(true);
}
#ifdef DEBUGGING
// List files.
printDirectory(SD.open("/"), 0);
#endif
// Set GPIO pins to input.
for(uint8_t idx = 0; idx < 8; ++idx)
{
musicPlayer.GPIO_pinMode(idx, INPUT);
}
// Set volume for left, right channels. lower numbers == louder volume!.
volume = DEF_VOLUME;
musicPlayer.setVolume(volume, volume);
// Do background audio playing.
#ifdef DEBUGGING
if(!musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
{
Serial.println(F("DREQ pin is not an interrupt pin."));
}
#else
musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);
#endif
// Play file in the background.
song = 0;
NextSong();
}
// *********************************************************************
void loop()
{
// File is playing in the background
if (musicPlayer.stopped())
{
NextSong();
}
uint16_t buttons = musicPlayer.GPIO_digitalRead();
switch(buttons)
{
case 4:
// Skip 10 songs.
Skip10Songs();
break;
case 8:
// Next song.
NextSong();
break;
case 16:
// Previous song.
PreviousSong();
break;
case 32:
// Higher volume.
if(volume > 0)
{
volume -= 2;
}
musicPlayer.setVolume(volume, volume);
break;
case 64:
// Lower volume.
if(volume < 127)
{
volume += 2;
}
musicPlayer.setVolume(volume, volume);
break;
}
delay(50);
}
// *********************************************************************
// File listing helper function.
// *********************************************************************
void printDirectory(File dir, int numTabs)
{
while(true)
{
File entry = dir.openNextFile();
if (!entry)
{
break;
}
for (uint8_t idx = 0; idx < numTabs; ++idx)
{
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();
}
}
// *********************************************************************
void PreviousSong()
{
song -= 1;
if(song < 1)
{
song = MAX_SONG;
}
PlayCurrent();
}
// *********************************************************************
void NextSong()
{
song += 1;
if(song > MAX_SONG)
{
song = 1;
}
PlayCurrent();
}
// *********************************************************************
void Skip10Songs()
{
song += 10;
if(song > MAX_SONG)
{
song -= MAX_SONG;
}
PlayCurrent();
}
// *********************************************************************
void PlayCurrent()
{
musicPlayer.stopPlaying();
sprintf(songBuffer, "%.02d.mp3", song);
musicPlayer.startPlayingFile(songBuffer);
delay(10);
}
// *********************************************************************
@ygreq
Copy link

ygreq commented Apr 21, 2021

Did you use the WAV shield or the VS1053? I have both. I actually have used the VS1053 on a couple of projects. Now I want to update one of the projects to have the Next and Previous buttons options. This is why I was curious about your project. I see that you code differently than how I am used to :). For example I always get confused whenever I see uint8_t being used. ;))

Anyway I will try to get inspired by your example. Maybe I will write to you in private in case you can explain a few things about what you did in this sketch. You used lots of comments so that is a good thing.

Thank you so much!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment