Teensy LC + VS1053 musicPlayer.begin() don't work when in the Main loop.

Demokrato

New member
Hi there,

Background of the project :
I'm working on a project where I alternately switch from playing audio to recording audio with the Adafruit VS0153 breakout board. I had a program working fine using an arduino UNO, in exception of the loading time of the plugin made for the the audio recording (I managed to reduce the loading time by half by modifiing the library, but it was still too long). Therefore i swiched to a Teensy LC i had laying around, hoping the 32 bits capacity would make this loading time faster.

Problem :
After adapting the program for the teensy LC (basicaly just changing the pins and the source library), nothing really worked anymore. Main thing beeing the audio started to play and stopped right away.


Investigations on my side :
- The Player simple exemple works great
- When diging in the library I notice that in the feedbuffer() function, the "while (readyForData()) " get called repetedly for from 2 to 32 time when used in the Player simple exemple, and only once for approx 150 times when used in my exemple. (see picture)
- as soon as I add the musicPlayer.begin() function in the main loop in the player simple I get the same symptoms as in my own program (even if I put an if condition to make sure that the musicPlayer.begin() will only be called if the musicPlayer wasn't already done)

Question :
As I need to alternate between recording and playing, (and therefore having to re-redo a musicPlayer.begin() when I'm swiching from one to an other). Is there a way I could make the teensy accept the musicPlayer.begin() function in the main loop ?

Thanks in advance,

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

#define Decrocheur A0

// 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)
#define CARDCS 7     // Card chip select pin
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin



Adafruit_VS1053_FilePlayer musicPlayer =
  Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);

bool initialized_audio = 0;

void setup() {
  Serial.begin(9600);
  
  // init des pins en lecture
  pinMode (Decrocheur, INPUT_PULLUP);
  pinMode (Composition_en_cours, INPUT_PULLUP);
  pinMode (Valeur_compo, INPUT);

  
  // 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);
  }
  bool initialized_audio = 1;
  Serial.println(F("VS1053 found"));

  //musicPlayer.sineTest(0x44, 500);    // Make a tone to indicate VS1053 is working

  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(20, 20);

  /***** Two interrupt options! *******/
  // This option uses timer0, this means timer1 & t2 are not required
  // (so you can use 'em for Servos, etc) BUT millis() can lose time
  // since we're hitchhiking on top of the millis() tracker
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT);

  // This option uses a pin interrupt. No timers required! But DREQ
  // must be on an interrupt pin. For Uno/Duemilanove/Diecimilla
  // that's Digital #2 or #3
  // See http://arduino.cc/en/Reference/attachInterrupt for other pins
  // *** This method is preferred
  if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
    Serial.println(F("DREQ pin is not an interrupt pin"));
}

void loop() {

  // Start playing a file, then we can do stuff while waiting for it to finish
  if (initialized_audio == 0){
    initialized_audio =1;
    /*  if (! musicPlayer.begin()) { // initialise the music player  -> don't work when placed here, even if the programm don't go through the loop
      Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
      while (1);
    } */
    Serial.println(F("hi there ?"));
    delay(500);   //  Make the that the play function doesn't start to quickly after
  }
  if (! musicPlayer.startPlayingFile("track001.mp3")) {
    Serial.println("Could not open file track001.mp3");
    while (1);
  }
  Serial.println(F("Started playing"));

  while (musicPlayer.playingMusic) {
    if (digitalRead(Decrocheur) == HIGH) {
      musicPlayer.stopPlaying();
    }
  }
  Serial.println("Done playing music");
}


/// 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();
  }
}

Capture d’écran 2022-07-31 100843.png
 
Last edited:
Sorry, I realised I uploaded an old version of the code with mistakes, here is the correct one :

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

#define Decrocheur A0

// 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)
#define CARDCS 7     // Card chip select pin
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin



Adafruit_VS1053_FilePlayer musicPlayer =
  Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, CARDCS);

bool initialized_audio = 0;

void setup() {
  Serial.begin(9600);
  
  // init des pins en lecture
  pinMode (Decrocheur, INPUT_PULLUP);
  pinMode (Composition_en_cours, INPUT_PULLUP);
  pinMode (Valeur_compo, INPUT);

  
  // initialise the music player
  /*
  if (! musicPlayer.begin()) { // initialise the music player      If placed here the begin() function works
    Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
    while (1);
  } */
  
  Serial.println(F("VS1053 found"));

  //musicPlayer.sineTest(0x44, 500);    // Make a tone to indicate VS1053 is working

  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(20, 20);

  /***** Two interrupt options! *******/
  // This option uses timer0, this means timer1 & t2 are not required
  // (so you can use 'em for Servos, etc) BUT millis() can lose time
  // since we're hitchhiking on top of the millis() tracker
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT);

  // This option uses a pin interrupt. No timers required! But DREQ
  // must be on an interrupt pin. For Uno/Duemilanove/Diecimilla
  // that's Digital #2 or #3
  // See http://arduino.cc/en/Reference/attachInterrupt for other pins
  // *** This method is preferred
  if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
    Serial.println(F("DREQ pin is not an interrupt pin"));
}

void loop() {

  // Start playing a file, then we can do stuff while waiting for it to finish
  if (initialized_audio == 0){
    initialized_audio =1;
    if (! musicPlayer.begin()) { // initialise the music player  -> player don't work when begin() is placed here, even if called only once
      Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
      while (1);
    }
    Serial.println(F("hi there ?"));
    delay(500);   //  Make the that the play function doesn't start to quickly after
  }
  if (! musicPlayer.startPlayingFile("track001.mp3")) {
    Serial.println("Could not open file track001.mp3");
    while (1);
  }
  Serial.println(F("Started playing"));

  while (musicPlayer.playingMusic) {
    if (digitalRead(Decrocheur) == HIGH) {
      musicPlayer.stopPlaying();
    }
  }
  Serial.println("Done playing music");
}


/// 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();
  }
}
 
Sorry, I don't have your setup, so cannot test.

But the things I would try include moving the calls:
Code:
  musicPlayer.setVolume(20, 20);

  /***** Two interrupt options! *******/
  // This option uses timer0, this means timer1 & t2 are not required
  // (so you can use 'em for Servos, etc) BUT millis() can lose time
  // since we're hitchhiking on top of the millis() tracker
  //musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT);

  // This option uses a pin interrupt. No timers required! But DREQ
  // must be on an interrupt pin. For Uno/Duemilanove/Diecimilla
  // that's Digital #2 or #3
  // See http://arduino.cc/en/Reference/attachInterrupt for other pins
  // *** This method is preferred
  if (!musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
    Serial.println(F("DREQ pin is not an interrupt pin"));
into loop as well, within the same if block as the begin... After the begin
 
Hi KurtE,
You spotted the right point, I just tried it and it worked with the Interrupt initialisation into the loop.
Thanks a lot !

I still don't understand why it worked on the an ATMEGA 328 and not on the Teensy LC but I guess the interrupts work a bit differently on both µC
 
Hi KurtE,
You spotted the right point, I just tried it and it worked with the Interrupt initialisation into the loop.
Thanks a lot !

I still don't understand why it worked on the an ATMEGA 328 and not on the Teensy LC but I guess the interrupts work a bit differently on both µC

IIRC, not all pins have interrupt capability on the LC. Let's see, from the back of the LC card, pins 0, 1, 16/A2, 17/A3,18/A4, 19/A5, 24/A10, 25/A11 and 26/AC12 aren't listed as having interrupts.
 
Back
Top