ArduinoでDFPlayer Miniを使う:MP3の再生、SDカード、スピーカー
ArduinoでDFPlayer Miniを使う方法。RXの1kΩ抵抗、SDカードと0001.mp3の命名、ライブラリのコード、ボタン、スピーカー、ESP32とPicoの例を解説します。
DFPlayer Miniは、ArduinoでMP3を再生する最も安く簡単な方法です。microSDカードの音声ファイルを自分でデコードし、内蔵の小さなアンプでスピーカーを直接鳴らし、2本線のシリアル通信でArduinoからコマンドを受け取ります。ブザーのビープ音と違い、歌、話し声、玄関チャイムのメロディー、「ドアが開いたままです」のような音声の警告も再生できます。初めてつないだ人の多くは同じ問題にぶつかります。音が出ない、スピーカーからサーッという雑音がする、ファイルが違う順番で再生される、シリアルモニタに「Unable to begin」と出る、などです。このガイドでは、そのすべてを解決し、なぜそうなるのかも説明します。
まず、モジュールのピンと、RXの線に1 kΩの抵抗を入れる理由を学びます。次に、SDカードをFAT32で準備し、ファイルを0001.mp3と01のフォルダの形式で名前を付け、DFRobotDFPlayerMiniライブラリで最初の音を鳴らし、音量とEQを設定し、ボタンで曲を変え、適切なスピーカーや外付けアンプを選ぶ方法を見ていきます。最後のセクションでは、「Unable to begin」エラーのステップごとの直し方、ESP32でWebページから操作するMP3プレーヤー、Raspberry Pi Pico用のライブラリを使わないMicroPythonの例を紹介します。ビープ音や簡単なメロディーだけでよければ、ブザーのほうが簡単です。

DFPlayer Miniとは?どう動くのか
DFPlayer Miniは、MP3デコーダーのチップ、24ビットのDAC、microSDカードのスロット、小さなモノラルアンプでできた、それだけで完結したMP3プレーヤーです。Arduinoは「3曲目を再生して」「音量を20にして」といった短いコマンドを送るだけです。カードからファイルを読み、圧縮された音声をデコードし、スピーカーを鳴らすのはモジュールの仕事です。そのため、RAMが2 KBしかないArduino Unoでも楽々と音楽を再生できます。コマンドは9600ボーで、1つ10バイトのパケットとして送られます。モジュールも、曲が終わったとき、カードが挿されたり抜かれたりしたとき、エラーが起きたときに同じ形式で知らせてきます。基板上のチップはメーカーによって違います(YX5200-24SS、MH2024K-24SS、GD3200Bなど)。どれも同じコマンドを理解しますが、応答にかかる時間が違うことがあり、これはあとで「Unable to begin」エラーのときに重要になります。モジュールは3つの方法で操作できます。シリアルポート(UART)、IOボタン、ADKEYの抵抗ラダーです。
| 項目 | 値 |
|---|---|
| 対応ファイル | MP3、WAV、WMA |
| サンプリング周波数 | 8 / 11.025 / 12 / 16 / 22.05 / 24 / 32 / 44.1 / 48 kHz |
| DAC | 24ビット。ダイナミックレンジ90 dB、S/N比85 dB |
| 記録メディア | 32 GBまでのmicroSD(TF)カード、FAT16またはFAT32。USBメモリにも対応 |
| フォルダの容量 | 最大100フォルダ、1フォルダあたり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 mm |
DFPlayer Miniのピン配置
| ピン | 名前 | 機能 |
|---|---|---|
| 1 | VCC | 電源入力、3.2〜5.0 V |
| 2 | RX | シリアル入力:1 kΩの抵抗を通してボードのTXピンにつなぐ |
| 3 | TX | シリアル出力:ボードのRXピンへ |
| 4 | DAC_R | 右チャンネルのライン出力(ヘッドホンかアンプ) |
| 5 | DAC_L | 左チャンネルのライン出力(ヘッドホンかアンプ) |
| 6と8 | SPK_1、SPK_2 | スピーカー出力:3 W未満のスピーカーの2本の線をここにつなぐ |
| 7 | GND | グランド |
| 9 | IO_1 | GNDに短く押す:前の曲、長押し:音量を下げる |
| 10 | GND | グランド |
| 11 | IO_2 | GNDに短く押す:次の曲、長押し:音量を上げる |
| 12 | ADKEY1 | 抵抗ラダーによる複数ボタンの入力 |
| 13 | ADKEY2 | 2つ目の抵抗ラダーの入力 |
| 14 | USB+ | USBメモリ用のD+ |
| 15 | USB− | USBメモリ用のD− |
| 16 | BUSY | 再生中はLOW、待機中はHIGH |
シリアルポートを使う場合に必要なのは、VCC、GND、RX、TX、スピーカーのピンだけです。BUSYピンを使えば、シリアル通信なしで曲が終わったかがわかり、基板上の小さなLEDも再生中に点きます。IO_1とIO_2のピンを使えば、Arduinoなしでもモジュールを動かせます。各ピンとGNDの間にボタンを付ければ、短く押すと曲が変わり、長押しで音量が変わります。値の違う抵抗を通してADKEYのピンにつないだボタンで、特定の曲を再生することもできます。つまり、電池、スピーカー、ボタン2つがあれば、マイコンなしで玄関チャイムやしゃべるおもちゃを作れます。USB+とUSB−のピンはSDカードの代わりにUSBメモリから再生するためのもので、ほとんどのプロジェクトでは未接続のままです。
DFPlayer MiniとArduinoの配線、RXの1kΩ抵抗
| DFPlayerのピン | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 5V(VIN) | VBUS(USBの5 V、40番ピン) |
| GND | GND | GND | GND |
| RX | 1 kΩの抵抗を通してD11 | 1 kΩの抵抗を通してGPIO 17(TX2) | 1 kΩの抵抗を通してGP0(UART0のTX) |
| TX | D10 | GPIO 16(RX2) | GP1(UART0のRX) |
| SPK_1とSPK_2 | スピーカーの2本の線 | スピーカーの2本の線 | スピーカーの2本の線 |
| BUSY(任意) | D5 | 使わない | 使わない |



