MP3-player YX5300

About the post

In this article I would like to introduce an MP3 player module based on the YX5300 chip. I will deal with the following topics:

The YX5300 MP3 player
Serial MP3 player YX5300

Features / Specification

The MP3 player YX5300 module   is available for 5-10 Euro e.g. on Amazon. The supplied documentation is – as mostly with electronic components – very poor, but there is a data sheet on the net. The main features are:

Power supply3.2 – 5.2 V
Power consumptionmax. 200 mA
File typesWAV / MP3
SD card

Micro SD (<= 2 GB)

Micro SDHC (<=32 GB)

FormatFAT16 / FAT 32
CommunicationSerial via RX/TX
Max. voltage for TX/RX3.3 V / 5 V
Baud rate9600
Loudspeaker/headphone jack3.5mm jack

I successfully tested the module with a 2GB SD card and a 16GB SDHC card. If you have a problem with your SD card, just like me at first, then maybe the chapter below about this issue will help you.

The module expects the directory names in the format “01”, “02”, “03”, etc. on the SD card. The files in the directories must have the format “001xxx.mp3”, “002xxx.mp3”, … Have. “xxx” is freely selectable (apart from special characters). 

The jack connection can be seen as a positive or negative feature. Additional pins for connecting to self-built amplifiers or loudspeakers would have made sense. But first of course it is very convenient to be able to connect a headphone or (active) speaker directly. 

The module is addressed serially and has implemented a set of instructions that one would expect from an MP3 player. I do not want to go through the instructions individually. Either you look in the data sheet or in the example sketch of the library, which I would like to introduce in a moment. The only thing I miss a little is a function to switch from single song mode to playlist mode (or back), which does not interrupt the currently played song.

SerialMP3Player library

Actually, it is not very difficult to control the module without a library, but it is a lot of work to copy all the commands from the data sheet manually. Using the SerialMP3Player library, you don’t need to do this and therefore you can get started right away. Nevertheless, I recommend to look at data sheets sometimes, e.g. in order to be able to improve libraries if necessary.

With the help of the example sketch BasicCommands, the module can be tested extensively. The sketch lists the available commands on the serial monitor, which can then be executed accordingly.   It is nice that the raw data that are sent or received are displayed on the serial monitor. You can change this in line 42   by replacing the “1” with a “0” and commenting the lines 67-69.

The sketch is easy to understand and I don’t think it needs any great explanations. The loop function checks whether entries have been made on the serial monitor. The inputs are evaluated by the “decode_c” function and then passed to the “menu” function. The menu function then calls the functions defined in the library.  

/******************************************************************************
  Basic Commands examples for the SerialMP3Player YX5300 chip.

  Copy the files of "SDcard_example" to an empty SD card
  Connect the Serial MP3 Player to the Arduino board
    GND → GND
    VCC → 5V
    TX → pin 11
    RX → pin 10

  After compile and upload the code,
  you can test some basic commands by sending the letters
  ? - Display Menu options.
  P01 - Play 01 file
  F01 - Play 01 folder
  S01 - Play 01 file in loop
  p - play
  a - pause
  s - stop
  > - Next
  < - Previous
  ...

  Some commands like 'P' must be followed by two digits.

  This example code is in the public domain.

  https://github.com/salvadorrueda/ArduinoSerialMP3Player

  by Salvador Rueda
 *******************************************************************************/

#include "SerialMP3Player.h"

#define TX 11
#define RX 10

SerialMP3Player mp3(RX,TX);


void setup() {
  mp3.showDebug(1);       // print what we are sending to the mp3 board.

  Serial.begin(9600);     // start serial interface
  mp3.begin(9600);        // start mp3-communication
  delay(500);             // wait for init

  mp3.sendCommand(CMD_SEL_DEV, 0, 2);   //select sd-card
  delay(500);             // wait for init

  menu('?',0); // print the menu options.
}

 char c;  // char from Serial
 char cmd=' ';
 char cmd1=' ';


