こんにちは。Yukiです。
今回は、40円マイコンと100円モータードライバだけで、スピーカーから音声を流したいと思います。
この記事でやりたいこと
要は格安で音を鳴らしたいんですよ。たかだか1秒位の音声にDFPlayer使うのはバカバカしいです。
ということでやっていきましょうか。
この記事は誰向け?
なんか文章おかしいですが、この記事は下のような人に向きます。
- とにかく格安で音楽を再生したい
- かつ、1.5秒以下の音声
- DFPlayerとか使うのバカバカしい
費用がいっぱいあるのであれば、DFPlayerとか使ったほうが楽ですし、幸せな気はします。
マイコンの容量的な問題で1.5秒くらいが限界です。音質をさらに犠牲にすれば、もう少しいけます。
DFPlayerを使わない理由
というか最初はDFPlayer使っていたんですが、パチモノが原因なのか知らないですが、次のような現象に襲われました。
- 4日くらい通電しっぱなしにすると音が鳴らなくなる
- 定期的に電源を切ると、なぜかボリュームMAXになりうるさい
- 思っていたより消費電力が大きくてビビっている
どうせ鳴らしたい音声って2秒ちょいなので、それならばマイコン単体で鳴らせばよいのでは?となりました。
なんでモータードライバ?
音声用のアンプを使っても良かったんですが、色々とゲインとかめんどくさそうなので、モータードライバでやります。(出力がPWM波なので、やっていることはD級アンプと同じ理論のはずです)
あと、モータードライバー AM2837を使う理由ですが、正直ないです。12V耐圧もいらないですし、そもそも3A近く流せるモータードライバなので、ハイスペックすぎます。全然こいつじゃなくていい。
(たまたま家にあるモータードライバICがこいつくらいしかなかった)
使うもの
- 32ビットRISC-Vマイコン CH32V003J4M6
- モータードライバー AM2837
- 0.47uFコンデンサ (フィルムコンデンサ推奨)
- 0.1uF コンデンサ (フィルムコンデンサ推奨)
- 10uH インダクタ
AliExpress – セラコン いろんな種類が入っています。ここから買ってくると自分にいくらか還元されて嬉しい
その他には、CH32V003J4M6に書き込むための書き込み機(WCH-LinkEエミュレーター)が必要です。

↑過去の自分が書いている記事ですが、参考になるかと思います。
これくらいです。すべて秋月電子さんで手に入る部品にしました。全部合わせても200円いかないのではないでしょうか?
ちなみに、もっとケチりたい人は、AM1025EAとかでもいけると思います。(耐圧が低いだけだと思う)
さらにさらにケチりたい人は、30円くらいのオーディオアンプを使っても行けると思います。(ゲインとか増幅とかに注意してください。このあたりが面倒なので自分は使いません)
なお、音質にこだわりたい方は、フィルムコンデンサを推奨します。ただそんなに音質は良くないので、適当にセラコンでもいいとは思いますが。
まず音声の変換をする
今回使うCH32V003J4M6マイコンは、プログラムメモリサイズが16kBと非常に少ないです。(音声データを入れるとなると)
また、MP3形式は、マイコンとしては非常に使いにくい形式です。よって、今回はマイコンにとって使いやすい形式&音質を犠牲にして容量を減らす ことを行います。
- RAW unsigned 8bit
- サンプルレート:8000Hz
今回は、Audacityを使用します。
自分の環境に合わせて、適当にダウンロード&インストールしてください。

まず再生したい音声ファイルを開きます。ファイル→開く

開いたら、いらない部分などをトリミングしてください。(選択してdelキーで消せます)

次に、編集→環境設定を押します。

品質をどちらも8000Hzにします。(もしかしたらこれやらなくていいかも)

もしステレオの場合、トラック→ミックス→ステレオをモノラルへミックスダウンを選択します。(これもやらなくて良くなったかも)

編集が完了したら、ファイル→オーディオをエクスポートをクリック。

コンピューターにエクスポート

形式を そのほかの非圧縮ファイルにします。
オーディオオプションを モノラル・8000Hz・RAW(header-less)・Uninged 8bit PCMにしてエクスポートします。

こんな感じでファイルが生成されたかと思います。(後でコマンドで処理するので、打ちやすい名前に変更することをおすすめします。 例:Music.raw)

