Raspberry Pi PicoとDFPlayerで、起動すると自動でランダム再生を開始する装置を作った

我が家で所有している自家用車は、カーオーディオが標準のものになっています。
そのため再生できるのは、AM/FM/CDと外部入力(AUX)のみ、という本当に最低限の機能しかありません。
そんな車で、

* エンジンを入れたら自動的に再生が始まって、
* 大量の音楽データが再生出来て、
* ランダムに再生される

というのを何とか実現できなかと思い悩んで、Raspberry Pi PicoとDFPlayerを組み合わせることに思い至った件について記事を作成しました。

# 装置の概要

Raspberry Pi PicoからDFPlayerを制御し、SDカードに保存したMP3音声をAUXに出力します。
Picoの電源はシガーソケットからUSBに変換して得るものとします。
エンジンが入ると自動でPicoに給電→起動し、そのあとはひたすらランダムでMP3を再生することを目指します。

# 必ず用意するもの

1. Raspberry Pi Pico
1. [DFPlayer mini](https://akizukidenshi.com/catalog/g/g112544/)
1. [3.5mmステレオミニジャックDIP化キット](https://akizukidenshi.com/catalog/g/g105363/)
※リンクはいずれも秋月電子の商品ページです
1. 1秒程度の長さの、無音のMP3ファイル
（ネットで検索すれば作成されてる方は多数いらっしゃいますのでリンクは割愛）

なおDFPlayerに関しての使い方について、基本的な説明は割愛させていただきます。

# ソースコード

早速ですがPicoに投入するソースファイルを記載します。
DFPlayerに必要なシリアルデータを配列で定義して送信するだけの、非常にシンプルな内容です。
初期化すら必要なく、最初からランダム再生の命令を送信します。
ただこれだけなのですが、いくつか注意すべき要素があるので後述します。
```python:main.py
import machine

# UART初期設定（UART番号,クロックレート,TXピン,RXピン）
# ※RPiのTX/RXとDFPlayerのTX/RXはテレコになることに注意
uart = machine.UART(0,baudrate=9600,tx = machine.Pin(16),rx = machine.Pin(17))

# ランダム再生
sdata = bytearray([0x7E,0xFF,0x06,0x18,0x00,0x00,0x00,0xEF])

# シリアルデータの送信
uart.write(sdata)
```

# 注意すべきポイント
## UARTポートの設定

PicoからDFPlayerにシリアルデータを送信する際、Picoにあらかじめ準備されているUARTポートを使用します。
![Pico.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833373/6dc372b1-547e-4b9d-156b-5689ee391fbe.png)
具体的には以下のUARTの組み合わせのいずれかを選択する必要があります。
* GP0と1のUART0 TX/RX
* GP4と5のUART1 TX/RX
* GP8と9のUART1 TX/RX
* GP12と13のUART0 TX/RX
* GP16と17のUART0 TX/RX

機能的にはどのUARTを選んでもよいのですが、物理的な配線の都合から「GP16と17のUART0 TX/RX」を選択します。
UARTからDFPlayerのRX/TXに配線をするわけですが、ここ以外の場所からでは、どうしても配線が空中で交差してしまうからです。
なおこのUARTを使う場合、GNDは23番PINから引き回すようにしてください。
ほかのGNDから引き回すとうまく動きませんでした。

## UART RXとTX
PicoのUART RXはDFPlayerのTXと、PicoのTXはDFPlayerのRXとテレコになるように配線します。

## DFPlayerと3.5mmステレオミニジャック
3.5mmステレオミニジャックとの接続は、DFPlayerの「DAC_R」「DAC_L」から行います。
3.5mmステレオミニジャックの中央の2本のPINは両方ともGNDとなっています。
DFPlayerのGNDから接続する形になりますが、念のためハンダを多く持って両方のGNDとくっつくように配線しました。

## 回路図
以下は、雑ですが回路図となります。
Fritzingの使い方を全然知らないのでPINの名前がちゃんと編集出来ておらず申し訳ないですが、PINの場所のイメージをしていただけたらいいなと思います。
![Untitled Sketch_回路図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833373/db4aec83-31f6-c9de-5cc8-a60c38f5c746.png)

# SDカードへのデータ保存について
SDカードにMP3を保存する際ですが、まずファイル名はすべて数字の連番のみにしておくのが無難です。
そして詳細は後述しますが、SDカードにMP3を保存する順番について、あらかじめ用意いただいた「無音のMP3」を**必ず最初に保存してください**。
DFPlayerでランダム再生を指示するとき、1曲目に再生されるのは必ず「最初にデバイスに保存されたMP3」が選択される仕様のためです。
2曲目以降はランダムに曲が選択されるのですが、1曲目だけはどうしようもないので無音のMP3を再生させるという方法でこの問題を回避しています。

# 引用

[秋月電子の商品ページ](https://akizukidenshi.com/catalog/g/g112544/)に掲載されている[DFPlayerのデータシート](https://akizukidenshi.com/goodsaffix/DFPlayer_Mini_Manual.pdf)はわかりやすくてよいのですが、このデータシートには、今回使用するランダム再生のことは記載されていません。
ランダム再生についての情報は、メーカーである[DFROBOT](https://www.dfrobot.com/)の[販売ページ](https://www.dfrobot.com/product-1121.html)には記載がなくて、[Githubのリポジトリ](https://github.com/DFRobot/DFRobotDFPlayerMini)に情報を求める必要がありました。

https://github.com/DFRobot/DFRobotDFPlayerMini

[docディレクトリにあったPDF](https://github.com/DFRobot/DFRobotDFPlayerMini/blob/master/doc/FN-M16P%2BEmbedded%2BMP3%2BAudio%2BModule%2BDatasheet.pdf)に、かなりの詳細が書かれています。
これによると、"Set random playback"を実行するためのコマンドは"0x18"であることがわかります。
詳細は3.6.12節に書かれてありまして、`7E FF 06 18 00 00 00 FE E3 EF`を渡せばよさそうです。
なおこの項目には非常に重要なことが書かれております。

1). This command is used to randomly play sound files in the storage device according to physical sequence and no matter if there is a folder or not in the device. The first sound file that is conducted to be played is the first one in the device.
**最初のサウンドファイルは、デバイス内の最初のサウンドファイルです** とあります。
これが何を意味するかというと、ランダム再生を指示しても、デバイス内に一番最初に保存されたファイルが必ず1曲目に再生されるということです。