// the loop function runs over and over again forever
void loop() {

  if (Serial.available()){
    c = Serial.read();
    decode_c(); // Decode c.
  }
  // Check for the answer.
  if (mp3.available()){
    Serial.println(mp3.decodeMP3Answer()); // print decoded answers from mp3
  }
}

void menu(char op, int nval){
  // Menu
  switch (op){
    case '?':
    case 'h':
        Serial.println("SerialMP3Player Basic Commands:");
        Serial.println(" ? - Display Menu options. ");
        Serial.println(" P01 - Play 01 file");
        Serial.println(" F01 - Play 01 folder");
        Serial.println(" S01 - Play 01 file in loop");
        Serial.println(" V01 - Play 01 file, volume 30");
        Serial.println(" p - Play");
        Serial.println(" a - pause");
        Serial.println(" s - stop ");
        Serial.println(" > - Next");
        Serial.println(" < - Previous");
        Serial.println(" + - Volume UP");
        Serial.println(" - - Volume DOWN");
        Serial.println(" v15 - Set Volume to 15");
        Serial.println(" c - Query current file");
        Serial.println(" q - Query status");
        Serial.println(" x - Query folder count");
        Serial.println(" t - Query total file count");
        Serial.println(" r - Reset");
        Serial.println(" e - Sleep");
        Serial.println(" w - Wake up");
        break;

    case 'P':
        Serial.println("Play");
        mp3.play(nval);
        break;

    case 'F':
        Serial.println("Play Folder");
        mp3.playF(nval);
        break;

    case 'S':
        Serial.println("Play loop");
        mp3.playSL(nval);
        break;

    case 'V':
        Serial.println("Play file at 30 volume");
        mp3.play(nval,30);
        break;


    case 'p':
        Serial.println("Play");
        mp3.play();
        break;

    case 'a':
        Serial.println("Pause");
        mp3.pause();
        break;

    case 's':
        Serial.println("Stop");
        mp3.stop();
        break;

    case '>':
        Serial.println("Next");
        mp3.playNext();
        break;

    case '<':
        Serial.println("Previous");
        mp3.playPrevious();
        break;

    case '+':
        Serial.println("Volume UP");
        mp3.volUp();
        break;

    case '-':
        Serial.println("Volume Down");
        mp3.volDown();
        break;

    case 'v':
        Serial.println("Set to Volume");
          mp3.setVol(nval);
          mp3.qVol();
        break;

    case 'c':
        Serial.println("Query current file");
        mp3.qPlaying();
        break;

    case 'q':
        Serial.println("Query status");
        mp3.qStatus();
        break;

    case 'x':
        Serial.println("Query folder count");
        mp3.qTFolders();
        break;

    case 't':
        Serial.println("Query total file count");
        mp3.qTTracks();
        break;

    case 'r':
        Serial.println("Reset");
        mp3.reset();
        break;

    case 'e':
        Serial.println("Sleep");
        mp3.sleep();
        break;

    case 'w':
        Serial.println("Wake up");
        mp3.wakeup();
        break;
  }
}

void decode_c(){
  // Decode c looking for a specific command or a digit

  // if c is a 'v', 'P', 'F', 'S' or 'V' wait for the number XX
  if (c=='v' || c=='P' || c=='F' || c=='S' || c=='V'){
    cmd=c;
  }else{
    // maybe c is part of XX number
    if(c>='0' && c<='9'){
      // if c is a digit
      if(cmd1==' '){
        // if cmd1 is empty then c is the first digit
        cmd1 = c;
      }else{
        // if cmd1 is not empty c is the second digit
        menu(cmd, ((cmd1-'0')*10)+(c-'0'));
        cmd = ' ';
        cmd1 = ' ';
      }
    }else{
      // c is not a digit nor 'v', 'P', 'F' or 'S' so just call menu(c, nval);
      menu(c, 0);
    }
  }
}

 

Connection to Arduino and Co

