• If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • Stop wasting time looking for files and revisions. Connect your Gmail, DriveDropbox, and Slack accounts and in less than 2 minutes, Dokkio will automatically organize all your file attachments. Learn more and claim your free account.


Lab 6 Thompson

Page history last edited by Benjamin Tee 9 years, 1 month ago

Barebones MP3 Player

Answer the questions in green below, and show a video of your MP3 player playing a song! 

Part A. Audio Jack

We are using a 3.5mm audio jack in this lab. This type of jack is called 'TRS' for Tip, Ring and Sleeve.

Part B. Connect And Test Your Decoder

Your second task is to wire up and test your mp3 decoder. We're using a breakout board for the VS1033D, which is based on VLSI's VS1033D decoder chip. You can check out the datasheet here.

1. Install this updated Mp3 library in the Arduino IDE "libraries" folder.


Part C. Play Some Music!

Tell a member of the teaching team what your song is (or better yet, play it for us). If you don't know the name, just decipher some of the lyrics.

Sounds like some enya or something.  This song does not seem to be in English, so I have no idea what the lyrics are.

Now look at the example code a bit: specifically the dir_play() and setup() functions.

Does this code play all the songs in all the directories of the SD card? If not, which songs does it play? How does it keep from playing the text file?

It plays all songs in the root directory (only) and checks the file extension to keep from playing text files.

Here are some useful file management functions that can be used on a SdFile object. These are used in the example code. The CardInfo example also uses some of these functions.

Also note that in this example's setup(), we're using the Mp3 library's volume() function. This function re-inverts the decoder's volume setting back to what seems more natural: 0 is nearly silent, while 254 (which equals 0xFE) is full volume.

Change the 'song' code to save the current volume setting in your EEPROM and fetch and set that value during initialization.  Note that the first MAX_FILE_COUNT*MAX_NAME_LENGTH (in this case, 520) bytes of the EEPROM are used to store file names, so don't overwrite those. 


     int StoredVolume = 205;
     int EEPROM_VolLoc = 1023;

 // in setup:

  StoredVolume = EEPROM.read(EEPROM_VolLoc);
  Mp3.begin(mp3_cs,dcs,rst,dreq);  // decoder cs, dcs, rst, dreq pin from your setup
  Mp3.volume(StoredVolume);             // default volume level is silent (note: 0 = minimum, 254 = max)

Part D. Pause to Learn About Interrupts

The Teensy has 4 pins with external interrupts built in, on pins 5, 6, 7 and 8 (which correspond with interrupt 0, 1, 2, and 3 respectively). You can use them by using the attachInterrupt() function, which is part of the extended Arduino language.


Try the sample code from the attachInterrupt reference page with a button circuit that is tied high with a 10K resistor and that gets pulled to ground when the button is depressed.


In general (as in the sample code), when you set or change a variable within an interrupt service routine (ISR), you should declare that variable as volatile, to tell the compiler to load its value from RAM instead of storing it in a register to optimize.


Draw us a quick sketch of what your circuit looks like.


What happens when you press the button? What happens when you press the button 15 times in a row?


The LED on the teensy lights up when I press the button.  It works the same when I press it 15 times.

To debounce the button in software, you can create a "bouncer" object that waits a bit before reading the button:



What are the pros and cons of using this method?

The downside is that it slows things down and if the button presses are too fast for the delay you've set then you might miss information.✔Also it contains blocking code

A pro of this method is that if the signal is noisy from the button press you don't end up doing things like accidentally counting one button press as 2 or more.


To couple interrupts and debouncing, you can modify code at: Arduino Forum on Debouncing & Interrupts


Now, take what you learned to make an interrupt driven pause function for your Barebones MP3 player!

I added the pause functionality in the mp3_play function and made the other modifications to the program shown:


int pin = 11;
volatile int state = LOW;
volatile int pause = false;


void setup{


 pinMode(pin, OUTPUT);
 attachInterrupt(0, my_interrupt_handler, RISING);




void mp3_play (SdFile *file) {
  unsigned char bytes[read_buffer]; // buffer to send to the decoder
  unsigned int bytes_to_read;       // number of bytes to read from sd card
  // reset the file to be at the beginning of data
  // Try to read 'read_buffer' length of bytes and send it to the decoder.
  // If less than 'read_buffer' bytes are available, stop last send.
  do {
    bytes_to_read = file->read(bytes, read_buffer);
    Mp3.play(bytes, bytes_to_read);

    digitalWrite(pin, state);
  while (bytes_to_read == read_buffer);
#ifdef DEBUG
  Serial.println("Played song...");


void blink()
  state = !state;
  pause = !pause;

void my_interrupt_handler()
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 50)
  last_interrupt_time = interrupt_time;




video link above



Part E. Input Knob (Optional)

What if you want to change the volume? You can modify the following code:



 * Encoder_test

 * Based on code by Paul Badger

 * ----------------------------

 * WGJ 6MAY10: Updated pins, serial speed for Teensyduino


 * Read a rotary encoder with interrupts

 * Encoder hooked up with common to GROUND,

 * encoder0PinA to pin 6, encoder0PinB to pin 7

 * it doesn't matter which encoder pin you use for A or B


 * Uses Arduino pullups on A & B channel outputs

 * turning on the pullups saves having to hook up resistors

 * to the A & B channel outputs



#define encoder0PinA  2

#define encoder0PinB  3


volatile unsigned int encoder0Pos = 0;


void setup() {

  Serial.begin (115200);

  pinMode(encoder0PinA, INPUT);

  digitalWrite(encoder0PinA, HIGH);       // turn on pullup resistor

  pinMode(encoder0PinB, INPUT);

  digitalWrite(encoder0PinB, HIGH);       // turn on pullup resistor


  attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2




void loop() {

  /* Do some stuff here - the joy of interrupts is that they

   * take care of themselves




void doEncoder() {

  /* If pinA and pinB are both high or both low, it is spinning

   * forward. If they're different, it's going backward.


  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {


  } else {



  Serial.println (encoder0Pos, DEC);



Part F. Song List (Optional)

If you want some more functionality, here is an additional part you could add to your mp3 player. In the Song.pde example script the code lists all files in the root directory and plays any that are songs. However, it plays them in a specific order and is limited to loading ~40 songs. To help alleviate this problem, create a song list that contains all songs you want to play in a certain order and load the files to play in the correct sequence. From here you could do a lot to allow user input on song lists!

Comments (0)

You don't have permission to comment on this page.