Categories
Arduino hardware software

YX5300 Serial MP3 Player (Catalex Module)

YX5300_Serial_MP3_Player

While browsing eBay looking for a module to play extended sound effects (MP3 and WAV files), I came across these modules that looked like they would fit my purpose. The module has been around for a few years and is based on the YX5300 IC. As it turns out they are easy to use and produce a good sound in a small package.

The downside is that there is not a huge lot of documentation for the board and the original is in Chinese. A copy of the official documentation I was able to find can be reached through this link.

While it is easy to make the board play a sound, there are no examples (that I could find) of ‘advanced’ control of the board in a system multitasking other control tasks. So I decided to write a control library that would provide me with the interface I thought was needed. The library (MD_YX5300) can be found in my code repository.

Hardware Specifications

The YX5300 supports 8kHz to 48kHz sampling frequency MP3 and WAV file formats. The audio files are stored on a micro SD card that plugs into a TF card socket on the back of the board.

YX5300_Board_Layout

The MCU controls the device playback by sending serial commands through a TTL level UART control interface (GND, VCC, TX, RX). Pins are connected GND to MCU ground, VCC to 5V power supply, YX5300 TX (transmit) to the designated RX (receive) pin for the library, YX5300 RX to TX. The MCU RX/TX can be hardware serial pins or a software controlled serial port.

Sound is output through a headphone jack to headphones or an external amplifier. The board has a playback indicator LED that blinks during playback and is steady otherwise.

