DFPlayer Mini и Arduino: воспроизведение MP3, SD-карта и динамик
Как работать с DFPlayer Mini на Arduino: резистор 1k на RX, SD-карта и имена вида 0001.mp3, код с библиотекой, кнопки, динамик, а также примеры для ESP32 и Pico.
DFPlayer Mini — самый дешёвый и простой способ проигрывать MP3 на Arduino: он сам декодирует аудиофайлы с карты microSD, напрямую раскачивает динамик своим маленьким встроенным усилителем и получает команды от Arduino по двухпроводному последовательному каналу. В отличие от писка зуммера, он может играть песни, речь, мелодии дверного звонка или голосовые предупреждения вроде «Дверь всё ещё открыта». При первом подключении почти все сталкиваются с одними и теми же проблемами: звука нет, динамик шипит, файлы играют не по порядку или монитор порта пишет «Unable to begin». Это руководство решает каждую из них и объясняет, почему они возникают.
Сначала ты разберёшься с пинами модуля и узнаешь, зачем на линию RX ставят резистор 1 kΩ. Затем увидишь, как отформатировать SD-карту в FAT32, назвать файлы и папки по схеме 0001.mp3 и 01, проиграть первый звук с библиотекой DFRobotDFPlayerMini, настроить громкость и эквалайзер, переключать треки кнопками и подобрать подходящий динамик или внешний усилитель. В последних разделах — пошаговое решение ошибки «Unable to begin», MP3-плеер на ESP32 с управлением через веб-страницу и пример на MicroPython для Raspberry Pi Pico без библиотеки. Если нужен только писк или простая мелодия, проще взять зуммер.

Что такое DFPlayer Mini и как он работает?
DFPlayer Mini — это самостоятельный MP3-плеер, состоящий из микросхемы MP3-декодера, 24-битного ЦАП, слота для карты microSD и маленького монофонического усилителя. Arduino нужно лишь отправлять короткие команды вроде «играть трек 3» или «громкость 20»; чтение файла с карты, декодирование сжатого звука и раскачка динамика — работа модуля. Поэтому даже Arduino Uno с 2 КБ ОЗУ легко проигрывает музыку. Команды передаются на скорости 9600 бод пакетами по 10 байт, а модуль отвечает в том же формате, когда трек заканчивается, карта вставляется или извлекается либо возникает ошибка. Микросхема на плате зависит от производителя (YX5200-24SS, MH2024K-24SS, GD3200B и другие). Все они понимают одни и те же команды, но могут отвечать с разной задержкой, и эта деталь ещё пригодится при разборе ошибки «Unable to begin». Управлять модулем можно тремя способами: через последовательный порт (UART), кнопками на пинах IO или резисторной лестницей ADKEY.
| Характеристика | Значение |
|---|---|
| Поддерживаемые файлы | MP3, WAV, WMA |
| Частоты дискретизации | 8 / 11,025 / 12 / 16 / 22,05 / 24 / 32 / 44,1 / 48 kHz |
| ЦАП | 24 бита; динамический диапазон 90 dB, отношение сигнал/шум 85 dB |
| Носитель | Карта microSD (TF) до 32 ГБ, FAT16 или FAT32; поддерживаются и USB-флешки |
| Ёмкость папок | До 100 папок, 255 файлов в каждой |
| Громкость | 30 ступеней (0–30) |
| Эквалайзер (EQ) | 6 режимов: Normal, Pop, Rock, Jazz, Classic, Bass |
| Выход на динамик | Встроенный монофонический усилитель, динамики мощностью до 3 W |
| Линейный выход | DAC_L и DAC_R: стерео, для наушников или внешнего усилителя |
| Питание | 3,2–5,0 V (типично 4,2 V) |
| Ток в режиме ожидания | Около 20 mA |
| Интерфейс | UART, 9600 бод, 8N1 |
| Размер | 20 × 20 мм |
Распиновка DFPlayer Mini
| Пин | Название | Назначение |
|---|---|---|
| 1 | VCC | Вход питания, 3,2–5,0 V |
| 2 | RX | Последовательный вход: подключается к пину TX платы через резистор 1 kΩ |
| 3 | TX | Последовательный выход: идёт на пин RX платы |
| 4 | DAC_R | Линейный выход правого канала (наушники или усилитель) |
| 5 | DAC_L | Линейный выход левого канала (наушники или усилитель) |
| 6 и 8 | SPK_1, SPK_2 | Выход на динамик: сюда подключаются два вывода динамика мощностью до 3 W |
| 7 | GND | Земля |
| 9 | IO_1 | Кнопка на GND, короткое нажатие: предыдущий трек; долгое: тише |
| 10 | GND | Земля |
| 11 | IO_2 | Кнопка на GND, короткое нажатие: следующий трек; долгое: громче |
| 12 | ADKEY1 | Вход для нескольких кнопок через резисторную лестницу |
| 13 | ADKEY2 | Второй вход резисторной лестницы |
| 14 | USB+ | D+ для USB-флешки |
| 15 | USB− | D− для USB-флешки |
| 16 | BUSY | LOW во время воспроизведения, HIGH в покое |
При работе через последовательный порт нужны только пины VCC, GND, RX, TX и выходы на динамик. Пин BUSY сообщает, закончился ли трек, без всякого обмена по UART, а маленький светодиод на плате тоже горит во время воспроизведения. Пины IO_1 и IO_2 позволяют модулю работать вообще без Arduino: если поставить кнопку между каждым из них и GND, короткое нажатие переключает трек, а долгое меняет громкость. Кнопки, подключённые к пинам ADKEY через резисторы разного номинала, могут ещё и запускать конкретные треки. Значит, для дверного звонка или говорящей игрушки без микроконтроллера хватит батарейки, динамика и двух кнопок. Пины USB+ и USB− нужны для воспроизведения с USB-флешки вместо SD-карты и в большинстве проектов остаются неподключёнными.
Подключение DFPlayer Mini к Arduino и резистор 1k на RX
| Пин DFPlayer | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 5V (VIN) | VBUS (USB 5 V, пин 40) |
| GND | GND | GND | GND |
| RX | D11 через резистор 1 kΩ | GPIO 17 (TX2) через резистор 1 kΩ | GP0 (UART0 TX) через резистор 1 kΩ |
| TX | D10 | GPIO 16 (RX2) | GP1 (UART0 RX) |
| SPK_1 и SPK_2 | Два вывода динамика | Два вывода динамика | Два вывода динамика |
| BUSY (необязательно) | D5 | Не используется | Не используется |



