PIR->WaveShield->Speakers +total noob

Hi there, I'm working on a project where when someone enters the bathroom, a music track randomly selected begins to play, and then shuts off when motion is no longer detected. A test sketch that plays the track over and over, without the PIR, proves that the hardware is sound, and now I've attached the PIR to pin 0 and the 5v and ground, and added four more tracks to the SD card.

Now I'm not really sure where to go. I've done some searching around this forum and the adafruit forums and I cannot find a proper sketch for this, and the fact that I am new to all this means I don't really know how to go about modifying the one's I have seen to make them do what I want.

Can anyone help point me in the right direction?
Thanks in advance!

Can you post the sketch you have? Be sure to click the # button so than it formats as code!

I did a similar project, every time someone walks in and triggers a distance sensor a song plays. (it isn't randomized, it plays the next one down the line each time)
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1272995447/0#0

Hmm the serial monitor says:

WavWaveHC with 6 buttons
Free RAM: 608
Card init. failed!

SD I/O error: 6, 0

My code is:

#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"


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 filesystem on the card
FatReader f;      // This holds the information for the file we're play

WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 100  // button debouncer

// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

void setup() {
  // set up serial port
  Serial.begin(9600);
  putstring_nl("WaveHC with 6 buttons");
  
   putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
  
  // 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);
 
  // pin13 LED
  pinMode(13, OUTPUT);
 
  //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
  if (!card.init()) {         //play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
  
  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);
 
// Now we will look for a FAT partition!
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  
  // Lets tell the user about what we found
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
  
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
  
  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
}

void loop() {
  //putstring(".");            // uncomment this to see if the loop isnt running
  switch (check_switches()) {
    case 1:
      playcomplete("BanjoSong.wav");
      break;
    case 2:
      playcomplete("LittleMaggie.wav");
      break;
    case 3:
      playcomplete("OmieWise.wav");
      break;
    case 4:
      playcomplete("SameOldMan.wav");
      break;
    case 5:
      playcomplete("StrawFoot.wav");
      break;
    case 6:
      playcomplete("WayFaringStranger.wav");
  }
}

byte check_switches()
{
  if (digitalRead(14) == HIGH)  // check for high signal on pin 14 (analog 0)
    {
       return 1;
    }
  return 0;
}

// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
  // call our helper to find and play this name
  playfile(name);
  while (wave.isplaying) {
  // do nothing while its playing
  }
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.print(name); return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }
  
  // ok time to play! start playback
  wave.play();
}

How do you have the PIR wired? I was just setting one of those up.
This one in fact

and I found I had use an external pullup to +5V to get it to work well.
It has an open collector output, the output stays high unil it senses motion, then it pulls low. I used the low to create an interrupt on pin2 to wake up from sleep mode and do an action, then go back into sleep mode to save battery life (3 AAs).

