SRF 05 Sonic Range finder to Rogue RMP3 via Arduino

Hello,

I am currently working on a project - the aim of which is to detect when a person walks within 2m of a sensor ( SRF 05 ) and upon detection of the person I want to trigger the playback of an MP3 file from the Rogue Rmp3. The file should play through completely then stop. Then if a person is still within range, play the next file. There is a total of 5 files.

I imagine I need to make arduino read the SRF 05 data and when it gets the right 'figure' to send a command to the Rmp3?

Is this correct?

Can anyone give a an idea of how to start writing this code ?

Many Thanks
Twogan

The SRF04 is a virtually similar product, and I think a search would throw up some example code on how to drive it.

Edit: On second thoughts, the SRF05 looks more like a Ping than an SRF04.

Thanks Awol

The code I am using to run the SRF05 is :

int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05

void setup(){
Serial.begin(9600);
}

void loop(){
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
  Serial.println(distance);
  delay(50);                           // Wait before looping to do it again
}

I have also run the playback example code for my rmp3 shield and it is working.

I am trying to use the 'rmp3 trigger with delay code' as a starting point for my project:

I want to integrate the SRF05 to act as the trigger for the mp3 playback.

I have hacked these 2 pieces of code together, and added this in the loop:
if (distance < 20)
digitalWrite(INPUT_PIN, HIGH);

heres the mashed together code:

/******************************************
rMP3 Trigger with Time-Out Example
 
rMP3 Control Requirements
* Play songs in order when trigger is set.
* If trigger clears, start timer and stop
  playback if timer runs out.
 
Assumptions
* When timer runs out, playback starts
  at the beginning.
* Playback will continue if trigger re-sets
  before timer runs out.
 
******************************************/
 
#include <RogueSD.h>
#include <RogueMP3.h>
#include <NewSoftSerial.h>
 
// 30 second timeout
#define TIMER_MAX 30000
#define INPUT_PIN 8
 
// Objects
NewSoftSerial rmp3_serial(6, 7);
 
RogueMP3 rmp3(rmp3_serial);
RogueSD filecommands(rmp3_serial);
 
// global variables
int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05

int numberOfSongs;
int currentSong = 0;
boolean triggered = false;
boolean playing = false;
uint32_t triggerTimer = 0xffffffff - TIMER_MAX;
char filePath[96];
 
// consts
const char *directory = "/";
 
void setup()
{
  
  
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
  Serial.println(distance);
  delay(50);   
  
  
  pinMode(INPUT_PIN, INPUT);
  digitalWrite(INPUT_PIN, HIGH);
 
  
  Serial.begin(9600);
 
  rmp3_serial.begin(9600);
 
  // synchronize audio player
  rmp3.sync();
  rmp3.stop();
 
  // synchronize file system controller
  filecommands.sync();
 
  Serial.println("rMP3 Synchronized.");
 
  // get the number of songs available
  strcpy(filePath, directory);
  strcat(filePath, "/");
  strcat(filePath, "*.mp3");
 
  numberOfSongs = filecommands.filecount(filePath);
 
  if (numberOfSongs < 0)
  {
    // rMP3 error
    if (filecommands.LastErrorCode == 8)
      Serial.println("No card inserted.");
    else
    {
      Serial.print("rMP3 Error Code: ");
      Serial.println(filecommands.LastErrorCode, HEX);
    }
 
    Serial.println("Reset required to continue.");
    for (;;);
  }
 
  Serial.print(numberOfSongs, DEC);
  Serial.println(" files available.");
 
  // rewind directory
  filecommands.opendir(directory);
 
  Serial.println("Awaiting trigger.");
}
 
 
// Play next song, if we can
void playNextSong()
{
  char filename[80];
 
  if (playing == true)
  {
    if (filecommands.status() == 0)
    {
      // card is inserted and good to go
      if (currentSong == 0)
      {
        // rewind directory
        filecommands.opendir(directory);
      }
 
      if (currentSong < numberOfSongs)
      {
        // get the next song
        filecommands.readdir(filename, "*.mp3");
 
        rmp3.playfile(directory, filename);
 
        Serial.print("Playing: ");
        Serial.print(directory);
        Serial.print('/');
        Serial.println(filename);
 
        currentSong++;
      }
      else
      {
        playing = false;
        currentSong = 0;
      }
    }
    else
    {
      if (filecommands.LastErrorCode == 8)
      {
        Serial.println("No card inserted.");
      }
      else
      {
        Serial.print("rMP3 Error Code: ");
        Serial.println(filecommands.LastErrorCode, HEX);
      }
 
      Serial.println("Reset required to continue.");
      for (;;);
    }
  }
}
 