次に、コマンドを使い、先ほど作ったバイナリファイルを配列に変換させます。wslが入っていない場合、使えるようにインストールするか、BusyBox等を利用して行ってください。(Linuxを使える環境であれば大丈夫だと思います)
$ xxd -i Music.raw > music.hxxd -i でC言語の配列に変換してくれます。便利ですね。 Music.rawは入力ファイルです。
> music.h は標準出力だと文字数が大きくて見切れてしまうので、標準出力から別ファイルに出力していると思ってください。
ちなみに、WSLは/mnt/でPCのローカル領域(Windows側)にアクセスできます。今回はデスクトップにmusic.rawを保存したので、/mnt/c/users/ユーザー名/desktop/music.rawが保存先になります。
回路を作る

今回はこんな感じの回路にしました。どうやら出力はフィルタなしでも大丈夫らしいのですが、一応ローパスフィルタを通しています。(どうせ100均のスピーカーなので壊れてもそんなにですが)
また、0.1uFはそれぞれICの近くにおいてください。
ブレッドボードの参考例

ごちゃごちゃしていますね。すみません。一応こんな感じの配線でやりました。電源はニッケル水素電池3本(約4.3Vくらい)です。LEDはビジー端子につなげています。
プログラム (改変方法などの備忘録等も)
今回はGoogle Driveでの配布です。ダウンロードしてください。(プログラムかなり汚いです。すみみません)
MounRiver Studioで開きます。(その他でもできなくはないと思いますが、サポートしません)

File → Load

Browse… を選択して、ダウンロードしたプロジェクトを読み込んでください。
おそらくですが、CH32V003J4M6_MUSIC_Play.wvproj という名前だと思います。

読み込めたら、先ほど作ったmusic.hをコピーします。

Userフォルダの中にペーストします。(UserフォルダをクリックしてCtrl+V)
これでヘッダファイルが入れられました。

次に、追加したヘッダファイル(今回だとmusic.h)をダブルクリックで開きます。
先頭が、unsingned char ~~~~[]{
みたいになっていると思いますが、先頭にconstをつけます。(これでROMに保存される)

次にmain.cを開き、3行目くらいのところに、#include “~~~~~.h”とインクルードしてあげます。
(今回自分の場合だとmusic.h)

次に、#define FILE_NAME ~~~~~~ と #define FILE_NAME_LEN ~~~~~~を変えます。

#define FILE_NAME には unsigned char 〇〇[]{
の〇〇を入れます。 上の例だと music_raw に相当します。

#define FILE_NAME_LEN には music.h の一番下の方にある unsigned int ◯◯ = ~~~
の〇〇を入れます。 上の例だと music_raw_len です。
うまくいっていれば、コンパイルできるはずです。
コンパイルして書き込んでみてください。
(参考までに、ビルド(コンパイル)がF7 書き込みがF8)
簡単に解説
簡単に言うと、PWM波を出力してあげて、その波をモータードライバに入れているだけです。
アイドル時に極性を反転している理由として、BTL出力はPWMの相補出力を使うのですが、相補出力で0にしてしまうと、片方のピンは0Vに、もう片方が5Vになり、スピーカーに大電流が流れることになります。それは困るので、極性を一時的に反転させてどっちのピンも0Vにしています。
また、微弱ではありますが、どちらのピンも0Vにすることで待機時の電流を減らすことに成功しています。(待機時約5mA程度から2mA)
より待機電力を減らすには、スリープ機能などを使えば行ける気がしますが、疲れたのでこのへんでやめておきます。(気力があれば今後作ろうかなと思います)
動作時の様子
動画を見てもらえばわかると思いますが、音声再生時のポップ音などはほぼないです。また、電源接続時のポップ音もほぼしません。
「お金が足りないよ~」
疑似正弦波を入れたときの様子
今回、1度ずつ変化するパターンを入れておき、波形を出力してみました。

見えにくくて申し訳ありません。
黄色が出力波形です。基本波長は262Hzでおおよそあっているようです。
赤い線がFFTをした波形で、基本波長の横に小さい山があるかと思います。波形自体は歪んでいますが、188kHzのPWM波にしては良いのではないでしょうか。
(波形に関して詳しいこと知らないので、これ以上書けないです…)
謝辞

こちらのサイトから音声をお借りしました。音枝 優日 様 ありがとうございました。


コメント