You could poll the PIR output line every 1000mS or something, when you see it go low then play your song.
At top of void loop()
while (digitalRead(PIR_output) ==1){
delay (1000)
// at some point it will = 0 and then continue to the rest of the your code
}
If running on batteries, have it go to sleep and then wake up on interrupt into pin 2 or 3 (external interrupt lines:

at top of sketch:
#include <avr/sleep.h> // powerdown library
#include <avr/interrupt.h> // interrupts library
int interrupt = 2; // hardware interrupt, Motion Detector Open Collector pulls low

Interrupt Service Routine function:
//***************************************************
// * Name: pin2Interrupt, "ISR" to run when interrupted in Sleep Mode
void pin2Interrupt()
{
/* This brings us back from sleep. */
}

Sleep function:
//***************************************************
// * Name: enterSleep
void enterSleep()
{
/* Setup pin2 as an interrupt and attach handler. /
attachInterrupt(0, pin2Interrupt, LOW);
delay(50); // need this?
/
the sleep modes
SLEEP_MODE_IDLE - the least power savings
SLEEP_MODE_ADC
SLEEP_MODE_PWR_SAVE
SLEEP_MODE_STANDBY
SLEEP_MODE_PWR_DOWN - the most power savings
*/
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // setting up for sleep ...
sleep_enable(); // setting up for sleep ...
sleep_mode(); // now goes to Sleep and waits for the interrupt

/* The program will continue from here after the interrupt. */
// detachInterrupt(0); //disable interrupts while we wake up COMMENTED OUT, didn't work otherwise

/* First thing to do is disable sleep. */
sleep_disable();

// then go to the void Loop()
}

in setup:
pinMode (interrupt, INPUT); // hardware interrupt for waking up
digitalWrite (interrupt, HIGH); // internal pullup enabled

in loop:
// call this when song is done and you want to power down
enterSleep(); // call Sleep function to put us out
// THE PROGRAM CONTINUES FROM HERE after waking up in enterSleep()

I have it connected to the 5v pin

Steppenwolf:
I have it connected to the 5v pin

I always vowed never to be this guy, but that has to be one of the least helpful responses possible. No... "why?" would have beat it.

If possible, it's always helpful to post code and complete wiring information. Want to really impress? Go to http://www.fritzing.org and build a graphic showing how you've got it connected.

The PIR is connected to the 5v pin, the GND, and analog 0.

Serial Monitor returns:

Cardiled!

SD I/O error: 6, 0
WaveHC with 6 buttons
Free RAM: 608
Card init. failed!

SD I/O error: 6, 0

My code is:

#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"


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 filesystem on the card
FatReader f;      // This holds the information for the file we're play

WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 100  // button debouncer

// this handy function will return the number of bytes currently free in RAM, great for debugging!   
int freeRam(void)
{
  extern int  __bss_end; 
  extern int  *__brkval; 
  int free_memory; 
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end); 
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval); 
  }
  return free_memory; 
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

void setup() {
  // set up serial port
  Serial.begin(9600);
  putstring_nl("WaveHC with 6 buttons");
  
   putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!
  
  // 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);
 
  // pin13 LED
  pinMode(13, OUTPUT);
 
  //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
  if (!card.init()) {         //play with 8 MHz spi (default faster!)  
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }
  
  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);
 
// Now we will look for a FAT partition!
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part)) 
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }
  
  // Lets tell the user about what we found
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?
  
  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }
  
  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
}

void loop() {
  //putstring(".");            // uncomment this to see if the loop isnt running
  switch (check_switches()) {
    case 1:
      playcomplete("BANJOSONG.WAV");
      break;
    case 2:
      playcomplete("LITTLEMAGGIE.WAV");
      break;
    case 3:
      playcomplete("STRAWFOOT.WAV");
      break;
    case 4:
      playcomplete("SAMEOLDMAN.WAV");
      break;
    case 5:
      playcomplete("WAYFARINGSTRANGER.WAV");
      break;
    case 6:
      playcomplete("OMIEWISE.WAV");
  }
}

byte check_switches()
{
  if (digitalRead(14) == HIGH)  // check for high signal on pin 14 (analog 0)
    {
       return 1;
    }
  return 0;
}


// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
  // call our helper to find and play this name
  playfile(name);
  while (wave.isplaying) {
  // do nothing while its playing
  }
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); Serial.print(name); return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); return;
  }
  
  // ok time to play! start playback
  wave.play();
}

Not fritzing. Might as well take a blurry picture and post that.
Get a real schematic editor, so much more useful as tool.

So, your program stops right here:

// if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
if (!card.init()) { //play with 8 MHz spi (default faster!)
putstring_nl("Card init. failed!"); // Something went wrong, lets print out why
sdErrorCheck();
while(1); // then 'halt' - do nothing! <<<<<<<<<<<<<<<<<<<<<
}

Try changing the 2 lines around, maybe slower will work for you.

I tried that, no luck.

