Arduino Polska Forum

Pełna wersja: Mp3 player ;)
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Witajcie mam problem nie działa mi sciszanie,podgłasnianie + poprzenia piosenka sketch przerobiłem na tyle ile uwazałem ale problem pozostał, proszę o pomoc.

Kod:
#include <SPI.h>
#include <SD.h>
#include <EEPROM.h>
#include <VS1053.h>
#include <SoftwareSerial.h>// import the serial library

#define max_title_len 60
#define max_name_len  13
#define max_num_songs 40

#define read_buffer  256
#define mp3_vol      100 //range from 0(louder) to 100(really low)

#define volumeMemoryAddress  max_num_songs * max_name_len

#define sd_cs         10

VS1053 myVS(2, 7, 4, 8);
//Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, -1 ,4);

int BluetoothData; // the data given from Computer

File sd_file;

unsigned char num_songs = 0, current_song = 0;

char fn[max_name_len];

char title[max_title_len + 1];

enum state { DIR_PLAY, MP3_PLAY, PAUSED , NEXT , PREV};
state current_state = DIR_PLAY;

// set pin numbers:
const int buttonPinUp = A3;     // the number of the pushbutton pin
const int buttonPinDown = A4;     // the number of the pushbutton pin
const int ledPin =  9;      // the number of the LED pin
int buttonStateUp = 0;         // variable for reading the pushbutton status
int buttonStateDown = 0;         // variable for reading the pushbutton status

/*control volume variables*/
byte mp3_volume = 0; //variable to read initial value of volume

//Interrupt part
volatile int state = LOW;

void setup()
{

  // initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  // declare the ledPin as an OUTPUT:
// pinMode(sensorPin, INPUT);      // sets pin A5 as input
  
  //volume
  // initialize the pushbutton pin as an input:
  pinMode(buttonPinUp, INPUT);    
//volume
  // initialize the pushbutton pin as an input:
  pinMode(buttonPinDown, INPUT);      
  
  //interrupt
  pinMode(ledPin, OUTPUT);
  attachInterrupt(0, previous, FALLING );
  attachInterrupt(1, next, FALLING );
  attachInterrupt(4, play_pause, FALLING);
  
  SPI.begin();

  myVS.begin();

  
  //fetch volume from EEPROM
  mp3_volume = EEPROM.read(volumeMemoryAddress);
  //set volume
  myVS.setVolume(mp3_volume);
  
  sd_card_setup();
  sd_dir_setup();
  while (num_songs==0) {
  
    Serial.println("No songs on card");  
    delay(5000);
  }
  openSongFile(current_song);
  //song_title_to_display();
  song_title_to_cell_display();
}

void dir_play() {
  if (sd_file) {
    mp3_play();
  }
  else {
    if (current_song < (num_songs - 1)) {
      current_song++;
      openSongFile(current_song);
      //song_title_to_display();
      song_title_to_cell_display();
      myVS.startSong();
    }
    else {
      current_state = PAUSED;
    }
  }
}  

void mp3_play() {
  unsigned char bytes[read_buffer]; // buffer to read and send to the decoder
  unsigned int bytes_to_read;       // number of bytes read from microsd card

  bytes_to_read = sd_file.read(bytes, read_buffer);
  myVS.playChunk(bytes, bytes_to_read);
// Serial.println("Playing song");
  
  // 'bytes_to_read' is only smaller than 'read_buffer' when the song's over.

  if (bytes_to_read < read_buffer) {
    Serial.println("stoping song");
    sd_file.close();
    myVS.stopSong();
    
    // if we've been in the MP3_PLAY state, then we want to pause the player.
    if (current_state == MP3_PLAY) {
      current_state == PAUSED;
    }
  }
}

void previous_song(){
  
  Serial.println("Changing song ...");

   if (current_song >0) {
      sd_file.close();
      myVS.stopSong();
      current_song--;
      Serial.print("Going to song - ");
      Serial.println(current_song);
      openSongFile(current_song);
      song_title_to_cell_display();
      myVS.startSong();
      current_state=DIR_PLAY;
    }
    else {
      current_state = DIR_PLAY;
    }
}