// This is the function to check the input
boolean checkTrigger(void)
{
  if (digitalRead(INPUT_PIN) == HIGH)
    return true;
  else
    return false;
}
 
 
/******************************************
Main loop
******************************************/
 
void loop()
{
  char rMP3Status = rmp3.getplaybackstatus();
 if (distance < 20)
digitalWrite(INPUT_PIN, HIGH);
  // First, check the trigger
  if (checkTrigger())
  {
    if (triggered == false)
    {
      Serial.println("Trigger set.");
      if (playing == false)
      {
        // Start from the top
        playing = true;
        currentSong = 0;
      }
    }
    triggered = true;
  }
  else
  {
    if (triggered == true)
    {
      Serial.println("Trigger cleared.");
 
      triggered = false;
      triggerTimer = millis();
    }
    else
    {
      if ((millis() - triggerTimer) > TIMER_MAX)
      {
        if (playing == true)
        {
          playing = false;
          Serial.println("Playback stopped.");
        }
 
        if (rMP3Status == 'P')
        {
          // stop playback
          rmp3.stop();
        }
      }
    }
  }
 
  if (triggered == true || ((millis() - triggerTimer) < TIMER_MAX))
  {
    if (rMP3Status != 'P')
      playNextSong();
  }
 
  // Arbitrary delay
  delay(250);
}

When I run it, the activity light on the rmp3 flashes 3 times quickly and goes off. In the serial monitor I see :

rpm3 synchronised
3 files available
Trigger set
Playing // Snake Awake.mp3
Playing // Track 2.mp3
Playing// Track3.mp3

These are the 3 tracks on my sd card. It seems to begin playing the track then skips instantly on to the next and so on until it stops.
I hear no audio.

Can anyone help ?

Many Thanks
Twogan

 if (distance < 20)
digitalWrite(INPUT_PIN, HIGH);

If the distance (read only in setup) is less than 20, write to INPUT_PIN. Is that just a poor choice of names, or a mistake?

Why is distance only read once?

  if (digitalRead(INPUT_PIN) == HIGH)

You really should decide whether INPUT_PIN is an INPUT or an OUTPUT.

A few more Serial.println() statements would show you the flow through the program. More functions would be useful, too.

Thanks for the reply.

I used the name INPUT_PIN for digital pin 8 as I thought it was named that way at the beginning of the code I got from the RMP3 website :

#define INPUT_PIN 8

I am reading the srf05 on pin 3 (combined TX / RX mode). This is converted to centimeters. I am then asking the program to check that number and if its less than 20cm ( is going to be 200cm but 20 is easier to test for now) then make Pin 8 go high. This then supposed to start the playback...

Distance needs to be read and checked every loop of course. I'm not really sure which code to put in the loops section to achieve this?

Is this all woefully inadequate, or am I on the right lines ??? or both...

Thanks
Caleb

Look at your code in the setup() function:

  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm

Put this code in a function:

void getDistance()
{
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
}

Now, call this function whenever you want the sensor to report a distance:

