This is my first post here as a Particle newbie so please forgive and correct any issues with my post.
I am attempting to get an Adafruit VS1053B MP3 Decoder (Model 1381 V4) working with limited success. Sine wave and volume functions work fine, but my MP3’s are stopping randomly midstream and the led status goes to a solid cyan. They play for random lengths of time, anywhere from 5 seconds to their full length. Sometimes it will play 5-6 songs in a row and then die. Sometimes it dies on the first song. If I play the same song five times in a row it will die at different times and sometimes play to completion. During the time they do play the quality is excellent.
Here are things I’ve tried, all with no improvement:
Various bitrates from 64, 128, 225 and 256. A total of 30+ MP3s tried.
Two brand new Adafruit VS1053B boards.
Three different Sandisk Ultra HC class 10 cards.
De-spiking caps.
10K pullups on the SPI data pins.
Re-routing my wiring.
Various code mods.
I am using ScruffR’s VS1053B cpp and header and have tried a number of changes to the player_simple code. I have butchered things up a bit experimenting. I think I have my SPI pins and connections set up correctly, but haven’t tried the alternate set of SPI pins yet. I think my choice for DREQ pin is OK. I don’t know if set the "musicPlayer.useInterrupt(5)’ up properly because I had problems with the VS1053_FILEPLAYER_PIN_INT (but it said the value was 5 so I used that?)
Any suggestion would be much appreciated.
This is the INO
#include "application.h"
# define PREFER_SDFAT_LIBRARY 1
//# define ARDUINO_STM32_FEATHER 1
# define PARTICLE 1
// ********************************************************************** /
// This is a library for the Adafruit VS1053 Codec Breakout
//
// Designed specifically to work with the Adafruit VS1053 Codec Breakout
// ---->adafruitcom_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
//
// Original library: githubcom_adafruit_Adafruit_VS1053_Library
//
// Ported for Particle by ScruffR
// Forked and ported: githubcom_ScruffR_Adafruit_VS1053_Library
// ********************************************************************** /
//
// To run this example prepare a micro SD card with a file hierarchy like
// SD:
// ????01
// 001.mp3
// 002.mp3
// optionally up to ...
// 998.mp3
// 999.mp3
//
// ********************************************************************** /
SYSTEM_THREAD(ENABLED)
#include "SdFat.h"
#include "Adafruit_VS1053.h"
//SerialLogHandler traceLog(LOG_LEVEL_WARN, { { "app", LOG_LEVEL_INFO } });
SdFat SD;
#define CLK A3//13 // SPI Clock, shared with SD card BM "SCLK"
#define MISO A4//12 // Input data, from VS1053/SD card BM "MISO"
#define MOSI A5//11 // Output data, to VS1053/SD card BM "MOSI"
// These are the pins used for the music maker FeatherWing
const int MP3_RESET = D1; // VS1053 reset pin BM "RST"
const int SD_CS = A2; // SD Card chip select pin BM "SDCS"
const int MP3_CS = D3; // VS1053 chip select pin (output) BM "CS"
const int DREQ = D4; // VS1053 Data request, ideally an Interrupt pin BM "DREQ"
const int MP3_DCS = D5; // VS1053 Data/command select pin (output) BM "XDCS"
const char *fileNamePattern = "%03d.mp3"; // file name pattern to insert track number
Adafruit_VS1053_FilePlayer musicPlayer(MP3_RESET, MP3_CS, MP3_DCS, DREQ, SD_CS);
int trackNumber = 0;
bool needStart = false;
//bool needs_restart = false;
int led_debug = D6;
void setup() {
pinMode(A3, OUTPUT);
pinMode(A4, INPUT);
pinMode(A5, OUTPUT);
pinMode(D6, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(D1, OUTPUT);
pinMode(D7, OUTPUT);
//led_blink_fast(10);
Particle.function("playSine", playSine);
Particle.function("playTrack", playTrack);
Particle.function("setVolume", setVolume);
Particle.function("resetVS1053", resetVS1053);
if (!SD.begin(SD_CS)) {
//Log.error("SD failed, or not present");
while(1) yield(); // don't do anything more
}
led_blink_slow(5);
Serial.println("SD OK!");
//Log.info("Adafruit VS1053 Library Test");
// initialise the music player
if (!musicPlayer.begin()) { // initialise the music player
Log.error("Couldn't find VS1053, do you have the right pins defined?");
while(1) yield();
}
//Log.info("VS1053 found");
led_blink_fast(10);
// Make a tone to indicate VS1053 is working
musicPlayer.sineTest(0x44, 200);
// set current working directory
SD.chdir("/01", true);
// list files
//SD.ls(&Serial, LS_R);
// Set volume for left, right channels. lower numbers == louder volume!
musicPlayer.setVolume(11,11);
// ***** 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(5))//DREQ
{
digitalWrite(D7, HIGH);
musicPlayer.setIsrCallback(blink);
}
else
Log.info("DREQ pin is not an interrupt pin");
// Alternatively just play an entire file at once
// This doesn't happen in the background, instead, the entire
// file is played and the program will continue when it's done!
// musicPlayer.sineTest(0x44, 200);
//musicPlayer.playFullFile("001.mp3");
}
void loop() {
static uint32_t msPlayStarted = 0;
static uint32_t msLastAction = 0;
if (needStart && trackNumber) {
char fileName[32];
char msg[128];
uint32_t us = micros();
// Start playing a file, then we can do stuff while waiting for it to finish
snprintf(fileName, sizeof(fileName), fileNamePattern, trackNumber);
//Log.trace("Starting: %lu", micros() - us); us = micros();
if (musicPlayer.startPlayingFile(fileName)) {
//Log.trace("Started: %lu", micros() - us);
us = micros();
snprintf(msg, sizeof(msg), "Started playing '%s'",fileName);
msPlayStarted = millis();
}
else {
//Log.trace("Not started: %lu", micros() - us);
us = micros();
snprintf(msg, sizeof(msg), "Could not open file '%s'",fileName);
}
//Log.info(msg);
needStart = false;
}
if (millis() - msLastAction >= 1000) {
uint32_t sec = (millis() - msPlayStarted) / 1000.0;
//led_blink_fast(1);
// file is now playing in the 'background' so now's a good time
// to do something else like handling LEDs or buttons :)
msLastAction = millis();
//Serial.printf("\r%02lu:%02lu %s ", sec / 60, sec % 60, musicPlayer.playingMusic ? "playing" : "stopped");
}
}
void led_blink_fast(int reps)
{
for (size_t i = 0; i < reps; i++)
{
digitalWrite(led_debug, HIGH);
delay(10);
digitalWrite(led_debug, LOW);
delay(10); /* code */
}
}
void led_blink_slow(int reps)
{
for (size_t i = 0; i < reps; i++)
{
digitalWrite(led_debug, HIGH);
delay(500);
digitalWrite(led_debug, LOW);
delay(500); /* code */
}
}
int playTrack(const char* arg) {
int n = atoi(arg);
if (n > 0) {
trackNumber = n;
if (musicPlayer.playingMusic) {
musicPlayer.stopPlaying();
}
needStart = true;
}
return trackNumber;
}
int setVolume(const char* arg) {
int vol = atoi(arg);
musicPlayer.setVolume(vol, vol);
return vol;
}
int playSine(const char* arg) {
int freq = atoi(arg);
musicPlayer.sineTest(freq, 1000);
musicPlayer.reset();
return freq;
}
int resetVS1053(const char* arg){
int freq = atoi(arg);
musicPlayer.reset();
musicPlayer.begin();
return 1;
}
void blink(void) {
//digitalWriteFast(D7, !pinReadFast(D7));
}