Alarm with Adafruit Music Maker

Hi everyone,

I need some help with the Adafruit Music Maker. I try to make a door alarm with Arduino UNO, Adafruit Music Maker and an ultrasonic sensor (HC-SR04). In loop function my SD card is not recognize. In the setup function was initialized correctly Shield, SD card and sensor, but in loop, after the first reading of the sensor, will no longer recognize the SD card, and in the next entry in loop it will not read either the sensor, it will display only 0. I need some help with this problem. What can block the SD card and the sesnor? Here is the code. Mention that I have a function to random select the sound (on SD card are several sounds alarm).

P.S. I started with 3 programs: Ultrasonic_blink, SD-ReadWrite and player_simple. All 3 work good if I upload them separated. The big program was created from these 3 programs.

// include SPI, MP3 and SD libraries
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////
// These are the pins used for the music maker shield
#define SHIELD_RESET  -1          // VS1053 reset pin (unused!)
#define SHIELD_CS        7        // VS1053 chip select pin (output)
#define SHIELD_DCS      6         // VS1053 Data/command select pin (output)
// These are common pins between breakout and shield
#define CARDCS 4         // Card chip select pin
// DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt
#define DREQ 3     // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
#define trigPin 12
#define inputPin 11 // choose the input pin (for Ultrasonic sensor)

int distance = 0;
int duration;