Линии данных перекрещиваются: TX модуля идёт на RX платы, а его RX — на TX платы. Аппаратный последовательный порт Uno на D0 и D1 занят загрузкой по USB и монитором порта, поэтому модуль подключаем к D10 (RX) и D11 (TX) через SoftwareSerial. Резистор 1 kΩ последовательно со входом RX модуля — вовсе не мелочь. Микросхема DFPlayer работает с логикой 3,3 V, а пин TX у Uno выдаёт 5 V. Без резистора эта разница гонит ток через защитные диоды на входе микросхемы; этот ток нагружает микросхему и вызывает шипение и щелчки в динамике во время обмена данными. Если посчитать по закону Ома, видно, что 1 kΩ ограничивает этот ток примерно до 1–2 mA, а сигналу на 9600 бод это никак не мешает. Гораздо больший резистор, например 10 kΩ, может ослабить сигнал и нарушить связь. Выход TX модуля подключается к Uno напрямую, потому что Uno считывает 3,3 V как HIGH (порог около 3,0 V).
Подготовка SD-карты: FAT32, папки и имена вида 0001.mp3
DFPlayer Mini читает карты microSD объёмом до 32 ГБ, отформатированные в FAT16 или FAT32. Карты на 64 ГБ и больше продаются отформатированными в exFAT, а эту систему модуль не читает; для нескольких сотен треков с лихвой хватит карты на 1–16 ГБ. Кодировать MP3 с битрейтом 128–192 kbps и частотой 44,1 kHz надёжнее всего и для совместимости, и для скорости чтения с карты. Модуль различает файлы по номеру, а не по имени, поэтому имена папок и файлов должны следовать определённой схеме в зависимости от функции, которой ты их запускаешь:
| Расположение на карте | Пример | Функция библиотеки | Правило |
|---|---|---|---|
| Корневая папка | /0001.mp3, /0002.mp3 | play(1) | Играет в том порядке, в каком файлы копировались на карту, а не по имени |
| Нумерованные папки | /01/001.mp3 … /99/255.mp3 | playFolder(1, 1) | Имя папки из 2 цифр (01–99), имя файла из 3 цифр (001–255) |
| Папка mp3 | /mp3/0001.mp3 | playMp3Folder(1) | Имя файла из 4 цифр; файл ищется по номеру в имени |
| Папка advert | /advert/0001.mp3 | advertise(1) | Прерывает текущий трек и продолжает его, когда объявление заканчивается |
| Большие папки | /01/0001.mp3 … /15/3000.mp3 | playLargeFolder(1, 1) | До 15 папок, 3000 файлов в каждой, имена из 4 цифр |
- Отформатируй карту в FAT32 на компьютере (в Windows: правый клик › «Форматировать»; в macOS: «Дисковая утилита» › «Стереть» › MS-DOS (FAT)).
- Создай в корне папку с именем mp3 и, если нужно, нумерованные папки вроде 01 и 02.
- Переименуй файлы в 0001.mp3, 0002.mp3 (в нумерованных папках: 001.mp3). После номера можно добавить описание, например 0001_hello.mp3: модуль смотрит только на цифры в начале.
- Если файлы из корня будут запускаться через play(), копируй их по одному и по порядку: при копировании всех сразу порядок может перепутаться.
- Безопасно извлеки карту и вставь её в модуль при выключенном питании: если вставлять или вынимать её во время работы, файлы могут повредиться.
Библиотека DFRobotDFPlayerMini и первый тестовый скетч
- В Arduino IDE открой «Менеджер библиотек» (Library Manager), введи DFRobotDFPlayerMini и установи библиотеку от DFRobot. Установка подробно описана в статье Как добавить библиотеку в Arduino.
- Скопируй хотя бы один MP3 в корень SD-карты, вставь карту в модуль и собери схему, как показано в таблице.
- Загрузи скетч ниже и открой монитор порта на скорости 115200 бод.
- Через несколько секунд должны появиться строка «DFPlayer Mini online.» и количество файлов на карте, а затем зазвучит первый трек.
1#include <SoftwareSerial.h>
2#include <DFRobotDFPlayerMini.h>
3
4SoftwareSerial dfSerial(10, 11); // RX = D10 ← DFPlayer TX, TX = D11 → 1 kΩ → DFPlayer RX
5DFRobotDFPlayerMini player;
6
7void setup() {
8 Serial.begin(115200);
9 dfSerial.begin(9600); // DFPlayer her zaman 9600 baud / DFPlayer always uses 9600 baud
10 Serial.println(F("DFPlayer baslatiliyor / Starting DFPlayer..."));
11
12 if (!player.begin(dfSerial)) { // reset gönderir, kartı bekler / sends a reset, waits for the card
13 Serial.println(F("Unable to begin: kablolari ve SD karti kontrol et / check wiring and SD card"));
14 while (true) {} // burada dur / stop here
15 }
16 Serial.println(F("DFPlayer Mini online."));
17 Serial.print(F("Karttaki dosya / Files on card: "));
18 Serial.println(player.readFileCounts()); // gizli dosyalar da sayılır / hidden files are counted too
19
20 player.volume(20); // ses seviyesi 0-30 / volume 0-30
21 player.EQ(DFPLAYER_EQ_NORMAL); // ekolayzır: normal / equalizer: normal
22 player.play(1); // kökteki ilk dosya / first file in the root
23}
24
25void loop() {
26 if (player.available()) { // modülden bildirim geldi / a message arrived from the module
27 uint8_t type = player.readType();
28 int value = player.read();
29 if (type == DFPlayerPlayFinished) {
30 Serial.print(F("Parca bitti / Track finished: "));
31 Serial.println(value);
32 } else if (type == DFPlayerError) {
33 Serial.print(F("Hata kodu / Error code: "));
34 Serial.println(value); // kodların anlamı tabloda / meanings are in the table
35 } else if (type == DFPlayerCardRemoved) {
36 Serial.println(F("SD kart cikarildi / SD card removed"));
37 }
38 }
39}
40| Функция | Что делает |
|---|---|
| begin(порт, isACK, doReset) | Запускает модуль; по умолчанию отправляет сброс и ждёт сообщения о том, что карта готова |
| volume(0–30) | Задаёт громкость; volumeUp() и volumeDown() меняют её на одну ступень |
| EQ(DFPLAYER_EQ_POP) | Эквалайзер: NORMAL, POP, ROCK, JAZZ, CLASSIC, BASS |
| play(n) | Проигрывает n-й файл в корне (в порядке копирования) |
| next() / previous() | Следующий / предыдущий трек |
| pause() / start() | Пауза / продолжение с места остановки |
| stop() | Останавливает воспроизведение |
| loop(n) | Непрерывно повторяет трек n |
| enableLoopAll() / randomAll() | Проигрывает все треки по кругу / в случайном порядке |
| readState() / readVolume() / readFileCounts() | Запрашивает состояние, громкость и количество файлов на карте |
| available() / readType() / read() | Читает сообщения от модуля (трек закончился, ошибка, карта извлечена) |
Громкость, эквалайзер и объявления по очереди с пином BUSY
Громкость меняется от 0 до 30. С маленьким динамиком для большинства комнат хватает 15–20; выше 25, особенно при слабом питании, звук может начать искажаться (клиппинг), а модуль — перезагружаться. Настройка эквалайзера меняет баланс низких и высоких частот; на маленьких динамиках режим BASS может сделать звук глухим, поэтому начни с NORMAL. Нумерованные папки очень удобны для говорящих проектов: положи слова «Температура» и «градусов» в папку 01, а числа от 001.mp3 до 100.mp3 в папку 02, и Arduino сможет произносить числа целым предложением. Самый надёжный способ узнать, что файл доиграл, — пин BUSY: он в LOW, пока модуль играет, и в HIGH, когда модуль простаивает. Скетч ниже читает BUSY на D5 и проигрывает файлы один за другим, не накладывая их друг на друга:
1#include <SoftwareSerial.h>
2#include <DFRobotDFPlayerMini.h>
3
4SoftwareSerial dfSerial(10, 11); // RX = D10 ← DFPlayer TX, TX = D11 → 1 kΩ → DFPlayer RX
5DFRobotDFPlayerMini player;
6const byte BUSY_PIN = 5; // DFPlayer BUSY: çalarken LOW / LOW while playing
7
8// Klasör 01: 001.mp3 "Sıcaklık", 002.mp3 "derece" / folder 01: 001.mp3 "Temperature", 002.mp3 "degrees"
9// Klasör 02: 001.mp3 ... 100.mp3 = 1 ... 100 sayıları / folder 02: 001.mp3 ... 100.mp3 = numbers 1 ... 100
10
11void playAndWait(uint8_t folder, uint8_t file) {
12 player.playFolder(folder, file); // /01/001.mp3 gibi / e.g. /01/001.mp3
13 unsigned long start = millis();
14 while (digitalRead(BUSY_PIN) == HIGH && millis() - start < 1000) {} // çalma başlasın / wait for playback to start
15 while (digitalRead(BUSY_PIN) == LOW) {} // parça bitsin / wait for the track to end
16 delay(50);
17}
18
19void sayTemperature(int degrees) {
20 playAndWait(1, 1); // "Sıcaklık" / "Temperature"
21 if (degrees >= 1 && degrees <= 100) {
22 playAndWait(2, degrees); // sayıyı söyle / say the number
23 }
24 playAndWait(1, 2); // "derece" / "degrees"
25}
26
27void setup() {
28 pinMode(BUSY_PIN, INPUT);
29 Serial.begin(115200);
30 dfSerial.begin(9600);
31 if (!player.begin(dfSerial)) {
32 Serial.println(F("Unable to begin"));
33 while (true) {}
34 }
35 player.volume(22);
36 sayTemperature(23); // değer bir sensörden de gelebilir / the value can come from a sensor
37}
38
39void loop() {
40}
41playAndWait() сначала отправляет команду, до 1 секунды ждёт, пока BUSY перейдёт в LOW (модулю нужно несколько сотен миллисекунд, чтобы начать играть), а затем ждёт окончания трека. Аудиофайлы можно записать своим голосом или сгенерировать в сервисе синтеза речи (TTS); если обрезать тишину в начале и в конце каждого файла, объявление звучит естественнее. Чтобы прервать музыку коротким предупреждением, используй advertise(n): модуль проиграет объявление из папки /advert, а затем продолжит музыку с того же места. Эта команда работает только во время воспроизведения трека; если вызвать её, когда модуль простаивает, она вернёт ошибку.
Переключение треков кнопками и громкость с потенциометра
Теперь соберём собственный MP3-плеер: три кнопки работают как «предыдущий трек», «воспроизведение/пауза» и «следующий трек», а потенциометр задаёт громкость. Подключи кнопки между D2, D3, D4 и GND; так как используются встроенные подтягивающие резисторы, внешние резисторы не нужны (почему — объясняется в статье Как подключить кнопку). Крайние выводы потенциометра идут на 5V и GND, а средний — на A0. Когда трек заканчивается, скетч автоматически переходит к следующему.
1#include <SoftwareSerial.h>
2#include <DFRobotDFPlayerMini.h>
3
4SoftwareSerial dfSerial(10, 11); // RX = D10 ← DFPlayer TX, TX = D11 → 1 kΩ → DFPlayer RX
5DFRobotDFPlayerMini player;
6
7const byte BTN[3] = {2, 3, 4}; // önceki, oynat/duraklat, sonraki / previous, play/pause, next
8const byte POT_PIN = A0; // ses ayarı potu / volume potentiometer
9bool lastState[3] = {HIGH, HIGH, HIGH};
10unsigned long lastChange[3] = {0, 0, 0};
11bool paused = false;
12int lastRaw = -100; // ilk turda sesi mutlaka ayarla / always set the volume on the first pass
13unsigned long lastPotRead = 0;
14unsigned long lastFinish = 0;
15
16// Butona yeni basıldıysa true döner (50 ms sıçrama filtresi) / true on a new press (50 ms debounce)
17bool pressed(byte i) {
18 bool s = digitalRead(BTN[i]);
19 if (s != lastState[i] && millis() - lastChange[i] > 50) {
20 lastState[i] = s;
21 lastChange[i] = millis();
22 return s == LOW; // INPUT_PULLUP: basınca LOW / LOW when pressed
23 }
24 return false;
25}
26
27void setup() {
28 for (byte i = 0; i < 3; i++) pinMode(BTN[i], INPUT_PULLUP);
29 Serial.begin(115200);
30 dfSerial.begin(9600);
31 if (!player.begin(dfSerial)) {
32 Serial.println(F("Unable to begin"));
33 while (true) {}
34 }
35 player.play(1);
36}
37
38void loop() {
39 if (pressed(0)) { player.previous(); paused = false; }
40 if (pressed(2)) { player.next(); paused = false; }
41 if (pressed(1)) {
42 if (paused) player.start(); // kaldığı yerden devam / resume
43 else player.pause(); // duraklat / pause
44 paused = !paused;
45 }
46
47 if (millis() - lastPotRead > 100) { // potu saniyede 10 kez oku / read the pot 10 times per second
48 lastPotRead = millis();
49 int raw = analogRead(POT_PIN);
50 if (abs(raw - lastRaw) > 20) { // titremeyi yok say / ignore jitter
51 lastRaw = raw;
52 player.volume(map(raw, 0, 1023, 0, 30));
53 }
54 }
55
56 if (player.available() && player.readType() == DFPlayerPlayFinished) {
57 if (millis() - lastFinish > 1000) player.next(); // parça bitince sonrakine geç / go to the next track
58 lastFinish = millis(); // bazı modüller bitişi iki kez bildirir / some modules report the end twice
59 }
60}
61| Часть кода | Зачем нужна |
|---|---|
| pressed() | Ловит только момент нажатия кнопки и игнорирует дребезг в пределах 50 мс; если держать кнопку, всё равно уходит одна команда |
| abs(raw - lastRaw) > 20 | Обновляет громкость только при заметных изменениях, чтобы мелкие колебания показаний потенциометра не заваливали модуль командами и не вызывали щелчков |
| map(raw, 0, 1023, 0, 30) | Переводит аналоговое значение 0–1023 в диапазон громкости DFPlayer 0–30 |
| paused | Запоминает состояние воспроизведения, чтобы одна и та же кнопка и ставила на паузу, и продолжала |
| DFPlayerPlayFinished | Сообщение, которое приходит по окончании трека; скетч переходит к следующему |
| millis() - lastFinish > 1000 | Некоторые клоны сообщают о конце трека дважды; эта проверка не даёт пропустить трек |
Выбор динамика (3 W) и внешнего усилителя
Собственный усилитель DFPlayer (на большинстве плат это микросхема типа 8002) напрямую раскачивает динамик мощностью до 3 W с сопротивлением 4 Ω или 8 Ω. Лучший баланс даёт динамик на 8 Ω и 1–3 W; маленькие динамики на 0,5 W тоже работают, но на большой громкости не справляются. Цифра 3 W — это верхний предел усилителя при питании 5 V и нагрузке 4 Ω, в точке, где искажения становятся явными; чистая мощность в обычном использовании ниже. Если установить динамик в корпус или хотя бы на панель, басы заметно улучшатся, потому что звук от передней и задней стороны диффузора перестаёт гасить друг друга. На большой громкости модуль может кратковременно потреблять несколько сотен миллиампер; если Arduino питается от USB-порта компьютера, это может вызвать просадки напряжения, шипение и перезагрузки. Если нужна большая мощность или стереозвук, подключи линейные выходы DAC_L и DAC_R к внешнему усилителю:
| Путь сигнала | Подключение | Когда? |
|---|---|---|
| Встроенный усилитель | SPK_1 и SPK_2 → динамик 4–8 Ω мощностью до 3 W | Небольшие проекты: дверные звонки, игрушки, голосовые оповещения |
| Наушники | DAC_L, DAC_R и GND → гнездо 3,5 мм | Личное прослушивание; начинай с малой громкости |
| Модуль усилителя PAM8403 | DAC_L, DAC_R и GND → входы L, R и GND усилителя; усилитель питается от 5 V | Стерео 2 × 3 W, портативная колонка на батарейках |
| Усилитель PAM8610 или TPA3116 | Выходы ЦАП → вход усилителя; усилитель питается от 12 V | Больше мощности: от 2 × 10 W |
| Активная колонка (AUX) | DAC_L, DAC_R и GND → вход AUX активной колонки | Когда есть готовая компьютерная колонка |
Как избавиться от шипения, шума и щелчков
- Шипение и щелчки при отправке команд: на линии RX нет резистора 1 kΩ. Поставь его между пином TX Arduino и пином RX модуля.
- Постоянное шипение или гул: источник питания шумит или слишком слабый. Запитай DFPlayer от отдельного источника 5 V, добавь конденсатор между VCC и GND и соедини все GND вместе.
- Хлопок при запуске: его вызывает команда сброса, которую отправляет begin(). Если он мешает, пропусти сброс с помощью player.begin(dfSerial, true, false).
- Треск с ESP32: импульсы тока во время передачи по Wi-Fi попадают в питание, а оттуда в звук. Добавь конденсатор в питание DFPlayer и по возможности используй отдельный источник.
- Хриплый, искажённый звук на большой громкости: динамик или усилитель работает на пределе. Убавь громкость примерно до 20–25, выбери более чувствительный динамик или перейди на внешний усилитель.
- Тихое шипение, когда ничего не играет: это собственный шум встроенного усилителя, и на маленьких модулях он никогда не пропадает полностью. В проектах, где важна тишина, лучший результат даёт подключение выхода ЦАП к хорошему внешнему усилителю.
Ошибка «Unable to begin» и как её исправить
Если монитор порта показывает Unable to begin:, а следом 1.Please recheck the connection! и 2.Please insert the SD card! («проверь подключение», «вставь SD-карту»), значит, не прошла проверка begin() в примере скетча из библиотеки. begin() отправляет модулю команду сброса и 2 секунды ждёт сообщения «карта на месте»; если сообщение не приходит, функция возвращает false. Значит, причина может быть в подключении, SD-карте, питании или в том, как отвечает модуль. Проверяй в таком порядке:
| Возможная причина | Проверка и решение |
|---|---|
| TX и RX не перекрещены | TX модуля должен идти на D10 (RX для SoftwareSerial), а его RX — на D11 (TX для SoftwareSerial) через 1 kΩ; это должно совпадать с порядком (RX, TX) в SoftwareSerial(10, 11) |
| Нет общей земли GND | GND модуля должен быть соединён с GND Arduino; при отдельном источнике питания тоже соедини земли |
| SD-карта не читается | Карта вставлена, в FAT32, не больше 32 ГБ и на ней есть хотя бы один аудиофайл? Отформатируй её заново или попробуй другую карту |
| Не тот резистор | Линии RX нужен 1 kΩ; большие номиналы вроде 10 kΩ ослабляют сигнал |
| Не хватает питания | На VCC должно быть 4–5 V; временно отключи динамик, измерь напряжение мультиметром и добавь конденсатор |
| Не та скорость | Должно быть dfSerial.begin(9600); не путай со скоростью монитора порта (115200) |
| Заняты D0 и D1 | На Uno аппаратный последовательный порт общий с USB; перенеси модуль на пины SoftwareSerial |
| Микросхема-клон отвечает с опозданием | Добавь delay(1000) перед begin(); если не помогает, используй begin(dfSerial, true, false), чтобы пропустить ожидание после сброса |
| Код DFPlayerError | Имя в библиотеке | Значение |
|---|---|---|
| 1 | Busy | Модуль занят или карта не найдена (инициализация не завершена) |
| 2 | Sleeping | Модуль в режиме сна |
| 3 | SerialWrongStack | Получены повреждённые последовательные данные |
| 4 | CheckSumNotMatch | Контрольная сумма пакета не совпала |
| 5 | FileIndexOut | Запрошенный номер трека вне диапазона на карте |
| 6 | FileMismatch | Запрошенный файл не найден; проверь имена |
| 7 | Advertise | Ошибка объявления, например advertise() вызвана, когда ничего не играет |
DFPlayer Mini и ESP32: управление MP3 с веб-страницы
На ESP32 SoftwareSerial не нужен: любой из трёх аппаратных UART можно назначить на выбранные пины. В скетче ниже UART2 работает на GPIO 16 (RX) и GPIO 17 (TX), а DFPlayer питается от пина 5V (VIN) платы ESP32. Сигнал TX у ESP32 на 3,3 V напрямую совместим с модулем, но резистор 1 kΩ всё равно оставь как защиту от помех. В обратном направлении DFRobot указывает логический уровень модуля 3,3 V; тем не менее на линии TX некоторых плат-клонов с питанием 5 V намеряли более высокое напряжение. Перед подключением измерь мультиметром напряжение между TX и GND; если оно выше 3,6 V, добавь делитель напряжения 1 kΩ + 2 kΩ. Скетч подключается к домашней сети и отдаёт страницу, которую можно открыть на телефоне; её кнопки переключают треки, ставят на паузу и меняют громкость.
1#include <WiFi.h>
2#include <WebServer.h>
3#include <DFRobotDFPlayerMini.h>
4
5const char *WIFI_SSID = "WIFI_ADI"; // kendi ağ adın / your network name
6const char *WIFI_PASS = "WIFI_SIFRESI"; // kendi şifren / your password
7
8HardwareSerial dfSerial(2); // UART2
9DFRobotDFPlayerMini player;
10WebServer server(80);
11int volumeLevel = 15;
12
13const char PAGE[] = R"rawliteral(<!DOCTYPE html><html><head>
14<meta name="viewport" content="width=device-width,initial-scale=1"><title>ESP32 MP3</title>
15<style>body{font-family:sans-serif;text-align:center}button{font-size:22px;margin:6px;padding:10px 18px}</style>
16</head><body><h2>DFPlayer Mini</h2>
17<button onclick="c('prev')">Prev</button><button onclick="c('pause')">Pause</button>
18<button onclick="c('play')">Play</button><button onclick="c('next')">Next</button><br>
19<button onclick="c('down')">Vol -</button><button onclick="c('up')">Vol +</button>
20<p id="s"></p>
21<script>function c(x){fetch('/cmd?c='+x).then(r=>r.text()).then(t=>document.getElementById('s').innerText=t)}</script>
22</body></html>)rawliteral";
23
24void handleCmd() {
25 String c = server.arg("c");
26 if (c == "next") player.next();
27 else if (c == "prev") player.previous();
28 else if (c == "pause") player.pause();
29 else if (c == "play") player.start();
30 else if (c == "up" && volumeLevel < 30) player.volume(++volumeLevel);
31 else if (c == "down" && volumeLevel > 0) player.volume(--volumeLevel);
32 server.send(200, "text/plain", "Ses / Volume: " + String(volumeLevel));
33}
34
35void setup() {
36 Serial.begin(115200);
37 dfSerial.begin(9600, SERIAL_8N1, 16, 17); // RX = GPIO16 ← DFPlayer TX, TX = GPIO17 → 1 kΩ → DFPlayer RX
38 delay(1000); // modül kartı okusun / let the module read the card
39 if (!player.begin(dfSerial)) {
40 Serial.println("Unable to begin");
41 while (true) delay(10);
42 }
43 player.volume(volumeLevel);
44
45 WiFi.begin(WIFI_SSID, WIFI_PASS);
46 while (WiFi.status() != WL_CONNECTED) { // ağa bağlanana kadar bekle / wait for the network
47 delay(500);
48 Serial.print(".");
49 }
50 Serial.print("\nAdres / Address: http://");
51 Serial.println(WiFi.localIP());
52
53 server.on("/", []() { server.send(200, "text/html", PAGE); });
54 server.on("/cmd", handleCmd);
55 server.begin();
56 player.play(1);
57}
58
59void loop() {
60 server.handleClient(); // tarayıcı isteklerini işle / handle browser requests
61}
62После загрузки введи в браузере телефона адрес, который показан в мониторе порта (например, 192.168.1.42); телефон и ESP32 должны быть в одной сети Wi-Fi. Если подключиться не получается, пройди по шагам из статьи ESP32 не подключается к Wi-Fi. На платах с модулем ESP32-WROVER пины GPIO 16 и 17 заняты внутренней PSRAM, поэтому перенеси UART на другие пины, например 26 и 27; менять нужно только номера пинов в строке dfSerial.begin(). Если ESP32 сама перезагружается, когда динамик играет громко, проблема в питании; подробности — в статье Brownout на ESP32.
DFPlayer Mini с Raspberry Pi Pico и MicroPython (UART)
На Raspberry Pi Pico вместо поиска готовой библиотеки проще и полезнее работать напрямую с последовательным протоколом модуля. Каждая команда — это пакет из 10 байт: стартовый байт 0x7E, версия 0xFF, длина 0x06, код команды, флаг обратной связи (0 = без подтверждения), двухбайтовый параметр, двухбайтовая контрольная сумма и конечный байт 0xEF. Контрольная сумма — это 16-битное отрицание суммы шести байтов от версии до последнего байта параметра. Например, пакет, который запускает первый трек в корне, выглядит так: 7E FF 06 03 00 00 01 FE F7 EF. Модуль, в свою очередь, присылает сообщения с кодом 0x3D, когда трек заканчивается, 0x3F, когда карта готова, и 0x40 при ошибке. UART у Pico на 3,3 V подходит модулю напрямую; предупреждение о напряжении на TX из раздела про ESP32 действует и здесь, потому что пины Pico тоже не выдерживают 5 V. Питай модуль от пина VBUS (USB 5 V) на Pico.
| Команда | Код | Параметр |
|---|---|---|
| Следующий / предыдущий трек | 0x01 / 0x02 | Нет |
| Играть n-й трек в корне | 0x03 | 1–2999 |
| Громкость | 0x06 | 0–30 |
| Эквалайзер | 0x07 | 0–5 |
| Сброс | 0x0C | Нет |
| Продолжить / пауза | 0x0D / 0x0E | Нет |
| Играть из папки | 0x0F | Старший байт — папка (1–99), младший — файл (1–255) |
| Играть из папки mp3 | 0x12 | Номер файла (1 для 0001.mp3) |
| Объявление (advert) | 0x13 | Номер файла |
| Стоп | 0x16 | Нет |
| Трек закончился (присылает модуль) | 0x3D | Номер закончившегося трека |
1from machine import UART, Pin
2import time
3
4# GP0 (UART0 TX) → 1 kΩ → DFPlayer RX, GP1 (UART0 RX) ← DFPlayer TX
5uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
6btn_next = Pin(14, Pin.IN, Pin.PULL_UP) # sonraki parça / next track
7btn_play = Pin(15, Pin.IN, Pin.PULL_UP) # oynat-duraklat / play-pause
8TRACKS = 5 # /mp3 klasöründeki dosya sayısı / number of files in /mp3
9
10def send(cmd, param=0):
11 # 10 baytlık komut paketi, onay istemeden / 10-byte command frame without ACK
12 frame = bytearray([0x7E, 0xFF, 0x06, cmd, 0x00, param >> 8, param & 0xFF, 0, 0, 0xEF])
13 checksum = -sum(frame[1:7]) & 0xFFFF # sağlama toplamı / checksum
14 frame[7] = checksum >> 8
15 frame[8] = checksum & 0xFF
16 uart.write(frame)
17 time.sleep_ms(30)
18
19buf = b""
20
21def events():
22 # gelen 10 baytlık bildirimlerin komut kodlarını döndür / return command codes of incoming messages
23 global buf
24 if uart.any():
25 buf += uart.read()
26 codes = []
27 while True:
28 start = buf.find(b"\x7e")
29 if start < 0:
30 buf = b""
31 break
32 if len(buf) - start < 10:
33 buf = buf[start:]
34 break
35 frame = buf[start:start + 10]
36 if frame[9] == 0xEF:
37 codes.append(frame[3])
38 buf = buf[start + 10:]
39 else:
40 buf = buf[start + 1:]
41 return codes
42
43def play_track(n):
44 send(0x12, n) # /mp3/000n.mp3 dosyasını çal / play /mp3/000n.mp3
45
46time.sleep(2) # modül kartı okusun / let the module read the card
47send(0x06, 18) # ses 18/30 / volume 18 of 30
48track = 1
49play_track(track)
50playing = True
51last_end = 0
52
53while True:
54 if btn_next.value() == 0:
55 track = track % TRACKS + 1 # son parçadan sonra başa dön / wrap after the last track
56 play_track(track)
57 playing = True
58 time.sleep_ms(300) # basit sıçrama önleme / simple debounce
59 if btn_play.value() == 0:
60 send(0x0E if playing else 0x0D) # 0x0E duraklat, 0x0D devam / 0x0E pause, 0x0D resume
61 playing = not playing
62 time.sleep_ms(300)
63 for code in events():
64 # 0x3D: SD karttaki parça bitti / 0x3D: track on the SD card finished
65 if code == 0x3D and time.ticks_diff(time.ticks_ms(), last_end) > 1000:
66 last_end = time.ticks_ms() # çift bildirimi yok say / ignore the duplicate message
67 track = track % TRACKS + 1
68 play_track(track)
69Если сохранить код на Pico как main.py через Thonny, Pico будет работать как MP3-плеер при каждом включении; если MicroPython для тебя в новинку, загляни в статью Основы MicroPython. Кнопка на GP14 переключает на следующий трек, а кнопка на GP15 ставит на паузу и продолжает; второй вывод каждой кнопки идёт на GND. Функция events() собирает входящие байты в буфер и выделяет пакеты, которые начинаются с 0x7E и заканчиваются 0xEF. Когда приходит сообщение «трек закончился» (0x3D), код переходит к следующему файлу, а после последнего возвращается к первому. Не забудь задать в переменной TRACKS количество файлов в папке /mp3.
Идеи проектов с DFPlayer Mini
- Мелодичный дверной звонок: звонок, который при нажатии кнопки играет случайную мелодию, а ночью звучит тише.
- Система приветствия: PIR-датчик движения запускает приветствие, когда кто-то входит.
- Музыкальная шкатулка на картах: каждая RFID-карта запускает свою папку; музыкальный плеер без экрана для детей.
- Говорящие часы: часы с модулем часов реального времени (RTC), которые произносят время или объявляют каждый час.
- MP3-плеер с пультом: переключение треков и громкость через ИК-приёмник и пульт.
- Реквизит для Хэллоуина или коробка-розыгрыш: HC-SR04 включает страшный звук, когда замечает, что кто-то подходит.
- Голосовые тревоги и оповещения: понятные фразы вроде «На кухне обнаружен газ» вместо писка, когда утечка газа, протечка воды или дверь осталась открытой.
- MP3-плеер с дисплеем: номер трека и громкость на OLED-дисплее.
С правильно названными файлами на SD-карте, резистором 1 kΩ на линии RX и надёжным питанием 5 V DFPlayer Mini за считаные минуты добавит настоящий звук в твои проекты на Arduino. Если что-то не так, сначала проверь карту и подключение, потом питание: почти любая проблема кроется в одном из этих трёх мест. Если интересны основы последовательной связи, хороший следующий шаг — статья Последовательный интерфейс UART. В приложении BlueGrays есть звуковые проекты: мелодии на зуммере, простое пианино, дверной звонок с датчиком движения и мелодии на ESP32, у каждого схема подключения и пошаговый код, а потом им можно дать настоящий звук с DFPlayer Mini.
Частые вопросы
Какой объём SD-карты поддерживает DFPlayer Mini?
DFPlayer Mini читает карты microSD объёмом до 32 ГБ, отформатированные в FAT16 или FAT32. Карты на 64 ГБ и больше поставляются в формате exFAT, поэтому модуль их не видит. Для нескольких сотен MP3 с лихвой хватит карты на 1–16 ГБ.
Почему DFPlayer Mini не воспроизводит звук?
Сначала убедись, что в мониторе порта появляется «online»; если нет, проблема в подключении или SD-карте. Если модуль запускается, но звука нет, проверь, что громкость не 0, динамик подключён к SPK_1 и SPK_2, а имена файлов соответствуют вызываемой функции. Если светодиод на плате горит, модуль действительно играет.
Зачем на пин RX модуля DFPlayer Mini ставят резистор 1k?
Микросхема модуля работает от 3,3 V, а пин TX у Arduino Uno выдаёт 5 V. Резистор 1 kΩ последовательно с линией RX ограничивает ток, текущий в микросхему, и уменьшает шипение динамика во время обмена данными. Его советуют ставить и на платах с логикой 3,3 V, таких как ESP32 и Pico, для защиты от помех.
Может ли DFPlayer Mini работать без Arduino?
Да. Если подключить пины IO_1 и IO_2 к GND через кнопки, короткое нажатие переключает трек, а долгое меняет громкость. Кнопки, подключённые к пинам ADKEY через резисторы, могут ещё и запускать конкретные треки. Так можно собрать MP3-плеер или дверной звонок всего из батарейки, динамика и нескольких кнопок, без микроконтроллера.
Какой динамик можно подключить к DFPlayer Mini?
Динамик на 4 Ω или 8 Ω мощностью до 3 W подключается напрямую к пинам SPK_1 и SPK_2; лучший баланс дают динамики на 8 Ω и 1–3 W. Никогда не подключай ни один из выводов динамика к GND. Для более громкого или стереозвука подключи выходы DAC_L и DAC_R к усилителю, например PAM8403.
Почему DFPlayer Mini играет файлы не по порядку?
Функция play(n) смотрит не на имя файла, а на порядок, в котором файлы копировались на карту. Чтобы играть по имени, назови файлы /mp3/0001.mp3 и используй playMp3Folder() или назови их /01/001.mp3 и используй playFolder(). Если карта готовилась на Mac, удали ещё и скрытые файлы ._.
Что собрать после прочтения
Все проекты
Работа с зуммером
Интересно, как дверной звонок или сигнализация издают звук? Arduino заставляет маленький зуммер пищать через короткие промежутки: пик, пауза, пик, пауза. Ты видишь, как электричество превращается в зв

