プログラミング素人のはてなブログ

プログラミングも電気回路も専門外の技術屋の末端が勉強したことや作品をアウトプットするブログ。コードに間違いなど見つけられたら、気軽にコメントください。 C#、Python3、ラズパイなど。

Arduinoでmp3を再生する

DFPlayer Miniというmp3モジュールを使う

AmazonやAliexpress、秋月電子なので入手可能です。

ライブラリは、以下を使います。
github.com

Arduino IDE

Arduino IDE(Ver.1系で確認)では上記のGithubからダウンロードしたライブラリをマイドキュメント内のArduino\libraries内に保存することで利用しています。

C:\Users\***\ドキュメント\Arduino\libraries\DFPlayer_Mini_Mp3

Arduino IDE(Ver.1系で確認)ではライブラリマネージャからもインストールできるようですが、これらはすべて使えないと言われています。

(次に紹介するLink内で言及されています)

Platform IO

Platform IOではプロジェクトフォルダ内のlibフォルダに保存します。

Project_Folder/
├── platformio.ini
├── src/
│   └── main.cpp
├── lib/
│   └── DFPlayer_Custom_Lib/  <----- このフォルダにライブラリを格納(platformio.iniで指定)
│       ├── DFPlayer_Mini_Mp3.cpp
│       └── DFPlayer_Mini_Mp3.h
├── include/
└── test/

またplatform.iniは以下のように記述します。
ソフトウェアシリアルと外部ライブラリの設定をしています。
以下はESP32-s3の例です。

[env:esp32-s3-devkitc-1]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 9600
lib_deps = 
	plerup/EspSoftwareSerial@^8.2.0
lib_extra_dirs = lib

基本的な使いかた

基本の基本は、以下などを参照すれば使えると思います。
zenn.dev

配線は以下のようになりますが、RX/TXには抵抗(1~5kΩ程度)を挟むようにします。

Arduino DFP
5V VCC
D10(任意のIO) RX(抵抗を挟む)
D11(任意のIO) TX(抵抗を挟む)
GND GND

SPK_1SPK_2にスピーカーやイヤホンを接続します。

音声ファイルはMicro SDカードにmp3というフォルダを作り、そのなかに0001.mp30002.mp3のようなファイル名にして保存します。
正確には4桁の数字の後ろに任意の文字列があっても大丈夫なようです。
SdカードのフォーマットはFAT32にしておくのが無難です。

一番基本的なコードは以下のようになります。
mp3モジュールとはソフトウェアシリアルで通信しますが、いくつか試した範囲では2~13のdigitalピンであればどれでも使えそうでした。
他にシリアルを使っていたりすると問題が発生する可能性があり、もしうまくいかないときは違うピンで試してみると動く場合があります。

これで、2秒ごとに3種類のmp3を順番に再生します。
このとき、mp3が2秒以上あれば途中で強制的に次のトラックへ切り替わります。

#include "SoftwareSerial.h"
#include "DFPlayer_Mini_Mp3.h"

#define RX_PIN 10
#define TX_PIN 11

SoftwareSerial mySerial(RX_PIN, TX_PIN);

void setup () 
{
    delay(2000); //モジュール起動の待機時間
    mySerial.begin (9600);
    mp3_set_serial (mySerial); //set softwareSerial for DFPlayer-mini mp3 module
    mp3_set_volume (30);
}

void loop () 
{
    mp3_play (1); //(0001.mp3)を再生
    delay (2000);
    mp3_play (2); //(0002.mp3)を再生
    delay (2000);
    mp3_play (3); //(0003.mp3)を再生
    delay (2000);
}

初期化の中で音量も設定できますが、音量設定は感度が高いのでなかなかちょうどいい音量にするのは難しい場合があるように思います。
また、音量設定を30より大きく設定しているサンプルコードがありますが、ライブラリのコメントには最大30と記載があります。

ハードウェアシリアルを使う場合

ソフトウェアシリアルを他の機能に使いたい場合は、ハードウェアシリアルも使うことができます

HardwareSerial MP3Serial(1); // UART1を使用するHardwareSerialオブジェクトを作成

void mp3_hw_setup()
{
    // PCとのデバッグ用シリアル通信 (USB CDC) を開始
    while (!Serial)
    {
        delay(10);
    }

    // DFPlayer Miniは通常9600bpsで動作する
    MP3Serial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);

    // DFPlayerライブラリにシリアルポートを設定
    mp3_set_serial(MP3Serial);    // DFPlayer Miniとの通信に使用するシリアルポート
    mp3_set_debug_serial(Serial); // ライブラリのデバッグメッセージをUSBシリアルに出力

    delay(2000); // DFPlayerモジュールの起動を待つ

    // DFPlayer Miniの初期化
    mp3_set_volume(30); // 音量を設定 (0-30の範囲)
    delay(100);
}

初期化した後は、ソフトウェアシリアルの場合と同様に利用可能です。

ループ再生

次に、mp3が終わりまで再生されたら繰り返す、という形にしたい場合はループの設定があります。

void loop () 
{
    mp3_play(1);
    mp3_single_loop(true); //ループ設定
    delay(1000); // mp3_single_loopが反映されるまで時間がかかる
    while(1){}
}

しかし、複数のモジュールを使っていたところ、この機能がうまく動かないものがあることがわかりました。

右側がOKで左側がNGです(この機能のみに関して)。
ちなみにOK品は、先のAmazonのリンク品です。(ただし、私が購入したのは3年ほど前なので今も同じ仕様のものが送られてくるかどうかはわかりません。)

ループがうまく動かない場合はmp3が再生中であるかどうか?を取得する機能がありますのでこれを使います。
そのためにはBUSYピンの状態を読み取ります。
再生中はLOWになり、停止(終了)するとHIGHになります。
この機能を使うと、ループ処理は以下のようになります。

#include "SoftwareSerial.h"
#include "DFPlayer_Mini_Mp3.h"

#define RX_PIN 10
#define TX_PIN 11
#define BUSY_PIN 9
SoftwareSerial mySerial(RX_PIN, TX_PIN);

void setup ()
{
  delay(2000);
  pinMode(BUSY_PIN, INPUT_PULLUP);
  mySerial.begin (9600);

  mp3_set_serial (mySerial);
  mp3_set_volume (30);
}

void loop ()
{
  if (digitalRead(MP3_BUSY_PIN) == HIGH)
  {
    mp3_play();
    delay (1000);
  }
}

ランダム再生

ランダムは関数があるのでこれを使います。
BUSYと組み合わせると以下のようになります。
このとき、ファイルがいくつあってもうまくファイル数を一応取得できるようです。
ただ、気のせいかランダムが偏りがあるような気がします。
もしかしたら、本当にランダムにしたいならArduino組み込みのランダム関数を使ったほうがいいかもしれません。

  if (digitalRead(BUSY_PIN) == HIGH)
  {
    mp3_random_play();
    delay (1000);
  }

音声の停止

組み込み関数があります。

mp3_stop();

次の曲へ任意のタイミングで進める

ボタン押下などで次の曲へ行きたい場合は、プルアップとタクトスイッチなどを組み合わせて

mp3_play(1);

の引数を増やしてやるなどの方法を取ると実現可能です。

まとめ

電子工作で音声を流したいときに便利に使えますが、モジュールの仕様が若干異なるものがあるようなので注意が必要です。
出力は、スピーカのほかイヤホンなども使えますので、オリジナルの目覚まし時計やmp3プレイヤーなどといったアプリが作成できます。