データ線は交差させます。モジュールのTXはボードのRXへ、RXはボードのTXへつなぎます。UnoのD0とD1のハードウェアシリアルポートはUSBでの書き込みとシリアルモニタに使われているので、モジュールはSoftwareSerialでD10(RX)とD11(TX)につなぎます。モジュールのRX入力と直列に入れる1 kΩの抵抗は、ささいな部品ではありません。DFPlayerのチップは3.3 Vのロジックで動きますが、UnoのTXピンは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が読めるのは、FAT16かFAT32でフォーマットした32 GBまでのmicroSDカードです。64 GB以上のカードはexFATでフォーマットされて出荷されていて、モジュールでは読めません。数百曲なら1〜16 GBのカードで十分です。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フォルダ、1フォルダあたり3000ファイル、4桁の名前 |
- パソコンでカードをFAT32でフォーマットします(Windowsなら右クリック >「フォーマット」、macOSなら「ディスクユーティリティ」>「消去」>「MS-DOS (FAT)」)。
- ルートにmp3という名前のフォルダを作り、必要なら01や02のような番号付きのフォルダも作ります。
- ファイルの名前を0001.mp3、0002.mp3(番号付きのフォルダでは001.mp3)に変えます。0001_hello.mp3のように番号のあとに説明を加えても構いません。モジュールは先頭の数字だけを見ます。
- ルートのファイルをplay()で再生する場合は、1つずつ順番にコピーしてください。まとめてコピーすると順番がずれることがあります。
- カードを安全に取り出し、電源を切った状態でモジュールに挿します。動作中に抜き差しすると、ファイルが壊れることがあります。
DFRobotDFPlayerMiniライブラリと最初のテスト用スケッチ
- Arduino IDEでライブラリマネージャを開き、DFRobotDFPlayerMiniと入力してDFRobotのライブラリをインストールします。インストールの手順はArduinoにライブラリを追加する方法で詳しく説明しています。
- SDカードのルートにMP3を少なくとも1つコピーし、カードをモジュールに挿して、表のとおりに回路を組みます。
- 下のスケッチを書き込み、シリアルモニタを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(serial, isACK, doReset) | モジュールを起動する。初期設定ではリセットを送り、カードの準備ができたというメッセージを待つ |
| volume(0–30) | 音量を設定する。volumeUp()とvolumeDown()は1段階ずつ変える |
| 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() | モジュールからのメッセージ(曲の終了、エラー、カードの取り外し)を読む |
音量、EQ、BUSYピンを使った連続の案内
音量は0〜30の範囲です。小さなスピーカーなら、たいていの部屋では15〜20で十分です。25を超えると、特に電源が弱い場合、音が歪み始め(クリッピング)、モジュールがリセットされることがあります。EQの設定は低音と高音のバランスを変えます。小さなスピーカーではBASSモードだと音がこもることがあるので、NORMALから始めてください。番号付きのフォルダは、しゃべるプロジェクトにとても便利です。「温度は」と「度」という言葉をフォルダ01に、001.mp3〜100.mp3の数字をフォルダ02に入れれば、Arduinoが数字を文として話せます。ファイルが終わったことを知る最も確実な方法はBUSYピンです。モジュールが再生中はLOW、待機中はHIGHになります。下のスケッチはD5でBUSYを読み、ファイルを重ならないように1つずつ順番に再生します。
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()は、まずコマンドを送り、BUSYがLOWになるまで最大1秒待ち(モジュールが再生を始めるまで数百ミリ秒かかります)、そのあと曲が終わるまで待ちます。音声ファイルは自分の声で録音しても、音声合成(TTS)ツールで作っても構いません。各ファイルの最初と最後の無音を削ると、案内がより自然に流れます。短い警告のために音楽を中断したい場合はadvertise(n)を使います。モジュールは/advertフォルダの案内を再生し、そのあと音楽を止めたところから再開します。このコマンドは曲の再生中にしか使えません。モジュールが待機中に呼ぶとエラーが返ります。
ボタンで曲を変え、ポテンショメーターで音量を調整する
それでは自分のMP3プレーヤーを作りましょう。3つのボタンが前の曲、再生・一時停止、次の曲の役目をし、ポテンショメーターで音量を調整します。ボタンはD2、D3、D4とGNDの間につなぎます。内部プルアップ抵抗を使うので、外付けの抵抗は不要です(理由はArduinoに押しボタンをつなぐ方法で説明しています)。ポテンショメーターの両端のピンは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 ms以内のチャタリングを無視する。押し続けてもコマンドは1回だけ |
| abs(raw - lastRaw) > 20 | はっきりした変化のときだけ音量を更新し、ポテンショメーターの値の小さな揺れでモジュールにコマンドが殺到してプチプチ音が出るのを防ぐ |
| map(raw, 0, 1023, 0, 30) | 0〜1023のアナログ値をDFPlayerの0〜30の音量の範囲に変換する |
| paused | 再生状態を覚えておき、同じボタンで一時停止と再開の両方ができるようにする |
| DFPlayerPlayFinished | 曲が終わったときに送られるメッセージ。スケッチは次の曲に進む |
| millis() - lastFinish > 1000 | 互換品のモジュールの中には曲の終わりを2回知らせるものがある。このチェックで曲が飛ばされるのを防ぐ |
スピーカー(3 W)と外付けアンプの選び方
DFPlayer自身のアンプ(ほとんどの基板では8002型のチップ)は、インピーダンス4 Ωか8 Ω、3 W未満のスピーカーを直接鳴らします。最もバランスがよいのは8 Ω・1〜3 Wのスピーカーです。0.5 Wの小さなスピーカーも使えますが、大音量では苦しくなります。3 Wという値は、5 Vの電源と4 Ωの負荷でのアンプの上限で、歪みがはっきりしてくる点です。普段の使用で得られるきれいな出力はもっと低くなります。スピーカーを箱に入れるか、少なくとも板に取り付けると、コーンの前と後ろからの音が打ち消し合わなくなるので、低音がはっきり良くなります。大音量では、モジュールが一瞬数百ミリアンペアを引くことがあります。パソコンのUSBポートで給電したArduinoでは、これが電圧の低下、雑音、リセットの原因になります。より大きな出力やステレオの音が欲しい場合は、DAC_LとDAC_Rのライン出力を外付けアンプにつなぎます。
| 出力の経路 | 接続 | 使う場面 |
|---|---|---|
| 内蔵アンプ | SPK_1とSPK_2 → 3 Wまでの4〜8 Ωのスピーカー | 玄関チャイム、おもちゃ、音声の警告のような小さなプロジェクト |
| ヘッドホン | DAC_L、DAC_R、GND → 3.5 mmジャック | 個人で聴く。小さい音量から始める |
| PAM8403アンプモジュール | DAC_L、DAC_R、GND → アンプのL、R、GNDの入力。アンプは5 Vで動く | 2 × 3 Wのステレオ、電池で動く持ち運べるスピーカー |
| PAM8610またはTPA3116のアンプ | DACの出力 → アンプの入力。アンプは12 Vで動く | より大きな出力:2 × 10 W以上 |
| アンプ内蔵スピーカー(AUX) | DAC_L、DAC_R、GND → アンプ内蔵スピーカーのAUX入力 | 手持ちのパソコン用スピーカーを使う |
サーッという雑音、ノイズ、プチプチ音をなくすには
- コマンドを送るときにサーッという雑音やプチプチ音がする:RXの線の1 kΩの抵抗がありません。ArduinoのTXピンとモジュールのRXピンの間に入れてください。
- 常にサーッという雑音やブーンという音がする:電源にノイズがあるか、弱すぎます。DFPlayerを別の5 V電源から給電し、VCCとGNDの間にコンデンサを入れ、GNDをすべてつないでください。
- 起動時に「ポン」と鳴る:begin()が送るリセットのコマンドが原因です。気になる場合は、player.begin(dfSerial, true, false)でリセットを省いてください。
- ESP32でジーという音がする:Wi-Fiの送信中の電流のパルスが電源に入り込み、そこから音声に混ざっています。DFPlayerの電源にコンデンサを加え、できれば別の電源を使ってください。
- 大音量で音が割れて歪む:スピーカーかアンプが限界で動いています。音量を20〜25程度に下げるか、より効率のよいスピーカーを選ぶか、外付けアンプに切り替えてください。
- 何も再生していないときにかすかなサーッという音がする:これは基板上のアンプ自体のノイズで、小さなモジュールでは完全には消えません。無音が重要なプロジェクトでは、DACの出力をよい外付けアンプにつなぐのが最善です。
「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(SoftwareSerialのRX)へ、RXは1 kΩを通してD11(SoftwareSerialのTX)へ。SoftwareSerial(10, 11)の(RX, TX)の順と一致させる |
| 共通GNDがない | モジュールのGNDをArduinoのGNDにつなぐ。別の電源を使う場合もGNDを共通にする |
| SDカードが読めない | カードは挿さっているか、FAT32か、32 GB以下か、音声ファイルが少なくとも1つ入っているか。フォーマットし直すか、別のカードを試す |
| 抵抗が違う | RXの線には1 kΩが必要。10 kΩのような大きな値では信号が弱まる |
| 電源が不十分 | VCCは4〜5 Vが必要。スピーカーを一時的に外し、テスターで電圧を測り、コンデンサを追加する |
| ボーレートが違う | dfSerial.begin(9600);でなければならない。シリアルモニタの速度(115200)と混同しない |
| D0とD1を使っている | UnoではハードウェアシリアルポートがUSBと共用。モジュールをSoftwareSerialのピンに移す |
| 互換品のチップの応答が遅い | begin()の前にdelay(1000)を加える。効果がなければbegin(dfSerial, true, false)でリセット後の待ちを省く |
| DFPlayerErrorのコード | ライブラリでの名前 | 意味 |
|---|---|---|
| 1 | Busy | モジュールが処理中、またはカードが見つからない(初期化が終わっていない) |
| 2 | Sleeping | モジュールがスリープモード |
| 3 | SerialWrongStack | 壊れたシリアルデータを受信した |
| 4 | CheckSumNotMatch | パケットのチェックサムが一致しなかった |
| 5 | FileIndexOut | 要求した曲番号がカード上の範囲外 |
| 6 | FileMismatch | 要求したファイルが見つからない。命名を確認する |
| 7 | Advertise | 案内のエラー。たとえば何も再生していないときにadvertise()を呼んだ |
ESP32でDFPlayer Miniを使う:WebページからMP3を操作する
ESP32ではSoftwareSerialは不要で、3つあるハードウェアUARTのどれでも好きなピンに割り当てられます。下のスケッチではUART2をGPIO 16(RX)とGPIO 17(TX)で使い、DFPlayerはESP32ボードの5V(VIN)ピンから給電します。ESP32の3.3 VのTX信号はそのままモジュールに合いますが、ノイズ対策として1 kΩの抵抗は残しておいてください。逆方向については、DFRobotはモジュールのロジックレベルを3.3 Vとしています。それでも、5 Vで動かした一部の互換品の基板では、TXの線でもっと高い電圧が測定されています。つなぐ前にテスターで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が勝手に再起動する場合は、電源が原因です。詳しくはESP32のブラウンアウトを参照してください。
Raspberry Pi PicoとMicroPythonでDFPlayer Miniを使う(UART)
Raspberry Pi Picoでは、既製のライブラリを探すより、モジュールのシリアルプロトコルを直接使うほうが簡単で勉強にもなります。どのコマンドも10バイトのパケットです。開始バイト0x7E、バージョン0xFF、長さ0x06、コマンドのコード、応答のフラグ(0 = 応答なし)、2バイトのパラメーター、2バイトのチェックサム、終了バイト0xEFです。チェックサムは、バージョンから最後のパラメーターのバイトまでの6バイトの合計を16ビットで負にしたものです。たとえば、ルートの最初の曲を再生するパケットは7E FF 06 03 00 00 01 FE F7 EFです。モジュールのほうは、曲が終わるとコード0x3D、カードの準備ができると0x3F、エラーが起きると0x40のメッセージを送ります。Picoの3.3 VのUARTはそのままモジュールに合います。ESP32のセクションのTXの電圧についての注意はここでも当てはまります。Picoのピンも5 Vには耐えられないからです。モジュールはPicoのVBUS(USBの5 V)ピンから給電してください。
| コマンド | コード | パラメーター |
|---|---|---|
| 次の曲 / 前の曲 | 0x01 / 0x02 | なし |
| ルートのn番目の曲を再生 | 0x03 | 1〜2999 |
| 音量 | 0x06 | 0〜30 |
| EQ | 0x07 | 0〜5 |
| リセット | 0x0C | なし |
| 再開 / 一時停止 | 0x0D / 0x0E | なし |
| フォルダから再生 | 0x0F | 上位バイトがフォルダ(1〜99)、下位バイトがファイル(1〜255) |
| mp3フォルダから再生 | 0x12 | ファイル番号(0001.mp3なら1) |
| 案内(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)
69Thonnyでコードをmain.pyとしてPicoに保存すれば、Picoは電源を入れるたびにMP3プレーヤーとして動きます。MicroPythonが初めてならMicroPythonの基本を見てください。GP14のボタンで次の曲に進み、GP15のボタンで一時停止と再開をします。各ボタンのもう片側はGNDへつなぎます。events()関数は届いたバイトをバッファにためて、0x7Eで始まり0xEFで終わるパケットを取り出します。曲の終了(0x3D)のメッセージが届くと、コードは次のファイルに進み、最後のファイルのあとは最初に戻ります。TRACKS変数を/mp3フォルダのファイル数に合わせるのを忘れないでください。
DFPlayer Miniのプロジェクトアイデア
- メロディーの玄関チャイム:ボタンを押すとランダムなメロディーを鳴らし、夜は音量を下げる玄関チャイム。
- おかえりシステム:PIR人感センサーが、誰かが来るとあいさつを流します。
- カードで選ぶオルゴール:RFIDカードごとに別のフォルダを再生する、子ども向けの画面のない音楽プレーヤー。
- しゃべる時計:RTC時計モジュールを使い、時刻を読み上げたり、毎正時を知らせたりする時計。
- リモコンで操作するMP3プレーヤー:赤外線受信モジュールとリモコンで曲と音量を操作します。
- ハロウィーンの小道具やびっくり箱:HC-SR04が人の接近を検知すると怖い音を鳴らします。
- 音声の警報と通知:ガス、水漏れ、開けっぱなしのドアのとき、ビープ音の代わりに「キッチンでガスを検知しました」のようなはっきりした文を流します。
- ディスプレイ付きMP3プレーヤー:曲番号と音量をOLEDディスプレイに表示します。
正しく名前を付けたSDカード、RXの線の1 kΩの抵抗、しっかりした5 Vの電源があれば、DFPlayer MiniはArduinoのプロジェクトに数分で本物の音を加えてくれます。何かがうまくいかなければ、まずカードと配線、次に電源を確認してください。ほとんどの問題はこの3つのどれかから生じます。シリアル通信の基本に興味があれば、UARTシリアル通信が次のステップにちょうどよいでしょう。BlueGraysアプリには、ブザーでのメロディーの演奏、簡単なピアノ、人感センサーの玄関チャイム、ESP32のメロディーといった音のプロジェクトが、回路図とステップごとのコード付きで揃っています。それらにDFPlayer Miniで本物の音を持たせることもできます。
よくある質問
DFPlayer Miniが対応するSDカードの容量は?
DFPlayer Miniが読めるのは、FAT16かFAT32でフォーマットした32 GBまでのmicroSDカードです。64 GB以上のカードはexFATでフォーマットされているので、モジュールには見えません。数百曲のMP3なら1〜16 GBのカードで十分です。
DFPlayer Miniから音が出ないのはなぜ?
まずシリアルモニタに「online」と出ているか確認してください。出ていなければ、問題は配線かSDカードです。モジュールは起動するのに音が出ない場合は、音量が0になっていないか、スピーカーがSPK_1とSPK_2につながっているか、ファイル名が呼んでいる関数と合っているかを確認してください。基板のLEDが点いていれば、モジュールは確かに再生しています。
DFPlayer MiniのRXピンに1kΩの抵抗を入れるのはなぜ?
モジュールのチップは3.3 Vで動きますが、Arduino UnoのTXピンは5 Vを出します。RXの線と直列に入れた1 kΩの抵抗がチップに流れ込む電流を制限し、シリアル通信中にスピーカーから聞こえる雑音を減らします。ESP32やPicoのような3.3 Vのボードでも、ノイズ対策として推奨されます。
DFPlayer MiniはArduinoなしで動く?
はい。IO_1とIO_2のピンをボタンを通してGNDにつなげば、短く押すと曲が変わり、長押しで音量が変わります。抵抗を通してADKEYのピンにつないだボタンで、特定の曲を再生することもできます。こうすれば、マイコンなしで電池、スピーカー、いくつかのボタンだけでMP3プレーヤーや玄関チャイムを作れます。
DFPlayer Miniにはどんなスピーカーをつなげる?
3 W未満の4 Ωか8 Ωのスピーカーなら、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が小さなブザーを短い間隔で鳴らし、音を出す、止める、を繰り返します。電気で音が生まれる仕組みを学び、メロディーを演奏するプロジェクトへの第一歩を踏み出せます。