It might be my sd card. It's being totally inconsistent. Sometimes I get the card.init failure, sometimes it says ready, but then when I wave in front of the PIR, it says can't open BanjoSong.wav endlessly (which is at least encouraging, because it means the PIR is working).

How was the card loaded with songs? I imagine via PC or something? Is the card still readable there?

It was loaded on my mac, and it perfectly readable there. I used a program called Blue Harvest to erase the "dust" (the invisible files that macs put on things like usb drives and sd cards), because they were giving the wave shield a hard time. But it is fat16 formatted and what not.

Ok, then I guess the next step is looking at your code compared to this working come from this thread and see whats different that this works and yours doesn't
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1272995447/0#0

I don't have time right now, maybe later tonight, after 8pm east coast time.

#include <AF_Wave.h> //You will need the AF Wave library
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"

AF_Wave card;
File f;
Wavefile wave;      

#define redled 9

uint16_t samplerate;

int Power = 19;

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Wave test!");



  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(redled, OUTPUT);
  pinMode(Power, OUTPUT);
  
  if (!card.init_card()) {
    putstring_nl("Card init. failed!"); return;
  }
  if (!card.open_partition()) {
    putstring_nl("No partition!"); return;
  }
  if (!card.open_filesys()) {
    putstring_nl("Couldn't open filesys"); return;
  }

 if (!card.open_rootdir()) {
    putstring_nl("Couldn't open dir"); return;
  }

  putstring_nl("Files found:");
  ls();
}

void ls() {
  char name[13];
  int ret;
  
  card.reset_dir();
  putstring_nl("Files found:");
  while (1) {
    ret = card.get_next_name_in_dir(name);
    if (!ret) {
       card.reset_dir();
       return;
    }
    Serial.println(name);
  }
}

uint8_t tracknum = 0;

void loop() {
 int sensor = 0;
 int sensorPin = 0;
  sensor = analogRead(sensorPin);
  uint8_t i, r;
   char c, name[15];


   card.reset_dir();
   // scroll through the files in the directory
  
//------------------------------------------------  
   // THIS IS THE BUTTON IF STATEMENT!!!!
  //
  
    digitalWrite(Power, LOW);  //This turns the Speaker system
                              //Off using a powerSwitchTail relay
                             // when no music is playing.
                             // You don't need this if you
                             // want to leave your speakers on
  
   if (sensor > 300){    // 300 is for the IR distance sensor,
                         // you can change that number depending
                         // on the type of sensor you use.
                         // This sensor is on pin Analog 0.
  
  digitalWrite(Power, HIGH);  //This turns the speakers ON using
                                //the powerswitchtail Relay
   for (i=0; i<tracknum+1; i++) {
     r = card.get_next_name_in_dir(name);
     if (!r) {
       // ran out of tracks! start over
       tracknum = 0;
       return;
     }
   }
   putstring("\n\rPlaying "); Serial.print(name);
   // reset the directory so we can find the file
   card.reset_dir();
   playcomplete(name);
   tracknum++;
}
  }
void playcomplete(char *name) {
  uint16_t potval;
  uint32_t newsamplerate;
  
  playfile(name);
  samplerate = wave.dwSamplesPerSec;
  while (wave.isplaying) {    
	// you can do stuff here!
	delay(500);
   }
  card.close_file(f);
}

void playfile(char *name) {
   f = card.open_file(name);
   if (!f) {
      putstring_nl(" Couldn't open file"); return;
   }
   if (!wave.create(f)) {
     putstring_nl(" Not a valid WAV"); return;
   }
   // ok time to play!
   wave.play();
}

You don't have this in yours:

playfile(name);
samplerate = wave.dwSamplesPerSec; <<< maybe this line has something to do with playback not working ??
while (wave.isplaying) {
// you can do stuff here!
delay(500);
}

bah. It was the fact that my filenames were greater than the 8.3 limit. The sd card is working now and I'm almost done with it. I'll post my code when I'm finished.

Ooh, hate it when the simple stuff gets in the way! 8)