It couldn’t be easier: GND to GND, VCC to 5V or 3.3V, RX to TX and TX to RX. RX and TX are set as PIN 10 and PIN 11 in the example sketch via SoftwareSerial.

YX5300 MP3 Player attached to Arduino
YX5300 MP3 Player attached to Arduino

Smartphone control for the MP3 player YX5300

Alternative control of the YX5300

Being able to control the MP3 player YX5300 via the serial monitor is already a first success experience, but in the long run you probably want to work independently of the PC. In essence, I can think of three alternatives:

  • Install a button for each function, if necessary in conjunction with a small membrane switch keyboard.
  • Use a touch display, available for < €20 on Amazon
  • Smartphone control via Bluetooth

Since I find the smartphone variant particularly exciting, I will go into this in more detail. 

The functionality of the smartphone app

I have developed a small app (“Ardu YX5300 MP3 Player”) that has implemented the most important functions for the player. You can also easily expand the app and add more features. As a special feature, I added a voice control (“Talk2Me” button). 

Surface of the MP3 player YX5300 app.
The surface of the smartphone app

The “Continuous” Check Box switches from single song mode to folder mode or back. Unfortunately, this is interrupting of the current song. 

What exactly the app does in the background and how you can develop something like this without special knowledge in the app programming, I explain below. 

Setup of the Arduino side

First, however, let’s have a look into the Arduino side. We add Bluetooth capabilities to the Arduino with an HC-05 or HC-06 module. How to deal with these modules I have described here. The Bluetooth module communicates with the Arduino via a SoftwareSerial connection. In my sketch (below) I defined pin 5 and 6 as RX or TX. I used a small active loudspeaker. On the breadboard, it looks like this:

Arduino side of the smartphone-controlled MP3 player

To make the MP3 player independent of the PC, I replaced the Arduino Uno with a Pro Mini, put it in a case, switched to battery operation and added a control LED for the power supply. The battery power supply is external and is plugged in via a socket. How to program a Pro Mini I have described here. The circuit looks like this: 

Circuit for the smartphone-controlled MP3 player
The complete project.
Here’s what the full project looks like

Preparation – Adaptation of the sketch

For the sketch, I take the BasicCommand sketch as the basis and use its “infrastructure”. I renamed it Ardu_YX5300_MP3_player.ino. You can find the sketch below and copy it there or download it here.

The connection to the Bluetooth module is defined in line 40:

SoftwareSerial BT_Module(5,6);

In the loop function, rows 74-76 check whether there is data for retrieval:

if(BT_Module.available()){ decode_BT(); }.

The new function “decode_BT” in lines 206 – 216 evaluates the commands received so that the menu function understands them. The first character is expected to be “BT_START_CMD_CHAR” and is defined as “*” at the beginning of the sketch. 

void decode_BT(){
  char cmdType = ' ';
  int value = 0;
  char getChar = ' ';  //read serial
  if(BT_Module.find(BT_START_CMD_CHAR)){
    while(BT_Module.available()<1);
    cmdType = BT_Module.read(); // read the command
    value = BT_Module.parseInt();
  }
  menu(cmdType,value); 
}      

Here’s what the full sketch looks like:

/******************************************************************************
  Salavdor Rueda's Basic Commands examples for the SerialMP3Player YX5300 chip.

  Modified by Wolfgang Ewald in order to communicate with a smartphone app. 

    GND → GND
    VCC → 5V
    YX 5300 TX → pin 10
    YX 5300 RX → pin 11
    BT Modul TX → pin 5
    BT Modul RX → pin 6

  After compile and upload the code,
  you can test some basic commands by sending the letters
  ? - Display Menu options.
  P01 - Play 01 file
  F01 - Play 01 folder
  S01 - Play 01 file in loop
  p - play
  a - pause
  s - stop
  > - Next
  < - Previous
  ...

  Original:
  "This example code is in the public domain.
  https://github.com/salvadorrueda/ArduinoSerialMP3Player
  by Salvador Rueda"
  
 *******************************************************************************/

