Hello!
I'm using a YX5300 for a simple audio project, but I've yet to get the module to send any response to my MEGA(clone 2560/16U2). The module is otherwise functional, I can play different tracks without issue. (Bonus minor issue: slight noise/chirping in the headphones when not playing, silenced by a light touch of a finger on the SD card slot)
I have tested 2 YX5300 modules, 3 serial ports on the MEGA, and 2 libraries (SerialMP3Player and MD_YX5300) using their examples (BasicCommands and MD_YX5300_Test) changing only the RX/TX pins. I have yet to receive anything back in the form of a command acknowledge or unsolicited message (finished playback, SD card insert/remove, etc) even though both libraries are capable of receiving the responses. I have also checked my hardware, moved the components to different breadboard locations and used different connectors.
What I get back what I issue a command through the serial monitor:
MD_YX5300:
>Play Track 1
Cback status: STS_OK, 0x0
Cback status: STS_TIMEOUT, 0x0
SerialMP3Player:
Play //Specific Track
Sending: 0X7e 0Xff 0X06 0X03 0X01 0X00 0X0a 0Xef
Play //Play
Sending: 0X7e 0Xff 0X06 0X0d 0X01 0X00 0X00 0Xef
// There should be 8 bits coming back after each command
The best part is I only need a few simple functions for my project:
- Play a single file at a time.
- Receive a "playback finished" signal.
- Maybe volume control if I'm feeling fancy.
I feel like I'm missing something obvious, but for my life of me, I can't seem to find it. Do I need to update the firmware on the MEGA?
Has anyone else experienced this?
Example Sketches:
MD_YX5300 - MD_YX5300_Test
// Test program for the MD_YX5300 library
//
// Menu driven interface using the Serial Monitor to test individual functions.
//
// Dependencies
// MD_cmdProcessor library found at https://github.com/MajicDesigns/MD_cmdProcessor
//
#ifndef USE_SOFTWARESERIAL
#define USE_SOFTWARESERIAL 1 ///< Set to 1 to use SoftwareSerial library, 0 for native serial port
#endif
#include <MD_YX5300.h>
#include <MD_cmdProcessor.h>
#if USE_SOFTWARESERIAL
#include <SoftwareSerial.h>
// Connections for serial interface to the YX5300 module
const uint8_t ARDUINO_RX = 15; // connect to TX of MP3 Player module
const uint8_t ARDUINO_TX = 14; // connect to RX of MP3 Player module
SoftwareSerial MP3Stream(ARDUINO_RX, ARDUINO_TX); // MP3 player serial stream for comms
#define Console Serial // command processor input/output stream
#else
#define MP3Stream Serial2 // Native serial port - change to suit the application
#define Console Serial // command processor input/output stream
#endif
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#define CMD(s) { Console.print(F("\n>")); Console.print(F(s)); Console.print(F(" ")); }
// Define YX5300 global variables
MD_YX5300 mp3(MP3Stream);
bool bUseCallback = true; // use callbacks?
bool bUseSynch = false; // use synchronous?
void cbResponse(const MD_YX5300::cbData *status)
// Used to process device responses either as a library callback function
// or called locally when not in callback mode.
{
if (bUseSynch)
Console.print(F("\nSync Status: "));
else
Console.print(F("\nCback status: "));
switch (status->code)
{
case MD_YX5300::STS_OK: Console.print(F("STS_OK")); break;
case MD_YX5300::STS_TIMEOUT: Console.print(F("STS_TIMEOUT")); break;
case MD_YX5300::STS_VERSION: Console.print(F("STS_VERSION")); break;
case MD_YX5300::STS_CHECKSUM: Console.print(F("STS_CHECKSUM")); break;
case MD_YX5300::STS_TF_INSERT: Console.print(F("STS_TF_INSERT")); break;
case MD_YX5300::STS_TF_REMOVE: Console.print(F("STS_TF_REMOVE")); break;
case MD_YX5300::STS_ERR_FILE: Console.print(F("STS_ERR_FILE")); break;
case MD_YX5300::STS_ACK_OK: Console.print(F("STS_ACK_OK")); break;
case MD_YX5300::STS_FILE_END: Console.print(F("STS_FILE_END")); break;
case MD_YX5300::STS_INIT: Console.print(F("STS_INIT")); break;
case MD_YX5300::STS_STATUS: Console.print(F("STS_STATUS")); break;
case MD_YX5300::STS_EQUALIZER: Console.print(F("STS_EQUALIZER")); break;
case MD_YX5300::STS_VOLUME: Console.print(F("STS_VOLUME")); break;
case MD_YX5300::STS_TOT_FILES: Console.print(F("STS_TOT_FILES")); break;
case MD_YX5300::STS_PLAYING: Console.print(F("STS_PLAYING")); break;
case MD_YX5300::STS_FLDR_FILES: Console.print(F("STS_FLDR_FILES")); break;
case MD_YX5300::STS_TOT_FLDR: Console.print(F("STS_TOT_FLDR")); break;
default: Console.print(F("STS_??? 0x")); Console.print(status->code, HEX); break;
}
Console.print(F(", 0x"));
Console.print(status->data, HEX);
}
void setCallbackMode(bool b)
{
bUseCallback = b;
CMD("Callback");
Console.print(b ? F("ON") : F("OFF"));
mp3.setCallback(b ? cbResponse : nullptr);
}
void setSynchMode(bool b)
{
bUseSynch = b;
CMD("Synchronous");
Console.print(b ? F("ON") : F("OFF"));
mp3.setSynchronous(b);
}
char * getNum(char *cp, uint32_t &v, uint8_t base = 10)
{
char* rp;
v = strtoul(cp, &rp, base);
return(rp);
}
// Command processor handlers
void handlerHelp(char* param);
void handlerP_bang(char* param) { CMD("Play Start"); mp3.playStart(); cbResponse(mp3.getStatus()); }
void handlerPP(char* param) { CMD("Play Pause"); mp3.playPause(); cbResponse(mp3.getStatus()); }
void handlerPZ(char* param) { CMD("Play Stop"); mp3.playStop(); cbResponse(mp3.getStatus()); }
void handlerP_gt(char* param) { CMD("Play Next"); mp3.playNext(); cbResponse(mp3.getStatus()); }
void handlerP_lt(char* param) { CMD("Play Prev"); mp3.playPrev(); cbResponse(mp3.getStatus()); }
void handlerP(char* param)
{
uint32_t t;
getNum(param, t);
CMD("Play Track");
Console.print(t);
mp3.playTrack(t);
cbResponse(mp3.getStatus());
}
void handlerPT(char* param)
{
uint32_t fldr, file;
param = getNum(param, fldr);
getNum(param, file);
CMD("Play Specific Fldr");
Console.print(fldr);
Console.print(F(", "));
Console.print(file);
mp3.playSpecific(fldr, file);
cbResponse(mp3.getStatus());
}
void handlerPF(char* param)
{
uint32_t fldr;
getNum(param, fldr);
CMD("Play Folder");
Console.print(fldr);
mp3.playFolderRepeat(fldr);
cbResponse(mp3.getStatus());
}
void handlerPX(char* param)
{
uint32_t fldr;
getNum(param, fldr);
CMD("Play Shuffle Folder");
Console.print(fldr);
mp3.playFolderShuffle(fldr);
cbResponse(mp3.getStatus());
}
void handlerPR(char* param)
{
uint32_t file;
getNum(param, file);
CMD("Play File repeat");
Console.print(file);
mp3.playTrackRepeat(file);
cbResponse(mp3.getStatus());
}
void handlerVM(char *param)
{
uint32_t cmd;
getNum(param, cmd);
CMD("Volume Enable");
Console.print(cmd);
mp3.volumeMute(cmd != 0);
cbResponse(mp3.getStatus());
}
void handlerV(char *param)
{
uint32_t v;
getNum(param, v);
CMD("Volume");
Console.print(v);
mp3.volume(v);
cbResponse(mp3.getStatus());
}
void handlerV_plus(char* param) { CMD("Volume Up"); mp3.volumeInc(); cbResponse(mp3.getStatus()); }
void handlerV_minus(char* param) { CMD("Volume Down"); mp3.volumeDec(); cbResponse(mp3.getStatus()); }
void handlerQE(char* param) { CMD("Query Equalizer"); mp3.queryEqualizer(); cbResponse(mp3.getStatus()); }
void handlerQF(char* param) { CMD("Query File"); mp3.queryFile(); cbResponse(mp3.getStatus()); }
void handlerQS(char* param) { CMD("Query Status"); mp3.queryStatus(); cbResponse(mp3.getStatus()); }
void handlerQV(char* param) { CMD("Query Volume"); mp3.queryVolume(); cbResponse(mp3.getStatus()); }
void handlerQX(char* param) { CMD("Query Folder Count"); mp3.queryFolderCount(); cbResponse(mp3.getStatus()); }
void handlerQY(char* param) { CMD("Query Tracks Count"); mp3.queryFilesCount(); cbResponse(mp3.getStatus()); }
void handlerQZ(char* param)
{
uint32_t fldr;
getNum(param, fldr);
CMD("Query Folder Files Count");
Console.print(fldr);
mp3.queryFolderFiles(fldr);
cbResponse(mp3.getStatus());
}
void handlerS(char *param) { CMD("Sleep"); mp3.sleep(); cbResponse(mp3.getStatus()); }
void handlerW(char *param) { CMD("Wake up"); mp3.wakeUp(); cbResponse(mp3.getStatus()); }
void handlerZ(char *param) { CMD("Reset"); mp3.reset(); cbResponse(mp3.getStatus()); }
void handlerE(char *param)
{
uint32_t e;
getNum(param, e);
CMD("Equalizer");
Console.print(e);
mp3.equalizer(e);
cbResponse(mp3.getStatus());
}
void handlerX(char *param)
{
uint32_t cmd;
getNum(param, cmd);
CMD("Shuffle");
Console.print(cmd);
mp3.shuffle(cmd != 0);
cbResponse(mp3.getStatus());
}
void handlerR(char* param)
{
uint32_t cmd;
getNum(param, cmd);
CMD("Repeat");
Console.print(cmd);
mp3.repeat(cmd != 0);
cbResponse(mp3.getStatus());
}
void handlerY(char *param)
{
uint32_t cmd;
getNum(param, cmd);
setSynchMode(cmd != 0);
}
void handlerC(char * param)
{
uint32_t cmd;
getNum(param, cmd);
setCallbackMode(cmd != 0);
}
const MD_cmdProcessor::cmdItem_t PROGMEM cmdTable[] =
{
{ "?", handlerHelp, "", "Help", 0 },
{ "h", handlerHelp, "", "Help", 0 },
{ "p!", handlerP_bang, "", "Play", 1 },
{ "p", handlerP, "n", "Play file index n (0-255)", 1 },
{ "pp", handlerPP, "", "Play Pause", 1 },
{ "pz", handlerPZ, "", "Play Stop", 1 },
{ "p>", handlerP_gt, "", "Play Next", 1 },
{ "p<", handlerP_lt, "", "Play Previous", 1 },
{ "pt", handlerPT, "f n", "Play Track folder f, file n", 1 },
{ "pf", handlerPF, "f", "Play loop folder f", 1 },
{ "px", handlerPX, "f", "Play shuffle folder f", 1 },
{ "pr", handlerPR, "n", "Play loop file index n", 1 },
{ "v+", handlerV_plus, "", "Volume up", 2 },
{ "v-", handlerV_minus, "", "Volume down", 2 },
{ "v", handlerV, "x", "Volume set x (0-30)", 2 },
{ "vm", handlerVM, "b", "Volume Mute on (b=1), off (0)", 2 },
{ "qe", handlerQE, "", "Query equalizer", 3 },
{ "qf", handlerQF, "", "Query current file", 3 },
{ "qs", handlerQS, "", "Query status", 3 },
{ "qv", handlerQV, "", "Query volume", 3 },
{ "qx", handlerQX, "", "Query folder count", 3 },
{ "qy", handlerQY, "", "Query total file count", 3 },
{ "qz", handlerQZ, "f", "Query files count in folder f", 3 },
{ "s", handlerS, "", "Sleep", 4 },
{ "w", handlerW, "", "Wake up", 4 },
{ "e", handlerE, "n", "Equalizer type n", 5 },
{ "x", handlerX, "b", "Play Shuffle on (b=1), off (0)", 5 },
{ "r", handlerR, "b", "Play Repeat on (b=1), off (0)", 5 },
{ "z", handlerZ, "", "Reset", 5 },
{ "y", handlerY, "b", "Synchronous mode on (b=1), off (0)", 6 },
{ "c", handlerC, "b", "Callback mode on (b=1), off (0)", 6 },
};
MD_cmdProcessor CP(Console, cmdTable, ARRAY_SIZE(cmdTable));
// handler functions
void handlerHelp(char* param)
{
Console.print(F("\n[MD_YX5300 Test]\nSet Serial line ending to newline."));
CP.help();
Console.print(F("\n"));
}
void setup()
{
// YX5300 Serial interface
MP3Stream.begin(MD_YX5300::SERIAL_BPS);
mp3.begin();
setCallbackMode(bUseCallback);
setSynchMode(bUseSynch);
// command line interface
Console.begin(57600);
CP.begin();
CP.help();
}
void loop()
{
CP.run();
mp3.check();
}
SerialMP3Player - BasicCommands
/******************************************************************************
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 16
#define RX 17
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);
}
}
}
Hardware Hookup:
+5V from MEGA
GND to MEGA
TX to MEGA RX3(15)
RX to MEGA TX3(14)

