Last Updated: 21/12/2022
DFmini player & MP3-T-16P v3.0
Components >> DFmini player & MP3-T-16P v3.0
DFmini player & MP3-TF-16P v3.0 Player
This is a tutorial to deal with the differences between a DFmini player and a MP3-TF-16P v3.0 mpy player.
This tutorial came about after I needed another DFplayer on a model railway project, ordered one, and it didn't work. Ordered a second...and it didn't work. ordered a 3rd and yet again failure. I would plug in the replacement, power light would flash and then nothing.
All 3 had come from different suppliers, 2 in UK, the other from AliExpress....what is going on?
Well it seems that not all DFmini players are the same.
On the left is my existing, working DFmini player, on the right is a new one...sold as a DFmini player on numerous sites. They look identical apart from the writing on them.
Left version says: DFPlayer Mini HW-247A
Right side is: MP3-TF-16P v3.0
So the look the same until you turn them over.
The one on the left is the original DFplayer, the one on the right is the MP3-TF-16P. At a quick glance they look the same but then notice the top chip is a different form factor with a different number of legs, also a different number of resistors. So these boards may look alike but are not the same.
Model | Chip numbering | |
DFPlayer Mini HW-247A | MH2024K-24SS 220920 | |
MP3-TF-16P v3.0 | GT3200B 210824679F |
Looking at the specs both boards have the same pin out so a straight swap would be expected.
Looking at the data sheets they also seem to have the same instruction sets.
I managed to get some sound out of the MP3-TF-16P v3.0 by connecting VCC to 5V, Both GND's to GND and touching IO_1 to GND. Once I knew the unit would play I then randomly touched ADKey_2 and ADKey_1 and IO_2 as well as IO_1 to GND and track seemed to play and stuff happened.
Although this was great for those using push buttons, I wanted control via RX/TX as mine is driven by ESP32's and Arduinos.
The manual seems to be the same for both units so this is a link to one of them. MANUAL
Fortunately I had written my own code to control my DFplayer instead of using a library so the script is very simple.
For intial testing I used an Arduino Mega 2560 using Serial3, this helped to make sure software serial was not an issue.
At the end of my testsing I had both types of modules working with the same code and circuit...apart from 1 genuine DFPlayer that was actually damaged as I suspected!!
Problem Found?
After writing the scripts below and getting both boards working I still found that I could not swap between boards with a sketch for my model railway.It's possible that the sketch shows a slight difference between the performance of the boards.
original DFMini player code.
changeVolume(masterVolume * 3);//set volume playTrack(22);//compressorThis code would not work with the MP3-TF-16P v3.0, instead I had to put in a 1 second delay. I need to do some further tests to see if it's possible to put in a smaller delay(). I finally found something in the manual in section 3.3.2 that talks about having a delay of 100 milliseconds so this may be closer to what is required.
changeVolume(masterVolume * 3);//set volume delay(1000) playTrack(22);//compressor
It would seem that the DFPlayer can handle commands at a faster rate than the
MP3-TF-16P v3.0. This could mean that the DFPlayer has a slightly bigger buffer but if you are having problems sending multiple commands try a small delay() between them.
Circuit
In this circuit I have connected both GNDs and have a 1K resistor on the TX and RX lines. I have had both boards working without the 1K resistors but if you get stuck give it a try. It works with both types of DFPlayer board and with UNO/Mega2560 and ESP32.
Connect the TX/RX pins to your Arduino/ESP32 board.
Example 1: Arduino Mega 2560 TestScript1.ino
Click to Download code: TestScript1.ino
Written to run on Arduino Mega2560 Using Serial3
This is some very quick and dirty code and contains delay() so is best avoided in any project but will test your board connections and shows the simplicity of sending commands such as "Play Next Track", "Play Selected Track" and "Set Volume".
/* DFPlayerMegaV2
MP3-TF-16P
21/12/2022
running on Mega2560 Serial3
simple sketch just playing through the card, 2 secs of each track. This checked that ciruit was working
*/
//this function sends the actual command
//It receives the command byte and ParData is optional info such as track number or volume depending on the command
void sendDFCommand(byte Command, int ParData) {
byte commandData[10]; //This holds all the command data to be sent
byte q;
int checkSum;
Serial.print("Com: ");
Serial.print(Command, HEX);
//Each command value is being sent in Hexadecimal
commandData[0] = 0x7E;//Start of new command
commandData[1] = 0xFF;//Version information
commandData[2] = 0x06;//Data length (not including parity) or the start and version
commandData[3] = Command;//The command that was sent through
commandData[4] = 0x01;//1 = feedback
commandData[5] = highByte(ParData);//High byte of the data sent over
commandData[6] = lowByte(ParData);//low byte of the data sent over
checkSum = -(commandData[1] + commandData[2] + commandData[3] + commandData[4] + commandData[5] + commandData[6]);
commandData[7] = highByte(checkSum);//High byte of the checkSum
commandData[8] = lowByte(checkSum);//low byte of the checkSum
commandData[9] = 0xEF;//End bit
for (q = 0; q < 10; q++) {
Serial3.write(commandData[q]);
}
Serial.println("Command Sent: ");
for (q = 0; q < 10; q++) {
Serial.println(commandData[q],HEX);
}
Serial.println("End Command: ");
delay(100);
}
//play a specific track number
void playTrack(int tracknum){
Serial.print("Track selected: ");
Serial.println(tracknum);
sendDFCommand(0x03, tracknum);
}
//plays the next track
void playNext(){
Serial.println("Play Next");
sendDFCommand(0x01, 0);
}
//volume increase by 1
void volumeUp() {
Serial.println("Vol UP");
sendDFCommand(0x04, 0);
}
//volume decrease by 1
void volumeDown() {
Serial.println("Vol Down");
sendDFCommand(0x05, 0);
}
//set volume to specific value
void changeVolume(int thevolume) {
sendDFCommand(0x06, thevolume);
}
void setup() {
Serial.begin(9600);
Serial.println("DFPlayerMegaV2");
Serial3.begin (9600);//start the softwareSerial to DF player
delay(3500);//let everything initialise
changeVolume(20);//set volume to 20
}
int q = 5;
void loop() {
//Uncomment just to play through tracks one after another.
//playNext();
//delay(2000);
//Uncomment to play through a set of tracks
for(q=5;q<15;q++){
playTrack(q);
delay(2000);
}
}
Example 2: Arduino Mega 2560 TestScript2.ino
Click to Download code: TestScript2.ino
Written to run on Arduino Mega 2560 using Serial3
This sketch has a lot more interaction between the player and the Arduino.
It is reading the returned status and waiting for a track to finish before starting the next track.
I have left a lot of extra commenting in to try and help show what is happening and when.
Run the project with the serial monitor running to see the information.
In the setup() there are a couple of lines
changeVolume(20);//set volume to 20....30 is very loud even on small speaker.
delay(100);
playTrack(4);
The delay may need to be slightly longer if you are using the MP3-T-16P v3.0 as I found sending multiple command quickly could cause issues.
/* Test script 2...trying to get feedback from module.
MP3-TF-16P
21/12/2022
running on Mega2560 Serial3
simple sketch just playing through the card, 2 secs of each track. This checked that ciruit was working
*/
//this function sends the actual command
//It receives the command byte and ParData is optional info such as track number or volume depending on the command
void sendDFCommand(byte Command, int ParData) {
byte commandData[10]; //This holds all the command data to be sent
byte q;
int checkSum;
Serial.print("Com: ");
Serial.print(Command, HEX);
//Each command value is being sent in Hexadecimal
commandData[0] = 0x7E;//Start of new command
commandData[1] = 0xFF;//Version information
commandData[2] = 0x06;//Data length (not including parity) or the start and version
commandData[3] = Command;//The command that was sent through
commandData[4] = 0x01;//1 = feedback
commandData[5] = highByte(ParData);//High byte of the data sent over
commandData[6] = lowByte(ParData);//low byte of the data sent over
checkSum = -(commandData[1] + commandData[2] + commandData[3] + commandData[4] + commandData[5] + commandData[6]);
commandData[7] = highByte(checkSum);//High byte of the checkSum
commandData[8] = lowByte(checkSum);//low byte of the checkSum
commandData[9] = 0xEF;//End bit
for (q = 0; q < 10; q++) {
Serial3.write(commandData[q]);
}
Serial.println("Command Sent: ");
for (q = 0; q < 10; q++) {
Serial.println(commandData[q],HEX);
}
Serial.println("End Command: ");
delay(100);
}
//play a specific track number
void playTrack(int tracknum){
Serial.print("Track selected: ");
Serial.println(tracknum);
sendDFCommand(0x03, tracknum);
}
//plays the next track
void playNext(){
Serial.println("Play Next");
sendDFCommand(0x01, 0);
}
//volume increase by 1
void volumeUp() {
Serial.println("Vol UP");
sendDFCommand(0x04, 0);
}
//volume decrease by 1
void volumeDown() {
Serial.println("Vol Down");
sendDFCommand(0x05, 0);
}
//set volume to specific value
void changeVolume(int thevolume) {
sendDFCommand(0x06, thevolume);
}
void setup() {
Serial.begin(9600);
Serial.println("DFPlayer Test Script 2");
Serial3.begin (9600);//start the softwareSerial to DF player
delay(3500);//let everything initialise
changeVolume(20);//set volume to 20....30 is very loud even on small speaker.
delay(100);
playTrack(4);
}
int q = 5;
byte returnCodes[10];
byte returnByteCounter;
void loop() {
byte readByte;
while (Serial3.available()) {
readByte = Serial3.read();
Serial.print(readByte,HEX);
Serial.print(" Count: ");
Serial.println(returnByteCounter);
if(returnByteCounter == 0){
if(readByte == 0x7E){
returnCodes[returnByteCounter] = readByte;
returnByteCounter++;
}
}else{
returnCodes[returnByteCounter] = readByte;
returnByteCounter++;
}
if(returnByteCounter > 9){
Serial.println("Code String");
for(int w = 0;w<10;w++){
Serial.print(returnCodes[w],HEX);
Serial.print(" ");
}
Serial.println(" ");
if(returnCodes[3] == 0x3D){//track finished
Serial.println("Play Next Track");
playNext();//play next track
}
returnByteCounter = 0;
}
}
}
Example 3: Arduino UNO Software Serial UnoSoftSerialTestScript2.ino
Click to Download code: UnoSoftSerialTestScript2.ino
Written to run on ArduinoUNO using Software Serial
/* Test script 2...trying to get feedback from module.
MP3-TF-16P
21/12/2022
rcoded for software serial on UNO
*/
#include
SoftwareSerial mySerial(2, 3);//RX/TX
//this function sends the actual command
//It receives the command byte and ParData is optional info such as track number or volume depending on the command
void sendDFCommand(byte Command, int ParData) {
byte commandData[10]; //This holds all the command data to be sent
byte q;
int checkSum;
Serial.print("Com: ");
Serial.print(Command, HEX);
//Each command value is being sent in Hexadecimal
commandData[0] = 0x7E;//Start of new command
commandData[1] = 0xFF;//Version information
commandData[2] = 0x06;//Data length (not including parity) or the start and version
commandData[3] = Command;//The command that was sent through
commandData[4] = 0x01;//1 = feedback
commandData[5] = highByte(ParData);//High byte of the data sent over
commandData[6] = lowByte(ParData);//low byte of the data sent over
checkSum = -(commandData[1] + commandData[2] + commandData[3] + commandData[4] + commandData[5] + commandData[6]);
commandData[7] = highByte(checkSum);//High byte of the checkSum
commandData[8] = lowByte(checkSum);//low byte of the checkSum
commandData[9] = 0xEF;//End bit
for (q = 0; q < 10; q++) {
mySerial.write(commandData[q]);
}
Serial.println("Command Sent: ");
for (q = 0; q < 10; q++) {
Serial.println(commandData[q],HEX);
}
Serial.println("End Command: ");
delay(100);
}
//play a specific track number
void playTrack(int tracknum){
Serial.print("Track selected: ");
Serial.println(tracknum);
sendDFCommand(0x03, tracknum);
}
//plays the next track
void playNext(){
Serial.println("Play Next");
sendDFCommand(0x01, 0);
}
//volume increase by 1
void volumeUp() {
Serial.println("Vol UP");
sendDFCommand(0x04, 0);
}
//volume decrease by 1
void volumeDown() {
Serial.println("Vol Down");
sendDFCommand(0x05, 0);
}
//set volume to specific value
void changeVolume(int thevolume) {
sendDFCommand(0x06, thevolume);
}
void setup() {
Serial.begin(9600);
Serial.println("DFPlayer Test Script 2");
mySerial.begin(9600);
mySerial.begin (9600);//start the softwareSerial to DF player
delay(3500);//let everything initialise
changeVolume(20);//set volume to 20....30 is very loud even on small speaker.
delay(100);
playTrack(4);
}
int q = 5;
byte returnCodes[10];
byte returnByteCounter;
void loop() {
byte readByte;
while (mySerial.available()) {
readByte = mySerial.read();
Serial.print(readByte,HEX);
Serial.print(" Count: ");
Serial.println(returnByteCounter);
if(returnByteCounter == 0){
if(readByte == 0x7E){
returnCodes[returnByteCounter] = readByte;
returnByteCounter++;
}
}else{
returnCodes[returnByteCounter] = readByte;
returnByteCounter++;
}
if(returnByteCounter > 9){
Serial.println("Code String");
for(int w = 0;w<10;w++){
Serial.print(returnCodes[w],HEX);
Serial.print(" ");
}
Serial.println(" ");
if(returnCodes[3] == 0x3D){//track finished
Serial.println("Play Next Track");
playNext();//play next track
}
returnByteCounter = 0;
}
}
}
Example 4: ESP32 using Serial2 ESP32lTestScript2.ino
Click to Download code: ESP32lTestScript2.ino
Written to run on ESP32 using Serial2
/* Test script 2...trying to get feedback from module.
MP3-TF-16P
21/12/2022
Recoded for ESP32
*/
#define RXD2 16
#define TXD2 17
//this function sends the actual command
//It receives the command byte and ParData is optional info such as track number or volume depending on the command
void sendDFCommand(byte Command, int ParData) {
byte commandData[10]; //This holds all the command data to be sent
byte q;
int checkSum;
Serial.print("Com: ");
Serial.print(Command, HEX);
//Each command value is being sent in Hexadecimal
commandData[0] = 0x7E;//Start of new command
commandData[1] = 0xFF;//Version information
commandData[2] = 0x06;//Data length (not including parity) or the start and version
commandData[3] = Command;//The command that was sent through
commandData[4] = 0x01;//1 = feedback
commandData[5] = highByte(ParData);//High byte of the data sent over
commandData[6] = lowByte(ParData);//low byte of the data sent over
checkSum = -(commandData[1] + commandData[2] + commandData[3] + commandData[4] + commandData[5] + commandData[6]);
commandData[7] = highByte(checkSum);//High byte of the checkSum
commandData[8] = lowByte(checkSum);//low byte of the checkSum
commandData[9] = 0xEF;//End bit
for (q = 0; q < 10; q++) {
Serial2.write(commandData[q]);
}
Serial.println("Command Sent: ");
for (q = 0; q < 10; q++) {
Serial.println(commandData[q],HEX);
}
Serial.println("End Command: ");
delay(100);
}
//play a specific track number
void playTrack(int tracknum){
Serial.print("Track selected: ");
Serial.println(tracknum);
sendDFCommand(0x03, tracknum);
}
//plays the next track
void playNext(){
Serial.println("Play Next");
sendDFCommand(0x01, 0);
}
//volume increase by 1
void volumeUp() {
Serial.println("Vol UP");
sendDFCommand(0x04, 0);
}
//volume decrease by 1
void volumeDown() {
Serial.println("Vol Down");
sendDFCommand(0x05, 0);
}
//set volume to specific value
void changeVolume(int thevolume) {
sendDFCommand(0x06, thevolume);
}
void setup() {
Serial.begin(9600);
Serial.println("DFPlayer Test Script 2");
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
Serial.println("Serial2. started...");
delay(3500);//let everything initialise
changeVolume(20);//set volume to 20....30 is very loud even on small speaker.
delay(100);
playTrack(4);
}
int q = 5;
byte returnCodes[10];
byte returnByteCounter;
void loop() {
byte readByte;
while (Serial2.available()) {
readByte = Serial2.read();
Serial.print(readByte,HEX);
Serial.print(" Count: ");
Serial.println(returnByteCounter);
if(returnByteCounter == 0){
if(readByte == 0x7E){
returnCodes[returnByteCounter] = readByte;
returnByteCounter++;
}
}else{
returnCodes[returnByteCounter] = readByte;
returnByteCounter++;
}
if(returnByteCounter > 9){
Serial.println("Code String");
for(int w = 0;w<10;w++){
Serial.print(returnCodes[w],HEX);
Serial.print(" ");
}
Serial.println(" ");
if(returnCodes[3] == 0x3D){//track finished
Serial.println("Play Next Track");
playNext();//play next track
}
returnByteCounter = 0;
}
}
}
Additional Resource Links
Lesson 2: "Hello World" Basics of printing to Serial Window 17/07/2021
Comments
This site has been designed to be child friendly, this means that comments cannot be added to videos or directly to the site. To add a comment or ask a question please email the address in this image: and use DFmini player & MP3-T-16P v3.0 as a reference.