Pages: [1]   Go Down
Author Topic: Playing 1000 songs from SD card  (Read 2166 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

   I want some guidance to write a piece of code. I am not expert in coding.

   My gadget is Arduino atmega328 + LC Studio sd card breakout board.This gadget is to play wave audio files stored in the sd card.The wave files are numerically named as 0001.wav,0002.wav,0003.wav,....etc (they are 100s in numbers). I want to play these files as described below.

      I want to have 2 push buttons(called UP,DOWN) connected to the interrupts pins 2 & 3 respectively.At start-up, file "0001.wav" should be played.When I press 'UP' button once, file "0002.wav" should be played.Consecutively pressing 'UP', files with increment in name (0003.wav,0004.wav....so on), should be played. The 'DOWN' button is meant for decrement order play,you figured it out,I guess.

So far my code is this.

Code:
#include <SD.h>              // need to include the SD library
#define SD_ChipSelectPin 4       // using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h>              // also need to include this library...

TMRpcm tmrpcm;                    // create an object for use in this sketch

void setup(){

  tmrpcm.speakerPin = 9; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc

   Serial.begin(9600);
   if (!SD.begin(SD_ChipSelectPin)) {  // see if the card is present and can be initialized:
   Serial.println("SD fail"); 
    return;   // don't do anything more if not   
  }
   
   pinMode(2,INPUT);
   digitalWrite(2,HIGH);
   attachInterrupt(0,otherfile,FALLING); 
}
   
void loop(){
    noInterrupts();     
    tmrpcm.play("0001.wav");
    while(tmrpcm.isPlaying()) {}
    interrupts(); 
}

void otherfile() {
     noInterrupts();
     delay(10);        // clean switching
     tmrpcm.play("0002.wav");
     while(tmrpcm.isPlaying()) {} 
}


I am successfuly played the start up file 0001.wav.I donot know how to proceed.I have tried interrupt service routine and able to play one of the remaining songs, though it is not a good way, as shown in the codes .How to go about this ?
      I sought your help.

 BTW, apart from the standard <SD.h> ,I'm using "tmrpcm" library found here.
https://github.com/TMRh20/TMRpcm
   
 Thank you in advance.

manmachine
Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 98
Posts: 3575
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Im not familiar with that library, but you could maybe try this.

pseudo
Code:
//look at the two buttons
if(button1)
{
  //increment track
}
if(button2)
{
  //decrement track
}

//Make the track an int to inc or dec and then convert that int to a string.
//With the int now a string, use strcat() to make it look like "0002.wav".
track = 2;
char *StrTrack = itoa(track);
strcat(StrTrack,".wav"); // It should produce "0002.wav".
Logged

Created Libraries:
NPV2 (NewPasswordV2),  TFT_Extension, OneWireKeypad, SerialServo.
Will provide libraries if asked in PM or forum.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 610
Posts: 49074
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
void loop(){
    noInterrupts();     
    tmrpcm.play("0001.wav");
    while(tmrpcm.isPlaying()) {}
    interrupts(); 
}
Turn off interrupts, so the interrupt the switch is connected to never fires. Then, play a file, blocking while that file is playing.

As soon as that file quits playing, turn interrupts back on. Loop gets called again, and the process starts over.

You should NOT be disabling interrupts 99.9999% of the time.

You should be using sprintf() to construct the name of the file to be played, based on a variable. That variable should be incremented (and wrapped) when the current song ends.

The interrupt handler needs to set a flag that the while loop pays attention to (rather than doing nothing). That "paying attention to" simply means checking the flag, stopping the current track if the flag is true, and breaking out of the while loop if the flag is true.

You need two interrupt handlers for two switches.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for answering guys.Much helpful piece of advice.
I'll get back with my outcome.

Manmachine
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

    This is what worked for me.I am half way to my goal though.

Code:
#include <SD.h>              // need to include the SD library
#define SD_ChipSelectPin 4  //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h>        //  also need to include this library...

TMRpcm audio;   // create an object for use in this sketch
File myFile;
char trackname[] = "0000.wav"; //basic denomination
int tracknumber;
   
void setup(){

   audio.speakerPin = 9; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc
   Serial.begin(9600);
   if (!SD.begin(SD_ChipSelectPin)) {  // see if the card is present and can be initialized:
   Serial.println("SD fail"); 
   return;   // don't do anything more if not       
  }

   pinMode(2,INPUT);
   digitalWrite(2,HIGH);
   attachInterrupt(0,incfile,FALLING);
   
   pinMode(3,INPUT);
   digitalWrite(3,HIGH);
  // attachInterrupt(0,decfile,FALLING);
   
   sprintf(trackname, "%04d.wav",0);//startup file name
}
     
void loop(){   
 
    audio.play(trackname);
    while(audio.isPlaying()) {interrupts();}       
}

void incfile() {
     noInterrupts(); //diable further interrupts, avoid nesting
     if(tracknumber<100){tracknumber=tracknumber+1; //increment file name,curb the filename to 100(for testing=100) 
     Serial.println(tracknumber); //  debug line - to be discarded later
     sprintf(trackname, "%04d.wav",tracknumber);//calculate the file name
     Serial.println(trackname); //name of the new file to be played
     audio.stopPlayback();}  // this was found necessary to start the new file
                             //from the begining
     else{} 
}
/*void decfile() {
     noInterrupts();
     if(tracknumber!=0){tracknumber=tracknumber-1;   
     Serial.println(tracknumber);
     sprintf(trackname, "%04d.wav",tracknumber);
     Serial.println(trackname);
     audio.stopPlayback();}
     else{}       
}*/

@PaulS: Thank you for the ' sprintf ' hint. Could you please clarify a few more points?

Quote
As soon as that file quits playing, turn interrupts back on. Loop gets called again, and the process starts over.
What if the playing file is a long one and I want to switch to the next one , discontinuing the playing one ?

Quote
You should NOT be disabling interrupts 99.9999% of the time.
Even within the INTERRUPT service routine ? Wouldn't it leads to nesting ?

Sorry for a newbie question : If there are more than one INTERRUPT routine , as in the above code, how to place them in the sketch so that they are totally independent ? In the above code, the first one runs over the beneath one as well, and hence commented out for the time being.

@others:I have some difficulty in understanding interrupt handling in Arduino.Actually, I am thinking of adding some more buttons ( for- inc10s,inc100s,dec10s,dec100s,volume etc.)to be interfaced with additional logic circuits.Although, I know I can do this with the spare port pins, I prefer reseving those pis for display etc,.
So,could somebody point me to resources that may explain Arduino interrupts,to an 'assembly language' person ?

Thanks.

manmachine.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 610
Posts: 49074
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What if the playing file is a long one and I want to switch to the next one , discontinuing the playing one ?
Then, obviously, turning interrupts off (ignoring them) is not how you do that.

Code:
void loop(){   
 
    audio.play(trackname);
    while(audio.isPlaying()) {interrupts();}       
}
If you never turn interrupts off, there is no need to turn them on again. Turning them on over and over in a while loop, especially, is silly.

What you SHOULD do, in the while loop, is see if an interrupt occurred, which you know because the interrupt handler set a flag.

Your interrupt handler is turning interrupts off, which is silly because interrupts are disable WHILE AN INTERRUPT HANDLER IS RUNNING. It is using Serial.print(), which is silly because sending serial data requires that interrupts be functioning.

Suppose that you are watching TV (while(audio.isPlaying()), and the doorbell rings (that's an interrupt). What do you do? You we're watching a porn flick, and you don't want anyone to know.

You have some choices. You could make the process of answering the door turn the TV off or change the channel. Or, you could get a dog. When the doorbell rings, you can ignore it. When the dog runs out of the room (sets a flag), to the door, you know that you will need to change what you are watching.

So, periodically, (in the body of the while(audio.isPlaying())) you look to see if the dog is in the room. If not, stop the track, and go answer the door. Of course, the dog charging at the door scared off the person that rang the doorbell, so there is nothing to do except drag the dog back into the room with the TV (reset the flag) and change to the next track.

Code:
while(audio.isPlayiing())
{
   if(!dogInRoom)
   {
      audio.stop();
      dogInRoom = true;
      track++;
      break;
   }
}

Then, the interrupt handler is trivial:
Code:
void bellRang()
{
   dogInRoom = false;
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Manmachine, I'm very new in Arduino, I got a Arduino Due because I would like to play music from my SD card or a flash drive, I know the Arduino have two DAC pins, and I would like to know how connect de SD to the DUE, as you did it, I wondering id you can help me with the design.
Thank you very much, my e-mail is wdlarosa at gmail dot com
Wtito
Logged

Pages: [1]   Go Up
Jump to: