0

VS1053 + Pushbutton + Stop Playing issue
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Tue Sep 01, 2015 1:52 am

Greetings,

I can not for the life of me figure out how to stop playing an mp3 using our push button. Please take a look at the following code. I excerpted the portion I need help with.

Code: Select all | TOGGLE FULL SIZE
#include <UTFT.h>
#include <UTouch.h>
#include <UTFT_Buttons.h>
#include <SPI.h>
#include <UTFT_SdRaw.h>
#include <SdFat.h>
#include <Adafruit_VS1053.h>
// #include <SD.h>

#include <DueFlashStorage.h>
DueFlashStorage dueFlashStorage;

UTFT          display_LCD(EHOUSE70, 22, 23, 31, 33);
UTouch        touch(25, 26, 27, 29, 30);
UTFT_Buttons  button(&display_LCD, &touch);
UTFT_SdRaw    sd_Files(&display_LCD);

#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// #define CARDCS 4               // Card chip select pin
#define DREQ 3                 // VS1053 Data request, ideally an Interrupt pin

#define mosipin 11
#define misopin 12
#define clkpin 13

char* TRACK[] = {
  "MUSIC/track001.mp3",
  "MUSIC/track002.mp3",
  "MUSIC/track003.mp3",
  "MUSIC/track004.mp3",
  "MUSIC/track005.mp3",
};


// SD chip select pin
const uint8_t chipSelect = 42;

//Push Button Setup

const int p_button = 2;     // the number of the pushbutton pin

bool pressed = HIGH;
bool played = 0;
unsigned char count = 0;

// file system
SdFat sd;

Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(mosipin, misopin, clkpin, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, chipSelect);  // create breakout-example object!

extern unsigned short bw_logo[3100];
extern unsigned short uml_logo[7040];
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];
extern uint8_t Dingbats1_XL[];
extern uint8_t arial_bold[];

int more_b, less_b, start_b, set_b, enter, pressed_button;
int buf[798];
int g, prev_g, f, prev_f = 0;
int x, y, w, l;
int X, Y;

uint8_t counter = (dueFlashStorage.read(1));


void setup()
{
  // Setup the LCD
  display_LCD.InitLCD();
  display_LCD.setFont(BigFont);
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color

  // initialize the pushbutto n pin as an input:
  // pinMode(buttonPin, INPUT);

  pinMode(p_button, INPUT_PULLUP);
  digitalWrite(p_button, HIGH);

  randomSeed(analogRead(A0));

  Serial.begin(9600);

  while (!Serial) {
    ; // wait for serial port to connect. Needed for DUE & Leonardo only
  }
  counter = constrain(counter, 1, 10);
  Serial.println(F("Initialising SD card..."));
  bool mysd = 0;
  // see if the card is present and can be initialized:
  while (!mysd)
  {
    if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
      Serial.println(F("Card failed, or not present"));
      Serial.println(F("Retrying...."));
    }
    else
    {
      mysd = 1;
      Serial.println(F("Card initialised."));
    }
  }

  // initialise the music player
  if (!musicPlayer.begin()) {
    Serial.println(F("Couldn't find VS1053!"));
  }
  else
  {
    Serial.println(F("VS1053 found"));
  }
  // 
  //  if (!sd.begin(CARDCS)) // initialize the SD card
  //  {
  //    Serial.println(F("SD failed, or not present"));
  //  }
  //  else
  //  {
  //    Serial.println(F("SD OK"));
  //  }
  if (!musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) { // DREQ int
    Serial.println(F("DREQ Pin problem"));
  }

  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(20, 20);

  touch.InitTouch();
  touch.setPrecision(PREC_EXTREME);

  button.setTextFont(arial_bold);
  button.setSymbolFont(Dingbats1_XL);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

void loop()
{
  display_LCD.clrScr();
  button.deleteAllButtons();
  // MainMenu();
  MainProgram();
}

void MainMenu()
{
  button.deleteAllButtons();
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color

  // Make a Main Menu Title Bar
  display_buttons(0, 0, 799, 50, 20, 40, 140);
  display_LCD.setFont(BigFont);
  display_LCD.setBackColor(20, 40, 140);
  display_LCD.setColor(255, 255, 255);
  display_LCD.print("MAIN MENU", CENTER, 15);

  //Display text asking how to continue
  display_LCD.setFont(SmallFont);
  display_LCD.setBackColor(255, 255, 255);
  display_LCD.setColor(0, 0, 0);
  display_LCD.print("How would you like to continue?", 100, 100);

  start_b = button.addButton(150, 120, 500, 50, "Begin messaging");
  set_b = button.addButton(150, 200, 500, 50, "Change settings");
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_NAVY);
  button.drawButtons();

  //Display text telling battery percentage
  display_LCD.setFont(SmallFont);
  display_LCD.setBackColor(255, 255, 255);
  display_LCD.setColor(0, 0, 0);
  display_LCD.print("Battery Remaining", CENTER, 380);
  display_LCD.print("100%", CENTER, 420);

  while (1)
  {
    if (touch.dataAvailable() == true)
    {
      pressed_button = button.checkButtons();

      if (pressed_button == start_b)
      {
        MainProgram();
        loop();
      }
      if (pressed_button == set_b)
      {
        SettingsPage();
      }
    }
  }
}

void check(unsigned char num)
{
  count = 0;
  played = 0;
  while (count<(counter * 10))    //delay of 10 second with the checking of input
  {
    pressed = digitalRead(p_button);
    delay(100);
    if ((pressed == LOW) && (played == 0))  //the button is pressed
    {
      switch (num)
      {
      case 1:
        musicPlayer.playFullFile("talk.mp3");
        break;
      case 2:
        musicPlayer.playFullFile("hungry.mp3");
        break;
      case 3:
        musicPlayer.playFullFile("thirsty.mp3");
        break;
      case 4:
        musicPlayer.playFullFile("bathroom.mp3");
        break;
      case 5:
        musicPlayer.playFullFile("clean.mp3");
        break;
      case 6:
        musicPlayer.playFullFile("sick.mp3");
        break;
      case 7:
        musicPlayer.playFullFile("wheelc.mp3");
        break;
      default:
        break;
      }
      played = 1;
    }
    else if (touch.dataAvailable() == true)
    {
      pressed_button = button.checkButtons();
      if (pressed_button == set_b)
      {
        SettingsPage();
      }
    }
    count++;
  }
  pressed = HIGH;
}

void MainProgram()
{
  button.deleteAllButtons();
  display_LCD.clrScr(); // clear the screen
  display_LCD.setColor(255, 255, 255);
  int mytime1 = millis();
  int ret1 = sd_Files.load(0, 0, 800, 480, "talk.raw", 16);
  Serial.println(millis() - mytime1);
  Serial.println(ret1);
  set_b = button.addButton(599, 0, 200, 50, "SETTINGS");
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_NAVY);
  button.drawButtons();
  check(1);

  //    display_LCD.clrScr(); // clear the screen
  //          display_LCD.setColor(255, 255, 255);
  //  int mytime2 = millis();
  //  int ret2 = sd_Files.load(0, 0, 800, 480, "hungry.raw", 16);
  //  Serial.println(millis() - mytime2);
  //  Serial.println(ret2);
  //  check(2);
  //
  //    display_LCD.clrScr(); // clear the screen
  //          display_LCD.setColor(255, 255, 255);
  //  int mytime3 = millis();
  //  int ret3 = sd_Files.load(0, 0, 800, 480, "thirsty.raw", 16);
  //  Serial.println(millis() - mytime3);
  //  Serial.println(ret3);
  //  check(3);
  //
  //      display_LCD.clrScr(); // clear the screen
  //          display_LCD.setColor(255, 255, 255);
  //  int mytime4 = millis();
  //  int ret4 = sd_Files.load(0, 0, 800, 480, "bathroom.raw", 16);
  //  Serial.println(millis() - mytime4);
  //  Serial.println(ret4);
  //  check(4);
  //
  //  display_LCD.clrScr(); // clear the screen
  //          display_LCD.setColor(255, 255, 255);
  //  int mytime5 = millis();
  //  int ret5 = sd_Files.load(0, 0, 800, 480, "clean.raw", 16);
  //  Serial.println(millis() - mytime5);
  //  Serial.println(ret5);
  //  check(5);
  //
  //  display_LCD.clrScr(); // clear the screen
  //          display_LCD.setColor(255, 255, 255);
  //  int mytime6= millis();
  //  int ret6 = sd_Files.load(0, 0, 800, 480, "sick.raw", 16);
  //  Serial.println(millis() - mytime6);
  //  Serial.println(ret6);
  //  check(6);

  display_LCD.clrScr(); // clear the screen
  display_LCD.setColor(255, 255, 255);
  int mytime7 = millis();
  int ret7 = sd_Files.load(0, 0, 800, 480, "wheelc.raw", 16);
  Serial.println(millis() - mytime7);
  Serial.println(ret7);
  check(7);

  //all 7 pictures are shown
  //now show the picture for audio
  display_LCD.clrScr(); // clear the screen
  display_LCD.setColor(255, 255, 255);
  int mytime8 = millis();
  int ret8 = sd_Files.load(0, 0, 800, 480, "picmusic.raw", 16);
  Serial.println(millis() - mytime8);
  Serial.println(ret8);

  played = 0;
  count = 0;

  // put your main code here, to run repeatedly:
  while (count<counter * 10)    //delay of some selected time delay with the checking of input
  {
    pressed = digitalRead(p_button);
    delay(100);
    if ((pressed == LOW) && (played == 0))  //the button is pressed
    {
      musicPlayer.startPlayingFile(TRACK[random(5)]);

      //      musicPlayer.playFullFile("MUSIC/2.mp3");
      //      musicPlayer.playFullFile("MUSIC/3.mp3");
      played = 1;
    }
    //    while (musicPlayer.playingMusic)
    //    {
    //      if((pressed==LOW))  //the button is pressed
    //    {
    //      musicPlayer.stopPlaying();
    //      played=0;
    //      }
    //    }
    count++;
  }
  //        display_LCD.clrScr();
  //        display_LCD.fillScr(255, 255, 255);   //Fill screen with white color
  //        display_LCD.print("Main Program Begins", CENTER, 200);
}

void SettingsPage()
{
  button.deleteAllButtons();
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color
  display_LCD.setFont(BigFont);

  // Make a Settings Title Bar
  display_buttons(0, 0, 799, 50, 20, 40, 140);
  display_LCD.setBackColor(20, 40, 140);
  display_LCD.setColor(255, 255, 255);
  display_LCD.print("SETTINGS", CENTER, 15);

  //Display text asking how long
  display_LCD.setFont(SmallFont);
  display_LCD.setBackColor(255, 255, 255);
  display_LCD.setColor(0, 0, 0);
  display_LCD.print("How long would you like images to be displayed on screen for?", CENTER, 125);

  //Create '+' Button
  int w1 = 80;
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_GREEN);
  more_b = button.addButton(533, 150, w1, 48, "+");   //(X, Y, W, H, "") 
  button.drawButton(more_b);

  //Create '-' Button
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_RED);
  less_b = button.addButton(267 - w1, 150, w1, 48, "-");
  button.drawButton(less_b);

  //Seconds Counter & Label
  display_LCD.setFont(SevenSegNumFont);
  display_LCD.printNumI(counter, CENTER, 150, 2, '0');
  display_LCD.setFont(SmallFont);
  display_LCD.print("SECONDS", CENTER, 200);

  //Main Menu Button
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_NAVY);
  int w2 = 320;
  enter = button.addButton(400 - w2 / 2, 320, w2, 48, "Return to Main Menu");
  button.drawButton(enter);

  while (1)
  {
    if (touch.dataAvailable() == true)
    {
      pressed_button = button.checkButtons();

      if (pressed_button == more_b)
      {
        counter = counter + 1;
        counter = constrain(counter, 1, 10);
        display_LCD.setFont(SevenSegNumFont);
        display_LCD.printNumI(counter, CENTER, 150, 2, '0');
      }
      if (pressed_button == less_b)
      {
        counter = counter - 1;
        counter = constrain(counter, 1, 10);
        display_LCD.setFont(SevenSegNumFont);
        display_LCD.printNumI(counter, CENTER, 150, 2, '0');
      }
    }
    else if (pressed_button == enter)
    {
      button.deleteAllButtons();
      dueFlashStorage.write(1, counter);
      MainMenu();
    }
  }
}

void display_buttons(int x, int y, int w, int l, int R, int G, int B)
{
  display_LCD.setColor(R, G, B);
  display_LCD.fillRect(x, y, w, l);
}


And now the part I am having trouble with:

Code: Select all | TOGGLE FULL SIZE
played = 0;
  count = 0;

  // put your main code here, to run repeatedly:
  while (count<counter * 10)    //delay of some selected time delay with the checking of input
  {
    pressed = digitalRead(p_button);
    delay(100);
    if ((pressed == LOW) && (played == 0))  //the button is pressed
    {
      musicPlayer.startPlayingFile(TRACK[random(5)]);

      //      musicPlayer.playFullFile("MUSIC/2.mp3");
      //      musicPlayer.playFullFile("MUSIC/3.mp3");
      played = 1;
    }
    //    while (musicPlayer.playingMusic)
    //    {
    //      if((pressed==LOW))  //the button is pressed
    //    {
    //      musicPlayer.stopPlaying();
    //      played=0;
    //      }
    //    }
    count++;
  }


Music and images are both stored on the SD card. In the above code, once a certain image is reached, a random mp3 from a specified folder is played when the push button is pressed. I would like a way to have that same push button be able to stop the current song being played and continue with the rest of the program which loops.

In the current code, when a button is pressed to start playing music, the music only plays for a couple seconds (if that) until its time to load the next image/page. Then it all freezes up which is understandable since I shouldn't be able to load two things at once from the SD card. When changing to the playFullFile command instead of startPlaying command, it will solve this partially allowing the whole song to play but then I do not know of a way of stopping the mp3 in the middle of a song using that same button and allowing the program to continue.

Any guidance. Am I going about it the wrong way?

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Tue Sep 01, 2015 3:11 pm

You start playing when the button is low. Then you immediately check to see if the button is low and stop playing if it is. Of course it will still be low - you can't let go of the button that fast.

You need to see the button go high before you check for low again.

Also, don't use digitalRead. mechanical buttons have 'bounce'. That is, they make and break several times during the press and the release. This will confuse your code. You need to 'debounce' the button. Use this routine instead of digitalRead:
Code: Select all | TOGGLE FULL SIZE
uint8_t debounceRead(int pin)
{
  uint8_t pinState = digitalRead(pin);
  uint32_t timeout = millis();
  while (millis() < timeout+10)
  {
    if (digitalRead(pin) != pinState)
    {
      pinState = digitalRead(pin);
      timeout = millis();
    }
  }

  return pinState;
}

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Thu Sep 03, 2015 4:45 pm

Ok so, I played around a little more. I implemented debounce. I then went ahead and tested stopping at least with the serial console to make sure I have it it working the way i want.

Here is my slightly modified code:

Code: Select all | TOGGLE FULL SIZE
//////////////////////////////////////////////////////////////////////////////////////////////
   
  count = 0;
  played = 0;
  while(count<counter*10)    //delay of some selected time delay with the checking of input
  {
    pressed = debounceRead(p_button);
    delay(100);
    if (pressed == LOW)  //the button is pressed
    {
  if (! musicPlayer.startPlayingFile("MUSIC/track002.mp3")) {
    Serial.println("Could not open file track001.mp3");
    while (1);
  }
  pressed = HIGH;
  Serial.println(F("Started playing"));

  while (musicPlayer.playingMusic) {
    // file is now playing in the 'background' so now's a good time
    // to do something else like handling LEDs or buttons :)
   
    Serial.print(".");
    if (Serial.available()) {
    char c = Serial.read();
   
    // if we get an 's' on the serial console, stop!
    pressed = debounceRead(p_button);
    delay(100);
    if (c == 's') {
//    if (pressed == LOW) {
      musicPlayer.stopPlaying();
    }
    delay(1000);
  }
  Serial.println("Done playing music");
 
}
    }
    count++;
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////


Using the serial input of 's' works for stopping. Then when I try it with the button, it's a no go.

Am I placing
Code: Select all | TOGGLE FULL SIZE
pressed = HIGH;
in the wrong location?

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Fri Sep 04, 2015 9:49 am

It's not enough to set pressed to HIGH. You're interested in the state change when the button is initially pressed. That change happens when the pin first goes from HIGH to LOW. So you need to know the *previous* state of the button as well as the *current* state of the button. You *only* do something when the previous state was HIGH and the current state is LOW.

Have a look at this:
Code: Select all | TOGGLE FULL SIZE
/***************************************************
  This is an example for the Adafruit VS1053 Codec Breakout

  Designed specifically to work with the Adafruit VS1053 Codec Breakout
  ----> https://www.adafruit.com/products/1381

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries. 
  BSD license, all text above must be included in any redistribution
 ****************************************************/

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

// define the pins used
//#define CLK 13       // SPI Clock, shared with SD card
//#define MISO 12      // Input data, from VS1053/SD card
//#define MOSI 11      // Output data, to VS1053/SD card
// Connect CLK, MISO and MOSI to hardware SPI pins.
// See http://arduino.cc/en/Reference/SPI "Connections"

// These are the pins used for the breakout example
#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// 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 =
  // create breakout-example object!
  Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);
  // create shield-example object!
  //Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
 
 
const int p_button = 2;     // the number of the pushbutton pin

uint8_t buttonState,
        prevButtonState;

void setup() {
  Serial.begin(9600);
  Serial.println("Adafruit VS1053 Simple Test");

  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"));
 
  SD.begin(CARDCS);    // initialise the SD card
 
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(20,20);

  // Timer interrupts are not suggested, better to use DREQ interrupt!
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int

  // If DREQ is on an interrupt pin (on uno, #2 or #3) we can do background
  // audio playing
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
 
  pinMode(p_button, INPUT_PULLUP);
  buttonState = HIGH;
  prevButtonState = HIGH;

}


void loop()
{
 //////////////////////////////////////////////////////////////////////////////////////////////

  buttonState = debounceRead(p_button);
  if ((LOW == buttonState) && (buttonState != prevButtonState)) //if button was just pressed
  {
   
    if (musicPlayer.stopped())
    {
      if (! musicPlayer.startPlayingFile("MUSIC/track002.mp3")) {
        Serial.println("Could not open file track002.mp3");
        while (1);
      }
      Serial.println(F("Started playing"));
    }
    else
    {
      musicPlayer.stopPlaying();
    }
  }
  prevButtonState = buttonState;  //update prevButtonState

/////////////////////////////////////////////////////////////////////////////////////////////
}

//Use like digitalRead. Incorporates button debouncing.
uint8_t debounceRead(int pin)
{
  uint8_t pinState = digitalRead(pin);
  uint32_t timeout = millis();
  while (millis() < timeout+10)
  {
    if (digitalRead(pin) != pinState)
    {
      pinState = digitalRead(pin);
      timeout = millis();
    }
  }

  return pinState;
}

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Sat Sep 05, 2015 3:35 pm

Hi Rick,

I was able to implement that code and ran into some issues. This is what I changed:

Code: Select all | TOGGLE FULL SIZE
while(count<counter*80)    //delay of some selected time delay with the checking of input
  {
    buttonState = debounceRead(p_button);
  if ((LOW == buttonState) && (buttonState != prevButtonState)) //if button was just pressed
  {
   
    if (musicPlayer.stopped())
    {
      if (! musicPlayer.startPlayingFile("track002.mp3")) {
        Serial.println("Could not open file track002.mp3");
        while (1);
      }
      Serial.println(F("Started playing"));
    }
    else
    {
      musicPlayer.stopPlaying();
      loop();
    }
  }
//  count++;  // Without count it works but does not automatically loop the whole program unless I press button to play and then press button to stop
 
  prevButtonState = buttonState;  //update prevButtonState
  }


Now what happens is that without the count, the whole program will stop looping. It will stay at that last image and only play when I press button or stop when I press button.

When I un comment count, the program behaves like I want it to except that this time when I press the button to play, it will hang/freeze once it's time to loop which makes sense because the program is now trying to access multiple things from the SD card. However I only want it to loop and return to beginning of program after it plays the songs or after I hit the button again or if nothing is pressed, it loops after a set amount of time
Code: Select all | TOGGLE FULL SIZE
while(count<counter*80)


One other question, currently it only plays one track when I hit the button, track002.mp3. How would I go about playing multiple tracks continuously (after track002.mp3, track003.mp3 plays automatically and so on....) using the startPlaying command. Should there be a while statement involved. In the end these tracks will be randomly selected but for now I kept it as is.

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Sun Sep 06, 2015 7:36 am

I don't understand what you're trying to do. What do you mean, the program stops looping? The code I gave you has the button check in loop(), and it will never stop looping.

You seems to be doing something strange. Can you post the entire sketch again?

Also, can you please explain again what you want the sketch to do?
Here's what I understand so far:
1) You want to play a track when you press the button, and stop playing when you press the button again.
2) If you don't press stop, you want to move on to playing the next track.
3) I don't at all understand what you're talking about with 'looping'
4) Your counter stuff make no sense to me at all.
5) Why are you calling loop() after calling musicPlayer.stopPlaying()? You should never call loop() directly.

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Sun Sep 06, 2015 1:05 pm

Alright here is what this sketch is suppose to do, its basically a communication device with music playback functionality.

Device turns on.

Pic1.RAW (lets call it a picture of a bathroom) loads onto a tft screen. This picture stays on screen for a set amount of time, lets say 3 seconds for now.
While Pic1 is displayed on the screen for that 3 seconds, the program is checking to see if a push button is pressed.
If the push button is pressed, msg1.mp3 is played (lets call it a message saying "I need to go to the bathroom".)

If a push button is not pressed for those 3 seconds, the sketch moves on to displaying Pic2.RAW for 3 seconds and repeats the same as above with msg2.mp3 instead.

This happens for a total of 7 times allowing 7 messages.

Now, after the 7th picture, one more RAW image is displayed for 3 seconds (lets call it audiopic.RAW) but this time if the button is pressed during those 3 seconds, track001.mp3 is played, then track002.mp3 is played etc.... During playback of any of these songs, if the button is pressed, the music stops and we restart at Pic1.RAW again.

And here is the most recent code.

Code: Select all | TOGGLE FULL SIZE
#include <UTFT.h>
#include <UTouch.h>
#include <UTFT_Buttons.h>
#include <SPI.h>
#include <UTFT_SdRaw.h>
#include <SdFat.h>
#include <Adafruit_VS1053.h>
#include <DueFlashStorage.h>

// #include <SD.h>

UTFT          display_LCD(EHOUSE70, 22, 23, 31, 33);
UTouch        touch(25, 26, 27, 29, 30);
UTFT_Buttons  button(&display_LCD, &touch);
UTFT_SdRaw    sd_Files(&display_LCD);

#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// #define CARDCS 4               // Card chip select pin
#define DREQ 3                 // VS1053 Data request, ideally an Interrupt pin
#define mosipin 11
#define misopin 12
#define clkpin 13

DueFlashStorage dueFlashStorage;    //Memory Storage

// SD chip select pin
const uint8_t chipSelect = 42;

//Push Button Setup

const int p_button = 2;     // the number of the pushbutton pin

uint8_t buttonState,
        prevButtonState;

uint8_t debounceRead(int pin)
{
  uint8_t pinState = digitalRead(pin);
  uint32_t timeout = millis();
  while (millis() < timeout+10)
  {
    if (digitalRead(pin) != pinState)
    {
      pinState = digitalRead(pin);
      timeout = millis();
    }
  }

  return pinState;
}

boolean pressed = HIGH;
boolean played = 0;
unsigned char count=0;

// file system
SdFat sd;
SdFile file;
SdFile dirFile;

//char* TRACK[] = {             // All MP3s need to have there name changed to track###.mp3 in order to be played
//  "MUSIC/track001.mp3",
//  "MUSIC/track002.mp3",
//  "MUSIC/track003.mp3",
//  "MUSIC/track004.mp3",
//  "MUSIC/track005.mp3",
//  "MUSIC/track006.mp3",
//  "MUSIC/track007.mp3",
//  "MUSIC/track008.mp3",
//  "MUSIC/track009.mp3",
//  "MUSIC/track010.mp3",
//  "MUSIC/track011.mp3",
//  "MUSIC/track012.mp3",
//  "MUSIC/track013.mp3",
//  "MUSIC/track014.mp3",
//  "MUSIC/track015.mp3",
//  "MUSIC/track016.mp3",
//  "MUSIC/track017.mp3",
//  "MUSIC/track018.mp3",
//  "MUSIC/track019.mp3",
//  "MUSIC/track020.mp3",
//  "MUSIC/track021.mp3",
//  "MUSIC/track022.mp3",
//  "MUSIC/track023.mp3",
//  "MUSIC/track024.mp3",
//  "MUSIC/track025.mp3",
//};

char* TRACK[] = {
  "MUSIC/speech1.mp3",
  "MUSIC/speech2.mp3",
  "MUSIC/speechx.mp3",
  "MUSIC/speech4.mp3",
  "MUSIC/speech5.mp3"
};

Adafruit_VS1053_FilePlayer musicPlayer =
   Adafruit_VS1053_FilePlayer(mosipin, misopin, clkpin, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, chipSelect);  // create breakout-example object!
 
extern unsigned short bw_logo[3100];
extern unsigned short uml_logo[7040];
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];
extern uint8_t Dingbats1_XL[];
extern uint8_t arial_bold[];

int more_b, less_b, start_b, set_b, enter, pressed_button;
int buf[798];
int g, prev_g, f, prev_f = 0;
int x, y, w, l;
int X, Y;

uint8_t counter = 3;


void setup()
{
  // Setup the LCD
  display_LCD.InitLCD();
  display_LCD.setFont(BigFont);
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color

 // initialize the pushbutton pin as an input:
 // pinMode(buttonPin, INPUT);
 
// pinMode(p_button, INPUT_PULLUP);
// digitalWrite(p_button, HIGH);

 pinMode(p_button, INPUT_PULLUP);
  buttonState = HIGH;
  prevButtonState = HIGH;

  Serial.begin(9600);

    while (!Serial) {
    ; // wait for serial port to connect. Needed for DUE & Leonardo only
  }
  counter = constrain(counter, 1, 10);
  Serial.println(F("Initialising SD card..."));
  bool mysd = 0;
 
  // see if the card is present and can be initialized:
  while (!mysd)
  {
    if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
      Serial.println(F("Card failed, or not present"));
      Serial.println(F("Retrying...."));
    }
    else
    {
      mysd = 1;
      Serial.println(F("Card initialised."));
    }
  }

  // initialise the music player
  if (! musicPlayer.begin()) {
    Serial.println(F("Couldn't find VS1053!"));
  }
  else
  {
    Serial.println(F("VS1053 found"));
  }
// 
//  if (!sd.begin(CARDCS)) // initialize the SD card
//  {
//    Serial.println(F("SD failed, or not present"));
//  }
//  else
//  {
//    Serial.println(F("SD OK"));
//  }
  if (!musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) { // DREQ int
    Serial.println(F("DREQ Pin problem"));
  }
 
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(30,30);
 
  touch.InitTouch();
  touch.setPrecision(PREC_EXTREME);

  button.setTextFont(arial_bold);
  button.setSymbolFont(Dingbats1_XL);

  //Improves Random selection

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

void loop()
{
display_LCD.clrScr();
button.deleteAllButtons();
// MainMenu();
MainProgram();
}

void MainMenu()
{
    button.deleteAllButtons();
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color
 
  // Make a Main Menu Title Bar
  display_buttons(0, 0, 799, 50, 20, 40, 140);
  display_LCD.setFont(BigFont);
  display_LCD.setBackColor(20, 40, 140);
  display_LCD.setColor(255, 255, 255);
  display_LCD.print("MAIN MENU", CENTER, 15);

  //Display text asking how to continue
  display_LCD.setFont(SmallFont);
  display_LCD.setBackColor(255, 255, 255);
  display_LCD.setColor(0, 0, 0);
  display_LCD.print("How would you like to continue?", 100, 100);

  start_b = button.addButton(150, 120, 500, 50, "Begin messaging");
  set_b = button.addButton(150, 200, 500, 50, "Change settings");
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_NAVY);
  button.drawButtons();

  //Display text telling battery percentage
  display_LCD.setFont(SmallFont);
  display_LCD.setBackColor(255, 255, 255);
  display_LCD.setColor(0, 0, 0);
  display_LCD.print("Battery Remaining", CENTER, 380);
  display_LCD.print("100%", CENTER, 420);

  while(1)
  {
    if (touch.dataAvailable() == true)
    {
      pressed_button = button.checkButtons();

      if (pressed_button == start_b)
      {
        MainProgram();
        loop();
        }
      if (pressed_button == set_b)
      {
        SettingsPage();
      }
    }
  }
}

void check(unsigned char num)
{
  count = 0;
  played = 0;
  while(count<(counter*10))    //delay of 10 second with the checking of input
  {
    pressed = digitalRead(p_button);
    delay(100);
    if((pressed==LOW)&&(played==0))  //the button is pressed
    {
      switch(num)
      {
        case 1:
        musicPlayer.playFullFile("talk.mp3");
        break;
      case 2:
        musicPlayer.playFullFile("hungry.mp3");
        break;
      case 3:
        musicPlayer.playFullFile("thirsty.mp3");
        break;
      case 4:
        musicPlayer.playFullFile("bathroom.mp3");
        break;
      case 5:
        musicPlayer.playFullFile("clean.mp3");
        break;
      case 6:
        musicPlayer.playFullFile("sick.mp3");
        break;
      case 7:
        musicPlayer.playFullFile("wheelc.mp3");
        break;
        default:
          break;
      }
      played = 1;
    }
    else if (touch.dataAvailable() == true)
    {
      pressed_button = button.checkButtons();
      if (pressed_button == set_b)
      {
        SettingsPage();
      }
    }
    count++;
  }
  pressed = HIGH;
}

void MainProgram()
{
//   button.deleteAllButtons();
//  display_LCD.clrScr(); // clear the screen
//  display_LCD.setColor(255, 255, 255);
//  int mytime1 = millis();
//  int ret1 = sd_Files.load(0, 0, 800, 480, "talk.raw", 16);
//  Serial.println(millis() - mytime1);
//  Serial.println(ret1);
//  set_b = button.addButton(599, 0, 200, 50, "SETTINGS");
//  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_NAVY);
//  button.drawButtons();
//  check(1);

//    display_LCD.clrScr(); // clear the screen
//          display_LCD.setColor(255, 255, 255);
//  int mytime2 = millis();
//  int ret2 = sd_Files.load(0, 0, 800, 480, "hungry.raw", 16);
//  Serial.println(millis() - mytime2);
//  Serial.println(ret2);
//  check(2);
//
//    display_LCD.clrScr(); // clear the screen
//          display_LCD.setColor(255, 255, 255);
//  int mytime3 = millis();
//  int ret3 = sd_Files.load(0, 0, 800, 480, "thirsty.raw", 16);
//  Serial.println(millis() - mytime3);
//  Serial.println(ret3);
//  check(3);
//
//      display_LCD.clrScr(); // clear the screen
//          display_LCD.setColor(255, 255, 255);
//  int mytime4 = millis();
//  int ret4 = sd_Files.load(0, 0, 800, 480, "bathroom.raw", 16);
//  Serial.println(millis() - mytime4);
//  Serial.println(ret4);
//  check(4);
//
//  display_LCD.clrScr(); // clear the screen
//          display_LCD.setColor(255, 255, 255);
//  int mytime5 = millis();
//  int ret5 = sd_Files.load(0, 0, 800, 480, "clean.raw", 16);
//  Serial.println(millis() - mytime5);
//  Serial.println(ret5);
//  check(5);
//
  display_LCD.clrScr(); // clear the screen
          display_LCD.setColor(255, 255, 255);
  int mytime6= millis();
  int ret6 = sd_Files.load(0, 0, 800, 480, "sick.raw", 16);
  Serial.println(millis() - mytime6);
  Serial.println(ret6);
  check(6);

  display_LCD.clrScr(); // clear the screen
  display_LCD.setColor(255, 255, 255);
  int mytime7 = millis();
  int ret7 = sd_Files.load(0, 0, 800, 480, "wheelc.raw", 16);
  Serial.println(millis() - mytime7);
  Serial.println(ret7);
  check(7);

  //all 7 pictures are shown
  //now show the picture for audio
  display_LCD.clrScr(); // clear the screen
  display_LCD.setColor(255, 255, 255);
  int mytime8 = millis();
  int ret8 = sd_Files.load(0, 0, 800, 480, "picmusic.raw", 16);
  Serial.println(millis() - mytime8);
  Serial.println(ret8);


//////////////////////////////////////////////////////////////////////////////////////////////
//FILE COUNT IN MUSIC FOLDER OF SD CARD

int k = 0;

sd.chdir("/MUSIC");
  while (file.openNext(sd.vwd(), O_READ)) {
    file.printName(&Serial);
    k++;
    Serial.println();
    file.close();
  }
  sd.chdir("/");
  Serial.print("There are ");
  Serial.print(k);
  Serial.println(" files in the MUSIC directory");

//////////////////////////////////////////////////////////////////////////////////////////////
   
  count = 0;
  played = 0;
 
  while(count<counter*80)    //delay of some selected time delay with the checking of input
  {
    buttonState = debounceRead(p_button);
  if ((LOW == buttonState) && (buttonState != prevButtonState)) //if button was just pressed
  {
   
    if (musicPlayer.stopped())
    {
      if (! musicPlayer.startPlayingFile("track002.mp3")) {
        Serial.println("Could not open file track002.mp3");
        while (1);
      }
      Serial.println(F("Started playing"));
    }
    else
    {
      musicPlayer.stopPlaying();
      loop();
    }
  }
//  count++;  // Without count it works but does not automatically loop the whole program unless I press button to play and then press button to stop
 
  prevButtonState = buttonState;  //update prevButtonState
  }
 
}

////////////////////////////////////////////////////////////////////////////////
//    pressed = debounceRead(p_button);
//    delay(100);
//    if ((pressed == LOW))  //the button is pressed
//    {
//                while (musicPlayer.startPlayingFile(TRACK[ random(k)]))
//              {
//                              Serial.print(k);
//                              check(8);
//              }
//  if (! musicPlayer.startPlayingFile(TRACK[ random(k)])) {
//    Serial.println("Could not open file track001.mp3");
//  }
//  Serial.println(F("Started playing"));
//  while (musicPlayer.playingMusic)
//  {
//  check(8);
//      Serial.println("Done playing music");
//    }
/////////////////////////////////////////////////////////////////////////////////////////////

void SettingsPage()
{
  button.deleteAllButtons();
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color
  display_LCD.setFont(BigFont);
 
  // Make a Settings Title Bar
  display_buttons(0, 0, 799, 50, 20, 40, 140);
  display_LCD.setBackColor(20, 40, 140);
  display_LCD.setColor(255, 255, 255);
  display_LCD.print("SETTINGS", CENTER, 15);

  //Display text asking how long
  display_LCD.setFont(SmallFont);
  display_LCD.setBackColor(255, 255, 255);
  display_LCD.setColor(0, 0, 0);
  display_LCD.print("How long would you like images to be displayed on screen for?", CENTER, 125);

  //Create '+' Button
  int w1 = 80;
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_GREEN);
  more_b = button.addButton(533, 150, w1, 48, "+");   //(X, Y, W, H, "") 
  button.drawButton(more_b);

  //Create '-' Button
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_RED);
  less_b = button.addButton(267 - w1, 150, w1, 48, "-");
  button.drawButton(less_b);

  //Seconds Counter & Label
  display_LCD.setFont(SevenSegNumFont);
  display_LCD.printNumI(counter, CENTER, 150, 2, '0');
  display_LCD.setFont(SmallFont);
  display_LCD.print("SECONDS", CENTER, 200);

  //Main Menu Button
  button.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_NAVY);
  int w2 = 320;
  enter = button.addButton(400 - w2 / 2, 320, w2, 48, "Return to Main Menu");
  button.drawButton(enter);

  //Display Bridgewell Logo
//  display_LCD.drawBitmap(10, 429, 100, 31, bw_logo, 1);
  //Display UML Logo
//  display_LCD.drawBitmap(611, 390, 88, 80, uml_logo, 1);

  while(1)
  {
    if (touch.dataAvailable() == true)
    {
      pressed_button = button.checkButtons();
       
    if (pressed_button==more_b)
      {
              counter = counter + 1;
              counter = constrain(counter, 1, 10);
              display_LCD.setFont(SevenSegNumFont);
              display_LCD.printNumI(counter, CENTER, 150, 2, '0');
      }
    if (pressed_button==less_b)
      {
            counter = counter - 1;
            counter = constrain(counter, 1, 10);
            display_LCD.setFont(SevenSegNumFont);
            display_LCD.printNumI(counter, CENTER, 150, 2, '0');
        }
      }
     else if (pressed_button==enter)
      {
        button.deleteAllButtons();
//        dueFlashStorage.write(1, counter);
        MainMenu();
      }
    }
  }
 
void display_buttons(int x, int y, int w, int l, int R, int G, int B)
{
  display_LCD.setColor(R, G, B);
  display_LCD.fillRect(x, y, w, l);
}

//void ListLogs() {
//  sd.chdir("/MUSIC");
//  while (file.openNext(sd.vwd(), O_READ)) {
//    file.printName(&Serial);
//    k++;
//    Serial.println();
//    file.close();
//  }
//  sd.chdir("/");
//  Serial.print("There are ");
//  Serial.print(k);
//  Serial.println(" files in the MUSIC directory");
//}


This code is my first with Arduino which may explain how messy it is.

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Mon Sep 07, 2015 1:07 pm

Hmmm. I'm not sure you can get there from here. You've kind of subverted the basic structure of an arduino sketch by not using loop() properly.

Why don't you take a step back. I've put together the basic logic for the functionality you describe. You'll have to add the LCD, SD, and menu stuff back in, but this should get you started in a better direction:
Code: Select all | TOGGLE FULL SIZE
#include <SPI.h>
#include <SD.h>
#include <Adafruit_VS1053.h>

#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// #define CARDCS 4               // Card chip select pin
#define DREQ 3                 // VS1053 Data request, ideally an Interrupt pin
#define mosipin 11
#define misopin 12
#define clkpin 13

// SD chip select pin
const uint8_t chipSelect = 42;

Adafruit_VS1053_FilePlayer musicPlayer =
   Adafruit_VS1053_FilePlayer(mosipin, misopin, clkpin, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, chipSelect);  // create breakout-example object!
 

char* speech[] = {
  "MUSIC/talk.mp3",
  "MUSIC/hungry.mp3",
  "MUSIC/thirsty.mp3",
  "MUSIC/bathroom.mp3",
  "MUSIC/clean.mp3",
  "MUSIC/sick.mp3",
  "MUSIC/wheelc.mp3"
};

char* images[] = {
  "talk.raw",
  "hungry.raw",
  "thirsty.raw",
  "bathroom.raw",
  "clean.raw",
  "sick.raw",
  "wheelc.raw"
};

#define NUM_ACTIONS (sizeof(images) / sizeof(char*))

char* music[] = {
  "MUSIC/track001.mp3",
  "MUSIC/track002.mp3",
  "MUSIC/track003.mp3",
  "MUSIC/track004.mp3",
  "MUSIC/track005.mp3",
  "MUSIC/track006.mp3",
  "MUSIC/track007.mp3",
  "MUSIC/track008.mp3",
  "MUSIC/track009.mp3",
  "MUSIC/track010.mp3",
  "MUSIC/track011.mp3",
  "MUSIC/track012.mp3",
  "MUSIC/track013.mp3",
  "MUSIC/track014.mp3",
  "MUSIC/track015.mp3",
  "MUSIC/track016.mp3",
  "MUSIC/track017.mp3",
  "MUSIC/track018.mp3",
  "MUSIC/track019.mp3",
  "MUSIC/track020.mp3",
  "MUSIC/track021.mp3",
  "MUSIC/track022.mp3",
  "MUSIC/track023.mp3",
  "MUSIC/track024.mp3",
  "MUSIC/track025.mp3",
};

#define NUM_TRACKS (sizeof(music) / sizeof(char*))


long  imageStart;
int   actionIndex;
bool  playActions;

uint8_t buttonState,
        prevButtonState;

#define P_BUTTON 2


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

    while (!Serial) {
    ; // wait for serial port to connect. Needed for DUE & Leonardo only
  }

  // initialise the music player
  if (! musicPlayer.begin()) {
    Serial.println(F("Couldn't find VS1053!"));
  }
  else
  {
    Serial.println(F("VS1053 found"));
  }
 
  if (!musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) { // DREQ int
    Serial.println(F("DREQ Pin problem"));
  }
 
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(30,30);

  pinMode(P_BUTTON, INPUT_PULLUP);
  buttonState = HIGH;
  prevButtonState = HIGH;
 
  imageStart = millis() - 3000;
  actionIndex = -1;
  playActions = true;
 
  //Improves Random selection

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

void loop() {
 
  if (actionIndex >= NUM_ACTIONS)
  {
    playMusic();
    playActions = false;
  }
  else
  {
    if ((millis() - imageStart) >= 3000)
    {
      actionIndex++;
      imageStart = millis();
      if (actionIndex < NUM_ACTIONS)
      {
        sd_Files.load(0, 0, 800, 480, images[actionIndex], 16);
        playActions = true;
      }
    }
  }
  if (buttonPressed())
  {
    if (playActions)
    {
      musicPlayer.playFullFile(speech[actionIndex]);
    }
    else
    {
      stopMusic();
      imageStart = millis() - 3000;
      actionIndex = -1;
    }
  }
}

void playMusic()
{
  if (musicPlayer.stopped())
  {
    int trackNumber = random(0, NUM_TRACKS);
    musicPlayer.startPlayingFile(music[trackNumber]);
  }
}