#include "SerialMP3Player.h"
#define TX 11
#define RX 10
#define BT_START_CMD_CHAR '*'
int statusLEDPin = 4;

SerialMP3Player mp3(RX,TX);
SoftwareSerial BT_Module(5,6);

void setup() {
  mp3.showDebug(0);       // print what we are sending to the mp3 board. 1= active
  Serial.begin(9600);     // start serial interface
  mp3.begin(9600);        // start mp3-communication
  BT_Module.begin(9600);   // start serial connection to BT Modul
  delay(500);             // wait for init
  pinMode(statusLEDPin, OUTPUT);
  digitalWrite(statusLEDPin, HIGH);

  mp3.sendCommand(CMD_SEL_DEV, 0, 2);   //select sd-card
  mp3.setVol(15); 
  mp3.playF(1);  // Folder 1, cycle play
  delay(500);    // wait for init

  menu('?',0); // print the menu options.
}

 char c;  // char from Serial
 char cmd=' ';
 char cmd1=' ';


// the loop function runs over and over again forever
void loop() {
  if (Serial.available()){
    c = Serial.read();
    decode_c(); // Decode c.
  }
  // Check for the answer.
//  if (mp3.available()){
//    Serial.println(mp3.decodeMP3Answer()); // print decoded answers from mp3
//  }
  if(BT_Module.available()){
    decode_BT();
  }
}

void menu(char op, int nval){
  // Menu
  switch (op){
    case '?':
    case 'h':
        Serial.println("SerialMP3Player Basic Commands:");
        Serial.println(" ? - Display Menu options. ");
        Serial.println(" P01 - Play 01 file");
        Serial.println(" F01 - Play 01 folder");
        Serial.println(" S01 - Play 01 file in loop");
        Serial.println(" V01 - Play 01 file, volume 30");
        Serial.println(" p - Play");
        Serial.println(" a - pause");
        Serial.println(" s - stop ");
        Serial.println(" > - Next");
        Serial.println(" < - Previous");
        Serial.println(" + - Volume UP");
        Serial.println(" - - Volume DOWN");
        Serial.println(" v15 - Set Volume to 15");
        Serial.println(" c - Query current file");
        Serial.println(" q - Query status");
        Serial.println(" x - Query folder count");
        Serial.println(" t - Query total file count");
        Serial.println(" r - Reset");
        Serial.println(" e - Sleep");
        Serial.println(" w - Wake up");
        break;

    case 'P':
        Serial.println("Play");
        mp3.play(nval);
        break;

    case 'F':
        Serial.println("Play Folder");
        mp3.playF(nval);
        break;

    case 'S':
        Serial.println("Play loop");
        mp3.playSL(nval);
        break;

    case 'V':
        Serial.println("Play file at 30 volume");
        mp3.play(nval,30);
        break;


    case 'p':
        Serial.println("Play");
        mp3.play();
        break;

    case 'a':
        Serial.println("Pause");
        mp3.pause();
        break;

    case 's':
        Serial.println("Stop");
        mp3.stop();
        break;

    case '>':
        Serial.println("Next");
        mp3.playNext();
        break;

    case '<':
        Serial.println("Previous");
        mp3.playPrevious();
        break;

    case '+':
        Serial.println("Volume UP");
        mp3.volUp();
        break;

    case '-':
        Serial.println("Volume Down");
        mp3.volDown();
        break;

    case 'v':
        Serial.println("Set to Volume");
          mp3.setVol(nval);
          //mp3.qVol();
        break;

    case 'c':
        Serial.println("Query current file");
        mp3.qPlaying();
        break;

    case 'q':
        Serial.println("Query status");
        mp3.qStatus();
        break;

    case 'x':
        Serial.println("Query folder count");
        mp3.qTFolders();
        break;

    case 't':
        Serial.println("Query total file count");
        mp3.qTTracks();
        break;

    case 'r':
        Serial.println("Reset");
        mp3.reset();
        break;

    case 'e':
        Serial.println("Sleep");
        mp3.sleep();
        break;

    case 'w':
        Serial.println("Wake up");
        mp3.wakeup();
        break;
  }
}

