YX5300 Serial MP3 Player (Catalex Module)

YX5300_Serial_MP3_PlayerWhile 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 at on 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 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_SONG 0x01 Play next song.
PREV_SONG 0x02 Play previous song.
PLAY_WITH_INDEX 0x03 Play song with index number. Data is the index of the file.
VOLUME_UP 0x04 Volume increase by one.
VOLUME_DOWN 0x05 Volume decrease by one.
SET_VOLUME 0x06 Set the volume to level specified. Data is the volume level [0..30].
SET_EQUALIZER 0x07 Set the equalizer to specified level. Data is [0..5] – 0=Normal, 1=Pop, 2=Rock, 3=Jazz, 4=Classic or 5=Base.
SNG_CYCL_PLAY 0x08 Loop play (repeat) specified track. Data is the track number.
SEL_DEV 0x09 Select file storage device. The only valid choice for data is TF (0x02).
SLEEP_MODE 0x0a Chip enters sleep mode.
WAKE_UP 0x0b Chip wakes up from sleep mode.
RESET 0x0c Chip reset.
PLAY 0x0d Playback restart.
PAUSE 0x0e Pause playback.
PLAY_FOLDER_FILE 0x0f Play the file with the specified folder and index number
STOP_PLAY 0x16 Stop playback.
FOLDER_CYCLE 0x17 Loop playback within specified folder. Data is the folder index.
SHUFFLE_PLAY 0x18 Playback shuffle mode. Data is 0 to enable, 1 to disable.
SET_SNGL_CYCL 0x19 Set loop play (repeat) on/off for current file. Data is 0 to enable, 1 to disable.
SET_DAC 0x1a DAC on/off control (mute sound). Data is 0 to enable DAC, 1 to disable DAC (mute).
PLAY_W_VOL 0x22 Play track at the specified volume. Data hi byte is the track index, low byte is the volume level [0..30].
SHUFFLE_FOLDER 0x28 Playback shuffle mode for folder specified. Data high byte is the folder index.
QUERY_STATUS 0x42 Query Device Status.
QUERY_VOLUME 0x43 Query Volume level.
QUERY_EQUALIZER 0x44 Query current equalizer (disabled in hardware).
QUERY_TOT_FILES 0x48 Query total files in all folders.
QUERY_PLAYING 0x4c Query which track playing
QUERY_FLDR_FILES 0x4e Query total files in folder. Data is the folder index number.
QUERY_TOT_FLDR 0x4f Query 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_INSERT 0x3a TF Card was inserted (unsolicited message).
TF_REMOVE 0x3b TF card was removed (unsolicited message).
FILE_END 0x3d Track/file has ended (unsolicited message). Data is the index number of the file just completed.
INIT 0x3f Initialization complete (unsolicited message). Data is the file store types available (0x02 for TF).
ERR_FILE 0x40 Error file not found. Data is error code (no definition).
ACK_OK 0x41 Message acknowledged ok
STATUS 0x42 Current status. Data high byte is file store (2 for TF); low byte 0=stopped, 1=play, 2=paused.
VOLUME 0x43 Current volume level. Data is volume level [0..30].
EQUALIZER 0x44 Equalizer status. Data is equalizer mode types  0=Normal, 1=Pop, 2=Rock, 3=Jazz, 4=Classic or 5=Base.
TOT_FILES 0x48 TF Total file count
PLAYING 0x4c Current file playing
FLDR_FILES 0x4e Total number of files in the folder. Data is the number of files.
TOT_FLDR 0x4f Total 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 that 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.

Update: More information on Message Sequencing for the YX5300 in this blog.

Advertisements

35 thoughts on “YX5300 Serial MP3 Player (Catalex Module)

  1. TonyJ

    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

    1. 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

      1. 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

  2. Pingback: They see me moddin BB | dyne3d

  3. 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

    1. 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

  4. Daniel Szabo

    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

  5. Jan

    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

  6. Tim

    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

    1. TonyJ

      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

      1. 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

  7. JL McCabe

    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

    1. 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

    2. TonyJ

      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

  8. Ross

    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

      1. Ross

        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

      2. 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

      3. Ross

        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

      4. 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

    1. JL McCabe

      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

  9. Jeremy

    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

  10. Martin

    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 Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s