Adafruit WaveShield + PIR SENSOR

Hello,

I'm trying to use Adafruit WaveShield with a PIR sensor (what to generate an alarm when a motion is detected).

The code below is unfortunatly not working. :~

Without the PIR sensor (and code updated), the .wav file keep playing well. The PIR sensor is also working well with a buzzer.

Can a helpfull mind check the code below and see what's wrong ?

I'm using an Arduino Uno.

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

//START:variables
int ledPin        = 13;  // on board LED
int inputPin      = 12;  // input pin for the PIR sensor
int pirStatus     = LOW; // set to LOW (no motion detected)
int pirValue      = 0;   // variable for reading inputPin status
//END:variables


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


// 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
  pinMode(ledPin, OUTPUT);   // set pinMode of the onboard LED to OUTPUT
  pinMode(inputPin, INPUT);  // set PIR inputPin and listen to it as INPUT
  Serial.begin(9600);

  
  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);
 
  //  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!");

}


//////////////////////////////////// LOOP//START:main_loop
void loop() {
  pirValue = digitalRead(inputPin); // poll the value of the PIR
  if (pirValue == HIGH) {          // If motion is detected
    digitalWrite(ledPin, HIGH);  	// turn the onboard LED on
    if (pirStatus == LOW) {			// Trigger motion
      Serial.println("Motion detected");
      
playcomplete("1.wav");  
    }

      delay(1000);          // wait a second

      pirStatus = HIGH;     // set the pirStatus flag to HIGH to stop
                            // repeating motion
    }
   else {
    digitalWrite(ledPin, LOW); // turn the onboard LED off
    if (pirStatus == HIGH){
      Serial.println("No motion");
      pirStatus = LOW;      // set the pirStatus flag to LOW to 
                            // prepare it for a motion event
    }
  }
}
//END:main_loop

/////////////////////////////////// HELPERS



// 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();
}

Thanks for your help !!

I just found my solution, the code above works well if I comment this line :

  // enable optimize read - some cards may timeout. Disable if you're having problems
 // card.partialBlockRead(true);

I'd like to use the code above to do a similar task. I have an UNO, a WaveShield, and a PIR sensor (CP 0210). I want the sensor to go off when someone walks close, a sample to play through to completion, and then for it to pause only for 10 seconds or so, and then be ready to play again if the sensor is active (I think HI, is the right term).

I took the code above and only changed the pin number to 8. The sensor always fires a second after a reset is pressed on the WaveShield, but then it won't play again for another few minutes--even if there is motion in front of the sensor--sometimes up to 3 or 4 minutes. But, at some unknown time in the future, it will play the sample as soon as the sensor is activated.

Is there something I can do to the code to make this action more consistent? Can I make it actively wait after a full play of the audio, and then actively be ready to fire again? If so, I'm not sure how to approach coding this, so any help will be much appreciated.

I know how to hack some of this code (as I'm used to doing it with javascript for website plugins), but I don't know how to write it from scratch.

Thanks in advance! Here's the code I'm using, which is only slightly modified from what is posted above.

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

//START:variables
int ledPin        = 13;  // on board LED
int inputPin      = 8;  // input pin for the PIR sensor
int pirStatus     = LOW; // set to LOW (no motion detected)
int pirValue      = 0;   // variable for reading inputPin status
//END:variables


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


// 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
  pinMode(ledPin, OUTPUT);   // set pinMode of the onboard LED to OUTPUT
  pinMode(inputPin, INPUT);  // set PIR inputPin and listen to it as INPUT
  Serial.begin(9600);

  
  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);
 
  //  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!");

}


//////////////////////////////////// LOOP//START:main_loop
void loop() {
  pirValue = digitalRead(inputPin); // poll the value of the PIR
  if (pirValue == HIGH) {          // If motion is detected
    digitalWrite(ledPin, HIGH);  	// turn the onboard LED on
    if (pirStatus == LOW) {			// Trigger motion
      Serial.println("Motion detected");
      playcomplete("1.WAV");  
    }

      delay(1000);          // wait a second

      pirStatus = HIGH;     // set the pirStatus flag to HIGH to stop
                            // repeating motion
    }
   else {
    digitalWrite(ledPin, LOW); // turn the onboard LED off
    if (pirStatus == HIGH){
      Serial.println("No motion");
      pirStatus = LOW;      // set the pirStatus flag to LOW to 
                            // prepare it for a motion event
    }
  }
}
//END:main_loop

/////////////////////////////////// HELPERS



// 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();
}