void loop()
{
   getDistance();
   if(distance < 20)
   {
      // victim is close... play some scary music

Of course, you still need to make sure you don't start playing while a song is already playing, etc.

Thanks you very much this is really helping me to understand.

ok before I read you last post I thought about what you had said previously.

I put the distance measurement in the main loop and changed pin 8 to an output.

I also set the pin as low, therefore it waits till someone in range to go high and start playback.

It runs well and serial monitor is promising - says 'trigger set' when I wave my hand in front of it and says it is playing the track. All good. Big step forward.

/******************************************
rMP3 Trigger with Time-Out Example
 
rMP3 Control Requirements
* Play songs in order when trigger is set.
* If trigger clears, start timer and stop
  playback if timer runs out.
 
Assumptions
* When timer runs out, playback starts
  at the beginning.
* Playback will continue if trigger re-sets
  before timer runs out.
 
******************************************/
 
#include <RogueSD.h>
#include <RogueMP3.h>
#include <NewSoftSerial.h>
 
// 30 second timeout
#define TIMER_MAX 30000
#define triggerout 8
 
// Objects
NewSoftSerial rmp3_serial(6, 7);
 
RogueMP3 rmp3(rmp3_serial);
RogueSD filecommands(rmp3_serial);
 
// global variables
int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05

int numberOfSongs;
int currentSong = 0;
boolean triggered = false;
boolean playing = false;
uint32_t triggerTimer = 0xffffffff - TIMER_MAX;
char filePath[96];
 
// consts
const char *directory = "/";
 
void setup()
{
  
  
  
  
  pinMode(triggerout, OUTPUT);
 // digitalWrite(INPUT_PIN, LOW);
 
  
  Serial.begin(9600);
 
  rmp3_serial.begin(9600);
 
  // synchronize audio player
  rmp3.sync();
  rmp3.stop();
 
  // synchronize file system controller
  filecommands.sync();
 
  Serial.println("rMP3 Synchronized.");
 
  // get the number of songs available
  strcpy(filePath, directory);
  strcat(filePath, "/");
  strcat(filePath, "*.mp3");
 
  numberOfSongs = filecommands.filecount(filePath);
 
  if (numberOfSongs < 0)
  {
    // rMP3 error
    if (filecommands.LastErrorCode == 8)
      Serial.println("No card inserted.");
    else
    {
      Serial.print("rMP3 Error Code: ");
      Serial.println(filecommands.LastErrorCode, HEX);
    }
 
    Serial.println("Reset required to continue.");
    for (;;);
  }
 
  Serial.print(numberOfSongs, DEC);
  Serial.println(" files available.");
 
  // rewind directory
  filecommands.opendir(directory);
 
  Serial.println("Awaiting trigger.");
}
 
 
// Play next song, if we can
void playNextSong()
{
  char filename[80];
 
  if (playing == true)
  {
    if (filecommands.status() == 0)
    {
      // card is inserted and good to go
      if (currentSong == 0)
      {
        // rewind directory
        filecommands.opendir(directory);
      }
 
      if (currentSong < numberOfSongs)
      {
        // get the next song
        filecommands.readdir(filename, "*.mp3");
 
        rmp3.playfile(directory, filename);
 
        Serial.print("Playing: ");
        Serial.print(directory);
        Serial.print('/');
        Serial.println(filename);
 
        currentSong++;
      }
      else
      {
        playing = false;
        currentSong = 0;
      }
    }
    else
    {
      if (filecommands.LastErrorCode == 8)
      {
        Serial.println("No card inserted.");
      }
      else
      {
        Serial.print("rMP3 Error Code: ");
        Serial.println(filecommands.LastErrorCode, HEX);
      }
 
      Serial.println("Reset required to continue.");
      for (;;);
    }
  }
}
 


// This is the function to check the input
boolean checkTrigger(void)
{
  if (digitalRead(triggerout) == HIGH)
    return true;
  else
    return false;
}
 
 
/******************************************
Main loop
******************************************/
 
void loop()
{
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
  Serial.println(distance);
  delay(50);   
  if (distance < 20)
digitalWrite(triggerout, HIGH);

  char rMP3Status = rmp3.getplaybackstatus();
 
  // First, check the trigger
  if (checkTrigger())
  {
    if (triggered == false)
    {
      Serial.println("Trigger set.");
      if (playing == false)
      {
        // Start from the top
        playing = true;
        currentSong = 0;
      }
    }
    triggered = true;
  }
  else
  {
    if (triggered == true)
    {
      Serial.println("Trigger cleared.");
 
      triggered = false;
      triggerTimer = millis();
    }
    else
    {
      if ((millis() - triggerTimer) > TIMER_MAX)
      {
        if (playing == true)
        {
          playing = false;
          Serial.println("Playback stopped.");
        }
 
        if (rMP3Status == 'P')
        {
          // stop playback
          rmp3.stop();
        }
      }
    }
  }
 
  if (triggered == true || ((millis() - triggerTimer) < TIMER_MAX))
  {
    if (rMP3Status != 'P')
      playNextSong();
  }
 
  // Arbitrary delay
  delay(250);
}

My problem now, as you point out, is that I am sending to many play commands and this seems to be skipping through the tracks at each loop.. can I just put a big delay in somewhere...?

I will change it to use your latest code, and see how it goes,

thank you

heres the latest code

/******************************************
rMP3 Trigger with Time-Out Example
 
rMP3 Control Requirements
* Play songs in order when trigger is set.
* If trigger clears, start timer and stop
  playback if timer runs out.
 
Assumptions
* When timer runs out, playback starts
  at the beginning.
* Playback will continue if trigger re-sets
  before timer runs out.
 
******************************************/
 
#include <RogueSD.h>
#include <RogueMP3.h>
#include <NewSoftSerial.h>
 
// 30 second timeout
#define TIMER_MAX 30000
#define triggerout 8
 
// Objects
NewSoftSerial rmp3_serial(6, 7);
 
RogueMP3 rmp3(rmp3_serial);
RogueSD filecommands(rmp3_serial);
 
// global variables
int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05

int numberOfSongs;
int currentSong = 0;
boolean triggered = false;
boolean playing = false;
uint32_t triggerTimer = 0xffffffff - TIMER_MAX;
char filePath[96];
 
// consts
const char *directory = "/";
  void getDistance()
{
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
} 
void setup()
{

  
  
  
  pinMode(triggerout, OUTPUT);
 digitalWrite(triggerout, LOW);
 
  
  Serial.begin(9600);
 
  rmp3_serial.begin(9600);
 
  // synchronize audio player
  rmp3.sync();
  rmp3.stop();
 
  // synchronize file system controller
  filecommands.sync();
 
  Serial.println("rMP3 Synchronized.");
 
  // get the number of songs available
  strcpy(filePath, directory);
  strcat(filePath, "/");
  strcat(filePath, "*.mp3");
 
  numberOfSongs = filecommands.filecount(filePath);
 
  if (numberOfSongs < 0)
  {
    // rMP3 error
    if (filecommands.LastErrorCode == 8)
      Serial.println("No card inserted.");
    else
    {
      Serial.print("rMP3 Error Code: ");
      Serial.println(filecommands.LastErrorCode, HEX);
    }
 
    Serial.println("Reset required to continue.");
    for (;;);
  }
 
  Serial.print(numberOfSongs, DEC);
  Serial.println(" files available.");
 
  // rewind directory
  filecommands.opendir(directory);
 
  Serial.println("Awaiting trigger.");
}
 
 
// Play next song, if we can
void playNextSong()
{
  char filename[80];
 
  if (playing == true)
  {
    if (filecommands.status() == 0)
    {
      // card is inserted and good to go
      if (currentSong == 0)
      {
        // rewind directory
        filecommands.opendir(directory);
      }
 
      if (currentSong < numberOfSongs)
      {
        // get the next song
        filecommands.readdir(filename, "*.mp3");
 
        rmp3.playfile(directory, filename);
 
        Serial.print("Playing: ");
        Serial.print(directory);
        Serial.print('/');
        Serial.println(filename);
 
        currentSong++;
      }
      else
      {
        playing = false;
        currentSong = 0;
      }
    }
    else
    {
      if (filecommands.LastErrorCode == 8)
      {
        Serial.println("No card inserted.");
      }
      else
      {
        Serial.print("rMP3 Error Code: ");
        Serial.println(filecommands.LastErrorCode, HEX);
      }
 
      Serial.println("Reset required to continue.");
      for (;;);
    }
  }
}
 


// This is the function to check the input
boolean checkTrigger(void)
{
  if (digitalRead(triggerout) == HIGH)
    return true;
  else
    return false;
}
 
 
/******************************************
Main loop
******************************************/
 
void loop()
{
  getDistance();
   
  if (distance < 20)
digitalWrite(triggerout, HIGH);

  char rMP3Status = rmp3.getplaybackstatus();
 
  // First, check the trigger
  if (checkTrigger())
  {
    if (triggered == false)
    {
      Serial.println("Trigger set.");
      if (playing == false)
      {
        // Start from the top
        playing = true;
        currentSong = 0;
      }
    }
    triggered = true;
  }
  else
  {
    if (triggered == true)
    {
      Serial.println("Trigger cleared.");
 
      triggered = false;
      triggerTimer = millis();
    }
    else
    {
      if ((millis() - triggerTimer) > TIMER_MAX)
      {
        if (playing == true)
        {
          playing = false;
          Serial.println("Playback stopped.");
        }
 
        if (rMP3Status == 'P')
        {
          // stop playback
          rmp3.stop();
        }
      }
    }
  }
 
  if (triggered == true || ((millis() - triggerTimer) < TIMER_MAX))
  {
    if (rMP3Status != 'P')
     playNextSong();
  }
 Serial.println(distance);
  // Arbitrary delay
  delay(250);
}

Just need to work out where I am going wrong with the play command. I seem to be sending play repeatedly, but from the code it looks like if the song is playing it will let it continue to play??

When I trigger the playback it still almost instantly plays all 3 files on the card then stops. I hear no audio because this all happens so fast.

Is it the Boolean logic in the loop or a problem with the setup?

I feel so close to making it work.....

You are going to a lot of trouble to make the program more complicated than it needs to be.

On every pass through loop(), read the distance. If it is less than 20 cm, do something. Else, do nothing:

void loop()
{
   getDistance();
   if(distance < 20)
   {
      // Everything happens here...
   }
}

So, create a function, makeSomeNoise() with a return type of void. In that function, see if a song is playing. If so, return. If not, start one playing.

I don't see that setting/reading a pin is necessary, or that the checkTrigger() function is useful. I also don't see that triggered is necessary. The distance is less than the threshold, or it isn't. The triggered flag is telling you the same thing. With two things telling you the same thing, the odds of keeping them in sync fall.

Forget about the eventual goal of stopping the music when there is no one around, for now. Get the music to play to completion, then trigger the next song, first.

Then, come back and add the timeout functionality (in makeSomeNoise()).

Many thanks for the continued support on this.

I have managed to make the sensor trigger the mp3 playback!

It was constantly restarting the track so I used 'while' with a delay :

#include <RogueSD.h>
#include <RogueMP3.h>
#include <NewSoftSerial.h>

NewSoftSerial rmp3_serial(6, 7);
RogueMP3 rmp3(rmp3_serial);
RogueSD filecommands(rmp3_serial);

int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05

int numberOfSongs;
int currentSong = 0;
boolean playing = false;
char filePath[96];

// consts
const char *directory = "/";
  void getDistance()
{
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
} 


void setup()
{
  
  
Serial.begin(9600);
 
  rmp3_serial.begin(9600);
 
  // synchronize audio player
  rmp3.sync();
  rmp3.stop();
 
  // synchronize file system controller
  filecommands.sync();
 
  Serial.println("rMP3 Synchronized.");
 
  // get the number of songs available
  strcpy(filePath, directory);
  strcat(filePath, "/");
  strcat(filePath, "*.mp3");
 
  numberOfSongs = filecommands.filecount(filePath);
}
  void loop()
{
  getDistance();
  
 if (distance < 20){
  rmp3.playfile("/Snake Awake.mp3");
  playing=true;
  }
while (playing == true){
  delay (10000);
}
   Serial.println(distance);
  // Arbitrary delay
  delay(250);
}

Basically it has a look to see if someone is in range, if yes, it plays the song, then it checks if the song is playing, if it is playing it waits 10 seconds to check again, hopefully if the song ends it goes back to range checking ( waits for the 10 minute mp3 to finish)...ahh no...

Still its a step closer....

Any tips ?

This, as you have no doubt discovered, is an infinite loop:

while (playing == true){
  delay (10000);
}

so it never goes back to scanning.

You can ask the device itself if it's still playing using getplaybackstatus(). If it is, don't even bother scanning for objects.

Many thanks for the help,

I have got rid of the while loop and put my play command in a function.

I have stripped all the extraneous code as far as I can tell.

It works so a person in range can trigger the playback - playback plays all the way through - at this point it stops if someone is out of range - then starts again if someone is within range.

Here is the code:

#include <RogueSD.h>
#include <RogueMP3.h>
#include <NewSoftSerial.h>

NewSoftSerial rmp3_serial(6, 7);
RogueMP3 rmp3(rmp3_serial);
RogueSD filecommands(rmp3_serial);

int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05

int numberOfSongs;
int currentSong = 0;
boolean playing = false;
char filePath[96];

// consts
const char *directory = "/";
  void getDistance()
{
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
} 
void playTrack ()
{
 char status;
 status = rmp3.getplaybackstatus ();
 if (status == 'P')
 {
 return;
 }
 else
 {
 rmp3.playfile("/Snake Awake.mp3");
 }
}
void setup()
{
 
Serial.begin(9600);
 
  rmp3_serial.begin(9600);
 
  // synchronize audio player
  rmp3.sync();
  rmp3.stop();
 
  // synchronize file system controller
  filecommands.sync();
 
  Serial.println("rMP3 Synchronized.");
 
  // get the number of songs available
  strcpy(filePath, directory);
  strcat(filePath, "/");
  strcat(filePath, "*.mp3");
 
  numberOfSongs = filecommands.filecount(filePath);
}
  void loop()
{
  getDistance();

  if (distance < 20){
 playTrack();
  }

   Serial.println(distance);
  // Arbitrary delay
  delay(250);
}

It would be good to now add back in a timer function so that playback is killed if someone is out of range for more than say, 10 seconds..

http://www.roguerobotics.com/wikidocs/code/rmp3_trigger_with_time-out_example

which parts of this do I need ? Is there a more simple way ?

Many Thanks

No, you don't need all that code. For a simple version, just store the time from millis every time you detect someone. Each iteration of loop, check whether the difference between millis now and that stored time is greater than your threshold. If it is, issue a stop() to the device.

Thanks for the suggestion. It does look like the right way to go, however implementing it was too hard for me! I have never used millis before....

I have decided just to let the tracks play through to the end.

I now just need to work out how to trigger the next track each time the sensor gets someone in range ?

At the moment I am triggering the specific audio file, but I need to trigger successive tracks on the card, and once the last one has played, play the first again, and so on.

I assume I need to understand the rmp3 file handling stuff, but I cant get my head round it...

Can anyone help ?

Many Thanks

Here's a crude way to handle the timeout, just replace your loop routine with this snippet:

#define DETECTION_THRESHOLD 10000UL
unsigned int LastDetectionTime=0;

void loop()
{
getDistance();

if (distance < 20)
  {
  LastDetectionTime=millis();
  playTrack();
  }
else if(millis()-LastDetectionTime > DETECTION_THRESHOLD)
  {
  rmp3.stop();
  }
   Serial.println(distance);
  // Arbitrary delay
  delay(250);
}

Not compiled, not tested. Note that it doesn't bother to check whether there is anything playing when the timeout is exceeded, it just issues a stop anyway. This means that in downtimes, the mp3 player is continually being ordered to stop. I assume this doesn't matter, but it is easily fixed if it does.

As to playing different tracks, you need to master the filesystem commands - I'll take a look later if someone hasn't already offered some hints.

Actually, it looks as though the playNextSong routine at the Rogue Robotics site will do what you need and I see you already have included their code to count the number of songs available. If you don't want the randomness, pull that code out and make nextSong a global. Then increment it every time you start playing & revert to 0 when you get to numberOfSongs-1;

Many Many Thanks wildbill.

I have added the millis code and it compiles OK! I will try running on the hardware later tonight. It makes it so much easier to understand when I see the code correctly written.

And many thanks for the suggestions about the playNextSong command. I had the track-counting code left in there from the MP3 trigger code I originally used as a start point.

OK I am going to try and digest what you say about making nextSong a global...etc. Please expand on this if you have the time...

Thanks again

I have run the time-out code with arduino and the sensor/shield and it works perfectly. Many Thanks indeed Wildbill.

I am not too worried about the constant stop commands being sent, however this project needs to run for 10 days from a car battery (battery not installed in a car). Do you think the constant stop commands will use up precious battery time ?

I assume its the read/write operations that use the most power on the Rmp3, and therefore just receiving a stop command shouldn't add to much... what do you think ?

I am still having trouble implementing the file commands to skip to the next track each time the sensor sends a new play command, cant seem to get the (*.mp3) bit working... Just to reiterate what I need to do :

Ihave 5 tracks on the SD card. I don't want to always trigger the first track on the card as this would be repetitive.

I am wondering if I can make a int variable called say - trackCount and each time playTrack is triggered I increment it by +1. if trackCount gets >5 then reset to 1. Then in the playback command instead of triggering the specific file 'Snake Awake.mp3', I would say 'if trackCount is 1 play 'Snake Awake.mp3' else if track count is 2 play 'next track.mp3', else if track count is 3 play 'track three.mp3'....etc..

i.e I am looking at linking to each specific filename, rather than using the fileCount and *.mp3 method..

Any help here would be very much appreciated.

Actually there is a problem with the millis timeout code.

On first powering up the arduino the time-out funtion works perfectly, however after a certain amount of time the playback stops immediately when no one is in range, rather than waiting for the threshold to be exceeded.

It appears to me that the once the threshold time is exceeded by millis it stops working....is it that the threshold is referencing the total millis time rather than the difference between millis time when sensor triggered and sensor cleared?

entire latest code

#include <RogueSD.h>
#include <RogueMP3.h>
#include <NewSoftSerial.h>
#define DETECTION_THRESHOLD 20000UL
unsigned int LastDetectionTime=0;
//#define TIMER_MAX 30000
NewSoftSerial rmp3_serial(6, 7);
RogueMP3 rmp3(rmp3_serial);
RogueSD filecommands(rmp3_serial);


int duration;                          // Stores duratiuon of pulse in
int distance;                          // Stores distance
int srfPin = 3;                        // Pin for SRF05
//uint32_t triggerTimer = 0xffffffff - TIMER_MAX;
int numberOfSongs;
int currentSong = 0;
boolean playing = false;
char filePath[96];

// consts
const char *directory = "/";
  void getDistance()
{
  pinMode(srfPin, OUTPUT);
  digitalWrite(srfPin, LOW);           // Make sure pin is low before sending a short high to trigger ranging
  delayMicroseconds(2);
  digitalWrite(srfPin, HIGH);          // Send a short 10 microsecond high burst on pin to start ranging
  delayMicroseconds(10);
  digitalWrite(srfPin, LOW);           // Send pin low again before waiting for pulse back in
  pinMode(srfPin, INPUT);
  duration = pulseIn(srfPin, HIGH);    // Reads echo pulse in from SRF05 in micro seconds
  distance = duration/58;              // Dividing this by 58 gives us a distance in cm
} 
void playTrack ()
{
 char status;
 status = rmp3.getplaybackstatus ();
 if (status == 'P')
 {
 return;
 }
 else
 {
 rmp3.playfile("/Snake Awake.mp3");
 }
}

 void stopTrack ()
 {
 char status;
 status = rmp3.getplaybackstatus ();
 if (status == 'S')
 {
 return;
 }
 else
 {
 rmp3.stop();
 
 }
 
 }
void setup()
{
  

  
  

Serial.begin(9600);
 
  rmp3_serial.begin(9600);
 
  // synchronize audio player
  rmp3.sync();
  rmp3.stop();
 
  // synchronize file system controller
  filecommands.sync();
 
  Serial.println("rMP3 Synchronized.");
 
  // get the number of songs available
  strcpy(filePath, directory);
  strcat(filePath, "/");
  strcat(filePath, "*.mp3");
 
  numberOfSongs = filecommands.filecount(filePath);
}
  void loop()
{
  getDistance();

  if (distance < 100){
   LastDetectionTime=millis();
   playTrack();
  }
else if(millis()-LastDetectionTime > DETECTION_THRESHOLD)
  {
  rmp3.stop();
  }
   Serial.println(distance);
  // Arbitrary delay
  delay(250);
}

oops, rookie mistake!- (mine) This:

unsigned int LastDetectionTime=0;

should of course be

unsigned long LastDetectionTime=0;