Documentation

MP3-TF-16P Mini MP3 Player Module with TF Card Slot for Arduino & Raspberry Pi | ShillehTek Product Manual
Documentation / MP3-TF-16P Mini MP3 Player Module with TF Card Slot for Arduino & Raspberry Pi | ShillehTek Product Manual

MP3-TF-16P Mini MP3 Player Module with TF Card Slot for Arduino & Raspberry Pi | ShillehTek Product Manual

mp3-player-module-tf-card-arduino-raspberry-pishillehtek

Overview

The MP3-TF-16P — the module the world knows as the DFPlayer Mini — is a complete MP3 player on a postage stamp: microSD slot, MP3/WAV decoder, DAC, and a 3W class-D amplifier that drives a small speaker directly. Your microcontroller sends short serial commands ("play track 7", "volume 20") and the module does everything else, streaming audio with zero load on your code.

That architecture is why it powers half the talking props on the internet: Halloween decorations, museum exhibit buttons, doorbells with custom chimes, talking clocks, model railway sound effects, toy voice boxes, and accessibility devices. Load numbered MP3 files onto a FAT32 card, wire two UART pins (9600 baud), connect a 4-8 ohm speaker across SPK_1/SPK_2 — done. It can even run standalone with buttons on the ADKEY pins, no microcontroller at all.

Beyond the basics it offers folder-based organization (playing "folder 3, track 12" for multi-category sound boards), a BUSY pin that reports playback state without polling, stereo line-level DAC outputs for feeding an external amplifier like the PAM8406, and volume/EQ control from code. It runs from 3.2-5V and is happiest at 5V with a decent capacitor when driving a speaker hard.

At a Glance

Plays
MP3 / WAV from microSD
Control
UART 9600 commands
Amplifier
3W onboard (4-8 ohm)
Line Out
DAC_L / DAC_R
Supply Voltage
3.2 - 5V (5V best)
Card Support
microSD up to 32GB FAT32

Specifications

Parameter Value
Module MP3-TF-16P (DFPlayer Mini compatible)
Formats MP3 (8-320 kbps), WAV; 11-48 kHz sample rates
Storage microSD (TF) up to 32 GB, FAT16/FAT32
Control UART 9600 8N1 command set; ADKEY resistor buttons; IO_1/IO_2 short-press keys
Amplifier ~3W into 4 ohm (5V) on SPK_1/SPK_2 — speaker floats, no ground!
DAC Output Stereo line-level on DAC_L / DAC_R (24-bit DAC)
Volume / EQ 30 volume steps; 6 EQ presets
BUSY Pin LOW while playing, HIGH when idle
Supply 3.2 - 5.0V; ~20 mA idle, peaks ~200 mA+ at loud playback
File Naming 0001.mp3, 0002.mp3… in root or /01-/99 folders (001.mp3…)
Size 21 x 21 mm, 16 pins

Pinout Diagram

Left side: VCC, RX, TX, the stereo DAC pair, SPK_1, GND, SPK_2. Right side: BUSY, the USB data pair, the two ADKEY resistor-button inputs, IO_2, GND, IO_1. For microcontroller use you'll touch VCC, GND, RX, TX, the speaker pair, and optionally BUSY — the rest can stay unconnected.

MP3-TF-16P DFPlayer Mini pinout diagram showing VCC RX TX DAC SPK BUSY ADKEY and IO pins around the microSD slot

Wiring Guide

Two universal rules: put a 1k resistor in series with the module's RX pin (tames 5V logic and the noise-injection quirk), and wire the speaker ONLY across SPK_1/SPK_2 — never to ground.

Arduino Wiring

Module Pin Arduino Pin Details
VCC / GND 5V / GND 100-470 uF cap helps at volume
RX D11 via 1k Commands in
TX D10 Replies out
SPK_1 / SPK_2 Speaker 4-8 ohm Across the pair only
BUSY D7 (optional) LOW = playing

ESP32 Wiring (UART2)