void stopMusic()
{
  if (!musicPlayer.stopped())
    musicPlayer.stopPlaying();
}
       
bool buttonPressed()
{
  bool pressed;
  buttonState = debounceRead(P_BUTTON);
  pressed = ((LOW == buttonState) && (buttonState != prevButtonState));
  prevButtonState = buttonState;
  return pressed;
}

uint8_t debounceRead(int pin)
{
  uint8_t pinState = digitalRead(pin);
  uint32_t timeout = millis();
  while ((millis() - timeout) < 10)
  {
    if (digitalRead(pin) != pinState)
    {
      pinState = digitalRead(pin);
      timeout = millis();
    }
  }

  return pinState;
}

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Mon Sep 07, 2015 3:38 pm

Hi Rick,

Thank you for that, it will be a useful reference. I played around with it and didn't get too far. Currently the screen fills up white at initialization but after that no pictures display and pressing the button doesn't do anything.

Code: Select all | TOGGLE FULL SIZE
#include <UTFT.h>
#include <UTouch.h>
#include <UTFT_Buttons.h>
#include <SPI.h>
#include <UTFT_SdRaw.h>
#include <SdFat.h>
#include <Adafruit_VS1053.h>
#include <DueFlashStorage.h>

// #include <SD.h>

UTFT          display_LCD(EHOUSE70, 22, 23, 31, 33);
UTouch        touch(25, 26, 27, 29, 30);
UTFT_Buttons  button(&display_LCD, &touch);
UTFT_SdRaw    sd_Files(&display_LCD);


#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// #define CARDCS 4               // Card chip select pin
#define DREQ 3                 // VS1053 Data request, ideally an Interrupt pin
#define mosipin 11
#define misopin 12
#define clkpin 13

// SD chip select pin
const uint8_t chipSelect = 42;

Adafruit_VS1053_FilePlayer musicPlayer =
   Adafruit_VS1053_FilePlayer(mosipin, misopin, clkpin, BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, chipSelect);  // create breakout-example object!
 

char* speech[] = {
  "MUSIC/talk.mp3",
  "MUSIC/hungry.mp3",
  "MUSIC/thirsty.mp3",
  "MUSIC/bathroom.mp3",
  "MUSIC/clean.mp3",
  "MUSIC/sick.mp3",
  "MUSIC/wheelc.mp3"
};

char* images[] = {
  "talk.raw",
  "hungry.raw",
  "thirsty.raw",
  "bathroom.raw",
  "clean.raw",
  "sick.raw",
  "wheelc.raw"
};

#define NUM_ACTIONS (sizeof(images) / sizeof(char*))

char* music[] = {
  "MUSIC/track001.mp3",
  "MUSIC/track002.mp3",
  "MUSIC/track003.mp3",
  "MUSIC/track004.mp3",
  "MUSIC/track005.mp3",
  "MUSIC/track006.mp3",
  "MUSIC/track007.mp3",
  "MUSIC/track008.mp3",
  "MUSIC/track009.mp3",
  "MUSIC/track010.mp3",
  "MUSIC/track011.mp3",
  "MUSIC/track012.mp3",
  "MUSIC/track013.mp3",
  "MUSIC/track014.mp3",
  "MUSIC/track015.mp3",
  "MUSIC/track016.mp3",
  "MUSIC/track017.mp3",
  "MUSIC/track018.mp3",
  "MUSIC/track019.mp3",
  "MUSIC/track020.mp3",
  "MUSIC/track021.mp3",
  "MUSIC/track022.mp3",
  "MUSIC/track023.mp3",
  "MUSIC/track024.mp3",
  "MUSIC/track025.mp3",
};

#define NUM_TRACKS (sizeof(music) / sizeof(char*))

// file system object
SdFat sd;

long  imageStart;
int   actionIndex;
bool  playActions;

uint8_t buttonState,
        prevButtonState;
       
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
extern uint8_t SevenSegNumFont[];
extern uint8_t Dingbats1_XL[];
extern uint8_t arial_bold[];

#define P_BUTTON 2


void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

    while (!Serial) {
    ; // wait for serial port to connect. Needed for DUE & Leonardo only
  }

  Serial.println(F("Initialising SD card..."));
  bool mysd = 0;
  // see if the card is present and can be initialized:
  while (!mysd)
  {
    if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
      Serial.println(F("Card failed, or not present"));
      Serial.println(F("Retrying...."));
    }
    else
    {
      mysd = 1;
      Serial.println(F("Card initialised."));
    }
  }

///////////////////////////////////////////////////////////////////////////////////

// Setup the LCD
  Serial.println(F("Initialising LCD."));
  display_LCD.InitLCD();
  display_LCD.clrScr();
  display_LCD.setFont(BigFont);
  display_LCD.clrScr();
  display_LCD.fillScr(255, 255, 255); //Fill screen with white color
  touch.InitTouch();
  touch.setPrecision(PREC_EXTREME);
  button.setTextFont(arial_bold);
  button.setSymbolFont(Dingbats1_XL);
  Serial.println(F("LCD initialised."));

////////////////////////////////////////////////////////////////////////////////////
  // initialise the music player
  if (! musicPlayer.begin()) {
    Serial.println(F("Couldn't find VS1053, however library has been modified so it is ok."));
  }
  else
  {
    Serial.println(F("VS1053 found"));
  }
 
  if (!musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT)) { // DREQ int
    Serial.println(F("DREQ Pin problem"));
  }
 
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(30,30);

  pinMode(P_BUTTON, INPUT_PULLUP);
  buttonState = HIGH;
  prevButtonState = HIGH;
 
  imageStart = millis() - 3000;
  actionIndex = -1;
  playActions = true;
 
  //Improves Random selection

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

void loop() {

    Serial.println(F("Program Running."));
 
  if (actionIndex >= NUM_ACTIONS)
  {
    playMusic();
    playActions = false;
  }
  else
  {
    if ((millis() - imageStart) >= 3000)
    {
      actionIndex++;
      imageStart = millis();
      if (actionIndex < NUM_ACTIONS)
      {
//        sd_Files.load(0, 0, 800, 480, images[actionIndex], 16);

        int ret1 = sd_Files.load(0, 0, 800, 480, "hungry.raw", 16);          //Testing to see if it has to do with images[actionIndex]
        playActions = true;
      }
    }
  }
  if (buttonPressed())
  {
    if (playActions)
    {
      musicPlayer.playFullFile(speech[actionIndex]);
    }
    else
    {
      stopMusic();
      imageStart = millis() - 3000;
      actionIndex = -1;
    }
  }
}

void playMusic()
{
  if (musicPlayer.stopped())
  {
    int trackNumber = random(0, NUM_TRACKS);
    musicPlayer.startPlayingFile(music[trackNumber]);
  }
}

void stopMusic()
{
  if (!musicPlayer.stopped())
    musicPlayer.stopPlaying();
}
       
bool buttonPressed()
{
  bool pressed;
  buttonState = debounceRead(P_BUTTON);
  pressed = ((LOW == buttonState) && (buttonState != prevButtonState));
  prevButtonState = buttonState;
  return pressed;
}

