Last Updated: 29/12/2023
DY-SV5W MP3 Player
Components >> DY-SV5W MP3 Player
DY-SV5W MP3 Player
This is a tutorial will deal with the basics of serial communication with the DY-SV5W MP3 player.
The DY-SV5W MP3 player has advantages over the DFPlayer and the Serial MP3 player as it has a built in amplifier that gives better sound quality.
It laos has the
advantage of being able to load the files directly to the SD Card through the build in USB port.
The only disadvatage I have found is it is physically bigger.
As with the Serial MP3 player and the DF MIni player you cannot read file names so it is best to number your files in the format 001.mp3, 002.mp3 etc.
There can also be some odd issues if youadd new files. Try to add them in numerical filename order.
I tend to write a sketch that plays through the files in order noting their number as the board sees them.
The technical specs for this board can be found here.
As my sketches are biased towards model railways I have created 2 sketches.
The first works through 5 files in order on the card (can easily be changed to random).
The 2nd sketch does the same except when the arc welder sound is played an LED flashes in an arc welder style.
The sketches are based on the Arduino Mega using Serial1, this could easily be adapted to use Software Serial on an Uno/Nano (See the Arduino UNO section below) or using the Serial1 on an ESP32 or ESP8266.
Arduino Mega Connections.
Arduino Mega | DY-SV5W |
5V | 5V+ |
Gnd | Gnd |
RX1 | TX |
TX1 | RX |
Pin 8 | Busy Pin |
In the Arc Welder sketch Pin 9 is connected to the LED through a 330Ohm resistor.
The Selectors on the Red switchbox should be set to:
1 = OFF
2 = OFF
3 = ON
Arduino Uno Version
I had a request for a version that would run on the Arduino Uno.As the Uno only has one Serial output it requires the use of the Software Serial library to imitate another Serial port.
Arduino UNO | DY-SV5W |
5V | 5V+ |
Gnd | Gnd |
Pin 10 | TX |
Pin 11 | RX |
Pin 8 | Busy Pin |
The code can be found in examples 4-6 below
Problem
When I wrote some sketches for the DF Mini player I was able to use the serial communication from the DF Mini player to let me know when the track had finished playing. This is not available on the DY-SV5W.
However, the busy pin reads HIGH when nothing is playing, LOW when track is playing so I have utilised that in my sketches.
If you don't need to know when the sound has ended there is no need to connect pin 8.
Example 1: Arduino Mega 2560 DYSV5Wv4.ino
Click to Download code: DYSV5Wv4.ino
Written to run on Arduino Mega2560 Using Serial1
This is a very simple test sketch, it sets the volume, selects "random" mode, and sends a play command.
The board then plays all the tracks on the SD card in a random order.
/* DYSV5Wv4
* Playing Random Tracks
* Mega 2560
*
* Player on Serial 1 (pins 18-19)
*/
byte volume = 0x40;
byte commandLength;
byte command[6];
int checkSum = 0;
void sendCommand(){
int q;
for(q=0;q < commandLength;q++){
Serial1.write(command[q]);
Serial.print(command[q],HEX);
}
Serial.println("End");
}
void setup() {
Serial.begin(115200);
Serial1.begin(9600);
Serial.println("DYSV5Wv4");
//set volume to 17
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x13;
command[2] = 0x01;
command[3] = 17;//volume
checkSum = 0;
for(int q=0;q<4;q++){
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
//play track
//select random mode
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x18;
command[2] = 0x01;
command[3] = 0x03;//random
checkSum = 0;
for(int q=0;q<4;q++){
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
//play track
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x02;
command[2] = 0x00;
command[3] = 0xAC;
commandLength = 4;
sendCommand();
}
void loop() {
}
Example 2: Arduino Mega 2560 DYSV5Wv7.ino
Click to Download code: DYSV5Wv7.ino
Written to run on Arduino Mega2560 Using Serial1
I have written a few functions based on the information in the data sheet. If you want more functions you can use the ones created as a basis.
/* DYSV5Wv7
Just plays track 5 with 2 sec gap after playing
Mega 2560
Player on Serial 1 (pins 18-19)
busyPin = 8 //receives busy signal from DY-SV5W
*/
//variables always required to work DY-SV5W
const int busyPin = 8;//change to any suitable digital pin
byte commandLength;
byte command[6];
int checkSum = 0;
//my variables for demo sketch
int trackNum = 1;
int playStatus; //0 playing 1 stopped 2 waiting to start next track
unsigned long lastCheckTime;
unsigned long currentMillis;
int busyPinstate;
void playTrack(int soundTrack) {
//select track
//Serial.print("soundTrack: ");
//Serial.println(soundTrack);
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x07;
command[2] = 0x02;
command[3] = highByte(soundTrack);//snh...track HIGH bit
command[4] = lowByte(soundTrack);//SNL... track low bit
checkSum = 0;
for (int q = 0; q < 5; q++) {
checkSum += command[q];
}
command[5] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 6;
sendCommand();
}
//plays whatever track has been paused or 1st track if nothing selected
//May need to be selected after putting into random mode
void play() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x02;
command[2] = 0x00;
command[3] = 0xAC;
commandLength = 4;
sendCommand();
}
//selects random mode
void randomMode() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x18;
command[2] = 0x01;
command[3] = 0x03;//random
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
//play() needs to be selected if you want the random tracks to start playing instantly
play();
}
//sets the device volume...0 - 30
void playbackVolume(int vol) {
if (vol > 30) { //check within limits
vol = 30;
}
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x13;
command[2] = 0x01;
command[3] = vol;//volume
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
}
//sends the command
void sendCommand() {
int q;
for (q = 0; q < commandLength; q++) {
Serial1.write(command[q]);
Serial.print(command[q], HEX);
}
Serial.println("End");
}
void setup() {
Serial.begin(115200);
Serial1.begin(9600);
Serial.println("DYSV5Wv7");
pinMode(busyPin, INPUT);//pin to read from DY-SV5W buyPin
playbackVolume(17);//sets volume to lvl 17
}
void loop() {
currentMillis = millis();//stores time in millis() for non blocking timings
busyPinstate = digitalRead(busyPin);
if (busyPinstate > 0) { //nothing playing
if (playStatus < 1) {
playStatus = 1;
lastCheckTime = currentMillis;//set system ready for 2 sec delay
}
}
switch (playStatus) {
case 1:
if (currentMillis - lastCheckTime >= 2000) { //2000 = 2 seconds of silence between tracks
playStatus = 2;
//Just selecting a new track
//this could have been something like
//trackNum = random(1,5);
//trackNum = 5;//fixed track number
playTrack(trackNum);
trackNum++;
if(trackNum > 5){
trackNum = 1;
}
}
break;
case 2:
if(busyPinstate < 1){
playStatus = 0;
}
break;
default:
break;
}
}
Example 3: Arduino Mega 2560 DYSV5Wv8.ino
Click to Download code: DYSV5Wv8.ino
Written to run on Arduino Mega 2560 using Serial1
This sketch has an LED on pin 9 that is connected through a 330Ohm resistor.
It will flicker when track 5 is played which on my SD card is the arc welder.
/* DYSV5Wv8
Just plays throgh tracks with 2 sec gap after playing
When track 5 plays (arc welder) the led on pin 9 with do arc flicker
Mega 2560
Player on Serial 1 (pins 18-19)
busyPin = 8 //receives busy signal from DY-SV5W
arcPin = 9 //pin for arc welder led 330ohm resistor
*/
//variables always required to work DY-SV5W
const int busyPin = 8;//change to any suitable digital pin
byte commandLength;
byte command[6];
int checkSum = 0;
//my variables for demo sketch
int trackNum = 1;
int playStatus; //0 playing 1 stopped 2 waiting to start next track
unsigned long lastCheckTime;
unsigned long currentMillis;
int busyPinstate;
//Arc Welder
const int arcPin = 9;//pin used
unsigned long arcTimer;//keeps track of when next arc change is due
int arcTimerPeriod = 50;//intial value but will change all the time
byte arcState = 0; //0 = off, 1 = ON...should the welder be running
byte arcLEDState;//0 = off, 1 = ON...current state of led
void playTrack(int soundTrack) {
//select track
//Serial.print("soundTrack: ");
//Serial.println(soundTrack);
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x07;
command[2] = 0x02;
command[3] = highByte(soundTrack);//snh...track HIGH bit
command[4] = lowByte(soundTrack);//SNL... track low bit
checkSum = 0;
for (int q = 0; q < 5; q++) {
checkSum += command[q];
}
command[5] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 6;
sendCommand();
}
//plays whatever track has been paused or 1st track if nothing selected
//May need to be selected after putting into random mode
void play() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x02;
command[2] = 0x00;
command[3] = 0xAC;
commandLength = 4;
sendCommand();
}
//selects random mode
void randomMode() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x18;
command[2] = 0x01;
command[3] = 0x03;//random
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
//play() needs to be selected if you want the random tracks to start playing instantly
play();
}
//sets the device volume...0 - 30
void playbackVolume(int vol) {
if (vol > 30) { //check within limits
vol = 30;
}
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x13;
command[2] = 0x01;
command[3] = vol;//volume
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
}
//sends the command to the DY-SV5W
void sendCommand() {
int q;
for (q = 0; q < commandLength; q++) {
Serial1.write(command[q]);
Serial.print(command[q], HEX);
}
Serial.println("End");
}
//arc welder effect
//this will cause the LED in pin 9 to flash intermittently.
void arcWelder() {
if (arcState > 0) {//if arc state is set
if (currentMillis - arcTimer > arcTimerPeriod) {
arcTimer = currentMillis;
if (arcLEDState < 1) { //turn on
arcLEDState = 1; //on
arcTimerPeriod = random(40, 100);//set a new random timer period
} else { //turn off
arcLEDState = 0; //off
arcTimerPeriod = random(20, 80);//different random for off period
}
digitalWrite(arcPin, arcLEDState); //set the LED to new state
}
} else {
arcLEDState = 0;
digitalWrite(arcPin, arcLEDState); //turn the LED off if arc welder not running
arcState = 0;
}
}
void setup() {
Serial.begin(115200);
Serial1.begin(9600);
Serial.println("DYSV5Wv8");
pinMode(busyPin, INPUT);//pin to read from DY-SV5W buyPin
pinMode(arcPin, OUTPUT); //out put pin for LED flicker
playbackVolume(17);//sets volume to lvl 17
}
void loop() {
currentMillis = millis();//stores time in millis() for non blocking timings
busyPinstate = digitalRead(busyPin);//check the busyPin state
if (busyPinstate > 0) { //nothing playing
if (playStatus < 1) {//test playStatus to make sure we are not in waiting period between tracks
arcState = 0;//turn arc status off...nothing should be running
playStatus = 1; //set playstatus to next mode.
lastCheckTime = currentMillis;//set system ready for 2 sec delay
}
}
//works thorugh the various playStatus
switch (playStatus) {
case 1:
if (currentMillis - lastCheckTime >= 2000) { //2000 = 2 seconds of silence between tracks
playStatus = 2;//set the playStatus to next mode
//if the trackNum selected is 5 turn the arc welder flash on.
if(trackNum == 5){
arcState = 1;
}
playTrack(trackNum);//play the track
//Just selecting a new track
//this could have been something like
//trackNum = random(1,5);
trackNum++;
if(trackNum > 5){//I only have 5 tracks on SD Card
trackNum = 1;
}
//end of new track selection section
}
break;
case 2:
//resets system for next track
if(busyPinstate < 1){
playStatus = 0;
}
break;
default:
break;
}
arcWelder();//deal with arc welder routine
}
Example 4: Arduino UNO using Software Serial DYSV5Wsoftserialv4.ino
Click to Download code: DYSV5Wsoftserialv4.ino
Written to run on Arduino UNO using Software Serial
This is a very simple test sketch, it sets the volume, selects "random" mode, and sends a play command.
The board then plays all the tracks on the SD card in a random order.
/* DYSV5Wv4
* Playing Random Tracks
* arduino UNO
*
* Player on Software Serial (pins 10-11)
*/
#include "SoftwareSerial.h"
SoftwareSerial mySerial(10, 11); // RX, TX
byte volume = 0x40;
byte commandLength;
byte command[6];
int checkSum = 0;
void sendCommand(){
int q;
for(q=0;q
Example 5: Arduino UNO using Software Serial DYSV5Wsoftserialv7.ino
Click to Download code: DYSV5Wsoftserialv7.ino
Written to run on Arduino UNO using Software Serial
I have written a few functions based on the information in the data sheet. If you want more functions you can use the ones created as a basis.
/* DYSV5Wsoftserialv7
Just plays track 5 with 2 sec gap after playing
Arduino UNO unsing software Serial
Player on Serial 1 (pins 18-19)
busyPin = 8 //receives busy signal from DY-SV5W
*/
#include "SoftwareSerial.h"
SoftwareSerial mySerial(10, 11); // RX, TX
//variables always required to work DY-SV5W
const int busyPin = 8;//change to any suitable digital pin
byte commandLength;
byte command[6];
int checkSum = 0;
//my variables for demo sketch
int trackNum = 1;
int playStatus; //0 playing 1 stopped 2 waiting to start next track
unsigned long lastCheckTime;
unsigned long currentMillis;
int busyPinstate;
void playTrack(int soundTrack) {
//select track
//Serial.print("soundTrack: ");
//Serial.println(soundTrack);
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x07;
command[2] = 0x02;
command[3] = highByte(soundTrack);//snh...track HIGH bit
command[4] = lowByte(soundTrack);//SNL... track low bit
checkSum = 0;
for (int q = 0; q < 5; q++) {
checkSum += command[q];
}
command[5] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 6;
sendCommand();
}
//plays whatever track has been paused or 1st track if nothing selected
//May need to be selected after putting into random mode
void play() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x02;
command[2] = 0x00;
command[3] = 0xAC;
commandLength = 4;
sendCommand();
}
//selects random mode
void randomMode() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x18;
command[2] = 0x01;
command[3] = 0x03;//random
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
//play() needs to be selected if you want the random tracks to start playing instantly
play();
}
//sets the device volume...0 - 30
void playbackVolume(int vol) {
if (vol > 30) { //check within limits
vol = 30;
}
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x13;
command[2] = 0x01;
command[3] = vol;//volume
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
}
//sends the command
void sendCommand() {
int q;
for (q = 0; q < commandLength; q++) {
mySerial.write(command[q]);
Serial.print(command[q], HEX);
}
Serial.println("End");
}
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
Serial.println("DYSV5Wsoftserialv7");
pinMode(busyPin, INPUT);//pin to read from DY-SV5W buyPin
playbackVolume(17);//sets volume to lvl 17
}
void loop() {
currentMillis = millis();//stores time in millis() for non blocking timings
busyPinstate = digitalRead(busyPin);
if (busyPinstate > 0) { //nothing playing
if (playStatus < 1) {
playStatus = 1;
lastCheckTime = currentMillis;//set system ready for 2 sec delay
}
}
switch (playStatus) {
case 1:
if (currentMillis - lastCheckTime >= 2000) { //2000 = 2 seconds of silence between tracks
playStatus = 2;
//Just selecting a new track
//this could have been something like
//trackNum = random(1,5);
//trackNum = 5;//fixed track number
playTrack(trackNum);
trackNum++;
if(trackNum > 6){
trackNum = 1;
}
}
break;
case 2:
if(busyPinstate < 1){
playStatus = 0;
}
break;
default:
break;
}
}
Example 6: Arduino UNO using Software Serial DYSV5Wsoftserialv8.ino
Click to Download code: DYSV5Wsoftserialv8.ino
Written to run on Arduino UNO using Software Serial
This sketch has an LED on pin 9 that is connected through a 330Ohm resistor.
It will flicker when track 5 is played which on my SD card is the arc welder.
/* DYSV5Wsoftserialv8
Just plays throgh tracks with 2 sec gap after playing
When track 5 plays (arc welder) the led on pin 9 with do arc flicker
Arduino Uno using spoftware serial on pins 10-11
busyPin = 8 //receives busy signal from DY-SV5W
arcPin = 9 //pin for arc welder led 330ohm resistor
*/
#include "SoftwareSerial.h"
SoftwareSerial mySerial(10, 11); // RX, TX
//variables always required to work DY-SV5W
const int busyPin = 8;//change to any suitable digital pin
byte commandLength;
byte command[6];
int checkSum = 0;
//my variables for demo sketch
int trackNum = 1;
int playStatus; //0 playing 1 stopped 2 waiting to start next track
unsigned long lastCheckTime;
unsigned long currentMillis;
int busyPinstate;
//Arc Welder
const int arcPin = 9;//pin used
unsigned long arcTimer;//keeps track of when next arc change is due
int arcTimerPeriod = 50;//intial value but will change all the time
byte arcState = 0; //0 = off, 1 = ON...should the welder be running
byte arcLEDState;//0 = off, 1 = ON...current state of led
void playTrack(int soundTrack) {
//select track
//Serial.print("soundTrack: ");
//Serial.println(soundTrack);
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x07;
command[2] = 0x02;
command[3] = highByte(soundTrack);//snh...track HIGH bit
command[4] = lowByte(soundTrack);//SNL... track low bit
checkSum = 0;
for (int q = 0; q < 5; q++) {
checkSum += command[q];
}
command[5] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 6;
sendCommand();
}
//plays whatever track has been paused or 1st track if nothing selected
//May need to be selected after putting into random mode
void play() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x02;
command[2] = 0x00;
command[3] = 0xAC;
commandLength = 4;
sendCommand();
}
//selects random mode
void randomMode() {
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x18;
command[2] = 0x01;
command[3] = 0x03;//random
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
//play() needs to be selected if you want the random tracks to start playing instantly
play();
}
//sets the device volume...0 - 30
void playbackVolume(int vol) {
if (vol > 30) { //check within limits
vol = 30;
}
command[0] = 0xAA;//first byte says it's a command
command[1] = 0x13;
command[2] = 0x01;
command[3] = vol;//volume
checkSum = 0;
for (int q = 0; q < 4; q++) {
checkSum += command[q];
}
command[4] = lowByte(checkSum);//SM check bit... low bit of the sum of all previous values
commandLength = 5;
sendCommand();
}
//sends the command to the DY-SV5W
void sendCommand() {
int q;
for (q = 0; q < commandLength; q++) {
mySerial.write(command[q]);
Serial.print(command[q], HEX);
}
Serial.println("End");
}
//arc welder effect
//this will cause the LED in pin 9 to flash intermittently.
void arcWelder() {
if (arcState > 0) {//if arc state is set
if (currentMillis - arcTimer > arcTimerPeriod) {
arcTimer = currentMillis;
if (arcLEDState < 1) { //turn on
arcLEDState = 1; //on
arcTimerPeriod = random(40, 100);//set a new random timer period
} else { //turn off
arcLEDState = 0; //off
arcTimerPeriod = random(20, 80);//different random for off period
}
digitalWrite(arcPin, arcLEDState); //set the LED to new state
}
} else {
arcLEDState = 0;
digitalWrite(arcPin, arcLEDState); //turn the LED off if arc welder not running
arcState = 0;
}
}
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
Serial.println("DYSV5Wsoftserialv8");
pinMode(busyPin, INPUT);//pin to read from DY-SV5W buyPin
pinMode(arcPin, OUTPUT); //out put pin for LED flicker
playbackVolume(30);//sets volume to lvl 17
}
void loop() {
currentMillis = millis();//stores time in millis() for non blocking timings
busyPinstate = digitalRead(busyPin);//check the busyPin state
if (busyPinstate > 0) { //nothing playing
if (playStatus < 1) {//test playStatus to make sure we are not in waiting period between tracks
arcState = 0;//turn arc status off...nothing should be running
playStatus = 1; //set playstatus to next mode.
lastCheckTime = currentMillis;//set system ready for 2 sec delay
}
}
//works thorugh the various playStatus
switch (playStatus) {
case 1:
if (currentMillis - lastCheckTime >= 2000) { //2000 = 2 seconds of silence between tracks
playStatus = 2;//set the playStatus to next mode
//if the trackNum selected is 5 turn the arc welder flash on.
if(trackNum == 5){
arcState = 1;
}
playTrack(trackNum);//play the track
//Just selecting a new track
//this could have been something like
//trackNum = random(1,5);
trackNum++;
if(trackNum > 5){//I only have 5 tracks on SD Card
trackNum = 1;
}
//end of new track selection section
}
break;
case 2:
//resets system for next track
if(busyPinstate < 1){
playStatus = 0;
}
break;
default:
break;
}
arcWelder();//deal with arc welder routine
}
Additional Resource Links
If you want to use a PCA9685 board to control the leds this sketch could be combined with the effects from the turorial below.
Model Railway Light Effects using PCA685 and LED's with Arduino or ESP3217/07/2021
Comments
This site has been designed to be child friendly, this means that comments cannot be added to directly to the site. To add a comment or ask a question please email the address in this image: and use DY-SV5W MP3 Player as a reference.