The TF card socket on the PCB reverse side is for plugging in the micro SD card with MP3/WAV files. The micro SD card should be formatted as FAT16 or FAT32 and songs must be prefixed with a unique 3 digit index number (for example, 001xxx.mp3, 002xxx.mp3, 003xxx.mp3, etc, where xxx is an arbitrary optional name. Songs may also be grouped in folders named ’01’, ’02’, ’03’, etc. An example folder and file structure on the micro SD card might look like:

+-+- 01
  | + 001-Happy_Dance.mp3
  | + 002-O_Sole_Mio.mp3
  |
  +- 02
  | + 003-Humpty_Dumpty.mp3
  | + 004-Incy_Wincy_Spider.mp3
  | + 005-Grand_Duke.mp3
  | 
  +- 03
    + 006-Fernando.mp3
    + 007-Mamma_Mia.mp3

Songs are referenced by folder and by song ‘index’, although it seems that the numeric index is sometimes ignored and the songs played in the order they are stored in the SD card. The documentation is unclear on this and seems to imply both situations. So, even if you plan only one playlist, it is better to keep them in a ’01’ folder and save all the songs to the SD card at the same time.

Communicating with the Module

Communications is via asynchronous serial RS232 at 9600 bps, 8 data bits, No parity, 1 stop bit, no hardware flow control. Flow control is implemented using a request/response protocol with data packets in the following byte format:

YX5300_PSerial_Packet

where the fields have the following meaning:

  • Start (0x7e) and End (0xef) mark the start and end of the serial packet. A receiver should synchronize on the start byte and read the packet to the end.
  • Version is always 0xff. I assume this is to cater for future changes in the protocol and would allow comms software to adjust dynamically.
  • Length is the number of bytes between the Start byte and Checksum. In this implementation it is always 6 bytes (the lighter colored boxes).
  • Cmd (Command) in a request message is the control function code and in a response is error/status code.
  • Fback (Feedback) is set to 1 to receive a request acknowledgement, or 0 for no acknowledgement.
  • DataHi and DataLo are the high and low bytes of the command modifier or the status/error code. They are set to suit the Cmd byte (see the tables below).
  • ChkHi and ChkLo are the checksum high and low bytes. The checksum is optional and can be omitted from requests messages, but a response from the device always includes the checksum field. The checksum is calculated as the two’s complement of the 16-bit sum of the bytes between Start and Checksum (ie, the same as those counted in Length).

The module can also initiate sending a message to the MCU when certain events occur (an ‘unsolicited’ message). These are received and processed without a matching prior request.

Device Commands

The interesting elements of the protocol message are the Cmd and Data fields.

The Cmd field allows us to control the module. The official English documentation provides a set of valid command codes and the Chinese documentation provides an additional set of codes. All the commands I have discovered are collated in the table below. Where the data field is required this is noted, otherwise it is set to zero and  ignored.

NEXT_SONG0x01Play next song.
PREV_SONG0x02Play previous song.
PLAY_WITH_INDEX0x03Play song with index number. Data is the index of the file.
VOLUME_UP0x04Volume increase by one.
VOLUME_DOWN0x05Volume decrease by one.
SET_VOLUME0x06Set the volume to level specified. Data is the volume level [0..30].
SET_EQUALIZER0x07Set the equalizer to specified level. Data is [0..5] – 0=Normal, 1=Pop, 2=Rock, 3=Jazz, 4=Classic or 5=Base.
SNG_CYCL_PLAY0x08Loop play (repeat) specified track. Data is the track number.
SEL_DEV0x09Select file storage device. The only valid choice for data is TF (0x02).
SLEEP_MODE0x0aChip enters sleep mode.
WAKE_UP0x0bChip wakes up from sleep mode.
RESET0x0cChip reset.
PLAY0x0dPlayback restart.
PAUSE0x0ePause playback.
PLAY_FOLDER_FILE0x0fPlay the file with the specified folder and index number
STOP_PLAY0x16Stop playback.
FOLDER_CYCLE0x17Loop playback within specified folder. Data is the folder index.
SHUFFLE_PLAY0x18Playback shuffle mode. Data is 0 to enable, 1 to disable.
SET_SNGL_CYCL0x19Set loop play (repeat) on/off for current file. Data is 0 to enable, 1 to disable.
SET_DAC0x1aDAC on/off control (mute sound). Data is 0 to enable DAC, 1 to disable DAC (mute).
PLAY_W_VOL0x22Play track at the specified volume. Data hi byte is the track index, low byte is the volume level [0..30].
SHUFFLE_FOLDER0x28Playback shuffle mode for folder specified. Data high byte is the folder index.
QUERY_STATUS0x42Query Device Status.
QUERY_VOLUME0x43Query Volume level.
QUERY_EQUALIZER0x44Query current equalizer (disabled in hardware).
QUERY_TOT_FILES0x48Query total files in all folders.
QUERY_PLAYING0x4cQuery which track playing
QUERY_FLDR_FILES0x4eQuery total files in folder. Data is the folder index number.
QUERY_TOT_FLDR0x4fQuery number of folders.

The error/Status values returned from the device are also listed below. The Data field  usually contains the status value or data requested.

TF_INSERT0x3aTF Card was inserted (unsolicited message).
TF_REMOVE0x3bTF card was removed (unsolicited message).
FILE_END0x3dTrack/file has ended (unsolicited message). Data is the index number of the file just completed.
INIT0x3fInitialization complete (unsolicited message). Data is the file store types available (0x02 for TF).
ERR_FILE0x40Error file not found. Data is error code (no definition).
ACK_OK0x41Message acknowledged ok
STATUS0x42Current status. Data high byte is file store (2 for TF); low byte 0=stopped, 1=play, 2=paused.
VOLUME0x43Current volume level. Data is volume level [0..30].
EQUALIZER0x44Equalizer status. Data is equalizer mode types  0=Normal, 1=Pop, 2=Rock, 3=Jazz, 4=Classic or 5=Base.
TOT_FILES0x48TF Total file count
PLAYING0x4cCurrent file playing
FLDR_FILES0x4eTotal number of files in the folder. Data is the number of files.
TOT_FLDR0x4fTotal number of folders. Data is the number of folders.

So why use a Library?

The MD_YX5300 library encapsulates each of the command messages as a class method. At its most basic, the library allows the processing of messages in the background while the application goes about its other business. This is done with a polling mechanism (check()) called once per loop() cycle.

The library can operate in synchronous or asynchronous mode. In synchronous mode, a call sending a request message will include waiting for the response before returning, allowing a simple flow in the main application provided it can tolerate the delays. This would satisfy most of the applications that I was able to find as examples.

Alternatively, asynchronous mode can be used, where the response can be processed by the application at a later stage. This is triggered by check() returning value signalling a message (response or unsolicited) is waiting.

Additionally, by defining a callback function, the application will be ‘called back’, including response status, when any message is been received. The callback approach particularly suits applications implemented as Finite State Machines.

Having this flexibility to tailor the programmer’s approach greatly simplifies handling the relatively slow serial comms link without losing efficiency in the rest of the application.

Updates:

  • More information on Message Sequencing for the YX5300 in this blog.
  • Building a YX5300 MP3 Player in this blog.

52 replies on “YX5300 Serial MP3 Player (Catalex Module)”

Hi Marco,
Thanks for the post, really great. I have a question regards song start delay? I’m working on footswitch looper project. Currently using MH2024K-24SS module. But I really have issue when I click play button, the song starts with noticable dalay around one secund. Which is totally not acceptable for live music. For this reason I’m looking for an alternative. Would YX5300 behave better?

Like

I am trying to find a serial mp3 module that is not limited to 255 songs.
this one https://www.banggood.com/Serial-Port-Control-Voice-Module-MP3-Player-Voice-Broadcast-Support-TF-Card-U-Disk-Insert-Function-p-1589685.html?cur_warehouse=CN&rmmds=search seems to do ” Supports playback of any segment of voice, audio data is sorted by folder, supports 100 folders, and each folder can be assigned 1000 songs;”
I am not sure it supports stereo analog output or if i need to use the DAC L+R for that.
The listing includes a rar file which has a pdf but it’s all in Chinese. Maybe it’s fairly similar and the API can be adapted.

Like

Maybe it is or maybe it isn’t compatible. I cannot work it out as EVERYTHING, including the code, is in Chinese and that is a language I do not speak or read. Maybe you can do an internet search for this product name. Someone else may have used this before and will be able to help you.

Like

Really neat board and library!
Thank you!

I have been trying to play mp3 with an arduino with an mp3 shield that uses SPI and the experience was not pleasant. Using a simple serial interface is much nicer.
The biggest limitation seems to be that the maximum number of tracks is 256
At https://majicdesigns.github.io/MD_YX5300/class_m_d___y_x5300.html#af9a464f2cdbd272be42aac185283a755 playTrack takes a uint8_t

My project is to use rfid cards to select which album to play and I would like to support more than 256 songs.

I tried using playFolderRepeat hoping that it would be limited to 256 folders but inside it would let me use files with numbers over 255 but I have not been able to get it to run (i can’t get playFolderRepeat to work so maybe it works but i have not found the right way to call it yet!)

Like

I think I have the files set correctly on card with folder 01 with files 001-songname.mp3 002-othername.mp3 then folder 02 with songs 003-name.mp3 etc.
Playspecific works well though I don’t get why the folder number is needed as the song name is unique. Playfolderrepeat does not work for me and gives err_file with codes 05 and 06.
Also is it possible to play and album tracks once. (not repeat nor shuffle) play all tracks once and stop?
Thanks

Like

You can play a track and then once that is finished play the next but it is under program control. All the commands for this device that have public documentation are implemented, so if you cannot find a command for what you want to do, it does not exist. If you find a new command documented somewhere, let me know.

Like

Sir Is it possible to play file with file name from Sd card root directory using this module?
I know how to play file with file name from folder. Thanks.

Like

Is there any way to use famous tmrpcm library with this module, as there is a function that states:
audio.play(“filename”,30); // plays a file starting at 30 seconds into the track

Like

The answer does not change no matter how you ask the question. No, you cannot do this because the hardware does not support it. Maybe you should find hardware that supports what you want to do instead of focusing on this module.

Like

Hi, Thankyou for the library. I week ago I had the mp3 player working fine. Now none of my code works. To test I started running your test code. Every time I run the mp3_test.ino code after every command the serial prints “command ?”. What could be wrong.

Like

Hi it just prints the timeout error after it prints “command ?”.

I was also wondering if its possible to set variables as soon as the player finishes playing a track.

Like

Great library. Thank you! I really liked the sample files.

I don’t know if you’re ever thinking about expanding the functionality, but a fade would be nice.

Like

Thank you for providing this library – had no problems incorporating it into a project I am working to interface to a jukebox wallbox selector. I bought my first Mega 2560 this week as I’ve always just used the Uno in the past, and see there are 4 hardware serial ports. If I wanted to use the Mega board for my application, is there an advantage in not using the SoftwareSerial library and use on of the additional built in serial ports as far as code size/speed? Thank you.

Like

Definitely use the hardware ports instead of SoftwareSerial. The speed won’t change as it is relatively slow to the device at 9600 bps, but there is one less library to take up code space and the reliability of the hardware will be will be higher.

Like

Hi marco_c, I posted a reply asking how to get the hardware serial ports to work because by changing the line:
#define USE_SOFTWARESERIAL 1
to:
#define USE_SOFTWARESERIAL 0
did not work.
I then started to examine the library and think there is an error in the lines just below the define:
#define _S Serial2 ///< Native serial port – can be changed to suit
should be:
#define _Serial Serial2 ///< Native serial port – can be changed to suit
Now it works.
Thanks for the library, I am still trying to understand how it works with my limited programming experience.

Like

As a beginner, even after two nights I find it impossible to convert the example with the serial input into something I can use in my project to build a kids mp3 player.

I try to query the number of tracks, but a code like

tracksinfolder = mp3.queryFolderFiles(2);

does not work. There is an “mp3.check();” in the loop but I have no idea how to get the code that appears on serial.

What would be the easiest way to query the number of files in a folder?

Problem two (related) is, how can I quickly check if a file has stopped playing already, or what the status is?

The serial monitor example works great, but it is highly frustrating that I can’t translate it into a code that runs without any serial monitor input. Can you provide an example for a simple status query or how to detect if a file has stopped playing?

Like

The serial monitor ‘example’ is the test code the library and gives a clue as to how each functions should work. It is not meant to be something that people start from as it is essentially code fragments in a case statement.

There is extensive documentation about how the library works in the docs folder – have you read this? I expect that you are being confused by the asynchronous nature of the response to your request if you don’t get how mp3.check() works – the result comes in the callback function. This is explained in the library reference.

You are given a message when the song stops playing – again this should come through the callback function.

Like

Can it shows the name of the song? Or can we get the information and put it in to a variable or something to write it out to the serial?

regards,
Daniel

Like

I’am using an BY-8001 module to play mp3- and wav-files.
mp3-files are played correctly with the BY-8001, but wav-files are not.
Question:
Does a YX5300 play wav-files?

Like

I think that I have everything wired in and setup properly (checked 4 times)
When I run the sample application I get “Cback status: STS_TIMEOUT, 0x0” for every call.

Any ideas of what might be wrong?

Like

I ran into the same issue when I went from the UNO to a Mega2560 board using softwareserial. To make that work, I changed the Rx pin to 10 on the Mega2560 – not all pins are supported for Rx on the Mega2560. Even better, if you have the Mega2560, use one of the additional native ports on the board.

Like

It should work with the ESP32. The easiest is to try and compile without downloading and see if there are any errors in the compile.
I would try without the converter and see if it works. SD cards are generally 3.3V. As you are using the lower voltage you should be damaging anything. At worst it will not work.

Like

So I have managed to get this to work, but I have unearthed a bug.

Getting a STS_FILE_END status code to trigger playing the next file isn’t always reliable. Sometimes it will trigger it twice in a row, other times only once. Sometimes the code just throws a response “7E FE 40 EF -> 2 Ver error” response.

I have no way of knowing if it’s a bug in the library or in the player. The serial link is soldered directly onto a nano with the header pins, with a decoupling cap on the Vin, so there shouldn’t be a noise issue between player and Arduino.

Like

You can set the debug flag in the library and it will print to Serial the flow of message between the devices. If it receives the message twice, it is not in the library.

#define LIBDEBUG 1 ///< Set to 1 to enable Debug statement in the library

Library issues should be raised in the github repository under the 'issues' tab so they can be tracked properly.

Like

I found the same thing happening with my MP3 board so what I did is compared the millis() value on the last STS_FILE_END code received and disregard it if it is less than 1000mS apart. Of course if you have MP3 files that are shorter than 1 second in length (sound effects for example), you may need to use a different value than 1000mS. My application plays MP3 files based on selections made on a jukebox wallbox so it’s more than adequate.

Like

Can you give some examples for how to get the number of files and folders and store them in a variable? I’ve made an mp3 player using your library but can’t seem to figure out how to get the information from a query to use in code. I’m using buttons to send the appropriate command. The shuffle function doesn’t work and I would like to make my own thanks.

Like

Yes, but I’m not sending commands in a terminal. I hooked up buttons to an arduino. And call mp3.playtrack(i), I would like to randomize “i” but need to know how to get and store mp3.querytotalfiles into a variable. Then I could do something like
Mp3.playtrack(Random(0,totalfiles));
Thanks

Like

You are missing the point of the test example. It is to test the library AND provide examples of how it is used. If the test gives you back the wrong numbers for folders (ie the library does not work) then I need to find out what is wrong. If the test gives back the right numbers then you need to look at the example code, and/or read the library documentation, to work out how you use it in your code.

Like

It does print the correct numbers in the terminal when I send the query. I’m very new at programming and don’t understand how to get the numbers to use. I can play,pause and skip tracks just fine I just need help understanding how to get the data returned by a query.
And thank you for the great library!

Like

Ok, then you need to read the sections on message flow management, the role of the cbData structure and the entries for methods queryFolderCount() and queryFilesCount() in the documentation.

Like

I am totally here with you on this! You need to be able to load the number of files in a variable to call random() with the proper range.

I get where the dev is coming from, but trying to get a real world example of that nested serial interface is frustrating for someone who doesn’t code every day! A good ‘random player’ as an example would be marvelous for the example(s) directory!

So far all I have managed to get from this is an MP3 player that requires another microcontroller or computer to send commands and a very large headache!

Like

Hi Marco,

Many thanks for the comprehensive guide, you have included a few more commands than I found in the manual and your explanation of the status messages will be very helpful. I haven’t tested your library yet but will do so shortly – I have automated a pinball backboard with motion sensor (IR beam), lighting, sound and a servo to open the doors on a castle feature in the backboard.

I am using the YX5300 to play the mp3s which is mostly working well however I am having issues when copying several songs to the card. When I copy the files to the SD card (2Gb, FAT formatted) I receive the warning “Are you sure you want to copy the files without its properties?”, presumably because I am copying from NTFS drive to FAT (16). When I insert the SD card into the YX5300, the songs which showed the warning on copying cannot be played. When I remove the card and insert into my laptop, the files which showed warnings have either disappeared or have been corrupted so they cannot be played in Windows (VLC, etc.).

Have you experienced similar issues? Do I need to format the songs in a specific way?

Like

Many thanks for writing this library.

Unfortunately I am just a beginner to Arduino and can’t seem to get it to work. I have added the library to the arduino and loaded the test sketch but when I upload it to the arduino and open up the serial monitor I just get boxes and random characters. Entering in commands gets no response from the speakers.

Using another users original test sketch will allow me to play a mp3 track. I have also tried other sketches and they work .
such as

http://www.amazingtips247.co.uk/2015/11/how-to-play-sound-tracks-with-catalex.html

I am looking forward to getting your library and test sketch working as it looks very thorough and robust.

I just need to spend time understanding the code.

Thanks again.

regards,
Martin

Like

Leave a comment