Wednesday, May 8, 2013

Embedded Front End- Interfacing the MP3 shield


The mp3 shield is used to provide audio output which consists of the number of the bus which has just arrived at the bus stop. Even after the bus has passed by, it will continue to provide information about the bus which arrived the last. 

It can play up to 22KHz, 12bit uncompressed audio files of any length. It's low cost, available as an easy-to-make kit. It has an onboard DAC, filter and op-amp for high quality output. Audio files are read off of an SD/MMC card, which are available at nearly any store. Volume can be controlled with the onboard thumbwheel potentiometer.



Given below is a code which shows the mp3 shield initialization :

/*These header files are present in the WaveHC library which has to be imported to the libraries folder of the  Arduino IDE. This library can be obtained from https://code.google.com/p/wavehc/downloads/list */

#include <WaveHC.h>
#include <WaveUtil.h>

/* The WaveHC Library was developed for the Adafruit Arduino Wave Shield. It supports both standard SD and high capacity SDHC flash cards. The cards may be formatted with either FAT16 or FAT32 file systems.

The WaveHC Library is based on the four C++ classes, SdReader, FatVolume, FatReader and WaveHC.
SdReader is a standalone class that provides raw read access to standard SD cards and high capacity SDHC cards.

The FatVolume class provides access to data structures on FAT16 and FAT32 volumes.
File read access to FAT16 and FAT32 volumes is provided by the FatReader class.

The fourth class, WaveHC, is a modified version of Ladyada’s AF_Wave class that uses FatReader to read and play WAV files */




SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the volumes root directory
FatReader file;   // This object represent the WAV file for a pi digit or period
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time
/*
 * Define macro to put error messages in flash memory
 */
#define error(msg) error_P(PSTR(msg))

void setup()
{
      if (!card.init()) {
    error("Card init. failed!");
  }
  if (!vol.init(card)) {
    error("No partition!");
  }
  if (!root.openRoot(vol)) {
    error("Couldn't open dir");
  }

   PgmPrintln("Files found:");
   root.ls();
}

 The above piece of code will initialize the mp3 shield and check if the SD card is properly inserted, whether the .WAV files are present etc.  The files in the SD card are read using the Arduino SPI pins, which are :

Pin 10 - Slave Select
Pin 11-  MOSI
Pin 12 - MISO
Pin 13 - SCK

Pins 13, 12 and 11 are used to talk to the SD card and cant be changed. The rest of the pins, however, are more flexible. Connections of the other pins of the mp3 shield with the Arduino pins are given below:

Pin 2 - LCS
Pin 3 - CLK
Pin 4 - DI
Pin 5 - LAT
Pin 10 - CCS

In order to play a .WAV file, we use 4 functions - mp3play(), speaknum(), playcomplete() and playfile().
There are two files stored in the SD card namely, 1.WAV and 2.WAV. When bus 21 arrives at a bus stop the file 1.WAV will be played and if bus 22 arrives, 2.WAV will be played. 

Now we will describe each of these functions :

void mp3play(){
      speaknum(c);
        

This function will take a char input which will in turn call the speaknum function. 

void speaknum(char c) {
  uint8_t i=0;
  
  // copy flash string for 'period' to filename
  strcpy_P(filename, PSTR("P.WAV"));
  
  if ('0' <= c && c <= '9') {
    // digit - change 'P' to digit
    filename[0] = c;
    i = 1;
  } 
  else if (c != '.') {
    // error if not period
    return;
  }
  playcomplete(filename);
}

This function take the input char c and convert it to a string "c.WAV" and then call a function called playcomplete(filename). 

/*
 * Play a file and wait for it to complete
 */
void playcomplete(char *name) {
  playfile(name);
  while (wave.isplaying);
  
  // see if an error occurred while playing
  sdErrorCheck();
}

This function will call a function called playfile() and passes the filename that it receives as an argument to the function playfile() and it will wait until the file is played completely. It also calls a function sdErrorCheck() which checks if any errors occured while playing the file.

void playfile(char *name) {
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  if (!file.open(root, name)) {
    PgmPrint("Couldn't open file ");
    Serial.print(name); 
    return;
  }
  if (!wave.create(file)) {
    PgmPrintln("Not a valid WAV");
    return;
  }
  // ok time to play!
  wave.play();
}


This function actually plays the file which it receives as the input. It checks to see if any other file is being played and stops it and then checks if the file can be successfully opened and and if the file is valid and then plays the file.

During the early stages in the embedded back end development, there were certain problems which we faced when we integrated the Adruino at the bus stop with an LED Matrix and the MP3 shield. So we made the the Slave select, MOSI, MISO, and SCK pins of the LED matrix different from what the SD card is using here and this problem was solved. 

No comments:

Post a Comment