Can the Mega control multiple mp3 players?

I'm building an arcade game which will be controlled by the Arduino Mega. I have successfully figured out how to play MP3 files on a single YX5300 using the SerialMP3Player library through pins 14 and 15 (TX3 and RX3). This MP3 player plays a tone when a target is hit. Now I want to turn my attention to adding a second YX5300 for the sole purpose of playing background music that will play continuously (and at a lower volume) during the entire game through a separate speaker. The tones from the first YX5300 will played through a separate speaker and at a volume much higher than the background music so they can be heard. Can someone direct me to an example that might help me out? I've looked and can't find a good comparison. Thanks.

the library is pretty poorly written as it hardcodes Serial3 or use SoftwareSerial (or let's say it was created with a UNO in mind and only one module connected)

probably best course of action would be to borrow the commands from that library and just apply to Serial1, Serial2 and Serial3 - you would be able to handle this way multiple modules (and keep Serial for debug)

In the beginning of your code, that you did not post, should be a line similar to:

SerialMP3Player mp3(RX,TX);

Where you create an instance of a SerialMP3Player object in a specific serial port. You can try creating more of these for other serial ports, of which the Mega has 4. Each object will need a different name. So you could name one bg_mp3, and another sfx_mp3, etc. Then use them at different times in the program.

if you look at the library, it does instantiate a SoftwareSerial object with the pins... not good...

Looked at the sample code. Didn't realize it was hard wired. Your solution is better.

Ok I'll give that a look. Thank you

Found this example online that may help me:

Again the goal here is to be able to play 2 mp3 tunes at once on the Mega and the SerialMP3Player library doesn't support that. Per the above suggestion, I am attempting to pull out the code from this library and put it in my sketch. The YouTube video above shows how to do this with the ESP32 but it is not compatible with the Mega. I've got a good start to the code shown below but it won't compile. I have put messages in the code where you see the ***. Can anyone give me any coding advice here?

/*
  Sketch for YX5300 MP3 module using Mega and multiple serial ports so that two tunes can play at same time throught their own speaker via one Mega Arduino
*/

#include <Arduino.h>

static int8_t Send_buf[8] = {0} ;

/*  Byte Data Format
    Byte 0 = [0x7e] - Every command starts with this
    Byte 1 = [0xFF] - Version information
    Byte 2 = [0xxx] - Number of bytes of he command without starting byte and ending byte
    Byte 3 = [0xxx] - Command such as "Play"
    Byte 4 = [0xxx] - 0x00 = not feedback, 0x02 = feedback (use 0000)
    Byte 5 = [00xx] = 1st byte of data
    Byte 6 = [00xx] = 2nd byte of data
    Byte 7 = [0xEF] = Ending byte of the command
*/

#define DEV_TF 0X02 // Variable for TF card

//Byte 6 (opton 1) and 7 (option 2) data commands
#define CMD_SEL_DEV 0X09 // Sets storage device to TF card
#define CMD_PLAY_W_VOL 0X22
#define CMD_PLAY_W_INDEX 0X03
#define CMD_SET_VOLUME 0X06
#define CMD_PLAY_FOLDER_FILE 0X0F
#define CMD_STOP_PLAY 0X16

void setup() {

  Serial.begin(9600);
  // Serial2.begin(9600, SERIAL_8N1, 16, 17);  *** NOTE: This was from ESP32 example that does not compile ***
  Serial1.begin(9600); // Should be pins 18 & 19 // *** I added this code ***
  Serial2.begin(9600); // Should be pins 16 & 17 // *** I added this code ***
  delay(200);

  sendCommand(CMD_SEL_DEV, 0, DEV_TF); // *** Compiler says "sendCommand not defined in this scope"
}

void loop() {

  for (i=0; i<7; i++) {
    sendCommand(PLAY_FOLDER_FILE 1,i);   // plays 3 seconds of each of the 7 mp3 files in folder 1
    delay(3000);
  }

  void sendCommand(byte command, byte option1, byte option_2) // defines sendCommand
  delay(200);

  Send_buff[0] = 0x7e; // Compiler error says "expected initializer before 'Send_buff' "
  Send_buff[1] = 0xff;
  Send_buff[2] = 0x06;
  Send_buff[3] = command;
  Send_buff[4] = 0x00;
  Send_buff[5] = option1;
  Send_buff[6] = option2;
  Send_buff[7] = 0xef;
  for (i = 0; i < 8; i++) {
    Serial2.write(Send_buf[i]); // *** Not sure if Compiler will perform this ***
  }

}

This is the documentation for the Yx5300 MP3 player


[https://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf](https://YX5300 Documentation)

I’ll try to have a look at cleaning up the library later today if I get a chance (ie if weather gets bad :slight_smile: )

1 Like

I rewrote the code to more closely resemble the SerialMP3Player library (e.g. variable names). I did get this code to compile. I will now see if it works...

/*
 * Partial code taken from SerialMP3Player.h library - Library for Serial MP3 Player board from Catalex (YX5300 chip)
 * Modified for Mega Arduino to play two tunes simultaneously from two separate YX5300 MP3 players
 */

// *********************************************************************** //
//                              Libraries
// *********************************************************************** //
#include <Arduino.h>

// *********************************************************************** //
//                       Variables for set up
// *********************************************************************** //
static int8_t Send_buf[8] = {0} ; // 8 byte variable to be sent to YX5300 MP3 player
unsigned long int command = 0; // variable to keep track of value for Byte 3 in string above
unsigned long int dat1 = 0; // variable to keep track of value for Byte 5 in string above
unsigned long int dat2 = 0; // variable to keep track of value for Byte 6 in string above


/*  Byte Data Format from the YX5300 MP3 Player Documentation
    Byte 0 = [0x7e] - Every command always starts with this
    Byte 1 = [0xFF] - Version information which remains constant
    Byte 2 = [0xxx] - Number of bytes of he command without starting byte and ending byte and is always 06 [0x06]
    Byte 3 = [0xxx] - Command such as "Play" (see Byte 6 and 7 options below)
    Byte 4 = [0xxx] - 0x00 = not feedback, 0x02 = feedback (use 0000)
    Byte 5 = [00xx] = 1st byte of data(see options below)
    Byte 6 = [00xx] = 2nd byte of data (see options below)
    Byte 7 = [0xEF] = Ending byte of the command remains constant
    Resulting byte string is [0x7e] [0xff] [0x06] [Command] [dat1] [dat2] [0xEF]
*/

void setup() {
  Serial2.begin(9600); // Mega Arduino pins TX16 & RX17
  delay(200); 

  // Initialization required for YX5300 to direct to storage device
  command = 0x09; // Sets YX5300 storage device to TF card
  dat1 = 0x00; // Default settings for TF card initialization
  dat2 = 0x00; // Default settings for TF card initialization
  
  // Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
  Send_buf[0] = 0x7E;    // Start byte
  Send_buf[1] = 0xFF;    // Version
  Send_buf[2] = 0x06;    // Command length not including Start and End byte.
  Send_buf[3] = command; // Command
  Send_buf[4] = 0x00;    // Feedback 0x00 NO, 0x01 YES
  Send_buf[5] = dat1;    // DATA1 datah
  Send_buf[6] = dat2;    // DATA2 datal
  Send_buf[7] = 0xEF;    // End byte

  for(int i=0; i<8; i++) {
    Serial2.write(Send_buf[i]); //Sends 8 byte instruction code to YX5300
  }
}

void loop() {

  // Sample loop to play YX5300
  command = 0x22; // Play with volume
  dat1 = 0x01; // 1st file on micro SD card
  dat2 = 0x30; // Volume of 30

  // Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
  Send_buf[0] = 0x7E;    // Start byte
  Send_buf[1] = 0xFF;    // Version
  Send_buf[2] = 0x06;    // Command length not including Start and End byte.
  Send_buf[3] = command; // Command
  Send_buf[4] = 0x00;    // Feedback 0x00 NO, 0x01 YES
  Send_buf[5] = dat1;    // DATA1 datah
  Send_buf[6] = dat2;    // DATA2 datal
  Send_buf[7] = 0xEF;    // End byte

  for(int i=0; i<8; i++) {
    Serial2.write(Send_buf[i]); //Sends 8 byte instruction code to YX5300
  }  
}

OK - let us know if you need more eyes looking at this

I rewrote the code a bit and got it to compile (again). Now I've hooked up the Mega and YX5300 player and the code doesn't get the YX5300 player to play anything. The LED on the YX5300 board is a solid red. Based on prior experience, this means it's not getting correct instruction. When I had it working before it blinked the red LED. Here is the most recent code that I need help with.

For starters, this information will be helpful...

  • Board = Mega 2560 R3

  • YX5300 MP3 Player #1 TX wired to Mega RX1 (pin 19) RX wired to Mega TX1 (pin 18)

  • YX5300 MP3 Player #2 TX wired to Mega RX2 (pin 17) RX wired to Mega TX2 (pin 16)

  • Storage device on each YX5300 is a micro SD card. They are formated to FAT32. There are 2 files in the parent directory labeled "01" and "02". In file 01, there are 10 mp3 files.

  • Arduino library SoftSerial.h utilized to help designate serial ports 1 and 2 for Mega

  • Sketch utilizes int8_t Send_buf[8] to set up an 8 byte variable to pass commands to YX5300

  • The 8 byte variable is in this format: [0x7e] [0xff] [0x06] [Command] [dat1] [dat2] [0xEF] in which the only things that vary are the locations marked "command, dat1, and dat2".

  • Typical commands are "play" and "stop"

  • Most of the data from the command is in dat1 (dat2 is 0 in this case). Some commands require 2 bytes of data and in those cases dat1 and dat 2 are needed

  • YX5300 documentation found [here] (https://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf) with summary below:

/*
 * Partial code taken from SerialMP3Player.h library - Library for Serial MP3 Player board from Catalex (YX5300 chip)
 * Modified for Mega Arduino to play two tunes simultaneously from two separate YX5300 MP3 players
 */

// *********************************************************************** //
//                              Libraries
// *********************************************************************** //
#include <Arduino.h>
#include <SoftwareSerial.h>

// *********************************************************************** //
//                       Variables for set up
// *********************************************************************** //
static int8_t Send_buf[8] = {0} ; // 8 byte variable to be sent to YX5300 MP3 player
unsigned long int command = 0; // variable to keep track of value for Byte 3 in string above
unsigned long int dat1 = 0; // variable to keep track of value for Byte 5 in string above
unsigned long int dat2 = 0; // variable to keep track of value for Byte 6 in string above


/*  Byte Data Format from the YX5300 MP3 Player Documentation
    Byte 0 = [0x7e] - Every command always starts with this
    Byte 1 = [0xFF] - Version information which remains constant
    Byte 2 = [0xxx] - Number of bytes of he command without starting byte and ending byte and is always 06 [0x06]
    Byte 3 = [0xxx] - Command such as "Play" (see Byte 6 and 7 options below)
    Byte 4 = [0xxx] - 0x00 = not feedback, 0x02 = feedback (use 0000)
    Byte 5 = [0xxx] = 1st byte of data(see options below)
    Byte 6 = [0xxx] = 2nd byte of data (see options below)
    Byte 7 = [0xEF] = Ending byte of the command remains constant
    Resulting byte string is [0x7e] [0xff] [0x06] [Command] [dat1] [dat2] [0xEF]
*/

SoftwareSerial serialOne(18, 19); // Software Serial 1 pinouts on Mega for background music
SoftwareSerial serialTwo(16, 17); // Software Serial 2 pinouts on Mega for target sounds

void setup() {
  Serial.begin(9600);
  while (!Serial) { // wait till Serial
  }

  serialOne.begin(9600); // sets baud rate to 9600
  serialTwo.begin(9600); // sets baud rate to 9600
  delay(200); // necessary for initialization

  // Initialization required for YX5300 #1 to direct to storage device
  command = 0x09; // Sets YX5300 storage device to TF card
  dat1 = 0x00; // Default settings for TF card initialization
  dat2 = 0x00; // Default settings for TF card initialization

  // Serial 1 mp3 player initialization
  serialOne.listen(); // listening on Serial One

  while (serialOne.available() > 0) {
    // char inByte = serialOne.read();
      
    // Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
    Send_buf[0] = 0x7E;    // Start byte
    Send_buf[1] = 0xFF;    // Version
    Send_buf[2] = 0x06;    // Command length not including Start and End byte.
    Send_buf[3] = command; // Command
    Send_buf[4] = 0x00;    // Feedback 0x00 NO, 0x01 YES
    Send_buf[5] = dat1;    // DATA1 datah
    Send_buf[6] = dat2;    // DATA2 datal
    Send_buf[7] = 0xEF;    // End byte
  
    for(int i=0; i<8; i++) {
      Serial.write(Send_buf[i]); //Sends 8 byte instruction code to YX5300
    }
  }
    
  // Initialization required for YX5300 #2 to direct to storage device
    command = 0x09; // Sets YX5300 storage device to TF card
    dat1 = 0x00; // Default settings for TF card initialization
    dat2 = 0x00; // Default settings for TF card initialization
  
    serialTwo.listen(); // listening on Serial Two
  
  while (serialTwo.available() > 0) {
    // char inByte = serialOne.read();
    
    // Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
    Send_buf[0] = 0x7E;    // Start byte
    Send_buf[1] = 0xFF;    // Version
    Send_buf[2] = 0x06;    // Command length not including Start and End byte.
    Send_buf[3] = command; // Command
    Send_buf[4] = 0x00;    // Feedback 0x00 NO, 0x01 YES
    Send_buf[5] = dat1;    // DATA1 datah
    Send_buf[6] = dat2;    // DATA2 datal
    Send_buf[7] = 0xEF;    // End byte
    
    for(int i=0; i<8; i++) {
      Serial.write(Send_buf[i]); //Sends 8 byte instruction code to YX5300
    }
  }
    
}

void loop() {

  // Sample loop to play YX5300 #1
  command = 0x22; // Play with volume
  dat1 = 0x0F; // Set Volume to 15
  dat2 = 0x01; // Play 1st tune
  
  serialOne.listen(); // listening on Serial Two
    
  while (serialOne.available() > 0) {
    // char inByte = serialOne.read();
    
    // Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
    Send_buf[0] = 0x7E;    // Start byte
    Send_buf[1] = 0xFF;    // Version
    Send_buf[2] = 0x06;    // Command length not including Start and End byte.
    Send_buf[3] = command; // Command
    Send_buf[4] = 0x00;    // Feedback 0x00 NO, 0x01 YES
    Send_buf[5] = dat1;    // DATA1 datah
    Send_buf[6] = dat2;    // DATA2 datal
    Send_buf[7] = 0xEF;    // End byte

    for(int i=0; i<8; i++) {
      Serial2.write(Send_buf[i]); //Sends 8 byte instruction code to YX5300
    }  
  }
  
  // Sample loop to play YX5300 #2
  command = 0x22; // Play with volume
  dat1 = 0x0F; // Set Volume to 15
  dat2 = 0x01; // Play 1st tune
    
  serialTwo.listen(); // listening on Serial Two
    
  while (serialTwo.available() > 0) {
    // char inByte = serialOne.read();
    
    // Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
    Send_buf[0] = 0x7E;    // Start byte
    Send_buf[1] = 0xFF;    // Version
    Send_buf[2] = 0x06;    // Command length not including Start and End byte.
    Send_buf[3] = command; // Command
    Send_buf[4] = 0x00;    // Feedback 0x00 NO, 0x01 YES
    Send_buf[5] = dat1;    // DATA1 datah
    Send_buf[6] = dat2;    // DATA2 datal
    Send_buf[7] = 0xEF;    // End byte

    for(int i=0; i<8; i++) {
      Serial2.write(Send_buf[i]); //Sends 8 byte instruction code to YX5300
    }
   
  }
  
  delay (3000);
}

your mega has hardware serial ports, so don't use Software Serial... (and use those ports to send commands, not Serial)

try something like this (typed here based on your code, so totally untested)


#define serialOne Serial1
#define serialTwo Serial2

// Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
byte commandBuffer[8] = {0x7E, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0xEF} ; // 8 byte variable to be sent to YX5300 MP3 player

void setup() {
  Serial.begin(9600);
  serialOne.begin(9600); // sets baud rate to 9600
  serialTwo.begin(9600); // sets baud rate to 9600
  delay(200); // necessary for initialization

  commandBuffer[3] = 0x09; // Sets YX5300 storage device to TF card
  commandBuffer[5] = 0x00; // Default settings for TF card initialization
  commandBuffer[6] = 0x00; // Default settings for TF card initialization

  // Initialization required for YX5300 to direct to storage device
  serialOne.write((const char*) commandBuffer, sizeof commandBuffer);
  serialTwo.write((const char*) commandBuffer, sizeof commandBuffer);
}

void loop() {
  // Sample loop to play YX5300 #1
  commandBuffer[3] = 0x22; // Play with volume
  commandBuffer[5] = 0x01; // 1st file on micro SD card
  commandBuffer[6] = 0x30; // Volume of 30

  serialOne.write((const char*) commandBuffer, sizeof commandBuffer);
  serialTwo.write((const char*) commandBuffer, sizeof commandBuffer);

  delay (5000);
}

@J-M-L your suggested code works! Thank you so much! I did find an error in my hexadecimal callouts so the code below is now correct, compiles, and runs on a Mega 2560. Thanks again!

/* 
  The following code is written for the Mega Aruduino to communicate with multiple YX5300 MP3 Players using the various Mega serial ports.
  This allows for two or more mp3 files to play simultaneously.  This working code has been tested on the Mega 2560.
  

  Copy mp3 files to SD card in this format
    Create Folders 01, 02…
    Name Files 001xxx.mp3, 002xxx.mp3 // xxx can be anything
    Note that names for 008.xxx and 009.xxx return errors so must skip
	 
  Connect the Serial MP3 Player to the Arduino board
    YX5300 → Mega 
    GND → GND
    VCC → 5V
    TX → RX
    RX → TX

  YX5300 Available Commands for Byte 6 (dat1) and 7 (dat2)
    #define CMD_SEL_DEV          0X09 // Set device. 2 DEV_TF (SD Card)
    #define CMD_PLAY             0X0D // Play
    #define CMD_PLAYN            0X03 // Play n file from (1-255)
    #define CMD_PLAY_W_VOL       0X22 // Play with a volumen
    #define CMD_SET_VOL          0X06 // Set Volume (0-30)
    #define CMD_STOP_PLAY        0X16 // Stop
    #define CMD_NEXT             0X01 // Play next file
    #define CMD_PREV             0X02 // Play previous file
    #define CMD_VOL_UP           0X04 // Volumen up
    #define CMD_VOL_DOWN         0X05 // Volumen down
                              // 0x07 // Reserved.
    #define CMD_PLAY_SLOOP       0X08 // Single loop play
    #define CMD_SLEEP_MODE       0X0A
    #define CMD_WAKE_UP          0X0B
    #define CMD_RESET            0X0C
    #define CMD_PAUSE            0X0E // Pause
    #define CMD_PLAY_F_FILE      0X0F // only avaible for Flash not SD Card.
    #define CMD_PLAY_SHUFFLE     0x18 // Reserved
    #define CMD_FOLDER_CYCLE     0X17 // Play all the files in the f folder

  Query Commands
    #define CMD_PLAYING_N         0x4C // qPlaying();  // Ask for the file is playing
    #define CMD_QUERY_STATUS      0x42 // qStatus();   // Ask for the status
    #define CMD_QUERY_VOLUME      0x43 // qVol();      // Ask for the volumen. // Sometime board fails
    #define CMD_QUERY_FLDR_TRACKS 0x4E // qFTracks();  // Ask for the number of tracks folders
    #define CMD_QUERY_TOT_TRACKS  0x48 // qTTracks();  // Ask for the total of tracks
    #define CMD_QUERY_FLDR_COUNT  0x4F // qTFolders(); // Ask for the number of folders
    
  Byte Data Format
    Byte 0 = [0x7e] - Every command starts with this
    Byte 1 = [0xFF] - Version information
    Byte 2 = [0xxx] - Number of bytes of he command without starting byte and ending byte
    Byte 3 = [0xxx] - Command such as "Play"
    Byte 4 = [0xxx] - 0x00 = not feedback, 0x02 = feedback (use 0000)
    Byte 5 = [00xx] = 1st byte of data
    Byte 6 = [00xx] = 2nd byte of data
    Byte 7 = [0xEF] = Ending byte of the command
*/

#define serialOne Serial1 // For YX5300 #1 playing background music
#define serialTwo Serial2 // For YX5300 #2 playing specific tunes when targets knocked down

// Command Structure 0x7E 0xFF 0x06 CMD FBACK DAT1 DAT2 0xEF
byte commandBuffer[8] = {0x7E, 0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0xEF} ; // 8 byte variable to be sent to YX5300 MP3 player

void setup() {
  Serial.begin(9600);
  serialOne.begin(9600); // sets baud rate to 9600
  serialTwo.begin(9600); // sets baud rate to 9600
  delay(200); // necessary for initialization

  commandBuffer[3] = 0x09; // Sets YX5300 storage device to TF card
  commandBuffer[5] = 0x00; // Default settings for TF card initialization
  commandBuffer[6] = 0x00; // Default settings for TF card initialization

  // Initialization required for YX5300 to direct to storage device
  serialOne.write((const char*) commandBuffer, sizeof commandBuffer);
  serialTwo.write((const char*) commandBuffer, sizeof commandBuffer);
}

void loop() {
  // Sample loop to play YX5300 #1
  commandBuffer[3] = 0x22; // Play with volume
  commandBuffer[5] = 0x0F; // Set Volume to 15 (0F is hexadecimal for 15)
  commandBuffer[6] = 0x01; // Play 1st tune on YX5300 #1
  serialOne.write((const char*) commandBuffer, sizeof commandBuffer); //command that tells YX5300 #1 to play

  // Sample loop to play YX5300 #2
  commandBuffer[3] = 0x22; // Play with volume
  commandBuffer[5] = 0x1E; // Set Volume to 30 (1E is hexadecimal for 30)
  commandBuffer[6] = 0x02; // Play 2nd tune on YX5300 #2
  serialTwo.write((const char*) commandBuffer, sizeof commandBuffer); //command that tells YX5300 #2 to play

  delay (5000); // Slows down loop so at least 5 seconds of each mp3 plays before starting over
} 

Click here for current code shared with public

Have fun :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.