void next_song(){
  
  Serial.println("Changing song ...");

   if (current_song < (num_songs - 1)) {
      sd_file.close();
      myVS.stopSong();
      current_song++;
      Serial.print("Going to song - ");
      Serial.println(current_song);
      openSongFile(current_song);
      song_title_to_cell_display();
      myVS.startSong();
      current_state=DIR_PLAY;
    }
    else {
      current_state = MP3_PLAY;
    }
}

/*interrupt services*/

void play_pause()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 300)
  {
    state = !state;
    
    if (current_state == DIR_PLAY) {
      current_state = PAUSED;
    }else{
      current_state=DIR_PLAY;
    }
  }
  last_interrupt_time = interrupt_time;
  
}

void next()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  //Serial.print("next interrrupt");
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    //
    if (current_state == DIR_PLAY || current_state == MP3_PLAY) {
      current_state = NEXT;
    }
  }
  last_interrupt_time = interrupt_time;
  
}

void previous(){
  
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    //
    if (current_state == DIR_PLAY || current_state == MP3_PLAY) {
      current_state = PREV;
    }
  }
  last_interrupt_time = interrupt_time;
  
}

void  change_volume(){
  // read the state of the pushbutton value:
  buttonStateUp = digitalRead(buttonPinUp);
  buttonStateDown = digitalRead(buttonPinDown);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonStateUp == LOW &&  mp3_volume>1) {    
    mp3_volume-=1;
  }
  else if(buttonStateDown == LOW && mp3_volume<150){
    mp3_volume+=1;
  }

}

void bluetoothProcessing(){
  
  unsigned long positionToSeek = sd_file.position();
  
    if (Serial.available()){
      
      BluetoothData=Serial.read();
      //Serial.print("BluetoothData");
      //Serial.println(BluetoothData);
     if(BluetoothData=='1'){   // if number 1 pressed ....
       digitalWrite(ledPin,1);
       Serial.println("Pause music ");
       play_pause();
      
     }
    if (BluetoothData=='2'){// if number 2 pressed ....
       digitalWrite(ledPin,0);
       Serial.println("Next ");
       next();
    }
    if (BluetoothData=='3'){// if number 3 pressed ....
       digitalWrite(ledPin,0);
       Serial.println("Previous ");
       previous();
    }
    if (BluetoothData=='4'){// if number 4 pressed ....
       if(mp3_volume>=1){
         digitalWrite(ledPin,0);
         Serial.println("Increase Vol ");
         mp3_volume-=1;
       }
    }
    if (BluetoothData=='5'){// if number 5 pressed ....
      if(mp3_volume<150){
         digitalWrite(ledPin,0);
         Serial.println("Decrease Vol ");
         mp3_volume+=1;
      }
    }
    if (BluetoothData=='6'){// if number 6 pressed ....
      digitalWrite(ledPin,0);
       Serial.println("Seeking ");
       //if(positionToSeek + 300 < sd_file.size() )
       positionToSeek = sd_file.size()/2 ;
       sd_file.seek(positionToSeek);
    }
    
  }
  //delay(100);// prepare for next data ...
  
}

void loop()
{
  
  digitalWrite(ledPin, state);
  
  //check for volume change
  change_volume();
  
  EEPROM.write(volumeMemoryAddress, mp3_volume);
  myVS.setVolume(mp3_volume);
  

  
  switch(current_state) {

    case DIR_PLAY:
      dir_play();
      break;

    case MP3_PLAY:
      mp3_play();
      break;

    case PAUSED:
      break;
    
    case NEXT:
      next_song();
      break;
      
    case PREV:
      previous_song();
      break;
      
  }
  
  bluetoothProcessing();
}

//Id3Tag

// this utility function reads id3v1 and id3v2 tags, if any are present, from
// mp3 audio files. if no tags are found, just use the title of the file. :-|

