ボタンで音楽を操作してみよう
前回は、DFPlayerを使って音楽を再生しました。
今回はボタンを追加して、
「再生・停止」「曲送り」などの操作ができるようにしてみましょう。
DFPlayerには、色々なコマンドが用意されているので
リピート再生やランダム再生など、コマンドを使って色々なことができるようになります。
OLEDでボリュームや再生モードなどを表示するバージョン

ボタンを追加しよう
次の3つのボタンを用意します。
- 再生 / 停止ボタン
- 次の曲ボタン
- 前の曲ボタン
それぞれのボタンを、マイコンのピンに接続します。
今回は、2・5・11・7のピンをボタンにつなぎました。(7番は予備)
ボタンはINPUT_PULLUPを使って接続します。
・押していないとき → HIGH
・押したとき → LOW
となるので、プログラムではLOWのときを「押された」として扱います。
プログラムを書こう
ボタンの状態を読み取って、DFPlayerに命令を送ります。
// DFPlayerにコマンドを送る関数
void sendCommand(uint8_t cmd, uint8_t p1, uint8_t p2) {
uint8_t packet[10] = {
0x7E, 0xFF, 0x06, cmd, 0x00,
p1, p2,
0x00, 0x00, 0xEF
};
uint16_t sum = 0;
for (int i = 1; i < 7; i++) {
sum += packet[i];
}
sum = -sum;
packet[7] = (sum >> 8) & 0xFF;
packet[8] = sum & 0xFF;
Serial1.write(packet, 10);
delay(200);
}
#define BTN_PREV 2
#define BTN_PLAY 5
#define BTN_NEXT 11
#define BTN_SUB 7
bool isPlaying = true;
void setup() {
pinMode(BTN_PREV, INPUT_PULLUP);
pinMode(BTN_PLAY, INPUT_PULLUP);
pinMode(BTN_NEXT, INPUT_PULLUP);
pinMode(BTN_SUB, INPUT_PULLUP);
Serial1.begin(9600);
delay(2000);
sendCommand(0x0D, 0, 0); // 再生スタート
}
void loop() {
// 再生 / 停止ボタン
if (digitalRead(BTN_PLAY) == LOW) {
if (isPlaying) {
sendCommand(0x0E, 0, 0); // 一時停止
isPlaying = false;
} else {
sendCommand(0x0D, 0, 0); // 再生
isPlaying = true;
}
delay(300);
}
// 次の曲
if (digitalRead(BTN_NEXT) == LOW) {
sendCommand(0x01, 0, 0);
isPlaying = true;
delay(300);
}
// 前の曲
if (digitalRead(BTN_PREV) == LOW) {
sendCommand(0x02, 0, 0);
isPlaying = true;
delay(300);
}
}
DFPlayerは、「コマンド」という命令を送ることで動きます。
たとえば…
- 0x0D → 再生
- 0x0E → 一時停止
- 0x01 → 次の曲
- 0x02 → 前の曲
sendCommand()は、このコマンドをDFPlayerに送るための関数です。
動かしてみよう
プログラムを書き込んだら、 それぞれのボタンを押してみましょう。
- 再生 / 停止が切り替わる
- 次の曲に進む
- 前の曲に戻る
思い通りに動けば成功です。(1曲目を再生中に前の曲に戻ることはできません)
いまは、1曲終わるごとに停止するようになっていますね。
次は、ループ再生やランダム再生などを試してみましょう。
ループ再生できるようにしてみよう
DFPlayerは、曲が終わったあとに自動で次の曲を再生したり、同じ曲をくり返し再生したりすることができます。
BGMプレイヤーやゲームの音楽にもぴったりですね。
今回は「全曲リピート」と「1曲だけリピート」の2種類を試してみましょう。
DFPlayerのコマンド一覧を見てみよう
DFPlayerは、決められたコマンドをシリアル通信で送ることで操作できます。
どんな命令があるかは、仕様書(データシート)に書かれています。
仕様書はこちら:
[DFPlayer Mini Datasheet]
また、DFPlayer本体のバージョンによっても動かないことがあるかもしれません。
全曲をループ再生してみよう
まずは、SDカードに入っている曲を順番にくり返し再生してみます。
setup()でリピートのコマンドを送ってみましょう。
void setup() {
pinMode(BTN_PREV, INPUT_PULLUP);
pinMode(BTN_PLAY, INPUT_PULLUP);
pinMode(BTN_NEXT, INPUT_PULLUP);
pinMode(BTN_SUB, INPUT_PULLUP);
Serial1.begin(9600);
delay(2000);
sendCommand(0x11, 0, 1); // リピートオン
sendCommand(0x0D, 0, 0); // 再生スタート
}
この「0x11」という命令が、全曲リピート再生です。
曲が最後まで再生されると、自動で次の曲へ進みます。
「0x11」のような数字は、16進数という特別な数の表し方です。
マイコンではよく使われます。
DFPlayerは、この数字を見て
「次の曲へ進むモード」
「音量変更」
などを判断しています。
1曲だけループ再生してみよう
DFPlayerは、「何番の曲を再生するか?」を数字で指定できます。
ですが、ファイル名の付け方や、SDカードへのコピー順に少しクセがあります。
ルートフォルダに入れる場合
SDカードの一番上(フォルダの外)に曲を入れるときは、
ファイル名を「4ケタの数字」にする必要があります。
- 0001.mp3 → 1番の曲
- 0002.mp3 → 2番の曲
- 0003.mp3 → 3番の曲
として再生されます。
コピーする順番にも注意
実はDFPlayerは、ファイル名だけでなく
SDカードに書き込まれた順番も見ています。
たとえば…
- 最初に「0007.mp3」をコピー
- あとから「0001.mp3」をコピー
という順番にすると、
- 0007.mp3 → 1番目の曲
- 0001.mp3 → 2番目の曲
のように認識されてしまうことがあります。
- 先にパソコン上で「0001.mp3」などに名前をそろえる
- あとから全部まとめてコピーする
フォルダに入れる場合
フォルダを使う場合は、少しルールが変わります。
01/
├─001.mp3
├─002.mp3
02/
├─001.mp3
- フォルダ名 → 01〜99
- ファイル名 → 001.mp3〜255.mp3
この場合は、「フォルダ番号」と「曲番号」を指定して再生できます。
1曲だけリピートするプログラム
たとえば「0002.mp3」をずっとループしたい場合は、 次のようなコマンドを送ります。
void setup() {
pinMode(BTN_PREV, INPUT_PULLUP);
pinMode(BTN_PLAY, INPUT_PULLUP);
pinMode(BTN_NEXT, INPUT_PULLUP);
pinMode(BTN_SUB, INPUT_PULLUP);
Serial1.begin(9600);
delay(2000);
sendCommand(0x08, 0, 2); // 2番目のトラックをリピート再生
sendCommand(0x0D, 0, 0); // 再生スタート
}
最後の「2」が曲番号です。
つまり「2番目の曲をループ再生してね!」という意味になります。
よく使うDFPlayerコマンド一覧
DFPlayerは、「sendCommand()」で命令を送ることで操作できます。
たとえば、
sendCommand(コマンド番号, 引数1, 引数2);
という形で使います。
- コマンド番号 → 「何をしたいか」
- 引数1・引数2 → 追加の設定
を表しています。
使わない引数は「0」を入れておけばOKです。
| コマンド | 内容 | sendCommand() の例 |
|---|---|---|
| 0x01 | 次の曲 | sendCommand(0x01, 0, 0); |
| 0x02 | 前の曲 | sendCommand(0x02, 0, 0); |
| 0x03 | 曲番号を指定して再生 | sendCommand(0x03, 0, 5);→ 0005.mp3 を再生 |
| 0x04 | 音量アップ | sendCommand(0x04, 0, 0); |
| 0x05 | 音量ダウン | sendCommand(0x05, 0, 0); |
| 0x06 | 音量指定(0〜30) | sendCommand(0x06, 0, 20); |
| 0x07 | EQ設定 | sendCommand(0x07, 0, 2);→ Rockモード |
| 0x08 | 1曲リピート | sendCommand(0x08, 0, 2);→ 0002.mp3 をループ |
| 0x09 | 再生デバイス指定 | sendCommand(0x09, 0, 2);→ SDカード |
| 0x0C | リセット | sendCommand(0x0C, 0, 0); |
| 0x0D | 再生 | sendCommand(0x0D, 0, 0); |
| 0x0E | 一時停止 | sendCommand(0x0E, 0, 0); |
| 0x0F | フォルダ内トラック再生 | sendCommand(0x0F, 1, 3);→ 01/003.mp3 |
| 0x11 | 全曲リピート | sendCommand(0x11, 0, 1); |
| 0x16 | 停止 | sendCommand(0x16, 0, 0); |
| 0x17 | フォルダリピート | sendCommand(0x17, 0, 1);→ 01フォルダをループ |
| 0x18 | ランダム再生 | sendCommand(0x18, 0, 0); |
| 0x19 | 現在の曲をリピート | sendCommand(0x19, 0, 0); |
| 0x1A | DAC ON/OFF | sendCommand(0x1A, 0, 1); |
仕様書には細かいコマンドの使い方説明も載ってるので、チェックしてみて下さい
Busyピンで曲が再生中かどうかがわかる
DFPlayerには「いま音楽を再生しているか?」を教えてくれる Busyピンがあります。- 再生中 → LOW(0)
- 停止中 → HIGH(1)
#define BUSY_PIN 10
bool nowPlaying = (digitalRead(BUSY_PIN) == LOW);
digitalRead() でBUSYピンを読むことで、
- 曲が終わったかチェックする
- 次の曲を自動再生する
- 再生中だけアニメーションする
- LEDを点滅させる
OLEDディスプレイと組み合わせ
さいごにこれまでに作った ・ボタン入力 ・OLED表示 ・DFPlayer制御 を全部組み合わせて
音楽プレイヤーっぽくしてみました。(ボタンのピン配置が違うので、自分のピンに合わせて下さい)
さいごにサンプルだけあげておきます。
なんか途中で自動再生が止まっちゃったりしたので、ちょいゴリ押しぎみです。

コメント