code for PIR sensor & WaveShield

:)Hello to all!! I'm taxed with any ideas how to get these two things to work together and would love some help with it before my brain boils over!
Basically I'm looking to use my PIR sensor to start a wav file on my WaveShield- here's my code so far......it's hashed from two different codes!

#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"
#define SkattyKan Wavs 1 1.wav "SkattyKan Wavs 1 1.wav"
int pirPin = 8;

AF_Wave card;
File f;
Wavefile wave;

void setup() {
// set up serial port
Serial.begin(9600);
digitalWrite(pirPin, LOW);
pinMode(pirPin=8, INPUT); //Sensor 1

// set up waveshield pins
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
}

void loop() {
if(digitalRead(pirPin) == HIGH){
pinMode(pirPin=8, INPUT);
playcomplete("SkattyKan Wavs 1 1.wav");
}

}

void playcomplete(char *name) {
playfile(name);
while (wave.isplaying);
card.close_file(f);
}

void playfile(char *name) {
// stop any file already playing
if (wave.isplaying) {
wave.stop();
card.close_file(f);
}

f = card.open_file(name);
if (f && wave.create(f)) {
wave.play();
}
}

I would be happy enough to get a wav to play when motion is detected! Thanks, Goatboy

The button examples at ladyada use switch/case. This is a straightforward way to use a single input. This example is for a button push that goes LOW, your PIR probably goes HIGH with motion.

#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"

AF_Wave card;
File f;
Wavefile wave;

int inputPin = 16;
int ledPin = 6;
int val = 0;

void setup() {

digitalWrite(inputPin, HIGH); //set internal pull up resistor
pinMode(ledPin, OUTPUT);

// set up waveshield pins
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);

// open memory card
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;
}
}

void loop() {
val = digitalRead(inputPin); // read input value
if (val == LOW) { // check if the input is LOW
digitalWrite(ledPin, HIGH); // turn LED ON
playcomplete("1.WAV");
} else {
digitalWrite(ledPin, LOW); // turn LED OFF
}
}

void playcomplete(char *name) {
playfile(name);
while (wave.isplaying);
card.close_file(f);
}

void playfile(char *name) {
// stop any file already playing
if (wave.isplaying) {
wave.stop();
card.close_file(f);
}

f = card.open_file(name);
if (f && wave.create(f)) {
wave.play();
}
}

Very good Doctor Wang! ;D I managed to hash some of that switching code already and got some interesting results :slight_smile: but it seems that with mine and yours the wav is repeated several times for each sensed movement! I threw in a delay and this cleared it up better but not perfect! It works better after a single Wav! I wonder like buttons do you have to use some debouncing as well :-?
I like the switching and it seems easy enough now but do you have any ideas on how to set off a different Wav with each motion sensed? :slight_smile: Goatboy ``#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"
int pirPin=6; // Reading from digital pin 6 PIR sensor!

AF_Wave card;
File f;
Wavefile wave;

void setup() {
// set up serial port
Serial.begin(9600);
pinMode(pirPin, INPUT);
digitalWrite(pirPin, LOW);

// set up waveshield pins
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6,INPUT);

// open memory card...........This part is necessary to set up and read SDcard!
if (!card.init_card()) {
return;
}
if (!card.open_partition()) {
return;
}
if (!card.open_filesys()) {
return;
}
if (!card.open_rootdir()) {
return;
}
}

void loop() {
switch(digitalRead(pirPin) == HIGH){

case 1:
playcomplete("0.WAV");

playcomplete("2.WAV");

playcomplete("3.WAV");
delay(3000);

break;
case 4:
playcomplete("4.WAV");
break;
case 5:
playcomplete("5.WAV");
break;
case 6:
playcomplete("6.WAV");
}
}

void playcomplete(char *name) {
playfile(name);
while (wave.isplaying);
card.close_file(f);
}

void playfile(char *name) {
// stop any file already playing
if (wave.isplaying) {
wave.stop();
card.close_file(f);
}

f = card.open_file(name);
if (f && wave.create(f)) {
wave.play();
}
}
Does anyone know if you must include some code to calibrate the sensor to optimize it?

Based on the code that Dr. Wang provided (saw this code first on Adafruit and attributed it to goatboy when I asked for help), and with the help of a friend, I am trying to create a project where a the sound is on by default, and then goes off when someone triggers a PIR sensor. This will be part of a sculpture containing a porcelain bird, and I want to have a speaker playing birdsong that shuts off when someone comes close. I want it to seem as if the bird was frightened, and stopped singing, and then I want it to start up again if the person either moves far enough away, or holds still long enough to let the sensor reset.

Some other issues: To make this seem more realistic, I want to have a set of maybe 20 wav files, including some with no sound at all (as pauses), and I want them to play in random order. I also want to make sure no sounds are cut off, so they will need to play to the end, even when a signal to stop has been received from the PIR, and for this reason they will also be very short, so the system can respond quickly.

To be as specific as possible, here are the things I want the code to do:
1-Play wav files continuously unless the PIR is triggered
2-Play the wave files randomly (they could be named simply as sequential numbers, if that would help)
3-Play out the current wav file once the PIR signal is received, and then stop.
4-Allow a setting in the code to be adjusted to control how long the bird waits before singing again (ideally, this could be set as a random length of time, within a certain range)

Thanks in advance to anyone who is willing to help!

#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"
int pirPin = 8; // Reading from digital pin 8 PIR sensor!
int pirPinValue = 0; //variable to hold the digital value
AF_Wave card;
File f;
Wavefile wave;

void setup() {
// set up serial port
Serial.begin(9600);
pinMode(pirPin, INPUT);

// set up waveshield pins
pinMode(8, INPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);

// open memory card...........This part is necessary to set up and
read SDcard!
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);
}
}

