Es schein doch im Hintergrund zu laufen.
Aber irgendwie habe ich da ein unzuverlässig funktionierendes Programm.
//mp3 player for kids
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Rotary.h>
#include <Adafruit_VS1053.h>
#include <SdFat.h>
#include <SPI.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 SHIELD_CS 7 // VS1053 chip select pin (output)
#define SHIELD_DCS 6 // VS1053 Data/command select pin (output)
#define DREQ 3 // VS1053 Data request, ideally an Interrupt pin
#define CARDCS 4 // Card chip select pin
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);
// VS1053 play speed parameter
#define para_playSpeed 0x1E04
const uint8_t chipSelect = 4;
const int analogButtonsPin = A5;
SdFat sd;
SdFile file;
LiquidCrystal_I2C lcd(0x3f,16,2); //LCD Display mit 16 Zeichen und 2 Zeilen
Rotary r = Rotary(18, 19); //Encoder auf digitalen Eingängen
volatile int counter=1;
int lastCounter=0;
const int cMax=6; //Anzahl der Ordner
const int cMin=1;
char fName[]="/mp3.txt"; //Dateiname mit CSV-Datei
char vNum[16];
char* path; //Dateipfad für mp3.txt
byte currentFolder = 1; //mp3 player
unsigned int currentFile = 0;
unsigned int numberOfFiles[100];
byte volumeState = 254; // the current volume level, set to min at start
int pressedButton = 0;
#define N 2 //2 Elemente werden gelsen
char text[N][17]; // mit je 16 Zeichen
void encoder() { //Interrupt Funktion für Encoder
unsigned char result = r.process(); //Encoderwert bestimmen
if (result) {
if (result==16){
if (counter > cMin) counter--;
else counter = cMax; //Begrenzung des Wertebereichs
}
if (result==32){
if (counter < cMax) counter++;
else counter = cMin; //Begrenzung des Wertebereichs
}
Serial.println(counter);
}
}
void setup() {
Serial.begin(9600);
attachInterrupt(4, encoder, CHANGE);
attachInterrupt(5, encoder, CHANGE);
if (!musicPlayer.begin()){
Serial.println("VS1053 not found");
while (1); // don't do anything more
}
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) { // initialise the music player
sd.initErrorHalt();
}
for (byte i = cMin; i <= cMax; i++)
{
numberOfFiles[i]=countFiles(i);
Serial.println(numberOfFiles[i]-1);
}
// 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
musicPlayer.sineTest(0x44, 100); // 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
}
if (! musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
Serial.println(F("DREQ pin is not an interrupt pin"));
lcd.init();
lcd.backlight();
}
unsigned int countFiles(int index){
int fileCount = 0;
char dirName[8];
sprintf(dirName,"%02i",index);
Serial.print(dirName);
Serial.print(" / ");
sd.chdir(dirName);
sd.vwd()->rewind();
while (file.openNext(sd.vwd(), O_READ)) {
if (!file.isHidden()) {
fileCount++;
}
file.close();
}
sd.chdir("/");
return fileCount;
}
void readFileToVars(char* fn){
byte i,feld;
char c;
sd.chdir("/");
ifstream file(fn);
if (!file.is_open()){
sd.errorHalt("File open failed");
}
else{
i=0;feld=0;
while ((c = file.get()) >= 0)
{
switch(c){ //zeichen werden zusammengesetzt
case '\r': break;
case ';' : { //Trennzeichen
feld++;
i=0;
break;
}
default:
if (c>=32){
text[feld][i]=c;
i++;
}
}
}
}
file.close();
}
void displayChange(int num){
lcd.clear();
sprintf(vNum,"%02i",num); //Zeichenkette wird formatiert
path = strcat(vNum,fName); //Pfad mit Dateiname zusammenfügen z.B. "04/mp3.txt"
readFileToVars(path);
for (int i=0;i<N;i++) //Text wird in N Zeilen geschrieben
{
lcd.setCursor(0,i); //Zeile wählen
lcd.print(text[i]); //Anzeige im Display
Serial.println(text[i]);
for (int j=0; j<17; ++j) {text[i][j] = 0; } //lösche alten Inhalt
}
}
void loop(){
if (counter != lastCounter){ //Aktualisiere Anzeige wenn sich Zähler ändert
displayChange(counter);
lastCounter=counter;
}
pressedButton = getPressedButton();
delay(100);
if (pressedButton != 0){
Serial.print("Taste: ");
Serial.println(pressedButton);
checkButtons(pressedButton);
}
}
void checkButtons(byte buttonNum)
{
char* playFile;
sprintf(vNum,"%02i",counter);
playFile=strcat(vNum,"/1.mp3");
Serial.print(playFile);
switch(buttonNum){ //zeichen werden zusammengesetzt
case 1: if (! musicPlayer.startPlayingFile(playFile)) { //"02/1.mp3"
Serial.println("Could not open track");
//while (1);
}
//break;
case 2: break;
}
}
byte getPressedButton()
{
int buttonsPinValue = analogRead(analogButtonsPin);
byte pressedButton = 0;
char dirName[8];
if (buttonsPinValue < 100) pressedButton = 1;
return pressedButton;
}
Auf der SD Karte sind Verzeichnisse von 0 bis 6.
In jedem Verzeichnis sind mp3 Dateien 1..n und jeweils eine mp3.txt die den Namen des Albums enthält, der wiederum auf einem 16/2 Display angezeigt wird. Die Auswahl der Alben funkltioniert über einen Drehencoder.
Das alles funktionierte einwandfrei, bis ich die mp3 Abspielfunktion einbaute.
Jetzt gibt es oft Fehler beim laden der SD K arte, aber nicht immer.
Mein Vermutung ist folgende:
Während der musicplayer auf die Karte zugreift kann die Text-Datei nicht gelesen werden.
Lösung:
Alle mp3.txt zu beginn in eine chr Array laden.
Kann mal jemand schauen ob meine vermutung stimmt?