Arduino Audio Shield 01

From TheBeard Science Project Wiki
Jump to: navigation, search

I bought the Adafruit Wave Shield and thought it would be a funny first project to have an entrance theme play every time I get home from work. I created a compilation of audio clips from the TV show Seinfeld and made them play at random when my front door opens.

Components

  • Adafruit Wave Shield v1.1 (source)
  • Arduino Uno R3 (source)
  • AUX speaker adapter (dollar store)
  • Cheap door alarm (dollar store)
  • SD Card
  • USB power adapter
  • Cat-5 cable

File Downloads

Filename Description Size Modified Link

arduino_wave1.zip

Arduino code including WaveHC library. 31KB 12/29/2018

Download

seinfeld_audio.zip

Audio clips used in this project. 7.9MB 12/29/2018

Download

Additional Notes

The files need to be in WAV format (16 bit/sample, 22050 Hz sample rate).

The SD car needs to be formatted with a FAT32 file system.

Links

  • Wave Shield Assembly Instructions (link)

Gallery

DSC00580.JPG DSC00581.JPG DSC00582.JPG DSC00583.JPG DSC00584.JPG DSC00585.JPG DSC00586.JPG DSC00587.JPG DSC00588.JPG DSC00589.JPG DSC00590.JPG

Code

Here is the Arduino code. Requires the WaveHC library.

#include "WaveUtil.h"
#include "WaveHC.h"

// Pin that triggers audio
int inpin = 13;

// Delay before audio plays after trigger
int playDelay = 1500;

SdReader card;
FatVolume vol;
FatReader root;
WaveHC wave;
uint8_t dirLevel;
dir_t dirBuf;
int btnState = 0;
int fileCount = 0;
bool reset = false;

void setup() {
  Serial.begin(9600);
  Serial.println("\nStart");
 
  // Set the output pins for the DAC control
  // This pins are defined in the library
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
 
  pinMode(inpin, INPUT);
  
  if (!card.init())
  {
    Serial.println("Card init. failed!");
    while(1); // Halt
  }
  
  // Enable optimize read
  // Some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);
  
  // Look for a FAT partition
  uint8_t part;
  for (part = 0; part < 5; part++)
  {
    if (vol.init(card, part))
    { 
      break;
    }
  }
  if (part == 5)
  {
    Serial.println("No valid FAT partition!");
    while(1); // Halt
  }
  
  Serial.print("Using partition ");
  Serial.print(part, DEC);
  Serial.print(", type is FAT");
  Serial.println(vol.fatType(),DEC);
  
  // Try to open the root directory
  if (!root.openRoot(vol))
  {
    Serial.println("Can't open root dir!");
    while(1); // Halt
  }
  
  // Print the file names
  Serial.println("Files found:");
  dirLevel = 0;
  lsR(root);

  // Seed the random number generator by reading an analog pin
  randomSeed(analogRead(A0));

  // Count the number of files
  root.rewind();
  fileCount = countFiles(root);
  Serial.print("File count: ");
  Serial.println(fileCount);
}

void loop() {
  btnState = digitalRead(inpin);
  if (btnState == HIGH)
  {
    Serial.println("Door Closed; wait");
    reset = true;
    delay(200);

    while (reset == true)
    {
      btnState = digitalRead(inpin);
      if (btnState == LOW)
      {
         Serial.println("Door Open; play and wait");
         delay(playDelay);
         root.rewind();
         playRandom(root, fileCount);
         Serial.println();
         reset = false;
         delay(500);
         break;
      }
      else
      {
        continue;
      }
    }
  }
}

/*
 * Play a random file
 */
void playRandom(FatReader &dir, int fileCount)
{
  FatReader file;
  
  int playFile = random(1, fileCount);
  int fileIter = 1;

  // Read every file in the directory one at a time
  while (dir.readDir(dirBuf) > 0)
  {
    // skip . and .. directories
    if (dirBuf.name[0] == '.')
    { 
      continue;
    }
    
    if (fileIter < playFile)
    {
      fileIter++;
      continue;
    }

    if (!file.open(vol, dirBuf))
    {
      Serial.println("file.open failed");
      while(1); // Halt
    }

    Serial.print("Playing ");
    printEntryName(dirBuf);
    if (!wave.create(file))
    {
      Serial.print(" Not a valid WAV");
    }
    else
    {
      // playing occurs in interrupts
      wave.play();

      while (wave.isplaying)
      {
        putstring(".");
        delay(100);
      }
      
      if (wave.errors)
      {
        Serial.println(wave.errors);
      }
    }
    break;
  }
}

/*
 * Count files on the SD card
 */
int countFiles(FatReader &dir)
{
  int fileCount = 0;
  FatReader file;
  while (dir.readDir(dirBuf) > 0)
  {
    if (dirBuf.name[0] == '.' || !file.open(vol, dirBuf))
    {
      continue;
    }                                 
    fileCount++;
  }
  return fileCount;
}

/*
 * List files recursively
 */
void lsR(FatReader &d)
{
  // indicates the level of recursion
  int8_t r;
  
  while ((r = d.readDir(dirBuf)) > 0)
  {
    // skip subdirs . and ..
    if (dirBuf.name[0] == '.')
    {
      continue;
    }
    
    for (uint8_t i = 0; i < dirLevel; i++)
    {
      Serial.print(' ');
    }
     
    printEntryName(dirBuf);
    Serial.println();

    // Recurse on any direcory
    if (DIR_IS_SUBDIR(dirBuf))
    {
      FatReader s;
      dirLevel += 2;
      if (s.open(vol, dirBuf))
      {
        lsR(s);
      }
      dirLevel -=2;
    }
  }
}