uint8_t debounceRead(int pin)
{
  uint8_t pinState = digitalRead(pin);
  uint32_t timeout = millis();
  while ((millis() - timeout) < 10)
  {
    if (digitalRead(pin) != pinState)
    {
      pinState = digitalRead(pin);
      timeout = millis();
    }
  }

  return pinState;
}



However, after playing around with the original code I had (although not perfect), it is now working including stop functionality using the button and looping as intended.

Now the only thing is, it still only plays one track at a time.

After implementing this:

Code: Select all | TOGGLE FULL SIZE
  if (musicPlayer.stopped())
  {
    int trackNumber = random(0, NUM_TRACKS);
    musicPlayer.startPlayingFile(music[trackNumber]);
  }


into my code.

Does your code have playing ALL files randomly and continuously, and does this have something to do with it? I just need track1 to play then track2 and so one with the ability to stop during any track.

Code: Select all | TOGGLE FULL SIZE
if (actionIndex >= NUM_ACTIONS)
  {
    playMusic();
    playActions = false;
  }

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Mon Sep 07, 2015 4:02 pm

Oh - I thought you wanted the music tracks to be randomized. You can just use an index variable and play them in order.

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Mon Sep 07, 2015 5:02 pm

My mistake, I do want them to be randomized. So it plays random track1, then plays another random track, etc.

But for this example's sake and to keep it clear, let's go with an ordered sequence for now.

So after implementing this

Code: Select all | TOGGLE FULL SIZE
if (musicPlayer.stopped())
  {
    int trackNumber = random(0, NUM_TRACKS);
    musicPlayer.startPlayingFile(music[0]);
    musicPlayer.stopped();
    Serial.println(F("Playing Random Track 1."));
    delay(100);
    musicPlayer.startPlayingFile(music[1]);
    musicPlayer.stopped();
    Serial.println(F("Playing Random Track 2."));
    delay(100);
      }


It only plays Track 2 where as I would like both to be played back to back.

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Tue Sep 08, 2015 10:21 am

That code will play track 1 for 100ms and then play track 2.

If you want to simply play two files in sequence, then use playFullFile:
Code: Select all | TOGGLE FULL SIZE
if (musicPlayer.stopped())
  {
    musicPlayer.playFullFile(music[0]);
    musicPlayer.playFullFile(music[1]);
      }

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by ndnbolla on Tue Sep 08, 2015 12:44 pm

But now it no longer uses interrupts and I have no way of stopping in the middle of any tracks.

ndnbolla
 
Posts: 31
Joined: Tue Mar 31, 2015 11:17 am

Re: VS1053 + Pushbutton + Stop Playing issue

by adafruit_support_rick on Wed Sep 09, 2015 7:50 am

You need to go back to the sketch I posted earlier. The logic there is simple: on each time through loop, it checks the button. Whatever it's currently doing, whether it's displaying an activity or playing a random music track, it takes the appropriate action for the button press.

If you do it your way, you're going to have to check the button everywhere.

However, if you want to do it that way, try this:
Code: Select all | TOGGLE FULL SIZE
if (musicPlayer.stopped())
  {
    do {
    int trackNumber = random(0, NUM_TRACKS);
    bool pressed = false;
    musicPlayer.startPlayingFile(music[trackNumber]);
    Serial.print(F("Playing Random Track ")); Serial.println(trackNumber);
    while (!musicPlayer.stopped()) && (!pressed)) {
      pressed = buttonPressed();
    }
    delay(100);
    } while (!pressed);
  }


buttonPressed() is in the previous code I posted.

adafruit_support_rick
 
Posts: 35095
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: VS1053 + Pushbutton + Stop Playing issue

by Vomitcomet on Fri Feb 01, 2019 12:19 am

The following code worked great for a simple portion of my Audio Project using a Particle Photon (with a few modifications to include SPI pins and modify the DREQ constant within the header file). Just wanted to send a quick thank you to Rick!

adafruit_support_rick wrote:It's not enough to set pressed to HIGH. You're interested in the state change when the button is initially pressed. That change happens when the pin first goes from HIGH to LOW. So you need to know the *previous* state of the button as well as the *current* state of the button. You *only* do something when the previous state was HIGH and the current state is LOW.

Have a look at this:
Code: Select all | TOGGLE FULL SIZE
/***************************************************
  This is an example for the Adafruit VS1053 Codec Breakout

  Designed specifically to work with the Adafruit VS1053 Codec Breakout
  ----> https://www.adafruit.com/products/1381

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries. 
  BSD license, all text above must be included in any redistribution
 ****************************************************/

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

// define the pins used
//#define CLK 13       // SPI Clock, shared with SD card
//#define MISO 12      // Input data, from VS1053/SD card
//#define MOSI 11      // Output data, to VS1053/SD card
// Connect CLK, MISO and MOSI to hardware SPI pins.
// See http://arduino.cc/en/Reference/SPI "Connections"

// These are the pins used for the breakout example
#define BREAKOUT_RESET  9      // VS1053 reset pin (output)
#define BREAKOUT_CS     10     // VS1053 chip select pin (output)
#define BREAKOUT_DCS    8      // VS1053 Data/command select pin (output)
// 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 =
  // create breakout-example object!
  Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);
  // create shield-example object!
  //Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
 
 
const int p_button = 2;     // the number of the pushbutton pin

uint8_t buttonState,
        prevButtonState;

void setup() {
  Serial.begin(9600);
  Serial.println("Adafruit VS1053 Simple Test");

  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"));
 
  SD.begin(CARDCS);    // initialise the SD card
 
  // Set volume for left, right channels. lower numbers == louder volume!
  musicPlayer.setVolume(20,20);

  // Timer interrupts are not suggested, better to use DREQ interrupt!
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int

  // If DREQ is on an interrupt pin (on uno, #2 or #3) we can do background
  // audio playing
  musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int
 
  pinMode(p_button, INPUT_PULLUP);
  buttonState = HIGH;
  prevButtonState = HIGH;

}


void loop()
{
 //////////////////////////////////////////////////////////////////////////////////////////////

  buttonState = debounceRead(p_button);
  if ((LOW == buttonState) && (buttonState != prevButtonState)) //if button was just pressed
  {
   
    if (musicPlayer.stopped())
    {
      if (! musicPlayer.startPlayingFile("MUSIC/track002.mp3")) {
        Serial.println("Could not open file track002.mp3");
        while (1);
      }
      Serial.println(F("Started playing"));
    }
    else
    {
      musicPlayer.stopPlaying();
    }
  }
  prevButtonState = buttonState;  //update prevButtonState

/////////////////////////////////////////////////////////////////////////////////////////////
}

//Use like digitalRead. Incorporates button debouncing.
uint8_t debounceRead(int pin)
{
  uint8_t pinState = digitalRead(pin);
  uint32_t timeout = millis();
  while (millis() < timeout+10)
  {
    if (digitalRead(pin) != pinState)
    {
      pinState = digitalRead(pin);
      timeout = millis();
    }
  }

  return pinState;
}

Vomitcomet
 
Posts: 7
Joined: Fri Feb 01, 2019 12:16 am

Please be positive and constructive with your questions and comments.