void setup() {
  Serial.begin(9600);  //initialize the serial monitor
 
  uint32_t seed = 0;  // Generate random see start
  for ( uint8_t i = 10 ; i ; i-- ) {
        seed = ( seed << 5 ) + ( analogRead( 0 ) * 3 );
  }
  randomSeed( seed );  //set random seed

  pinMode(trigPin, OUTPUT);
  pinMode(inputPin, INPUT);      // declare sensor as input
  Serial.println("");
        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
        duration = pulseIn(inputPin, HIGH);
        distance = (duration/2) / 29.1;
  if (distance != 0)
  {
        Serial.print(distance);
        Serial.println(" cm");
        Serial.println("SENSOR ACTIVE");
        delay(50);
  }
 
  Serial.println("Adafruit VS1053 Library Test");
  Serial.print("RandomSeed value = ");
  Serial.println(seed);
  // initialise the music player
  if (! musicPlayer.begin()) { // initialise the music player
        Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
        while (1);
  }
  Serial.println(F("VS1053 found"));
  if (!SD.begin(CARDCS)) {
        Serial.println(F("SD failed, or not present"));
        while (1);  // don't do anything more
  }
  Serial.println("SD OK!");
  // list files
  printDirectory(SD.open("/"), 0);
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(50, 30);
  if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
        Serial.println(F("DREQ pin is not an interrupt pin"));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  // put your main code here, to run repeatedly:
  // Read ultrasonic sensor / Read distance 
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(inputPin, HIGH);
  distance = (duration/2) / 29.1;
  Serial.print(distance); 
  Serial.println(" cm");
  delay(100);
  File path = SD.open("/");
  File results;
  char* MP3 = selectRandomFileFrom( path, results );
  delay(100);
 
  // Start playing a file, then we can do stuff while waiting for it to finish
  if(distance <= 50){
  if (! musicPlayer.startPlayingFile(MP3)) {
        Serial.println("Could not open file: ");
        Serial.println(MP3);
  }
  Serial.print(F("Now playing "));
  Serial.println(MP3);
  while (musicPlayer.playingMusic) {
        delay(250);
        //Serial.print(".");
        //////////////////////////////////////////////////////////////////////////////////////////////////////////
  }
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// File listing helper
void printDirectory(File dir, int numTabs) {
  while (true) {
        File entry =  dir.openNextFile();
        if (! entry) {
          // no more files
          //Serial.println("**nomorefiles**");
          break;
        }
        for (uint8_t i = 0; i < numTabs; i++) {
          Serial.print('\t');
        }
        Serial.print(entry.name());
        if (entry.isDirectory()) {
          Serial.println("/");
          printDirectory(entry, numTabs + 1);
        } else {
          // files have sizes, directories do not
          Serial.print("\t\t");
          Serial.println(entry.size(), DEC);
        }
        entry.close();
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function to select random mp3
char* selectRandomFileFrom( File dir, File result ) {
  File entry;
  int count = 0;
  dir.rewindDirectory();
  while ( entry = dir.openNextFile() ) {
        if ( random( count ) == 0 ) {
          result = entry;
        }
        entry.close();
        count++;
  }
  return result.name();   // returns the randomly selected file name
}

The SD card presumably uses an SPI interface. On a Uno pin 11 is dedicated to the SPI MOSI and pin 12 to MISO, so there is probably a conflict with your use of pins for trigger and input.

UKHeliBob:
The SD card presumably uses an SPI interface. On a Uno pin 11 is dedicated to the SPI MOSI and pin 12 to MISO, so there is probably a conflict with your use of pins for trigger and input.

Thank you! Good point, you have right. I moved sensor to pins 1 and 2 and now the SD card is ok, the sound play when distance is <= 50cm. But this did’t solve the sensor bug. In the first run of loop i can read the sensor, but from the second run of loop distance is 0, it can not read the sensor anymore.

I moved sensor to pins 1 and 2

It is not usually a good idea to use pin 1 unless you know exactly what you are doing, because it can interfere with serial comms, including printing.

I

UKHeliBob: It is not usually a good idea to use pin 1 unless you know exactly what you are doing, because it can interfere with serial comms, including printing.

I have just pins 0,1,2 and 5 free (digital I/O). The rest are used by the Music Maker from what I see. Which pins from this 4 can I use for the sensor?

Pin 5 seems a good candidate. Have you used the analogue pins A0 to A5 ? They can be used as digital pins if required.

UKHeliBob:
Pin 5 seems a good candidate. Have you used the analogue pins A0 to A5 ? They can be used as digital pins if required.

I did’t know that I can use analog pins. Thnks! I moved sensor to A0 and A1. Now it work well, but still have a problem that I solved somehow, but I don’t know if it’s good. After 10-15 loop entry the program stop working cause it runs out of memory. For this I used a reset function and now it works perfect. It is ok this function or I have other possibility?

void loop() {
  // put your main code here, to run repeatedly:

  // Read ultrasonic sensor / Read distance  
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(inputPin, HIGH);
  distance = (duration/2) / 29.1;
  Serial.print(distance);  
  Serial.println(" cm");
  delay(50);

  File path = SD.open("/");
  File results;
  char* MP3 = selectRandomFileFrom( path, results );
  delay(100);
  
  // Start playing a file, then we can do stuff while waiting for it to finish
  if(distance <= 70){
  if (! musicPlayer.startPlayingFile(MP3)) {
      Serial.print("Could not open file: ");
      Serial.println(MP3);
    } else {   
      Serial.print(F("Now playing "));
      Serial.println(MP3);
      
      while (musicPlayer.playingMusic) {
        delay(250);
        //Serial.print(".");
      } 
    }
  } 
  else {
    Serial.println("No abject detected.");
  }

    memory = freeMemory();
    Serial.print("******* freeMemory()=");
    Serial.println(memory);
    
    if(memory <= 340){
    void(* resetFunc)(void)=0; //declare reset function at address 0
      if (!musicPlayer.playingMusic==false){
          musicPlayer.stopPlaying();  
         delay(250);     
      }      
      musicPlayer.softReset();
      delay(500);
      resetFunc(); //call reset
    } 
}

After 10-15 loop entry the program stop working cause it runs out of memory.

It would be much better to fix the problem rather than hit it with a sledgehammer.

UKHeliBob:
It would be much better to fix the problem rather than hit it with a sledgehammer.

I “cleaned” my code and I found that the problem came from random selector:

  File path = SD.open("/");
  File results;
  char* MP3 = selectRandomFileFrom( path, results );
  delay(100);

So i put this into if(distance <= 70) {…} and now it’s better. Memory decreases with 30k after a sound and I let that function for reset. Now the code looks like this:

// include SPI, MP3 and SD libraries
#include <SPI.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
#include <MemoryFree.h>

#define SHIELD_RESET  -1      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)
#define CARDCS 4     // Card chip select pin
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
#define trigPin A0
#define inputPin A1 // choose the input pin (for Ultrasonic sensor)
int distance = 0;
int duration;
int memory;

void setup() {
  Serial.begin(9600);  //initialize the serial monitor

  uint32_t seed = 0;  // Generate random seed start
  for ( uint8_t i = 10 ; i ; i-- ) {
    seed = ( seed << 5 ) + ( analogRead( 0 ) * 3 );
  }
  randomSeed( seed );  //set random seed

  pinMode(trigPin, OUTPUT);
  pinMode(inputPin, INPUT);     // declare sensor as input
  musicPlayer.begin();
  SD.begin(CARDCS);
  musicPlayer.setVolume(50, 20);

  if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)){
    Serial.println(F("DREQ pin is not an interrupt pin"));
  }
  delay(50);
}

void loop() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(inputPin, HIGH);
  distance = (duration/2) / 29.1;
  delay(50);
  
  if(distance <= 65){
    File path = SD.open("/");
    File results;
    char* MP3 = selectRandomFileFrom( path, results );
    delay(100);
    musicPlayer.startPlayingFile(MP3);  
      
      while (musicPlayer.playingMusic) {
        delay(250);
      } 
  } 
   memory = freeMemory();
    
  if(memory <= 350){
    void(* resetFunc)(void)=0; //declare reset function at address 0
    if (!musicPlayer.playingMusic==false){
      musicPlayer.stopPlaying();  
      delay(250);     
    }      
    musicPlayer.softReset();
    delay(300);
    resetFunc(); //call reset
  } 
}

char* selectRandomFileFrom( File dir, File result ) {
  File entry;
  int count = 0;

  dir.rewindDirectory();

  while ( entry = dir.openNextFile() ) {
    if ( random( count ) == 0 ) {
      result = entry;
    }
    entry.close();
    count++;
  }
  return result.name();   // returns the randomly selected file name
}