Module Pin ESP32 Pin Details
VCC / GND VIN (5V) / GND
RX GPIO 17 (TX2) via 1k 3.3V drive works fine
TX GPIO 16 (RX2) Module TX is ~3.3V level
SPK_1 / SPK_2 Speaker

Raspberry Pi Wiring (UART0)

Module Pin Pi Pin Details
VCC / GND Pin 2 (5V) / Pin 6
RX Pin 8 (GPIO 14, TXD) via 1k
TX Pin 10 (GPIO 15, RXD)
SPK_1 / SPK_2 Speaker
Tip: Enable the UART in raspi-config (login shell OFF, serial hardware ON) so /dev/serial0 is free.

Raspberry Pi Pico Wiring (UART0)

Module Pin Pico Pin Details
VCC / GND VBUS (5V) / GND
RX GP0 (UART0 TX) via 1k
TX GP1 (UART0 RX)
SPK_1 / SPK_2 Speaker

Code Examples

Card prep first: FAT32 format, files named 0001.mp3, 0002.mp3… copied one at a time in order. Arduino/ESP32 use the DFRobotDFPlayerMini library; Pi and Pico send the 10-byte command frames directly — same protocol, no dependencies.

Arduino

dfplayer_arduino.ino
// MP3-TF-16P / DFPlayer Mini - Arduino Example
// TX->D10, RX->D11 via 1k | Library: "DFRobotDFPlayerMini"

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

SoftwareSerial mp3Serial(10, 11);   // RX, TX
DFRobotDFPlayerMini player;

void setup() {
  Serial.begin(115200);
  mp3Serial.begin(9600);

  if (!player.begin(mp3Serial)) {
    Serial.println("DFPlayer not responding - check card and wiring");
    while (1);
  }
  player.volume(20);            // 0-30
  player.play(1);               // play 0001.mp3
  Serial.println("Playing track 1");
}

void loop() {
  // next track every 10 seconds as a demo
  delay(10000);
  player.next();
  Serial.println("Next track");
}

ESP32 (Arduino IDE) — sound-effect button

dfplayer_esp32.ino
// MP3-TF-16P - ESP32 sound-effect trigger
// TX->GPIO16, RX->GPIO17 via 1k, button GPIO 0 (BOOT) plays a random clip

#include <DFRobotDFPlayerMini.h>

DFRobotDFPlayerMini player;
const int NUM_TRACKS = 5;          // 0001.mp3 .. 0005.mp3 on the card

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, 16, 17);
  pinMode(0, INPUT_PULLUP);

  if (!player.begin(Serial2)) {
    Serial.println("DFPlayer not responding");
    while (1) delay(10);
  }
  player.volume(22);
  Serial.println("Press BOOT for a random sound");
}

void loop() {
  if (digitalRead(0) == LOW) {
    int track = random(1, NUM_TRACKS + 1);
    player.play(track);
    Serial.printf("Playing %04d.mp3\n", track);
    delay(400);                    // debounce
  }
}

Raspberry Pi (Python, raw protocol)

dfplayer_rpi.py
#!/usr/bin/env python3
# MP3-TF-16P - Raspberry Pi Example (raw 10-byte frames)
# TX->GPIO15, RX(via 1k)->GPIO14 | Install: pip3 install pyserial

import serial, time

port = serial.Serial("/dev/serial0", 9600)

def cmd(command, param=0):
    hi, lo = (param >> 8) & 0xFF, param & 0xFF
    frame = [0x7E, 0xFF, 0x06, command, 0x00, hi, lo]
    checksum = -sum(frame[1:]) & 0xFFFF
    frame += [(checksum >> 8) & 0xFF, checksum & 0xFF, 0xEF]
    port.write(bytes(frame))
    time.sleep(0.2)

cmd(0x3F)          # init
time.sleep(1)
cmd(0x06, 20)      # volume 20 (0-30)
cmd(0x03, 1)       # play track 0001.mp3
print("Playing track 1 for 15 s...")
time.sleep(15)