void get_title_from_id3tag () {
  unsigned char id3[3];       // pointer to the first 3 characters to read in

  // visit http://www.id3.org/id3v2.3.0 to learn all(!) about the id3v2 spec.
  // move the file pointer to the beginning, and read the first 3 characters.

  sd_file.seek(0);
  sd_file.read(id3, 3);
  
  // if these first 3 characters are 'ID3', then we have an id3v2 tag. if so,
  // a 'TIT2' (for ver2.3) or 'TT2' (for ver2.2) frame holds the song title.

  if (id3[0] == 'I' && id3[1] == 'D' && id3[2] == '3') {
    unsigned char pb[4];       // pointer to the last 4 characters we read in
    unsigned char c;           // the next 1 character in the file to be read
    
    // our first task is to find the length of the (whole) id3v2 tag. knowing
    // this means that we can look for 'TIT2' or 'TT2' frames only within the
    // tag's length, rather than the entire file (which can take a while).

    // skip 3 bytes (that we don't use), then read in the last 4 bytes of the
    // header, which contain the tag's length.

    sd_file.read(pb, 3);
    sd_file.read(pb, 4);
    
    // to combine these 4 bytes together into the single value, we first have
    // to shift each one over to get it into its correct 'digits' position. a
    // quirk of the spec is that bit 7 (the msb) of each byte is set to 0.
    
    unsigned long v2l = ((unsigned long) pb[0] << (7 * 3)) +
                        ((unsigned long) pb[1] << (7 * 2)) +
                        ((unsigned long) pb[2] << (7 * 1)) + pb[3];
                        
    // we just moved the file pointer 10 bytes into the file, so we reset it.
    
    sd_file.seek(0);

    while (1) {
      // read in bytes of the file, one by one, so we can check for the tags.
      
      sd_file.read(&c, 1);

      // keep shifting over previously-read bytes as we read in each new one.
      // that way we keep testing if we've found a 'TIT2' or 'TT2' frame yet.
      
      pb[0] = pb[1];
      pb[1] = pb[2];
      pb[2] = pb[3];
      pb[3] = c;

      if (pb[0] == 'T' && pb[1] == 'I' && pb[2] == 'T' && pb[3] == '2') {
        // found an id3v2.3 frame! the title's length is in the next 4 bytes.
        
        sd_file.read(pb, 4);

        // only the last of these bytes is likely needed, as it can represent
        // titles up to 255 characters. but to combine these 4 bytes together
        // into the single value, we first have to shift each one over to get
        // it into its correct 'digits' position.

        unsigned long tl = ((unsigned long) pb[0] << (8 * 3)) +
                           ((unsigned long) pb[1] << (8 * 2)) +
                           ((unsigned long) pb[2] << (8 * 1)) + pb[3];
        tl--;
        
        // skip 2 bytes (we don't use), then read in 1 byte of text encoding.

        sd_file.read(pb, 2);
        sd_file.read(&c, 1);
        
        // if c=1, the title is in unicode, which uses 2 bytes per character.
        // skip the next 2 bytes (the byte order mark) and decrement tl by 2.
        
        if (c) {
          sd_file.read(pb, 2);
          tl -= 2;
        }
        // remember that titles are limited to only max_title_len bytes long.
        
        if (tl > max_title_len) tl = max_title_len;
        
        // read in tl bytes of the title itself. add an 'end-of-string' byte.

        sd_file.read(title, tl);
        title[tl] = '\0';
        break;
      }
      else
      if (pb[1] == 'T' && pb[2] == 'T' && pb[3] == '2') {
        // found an id3v2.2 frame! the title's length is in the next 3 bytes,
        // but we read in 4 then ignore the last, which is the text encoding.
        
        sd_file.read(pb, 4);
        
        // shift each byte over to get it into its correct 'digits' position.
        
        unsigned long tl = ((unsigned long) pb[0] << (8 * 2)) +
                           ((unsigned long) pb[1] << (8 * 1)) + pb[2];
        tl--;
        
        // remember that titles are limited to only max_title_len bytes long.

        if (tl > max_title_len) tl = max_title_len;

        // there's no text encoding, so read in tl bytes of the title itself.
        
        sd_file.read(title, tl);
        title[tl] = '\0';
        break;
      }
      else
      if (sd_file.position() == v2l) {
        // we reached the end of the id3v2 tag. use the file name as a title.

        strncpy(title, fn, max_name_len);
        break;
      }
    }
  }
  else {
      // there is no id3 tag or the id3 version is not supported.
      title[0]='\0';
  }
}