ブザーでトルコ国歌を演奏
ボタンを押すと、小さなブザーがトルコ国歌を1音ずつ演奏し始めます。Arduinoが各音を正しい音程と長さで鳴らし、国歌の2節を最初から最後まで演奏した後、次のボタン操作を待ちます。シンプルな音響部品からメロディーが生まれる様子を、自分の耳で確かめられます。

ブザーの周波数を調整
4つのボタンでブザーの音を操作します。1つは音を鳴らし、1つは音を止め、残りの2つは音を高くしたり低くしたりします。音を高くするボタンや低くするボタンを押し続けると、音程が段階的に変化し、サイレンのように聞こえます。音の高低が生まれる理由を、自分の耳で確かめられます。

ESP32とブザーでメロディーを演奏
パッシブブザーで簡単なメロディー「きらきら星」を演奏します。Arduinoと同じようにtone()とnoTone()で音を鳴らします。ESP32 Arduino Core 3.0+でも同じ構文が使えます。パッシブブザーを使用してください。アクティブブザーではメロディーを演奏できません。

IR受信機・リモコン・ブザーでメロディーを再生
テレビのリモコンのボタンでメロディーを奏でるオルゴールを作ります。赤外線受信機がリモコンの信号を受け取り、1つ目のボタンで軽快なゲーム音楽、2つ目でおなじみの童謡、3つ目で新年の歌をブザーから流します。リモコンが目に見えない光で通信する仕組みと、音符を音に変える方法を学びます。

ブザーとボタンで作る簡単なピアノ
8個のボタンで小さなピアノを作ります。各ボタンには、低い音から順にド、レ、ミ、ファ、ソ、ラ、シ、高いドが割り当てられています。ボタンを押している間はブザーから音が鳴り、離すと止まります。簡単な曲を弾きながら、音符の正体が音の振動であることを実感できます。

モーションセンサーで作るドアベルとライト
玄関に誰かが近づくと、呼び鈴を押す前にわかります。モーションセンサーが人を検知するとLEDが点灯し、ブザーが高い音から低い音へ3音のチャイムを鳴らします。メロディーが終わるとライトが消え、センサーは再び待機します。音と光の両方で知らせるシンプルな玄関の見張り役です。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