void decode_BT(){
  char cmdType = ' ';
  int value = 0;
  char getChar = ' ';  //read serial
  if(BT_Module.find(BT_START_CMD_CHAR)){
    while(BT_Module.available()<1);
    cmdType = BT_Module.read(); // read the command
    value = BT_Module.parseInt();
  }
    menu(cmdType,value); 
}      

void decode_c(){
  // Decode c looking for a specific command or a digit

  // if c is a 'v', 'P', 'F', 'S' or 'V' wait for the number XX
  if (c=='v' || c=='P' || c=='F' || c=='S' || c=='V'){
    cmd=c;
  }else{
    // maybe c is part of XX number
    if(c>='0' && c<='9'){
      // if c is a digit
      if(cmd1==' '){
        // if cmd1 is empty then c is the first digit
        cmd1 = c;
      }else{
        // if cmd1 is not empty c is the second digit
        menu(cmd, ((cmd1-'0')*10)+(c-'0'));
        cmd = ' ';
        cmd1 = ' ';
      }
    }else{
      // c is not a digit nor 'v', 'P', 'F' or 'S' so just call menu(c, nval);
      menu(c, 0);
    }
  }
}

 

An adjustment has to be made in the library in SerialMP3Player.cpp, but nothing complicated. The library requires a time span of one second between two statements. This causes problems with the volume slider in the app, because each small move immediately triggers a corresponding instruction. That means, moving the slider from e.g. volume level 10 to 20 would take 10 seconds. All you have to do is comment line 185 (the delay command) in SerialMP3Player.cpp and that’s it.  

Before connecting to the smartphone, you can test the whole thing by sending the instructions from the smartphone via a terminal app such as Bluetooth Terminal. The app is available here on Google Play. For example, a “*F*1” should play all songs in directory 01. 

Development of the smartphone app

If you have read my last post Controlling Arduino with your smartphone, you can rush through the following explanations. 

Actually, learning to develop smartphone apps is quite time-consuming. If you really want to deep-dive into this topic, you should learn Java and deal with development environments like Eclipse or Android Studio. The good news is that there is a simple alternative that is completely sufficient for our purposes and that is called MIT App Inventor. If you follow this link, you will get a lot of information about who is behind this project, how it works, which tutorials tare available (highly recommended as an introduction) and much more. A step-by-step guide would go beyond the scope of this post, but I will try to convey the essential points to you. 

How does MIT App Inventor work?

First of all, MIT App Inventor is an online solution, i.e. no program installation is required on your PC. One does not write a single program line during app development, but constructs program blocks visually from prefabricated individual parts. If you’ve ever worked with Scratch, you’ll find yourself here quickly.

What is particularly cool is that you can follow the creation of your apps in real time on your smartphone. This applies to both design and functionality. It is not necessary to compile code in between and beam apk files to the smartphone. You don’t do that until you’re satisfied with your result and the app is supposed to run independently of the development environment.

To connect the smartphone to MIT App Inventor, you must first install the APP MIT AI2 Companion. MIT App Inventor then provides a number or QR code for the connection. Very convenient! I had some problems with Edge, but Chrome did a wonderful job.  

Following this link you will get to the development environment (log on with your Google account). 

The Designer screen

As already mentioned, I can’t provide step-by-step instructions here, but only explain the concept because it would be too big. The app development takes place in two basic steps, first the design development and then the definition of the functions behind it. For this purpose there are two screens between which you can switch, namely “Designer” and “Blocks”. The designer screen for the Ardu_YX5300_MP3_Player app looks like this: 

Designer screen of MIT App Inventor
The Designer screen – selection of components and arrangement

On the left side you see the menu for the different elements that can be inserted. In the submenu “User Interface” you find buttons, checkboxes, sliders, etc. Under “Layout” there are elements such as horizontal and vertical arrangements, which serve to keep defined spaces between the elements. As expected, the Bluetooth function can be found under connectivity. Just take a look. 