void loop(){

pirPinValue = digitalRead(pirPin); // read the digital input on pin 8;
Serial.println(pirPinValue, DEC); // print input of digital in 8;
delay(10); // delay 10 ms before next reading;

while (LOW==digitalRead(pirPin)) {;}
playcomplete("HOODED~1.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("BLUEBIRD.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("BOBWHITE.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("CARDINAL.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("GOLDFINCH.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("INDIGOBUNTING.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("OWL.WAV");
delay(1500);

while (LOW==digitalRead(pirPin)) {;}
playcomplete("REDWINGED.WAV");
delay(1500);
}

void playcomplete(char *name){

playfile(name);
while (wave.isplaying);
card.close_file(f);
}

void playfile(char *name) {
// stop any file already playing
if (wave.isplaying) {
wave.stop();
card.close_file(f);
}

f = card.open_file(name);
if (f && wave.create(f)) {
wave.play();
}
}

To be as specific as possible, here are the things I want the code to do:
1-Play wav files continuously unless the PIR is triggered

It appears as though this code already does this.

2-Play the wave files randomly (they could be named simply as sequential numbers, if that would help)

Generate a random number. Then, use a switch statement.

int songCount = 12; // Or, however many you have
int songNumber = random(songCount+1);
switch(songNumber)
{
   case 0:
     // Play a song
     break;
   case 1:
     // Play a different song
     break;
   // Add a case for each song
}

3-Play out the current wav file once the PIR signal is received, and then stop.

The first part of this is done by playcomplete. The second part is done by these statements:

while (LOW==digitalRead(pirPin)) {;}

4-Allow a setting in the code to be adjusted to control how long the bird waits before singing again (ideally, this could be set as a random length of time, within a certain range)

Replace delay(1500); with a delay based on a random number. The random function is overloaded. One variation takes two values - the minimum value, which you could set to maybe 250, and a maximum value, which you could set to maybe 2500.

I have done something similar. Using a MaxSonar EZ1, WAV Shield and photocell to act like a doorbell. If triggered it plays a random sound and if dark enough turns on a light (7 leds). I also put in the suggestion from PaulS to use case switching to play random files - works great.
Here is my code if helpful to anyone.

// Using WAV shield and MaxSonar EZ1 to act like a doorbell.
// led light and photocell light level test to turn light on when dark.
// Added timer

#include <AF_Wave.h>
#include <avr/pgmspace.h>
#include "util.h"
#include "wave.h"
#define ledPin 7
#include <MsTimer2.h>
boolean intTimer;
int i;
int y=0;
int distsensor=0;
int pread=0;
int county=0;
int counttime=0;
int prevcounttime=0;
int lo=0;
int photocellPin = 0;
int photocellReading;
int songCount = 6; // Or, however many you have

AF_Wave card;
File f;
Wavefile wave;      // only one!
#define redled 9
uint16_t samplerate;

void setup() {
  Serial.begin(9600);    
  Serial.println("Wave test!");
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(redled, OUTPUT);
  randomSeed(analogRead(0));

  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() { 
  county++
   if(true == intTimer) {
     digitalWrite(ledPin, HIGH); // turn light off after timer reaches end
   intTimer = false;
   county=0;
   lo=0;
   }

  for (i=0; i<5; i++) {            // read Max1 sensor 6 times and average.
    distsensor += analogRead(5);
    delay(5);
  }
  distsensor /= 6;

  delay(5);

  if (pread > (distsensor +8))// If true then something passed by.... trigger effects
  {
    if (y!=1 || prevcounttime +50 <= counttime)// Ignore first time through as sensors stabilize 
    {
      y=1;
      delay(10);
    }
    lo =1;
    lights();
    prevcounttime=counttime;
    counttime=0;

    int songNumber = random(songCount+1);
    Serial.println(songNumber);
    switch(songNumber)
{
   case 1:
     playcomplete("1MEMO.WAV");
     break;
   case 2:
     playcomplete("SOUND1.WAV");
     break;
   case 3:
    playcomplete("SOUND2.WAV");
     break;
   case 4:
    playcomplete("SOUND3.WAV");
     break;
   case 5:
    playcomplete("SOUND4.WAV");
     break;
   case 6:
    playcomplete("SOUND5.WAV");
     break;
} 

    delay(5);
  }
  pread=distsensor;
  counttime++;
  if (counttime >=50000)
  {
    counttime=0;
  }

}

void playcomplete(char *name) {
  uint16_t potval;
  uint32_t newsamplerate;
  tracknum++;
  playfile(name);
  Serial.write ("Playing ");
  Serial.write(name);
Serial.println("");
  samplerate = wave.dwSamplesPerSec;
  while (wave.isplaying) {     
    // you can do stuff here!
    //  delay(5);
  }
  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();

}

void lights () //test for light level.  If dark enough then turn on light.
{
  //photocellReading = analogRead(photocellPin); 
  Serial.print("Photocell reading = ");
  Serial.println(photocellReading);
  MsTimer2::set(15000, timerISR); // 60000ms/1min period
  MsTimer2::start();
  if (photocellReading<=100) // adjust number if not right
  {
  digitalWrite(ledPin, LOW);
  }
  else
  {
   digitalWrite(ledPin, HIGH); 
  }
 
}

void timerISR() {
       intTimer = true;
    }

One thing to maybe look at. The random function returns an integer value between 0 and 1 less than the input value, when called with one argument. You added one to song count, so the values returned will be between 0 and song count. You don't have a case statement for 0.

I have the wav shield and a ping and I was dying trying to figure out a code similar to this (my first intermediate project). I want to take, basically the codes the first guy was working with, but i want it to play the first song and then after that loop the second, within 137 and 100 inches, and as the distance gets smaller, the volume is increased. Anyone have any code that would help me do that?