The new Raspberry Pi B Model B+ is here - Pick one up in the store and check our detailed guide!

PIR sensor and wave shield - Code problem.

by ch_91 on Thu Apr 19, 2012 6:31 am

Hello,
I've hooked up a PIR motion sensor with my wave shield and I've got it working using the 6 button sketch, and just adding the sensor instead of a button. I then added some 'random' code in so that when motion is detected one of the 6 sounds are randomly selected. The problem is when I upload the code and motion is detected it plays the songs in a certain way. E.g. song 3, then song 5, etc...

So the code is not really playing a random song every time. Does anybody know where I have went wrong please? Here is the code:

Code: Select all | TOGGLE FULL SIZE
#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

uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
dir_t dirBuf;     // buffer for directory reads

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

// for PIR
  int inputPin = 14;               // choose the input pin (for PIR sensor)
  int pirState = LOW;             // we start, assuming no motion detected
  int val = 0;                    // variable for reading the pin statu

#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);

  //  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("OLDPIN.WAV");
      break;
    case 2:
      playcomplete("JCBSNG.WAV");
      break;
    case 3:
      playcomplete("INEDNS.WAV");
      break;
    case 4:
      playcomplete("LLMAFS.WAV");
      break;
    case 5:
      playcomplete("SKLEBI.WAV");
      break;
    case 6:
      playcomplete("DOTPAL.WAV");
  }
}

byte check_switches()
{
  if (digitalRead(14) == HIGH)  // check for high signal on pin 14 (analog 0)
    {
       return random(1,6);
    }
  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();
}
ch_91
 
Posts: 6
Joined: Thu Apr 19, 2012 6:09 am

Re: PIR sensor and wave shield - Code problem.

by adafruit_support_bill on Thu Apr 19, 2012 6:46 am

That is because "random" is a 'pseudorandom' number generator. The distribution of numbers is approximately random, but the behavior of the generator is very deterministic. What you need to do is to introduce a random seed to get the generator to start in a different place.
http://arduino.cc/hu/Reference/RandomSeed
User avatar
adafruit_support_bill
 
Posts: 28001
Joined: Sat Feb 07, 2009 9:11 am

Re: PIR sensor and wave shield - Code problem.

by ch_91 on Thu Apr 19, 2012 2:32 pm

Thank you for the reply and the advice.

Arduino coding is very new to me and I'm struggling to find a way to get the randomSeed code into my existing code. Any help on the code if possible please?

I know I should really learn the code I just don't know where to start.

Thanks once again.
ch_91
 
Posts: 6
Joined: Thu Apr 19, 2012 6:09 am

Re: PIR sensor and wave shield - Code problem.

by adafruit_support_bill on Thu Apr 19, 2012 3:27 pm

Just add a call to "randomSeed(analogRead(0))" in your setup function exactly as shown in the Example on the reference page.
(If you are using analog pin 0 for something already, just substitute any unused analog pin number for the random seed)
User avatar
adafruit_support_bill
 
Posts: 28001
Joined: Sat Feb 07, 2009 9:11 am

Re: PIR sensor and wave shield - Code problem.

by ch_91 on Fri Apr 20, 2012 8:36 am

Thank you for all the help.

I've just added a LED sensor also as I feel like pushing the boat out. As I want the LED to blink when the audio is playing. Could you possible point me in the right direction as to where I could find some code or a tutorial to help me with this?

Thanks.
ch_91
 
Posts: 6
Joined: Thu Apr 19, 2012 6:09 am

Re: PIR sensor and wave shield - Code problem.

by adafruit_support_bill on Fri Apr 20, 2012 8:51 am

Lady Ada's Arduino Tutorial Lesson 1 is a good place to start. Once you have mastered the led by itself, have a look at the Halloween Pumpkin project. That one shows how to blink the led while the sound is playing.
User avatar
adafruit_support_bill
 
Posts: 28001
Joined: Sat Feb 07, 2009 9:11 am

Re: PIR sensor and wave shield - Code problem.

by ch_91 on Sun Apr 22, 2012 11:34 am

I've added some extra code in so when the sensor senses motion the LED comes on aswell but it comes up with errors. I've probably done the code wrong but I don't know what part.

Heres the code I added:

val = digitalRead(pirState); //read input and store it