cmd(0x0E)          # pause
print("Paused. Next track...")
time.sleep(1)
cmd(0x01)          # next
time.sleep(10)
cmd(0x16)          # stop
print("Done.")

Raspberry Pi Pico (MicroPython, raw protocol)

dfplayer_pico.py
# MP3-TF-16P - Pico MicroPython Example (raw frames + BUSY pin)
# TX->GP1, RX(via 1k)->GP0, BUSY->GP2

from machine import UART, Pin
import time

uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
busy = Pin(2, Pin.IN, Pin.PULL_UP)     # LOW while playing

def cmd(command, param=0):
    hi, lo = (param >> 8) & 0xFF, param & 0xFF
    frame = [0x7E, 0xFF, 0x06, command, 0x00, hi, lo]
    checksum = -sum(frame[1:]) & 0xFFFF
    frame += [(checksum >> 8) & 0xFF, checksum & 0xFF, 0xEF]
    uart.write(bytes(frame))
    time.sleep_ms(200)

cmd(0x3F)              # init
time.sleep(1)
cmd(0x06, 18)          # volume
cmd(0x03, 1)           # play 0001.mp3
print("Playing...")

while busy.value() == 0:      # wait until the track finishes
    time.sleep_ms(100)
print("Track finished - playing track 2")
cmd(0x03, 2)

Frequently Asked Questions

The module powers up but won't play / library reports no response.
Ninety percent of the time it's the card: must be FAT32 (not exFAT — reformat 64GB+ cards or use ≤32GB), files named 0001.mp3-style, and the card fully seated. Give the module ~1-2 s after power before the first command. Remaining causes: RX/TX not crossed, or a counterfeit-slow card — try a different brand card before blaming the board.
Playback order is wrong — track 1 plays the wrong file.
The module indexes files by the order they were WRITTEN to the card, not by filename. Copy files one at a time in the order you want (or use a copy tool that preserves order), after formatting. The bulletproof pattern: folders 01-99 with files 001.mp3-255.mp3 inside, addressed via playFolder(folder, track) — that addressing is explicit and immune to copy order.
I hear a constant hiss/whine behind the audio. Fix?
Three stacked fixes: the 1k resistor in the RX line (the module's noisiest quirk is serial-line noise bleeding into audio); a solid 5V supply with 100-470 uF at the module (shared noisy rails hum); and grounds joined at one point. For hi-fi builds, skip the onboard amp entirely — take DAC_L/DAC_R into a PAM8406 and the noise floor drops dramatically.
Can it play two sounds at once, or crossfade?
No — it's a single-stream decoder: a new play command stops the current track and starts the next (which makes rapid-fire sound effects feel instant, but no mixing/overlap). For simultaneous effects, use two modules with their DAC outputs mixed through resistors into one amp — a common trick in prop-making.
What's the BUSY pin for, and the ADKEY pins?
BUSY reads LOW during playback — poll it (as the Pico example does) to sequence tracks or animations without parsing serial replies. ADKEY_1/ADKEY_2 are resistor-ladder button inputs for standalone use: different resistor values to ground trigger play/pause, next, previous, volume — a full no-microcontroller MP3 player with a handful of buttons.
How loud is the onboard amp, and what speaker should I use?
About 3W into 4 ohm at 5V — genuinely room-filling with an efficient 4-8 ohm speaker (2-3" full-range in a small enclosure sounds shockingly decent). Keep the speaker leads short and remember both SPK pins are driven: never ground one side or share a wire with anything. At 3.3V supply expect noticeably less volume.
Can I trigger it without any code at all?
Yes — IO_1 and IO_2 act as press keys (short press = prev/next, long press = volume) and the ADKEY ladder adds more functions; power plus speaker plus buttons is a complete player. For one-sound props, a pushbutton pulling IO_1 low replays the last/first track — the zero-firmware Halloween special.

Related Tutorials