Гимн Турции на зуммере
Нажми кнопку, и маленький зуммер начнёт нота за нотой играть Государственный гимн Турции. Arduino играет каждую ноту нужной высоты и длительности, исполняет два куплета гимна от начала до конца и ждёт

Настройка частоты зуммера
Ты управляешь звуком зуммера четырьмя кнопками: одна включает звук, другая выключает, а две оставшиеся делают его выше или ниже. Удерживай кнопку вверх или вниз, и высота звука меняется шаг за шагом,

Мелодия на зуммере с ESP32
Воспроизведение простой мелодии (Twinkle Twinkle Little Star) на пассивном зуммере. Ноты играются функциями tone() и noTone(), как в Arduino, — ESP32 работает с тем же синтаксисом в Arduino Core 3.0+. Нужен пассивный зуммер (активный мелодию не сыграет).

Мелодии с ИК-пультом и зуммером
Собери музыкальную шкатулку, которая играет мелодии по кнопкам пульта от телевизора. Инфракрасный приёмник ловит сигнал пульта; одна кнопка играет на зуммере весёлую мелодию из видеоигры, другая — зна

Простое пианино на зуммере и кнопках
Собери своё маленькое пианино из восьми кнопок. Каждая кнопка — одна нота, от низкой к высокой: до, ре, ми, фа, соль, ля, си и верхнее до. Нота звучит через зуммер, пока ты держишь кнопку, и замолкает

Дверной звонок и свет с датчиком движения
Когда кто-то подходит к твоей двери, ты узнаёшь об этом ещё до звонка. Как только датчик движения замечает человека, загорается светодиод, а зуммер играет мелодию из трёх нот сверху вниз; когда мелоди
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