//check whether the input is HIGH
if (val ==HIGH) {
digitalWrite(ledPin, HIGH); // Turns the LED on
if (pirState == HIGH) {

} else {
digitalWrite(ledPin, LOW); // turns the LED off
if (pirState == LOW) {


And the errors I get is:

Draft.cpp: In function 'void loop()':
Draft:147: error: a function-definition is not allowed here before '{' token
Draft:182: error: expected `}' at end of input
Draft:182: error: expected `}' at end of input
Draft:182: error: expected `}' at end of input


Theres my full sketch if you need it as well:

Code: Select all | TOGGLE FULL SIZE
#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

uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
dir_t dirBuf;     // buffer for directory reads

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

// for PIR
  int ledPin = 16;                 // choose the pin for the LED
  int inputPin = 14;               // choose the input pin (for PIR sensor)
  int pirState = LOW;             // we start, assuming no motion detected
  int val = 0;                    // variable for reading the pin status
 
#define LED 16  // LED connected to
                // digital pin 16

#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");
  randomSeed(analogRead(1));
 
   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);
 
  pinMode(16, OUTPUT);
  digitalWrite(16, HIGH);
 
  pinMode(LED, OUTPUT);   // sets the digital
                            // pin at 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("OLDPIN.WAV");
      break;
    case 2:
      playcomplete("JCBSNG.WAV");
      break;
    case 3:
      playcomplete("INEDNS.WAV");
      break;
    case 4:
      playcomplete("LLMAFS.WAV");
      break;
    case 5:
      playcomplete("SKLEBI.WAV");
      break;
    case 6:
      playcomplete("DOTPAL.WAV");
 
 val = digitalRead(pirState); //read input and store it
 
 //check whether the input is HIGH
 if (val ==HIGH) {
  digitalWrite(ledPin, HIGH);  // Turns the LED on
  if (pirState == HIGH) {
   
 } else {
  digitalWrite(ledPin, LOW);   // turns the LED off
  if (pirState == LOW) {

  }
}

byte check_switches()
{
  if (digitalRead(14) == HIGH)  // check for high signal on pin 14 (analog 0)
    {
       return random(1,6);
    }
  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();
}
ch_91
 
Posts: 6
Joined: Thu Apr 19, 2012 6:09 am

Re: PIR sensor and wave shield - Code problem.

by pburgess on Sun Apr 22, 2012 12:38 pm

Looks like you're missing a closing bracket on your loop() function. You may want to indent the new code you added (for clarity), then add an extra '}' at the end.
User avatar
pburgess
 
Posts: 2426
Joined: Sun Oct 26, 2008 1:29 am

Re: PIR sensor and wave shield - Code problem.

by ch_91 on Sun Apr 22, 2012 12:57 pm

Thanks for the reply.

I think I'm a idiot lol. I can't see where this bracket is supposed to go.
ch_91
 
Posts: 6
Joined: Thu Apr 19, 2012 6:09 am

Re: PIR sensor and wave shield - Code problem.

by adafruit_support_bill on Sun Apr 22, 2012 5:11 pm

Looks like several missing closing brackets. Remember that for every '{' there needs to be a '}'. The appropriate location depends on what you want the code to do.

As PBurgess notes, indenting your code consistently with conditional statements and switch statements makes it easier to see both the logical structure and where the brackets need to go.
User avatar
adafruit_support_bill
 
Posts: 28001
Joined: Sat Feb 07, 2009 9:11 am

Re: PIR sensor and wave shield - Code problem.

by ch_91 on Tue Apr 24, 2012 7:02 am

Such a little mistake can make a big difference, thank you for your assistance.

One more thing (I promise) I put this code in so when the sensor senses motion then it turns on and then off when theres no motion but the LED is constantly on still. I know I've done the code wrong but can't seem to get to grips with where.

Code: Select all | TOGGLE FULL SIZE
val = digitalRead(pirState); //read input and store it

//check whether the input is HIGH
if (val ==HIGH) {
  digitalWrite(ledPin, HIGH);  // Turns the LED on
  if (pirState == HIGH) {
   
} else {
  digitalWrite(ledPin, LOW);   // turns the LED off
  if (pirState == LOW) {


Once again all advice I appreciate!
ch_91
 
Posts: 6
Joined: Thu Apr 19, 2012 6:09 am

Re: PIR sensor and wave shield - Code problem.

by adafruit_support_bill on Tue Apr 24, 2012 7:11 am

A couple problems here:
Code: Select all | TOGGLE FULL SIZE
val = digitalRead(pirState); //read input and store it

"pirState" is not a pin number. I think you want:
Code: Select all | TOGGLE FULL SIZE
val = digitalRead(inputPin); //read input and store it


Code: Select all | TOGGLE FULL SIZE
if (val ==HIGH) {
  digitalWrite(ledPin, HIGH);  // Turns the LED on
  if (pirState == HIGH) {
   
} else {
  digitalWrite(ledPin, LOW);   // turns the LED off
  if (pirState == LOW) {


You only need the first 'if' here.
User avatar
adafruit_support_bill
 
Posts: 28001
Joined: Sat Feb 07, 2009 9:11 am