『部屋に雑音を発生させる機械』を自作する(MP3再生モジュール DFPlayer Mini を単体で鳴らす)

先日こういうまとめが話題になっていましたね。

togetter.com

ざっくりいうと

・ホワイトノイズを発生させるための機械がある
・部屋に置いておくと騒音がマスクされて気にならなくなる

という内容です。ホホウ……、と思ったのですが紹介されてる機械がけっこう高価でした。

なので自作することにしました。

ブレッドボードで作る

2つやり方をご紹介したいのですが、まずは簡単な方からいきましょう。

完成品はこんな感じです。

youtu.be

材料

f:id:slideglide:20180201222211p:plain
・何らかの5V電源(モバイルバッテリ(ブレッドボードに挿せるようにしておく→参考)または乾電池3本、など)
・スピーカー(秋月で100円で買えるやつを使用
DFPlayer Mini(MP3再生モジュール)
ブレッドボード
マイクロSDカード
タクトスイッチ×2
ジャンパ線

本物のノイズ発生器はホワイトノイズをジェネレートしているようですが、今回は事前に用意したMP3を再生することにします。(なのでノイズ再生機です)
ファイルを入れ替えれば普通にMP3プレーヤーにもなります。

今回のキモはMP3再生モジュールのDFPlayer Miniです。300円くらいで買えます。3Wのアンプ内蔵なのでスピーカーを直結可能。2018年2月現在、電子工作で音声ファイルを再生するならこの1択でしょう。

マニュアルはオフィシャルのWikiで見られます
使用例をネットで調べるとArduinoで制御する方法がよく紹介されているのですが、実は単体でも鳴らせるので、今回はそのやり方をご紹介します。

配線する

Wikiには3つほど接続方法が載っていますが、今回使うのはこれです。

f:id:slideglide:20180201221743j:plain

実際に配線してみましょう。

f:id:slideglide:20180201222237p:plain
f:id:slideglide:20180201221906p:plain
※電池3本の絵がなかったので2本の絵になっていますが、実際は3本がいいのではと思います。ただ動作電圧3.3V以上なのでアルカリ電池2本でもギリギリいけるかも?(試してない)

部品点数も少なくて簡単ですね。タクトスイッチは向きをまちがえると常時結線状態になってしまうので注意しましょう。図でいうと左右方向に足がくるようにします。あと足は「く」の字に曲がっているのでペンチか何かで伸ばさないと刺さらないかも。
この時点ではまだ音は出ません。

音を入れる

いったん電源を抜いて、SDカードをPCに挿してMP3を入れましょう。
じつは僕は以前より、作業に集中したい時にPCで雨音を流していました。今回もホワイトノイズではなく環境音を入れることにします。(こんなもの作らなくてもPCで再生すれば済むのがばれましたね!)

もちろんホワイトノイズを入れてもOK。
雨音のデータは今回はここのものを使用しました。短いので別のを探してもいいかも。
ノイズ系はここにたくさんあります。雨音のもうちょっと長いやつも少しある。

音声はMP3形式で、マイクロSDカードに入れます。

・「mp3」フォルダを作って
・0000xxxxx.mp3、0001xxxxx.mp3という感じで連番で始まるファイル名で格納(xxxx部分は英数字ならなんでもよい)

というのが正式な置き方のようです。僕の場合はダウンロードしたファイル名のまま直接ルートにおいても再生できました。

再生してみる

SDカードをDFPlayerに入れて、ふたたび電源を挿します。
これでノイズ再生機の完成です!このままだと武骨すぎるので

f:id:slideglide:20180201234842p:plain

適当な入れ物につっこんでもいいですね。写真は綿棒が入っていた容器です。ジャストサイズ。

操作方法は、

上のボタン … 再生開始、前の音へ
下のボタン … 次の音へ
上のボタン長押し … 音量UP
下のボタン長押し … 音量DOWN

です。
スピーカーも小さいし決して音はよくないので実用性は微妙ですが、とりあえず「9000円する機械の代用品を数百円程度でDIYできた」という満足感は十分に得られます。

もっと凝る

人間やはり一度着手すると凝り始めてしまうもので、もうちょっと機能的なものも作ってみました。

www.youtube.com

ケース(さっきの綿棒の容器です)に入って見ばえや携帯性が向上し、電源もACアダプタから取れるようになりました。さらにチルトスイッチ(角度でONになるスイッチ)を組み込んだので、逆さに置くと音が止まります。あと前回使用時に鳴らした音の種類や、音量などを記憶するようにしました。普通にいいものができた気がします。

f:id:slideglide:20180201224903p:plain

ひとつめの作例ではDFPlayerを単体で使いましたが、チルトスイッチの接続や前回ステータス記憶のため、今回はArduino Nanoからシリアルで制御しています。
この場合も、接続方法、サンプルコードともにWikiに丁寧に書いてあるので見てみましょう。

回路はArduinoが増えたぶん若干配線が増えますが、それでもかなりシンプルです。

f:id:slideglide:20180201231950p:plain

コードも一応載せておきます。

#include "SoftwareSerial.h"
#include "EEPROM.h"
#include "DFRobotDFPlayerMini.h"

#define NEXT_BTN 9
#define PLAY_SW 6
#define VOL_UP_BTN 8
#define VOL_DOWN_BTN 7
#define VOL_ADDRESS 0
#define FILE_NO_ADDRESS 1

SoftwareSerial softwareSerial(10, 11);
DFRobotDFPlayerMini dfPlayer;
boolean isPlaying;

void setup() 
{
  Serial.begin(115200);
  softwareSerial.begin(9600);
  
  Serial.println();
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  
  if (!dfPlayer.begin(softwareSerial)) {
    Serial.println(F("Unable to begin:"));
    while(true);
  }  
  Serial.println(F("DFPlayer Mini online."));
  
  pinMode(NEXT_BTN,INPUT_PULLUP); //音切り替えボタン
  pinMode(PLAY_SW,INPUT_PULLUP); //チルトスイッチ
  pinMode(VOL_UP_BTN,INPUT_PULLUP); //ボリュームUP
  pinMode(VOL_DOWN_BTN,INPUT_PULLUP); //ボリュームDOWN
  dfPlayer.volume(EEPROM.read(VOL_ADDRESS));
  isPlaying == false;
}

void loop(){
  int cnt;
  
  if(digitalRead(PLAY_SW) == LOW){
    if(isPlaying == false){
      digitalWrite(13, HIGH);
      dfPlayer.loop(EEPROM.read(FILE_NO_ADDRESS));
      Serial.println("start");
      isPlaying = true;
      delay(500);
      digitalWrite(13, LOW);
    } else {
      
      if(digitalRead(NEXT_BTN) == LOW){
        Serial.println("next");
        digitalWrite(13, HIGH);
        dfPlayer.next();
        dfPlayer.loop(dfPlayer.readCurrentFileNumber());
        EEPROM.update(FILE_NO_ADDRESS,dfPlayer.readCurrentFileNumber());
        delay(500);
        digitalWrite(13, LOW);
        
      } else if(digitalRead(VOL_UP_BTN) == LOW){
        Serial.println("volUp");
        digitalWrite(13, HIGH);
        dfPlayer.volumeUp();
        EEPROM.update(VOL_ADDRESS,dfPlayer.readVolume());
        delay(500);
        digitalWrite(13, LOW);
        
      } else if(digitalRead(VOL_DOWN_BTN) == LOW){
        Serial.println("volDown");
        digitalWrite(13, HIGH);
        dfPlayer.volumeDown();
        EEPROM.update(VOL_ADDRESS,dfPlayer.readVolume());
        delay(500);
        digitalWrite(13, LOW);
      } else {
        
        delay(100);
      }
    }
  } else if(digitalRead(PLAY_SW) == HIGH && isPlaying == true){ 
    //チャタリング防止
    for(int i=0;i<10;i++){
      delay(10);
      if(digitalRead(PLAY_SW) == HIGH){
        cnt++;
      }
    }
      Serial.println(cnt);
    if(cnt > 9){
      digitalWrite(13, HIGH);
      dfPlayer.stop();
      Serial.println("stop");
      isPlaying = false;
      delay(500);
      digitalWrite(13, LOW);
    }
  }

}

専用ライブラリを使用しているので、Arduino開発環境のライブラリマネージャから「DFRobotDFPlayerMini by DFRobot」をインストールしておく必要があります。(Sketch>Include library>Manage libraries...から開けます)

ライブラリがよくできているのでコードもかなりシンプルに書けます。(ちょっと長くなってるのはチルトスイッチのチャタリング対策だったりデバッグコードの出力だったりのせいです)

ちなみに再生中かどうかはreadState()という関数でも調べられるようなのですが、再生中に実行すると音が一瞬途切れるのと、返ってくるステータスコードの意味がマニュアルに書いてなくて不明なため、isPlayingという変数で独自管理しています。

あと完成してから気づいたのですが、「ひっくり返して音を止める」という仕様にもかかわらず、上面にスイッチをつけてしまいました。

f:id:slideglide:20180201152507j:plain

ひっくり返している間はボタンが効かないようなコードになっているのはそのためです。

おわりに

どうせMP3を聴くならPCのほうがいい音が出るし手間も少ないです。あと、うちにもあるGoogle Homeでもホワイトノイズが流せるらしいです。
しかしDIYの核心は実用ではなく「俺がこれを作った」という達成感です。達成感ハンターの皆さんはぜひ作ってみるべきでしょう。

あと今回はやりませんでしたが、MP3を使わずホワイトノイズをArduinoで合成して鳴らすこともできると思います。その場合DFPlayerは不要ですが別途アンプを用意する必要があります。達成感ハンター・エキスパートクラスの方はぜひ挑戦してください。