The Components window reflects the structure of the components. Here you can also rename components, which is absolutely advisable so as not to lose track. For example, “Playbutton” is a more helpful term than the pre-set “Button1”. 

In the “Properties” window you can define the properties of the components, e.g. shape, color or which values are displayed for the sliders. For example, for the Volume Slider, I specified a range from 0 to 30 because that’s the allowed range for the YX5300.  

The Blocks screen

The components assembled in the Designer screen can’t do anything at first. What they trigger and under what conditions or how they should change is specified in the Blocks screen: 

The Blocks screen of MIT App Inventor
The Blocks screen – function of the components

In the “Blocks” window, you can click on one of the components to get a selection of different blocks to choose from. The selected block will be transferred into the viewer window where it can be moved freely. For example, because a slider can only do certain things, only the corresponding blocks are suggested. This allows you to work quite intuitively and quickly. In addition, under “Built-In” there are general blocks e.g. for text, if-then-else constructs and much more. 

Another help is that the blocks are shaped like puzzle pieces. As a result, only certain components fit together and everything must be completed. This avoids syntax errors, but you have to pay attention to the logic errors yourself. 

Save and install the app

Finally, you can generate an apk file under the menu item “Build”, which can be conveniently transferred to the smartphone via a QR code.  

The project is saved online. You can also export it as a .aia file, save it to your PC, share it with others, and then import it again. You can download the “.aia” file for the Ardu_YX5300_MP3_Player app presented here and customize it as you wish. Alternatively, you can find the project in the gallery of MIT App Inventor if you follow this Link.

Problems with the SD card?

The SD card is not working? I experienced this problem and it took me quite some time to figure out why it happened. If the player does not want to play even though the audio format is correct, the directory structure has been created as required, the wiring is correct, etc., then it may be because of the partitioning of the card. An SD card can have a small boot partition ex works or if it was previously used for other purposes.  Accordingly, there are two drives in File Explorer: 

SD card with boot sector

Right-clicking and formatting is useless, as the partitions are preserved. When the problem occurred to me, I solved it with the small tool called SD Card Formatter, which is available here, for example. After installation, select the small boot partition (it doesn’t necessarily need to be called “boot”) and activate the “Overwrite Format” formatting option. The process takes several minutes. After that you only have one partition and everything works wonderfully.

SD Card Formatter
SD Card Formatter

Alternative MP3 modules

Alternatives to YX5300
Alternatives to the MP3 player YX5300

There are a number of alternatives to the YX5300 MP3 player. You will come across these, e.g. if you search for “MP3 module Arduino” on Amazon. I tried the WTV020M01 module (top right of the photo) and the no-name player on the left side of the photo. 

I would very much advise against the WTV020M01, because this device is very tricky in terms of the file format and the details of the audio recording. For example, the level and noise must meet certain specifications. If you still want to do this, there is a very compact instruction available here.  

In a separate post I explained the details of the DFPlayer Mini (here). In terms of control, it is very similar to the YX5300. The main advantages are the small size and that it can be operated very easily with buttons. The jack for the headphones is an advantage of the MP3 player YX5300.

The no-name modulet works perfectly, but apparently can only be operated manually. At least I haven’t found a way to communicate with it via software. However, since it starts immediately when it is supplied with power, you could attach an arduino-controlled on/off switch. 

I haven’t tried (at least so far) modules based on the VS1053 chip. These are available in various designs, e.g. as shields, with or without SD card slot, with or without microphone, etc. This may also find its way on my to-do list. 

Anyone who has had good or bad experiences with these or other alternative modules is welcome to share it as a comment.  

2 thoughts on “MP3-player YX5300

  1. After you send a serial command to start playing a track, how long does it take for the track to start playing? Thanks! 🙂

    1. Honest answer: I don’t know. At least I can say I have not noticed a delay and have not measured it. I would guess something it’s something in the range of millisecond range.

Leave a Reply

Your email address will not be published.