//UTILITIES

/*
* example sketch to play audio file(s) in a directory, using the VS1053 library
* for playback and the arduino sd library to read files from a microsd card.
* pins are setup to work well for Arduino Micro.
*
* originally based on frank zhao's player: http://frank.circleofcurrent.com/
* utilities adapted from previous versions of the functions by matthew seal.
*
* (c) 2011, 2012 david sirkin sirkin@cdr.stanford.edu
*                akil srinivasan akils@stanford.edu
*/

// first step, declare the variables used later to represent microsd objects.

File sd_root;                   // the sd partition's root ('/') directory

// check that the microsd card is present, can be initialized and has a valid
// root volume. 'sd_root' is a pointer to the card's root volume object.

void sd_card_setup() {
  pinMode(sd_cs, OUTPUT); //set SS pin as output.
  while (!SD.begin(sd_cs)) {
  
    Serial.println("Card failed!");

  }
  
  sd_root = SD.open("/");
  
  while (!sd_root) {
    Serial.println("Couldn't mount root.");
    delay(2000);
    return;
  }
}

// for each song file in the current directory, store its file name in eeprom
// for later retrieval. this saves on using program memory for the same task,
// which is helpful as you add more functionality to the program.

// it also lets users change songs on the microsd card without having to hard
// code file names into the program. ask an instructor if you want to use sub
// directories also.

void sd_dir_setup() {
  num_songs = 0;
  sd_root.rewindDirectory();
  
  while (num_songs < max_num_songs) {
    // break out of while loop when we check all files (past the last entry).
    File p = sd_root.openNextFile();
    if (!p) break;
    
    // only store current (not deleted) file entries, and ignore the . and ..
    // directory entries. also ignore any sub-directories.
    if (p.name()[0] == '~' || p.name()[0] == '.' || p.isDirectory()) {
      continue;
    }
    
    // to find the position of the '.' that precedes the file name extension,
    // we have to search through the file name (stored as an array of chars).
    
    // fat16 prefers 8.3 type file names, and the sd library will shorten any
    // names longer than that. so if we have an mp3 or wav file, the '.' will
    // appear no later than position 8 ('max_name_len'-5) of the file name.
    char i;
    for (i = max_name_len - 5; i > 0; i--) {
      if (p.name()[i] == '.') break;
    }
    i++;
    
    // only store mp3 or wav files in eeprom (for now). if you add other file
    // types, you should add their extensions here.
    if ((p.name()[i] == 'M' && p.name()[i+1] == 'P' && p.name()[i+2] == '3') ||
        (p.name()[i] == 'W' && p.name()[i+1] == 'A' && p.name()[i+2] == 'V')) {
          
      // store each character of the file name (including the terminate-array
      // character '\0' at position 12) into a byte in the eeprom.
      for (char i = 0; i < max_name_len; i++) {
        EEPROM.write(num_songs * max_name_len + i, p.name()[i]);
      }
      num_songs++;
    }
  }
}

// given the numerical index of a particular song to play, go to its location
// in eeprom, retrieve its file name and set the global variable 'fn' to it.
void getSongFilename(int songNum) {
  for (char i = 0; i < max_name_len; i++) {
    fn[i] = EEPROM.read(songNum * max_name_len + i);
  }
}

void openSongFile(int songNum) {  
  // first, find the file name (that's stored in eeprom) of the current song.
  getSongFilename(songNum);
  
  // then open the file using the name we just found (stored in 'fn' global).
  sd_file = SD.open(fn, FILE_READ);
}

void song_title_to_display() {
  get_title_from_id3tag();
  if (title[0]=='\0') {
   // display.println("File Name:\n");
   // display.print(fn);
  } else {
    //display.println("Song Title:\n");
    //display.print(title);
  }
  //display.display();
  delay(2000);
}  

void song_title_to_cell_display() {
  
  get_title_from_id3tag();
  if (title[0]=='\0') {
    Serial.print("File Name:\n");
    Serial.println(fn);
  } else {
    Serial.print("Song Title:\n");
    Serial.println(title);
  }

  //delay(2000);
}

Jak już całe uruchomię to zapodam wtedy poradnik