距離センサとDFPlayerMiniを組み合わせて、センサにモノを近づけた時にカウントしつつ音を鳴らす装置を作成する

# 目的
距離センサとDFPlayerMiniを組み合わせて、センサにモノを近づけた時にカウントしつつ音を鳴らす装置を作成した際の備忘録です。

# 準備
Arduino Uno
[DFPlayerMini](https://www.amazon.co.jp/gp/product/B01D1D0E7Q/ref=ppx_yo_dt_b_asin_title_o06__o00_s01?ie=UTF8&psc=1)
[VL53L0X Time-of-Flight 距離センサモジュール](https://www.switch-science.com/catalog/2869/)
[MAX7219 8×8ドットマトリックスモジュール](http://e-structshop.com/item/mlk0001/)

マイクロSDカードへ音楽ファイルを保存します。（[ArduinoにDFPlayerMiniを繋いでmp3音楽再生をする](https://qiita.com/seigot/items/719758b66b84698d1f0d)の通り準備します）

# 回路図
以下をジャンパーピンで接続すれば良い。

Arduino側　- 距離センサ側
SCL - SCL
SDA - SDA
VCC - VCC
GND - GND

DFPlayerMiniの接続は、[ArduinoにDFPlayerMiniを繋いでmp3音楽再生をする](https://qiita.com/seigot/items/719758b66b84698d1f0d)を参照します。

Arduino - Max7219
PIN10 - CLK
PIN9 - CS
PIN8 - DIN
GND - GND
5V - VCC

# コード

```
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUSY_PINNO 7

#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;

SoftwareSerial mySoftwareSerial(10, 11); // (TX, RX)
//SoftwareSerial mySoftwareSerial(3, 2); // (TX, RX)
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

 unsigned char i;
 unsigned char j; 
 int g_cnt = 0;
/*port definition*/
int Max7219_pinCLK = 6;
int Max7219_pinCS = 5;
int Max7219_pinDIN = 4;

unsigned char disp1[38][8]={
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
{0x10,0x18,0x14,0x10,0x10,0x10,0x10,0x10},//1
{0x7E,0x2,0x2,0x7E,0x40,0x40,0x40,0x7E},//2
{0x3E,0x2,0x2,0x3E,0x2,0x2,0x3E,0x0},//3
{0x8,0x18,0x28,0x48,0xFE,0x8,0x8,0x8},//4
{0x3C,0x20,0x20,0x3C,0x4,0x4,0x3C,0x0},//5
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0},//6
{0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8},//7
{0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
{0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E},//9
{0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x0},//B
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x0},//C
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x0},//D
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
{0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30},//J
{0x0,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0},//N
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x0,0x1E,0x20,0x20,0x3E,0x2,0x2,0x3C},//S
{0x0,0x3E,0x8,0x8,0x8,0x8,0x8,0x8},//T
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
{0x0,0x49,0x49,0x49,0x49,0x2A,0x1C,0x0},//W
{0x0,0x41,0x22,0x14,0x8,0x14,0x22,0x41},//X
{0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8},//Y
{0x0,0x7F,0x2,0x4,0x8,0x10,0x20,0x7F},//Z
{0x8,0x7F,0x49,0x49,0x7F,0x8,0x8,0x8},//Chinese character
{0xFE,0xBA,0x92,0xBA,0x92,0x9A,0xBA,0xFE},//Chinese character
};


void Write_Max7219_byte(unsigned char DATA) 
{   
            unsigned char i;
      digitalWrite(Max7219_pinCS,LOW);    
      for(i=8;i>=1;i--)
          {     
             digitalWrite(Max7219_pinCLK,LOW);
             digitalWrite(Max7219_pinDIN,DATA&0x80);//Obtain the MSB of the data
             DATA = DATA<<1;
             digitalWrite(Max7219_pinCLK,HIGH);
           }                                 
}


void Write_Max7219(unsigned char address,unsigned char dat)
{
        digitalWrite(Max7219_pinCS,LOW);
        Write_Max7219_byte(address);           //
        Write_Max7219_byte(dat);               //
        digitalWrite(Max7219_pinCS,HIGH);
}

void Init_MAX7219(void)
{
 Write_Max7219(0x09, 0x00);       //decode: BCD
 Write_Max7219(0x0a, 0x03);       //Brightness
 Write_Max7219(0x0b, 0x07);       //
 Write_Max7219(0x0c, 0x01);       //
 Write_Max7219(0x0f, 0x00);       //
}

void setup()
{
  Serial.begin(9600);  

  // software serial init
  mySoftwareSerial.begin(9600);
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }

  // init DFMiniPlayer
  // BUSY_PINNO init
  pinMode(BUSY_PINNO, INPUT);

  // DFPlayer Init
  myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms  
  myDFPlayer.volume(25);  //Set volume value (0~30).
  // myDFPlayer.volumeUp(); //Volume Up
  // myDFPlayer.volumeDown(); //Volume Down  
  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);    
  //myDFPlayer.play(1);  //Play the first mp3

  // init distance sensor
  Wire.begin();

  sensor.setTimeout(500);
  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
  }

  // Start continuous back-to-back mode (take readings as
  // fast as possible).  To use continuous timed mode
  // instead, provide a desired inter-measurement period in
  // ms (e.g. sensor.startContinuous(100)).
  sensor.startContinuous();

  // init DotMatrix Module
  pinMode(Max7219_pinCLK,OUTPUT);
  pinMode(Max7219_pinCS,OUTPUT);
  pinMode(Max7219_pinDIN,OUTPUT);
  delay(50);
  Init_MAX7219();

  for(i=1;i<9;i++) {
    Write_Max7219(i,disp1[g_cnt][i-1]);
  }
}

void PLAYBACK_MP3_MUSIC(void) {
  int isBusy = digitalRead(BUSY_PINNO); // 0:playing, 1:not playing (refer website)
  Serial.println(isBusy);
  //if (isBusy == 1) {
    myDFPlayer.next();  //Play next mp3 every 3 second.
  //}
}

void loop()
{
  int val;
  val = sensor.readRangeContinuousMillimeters();
  Serial.print(val);
  if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }

  Serial.println();

  if( val < 180 ) {
    PLAYBACK_MP3_MUSIC();
    g_cnt++;
    for(i=1;i<9;i++) {
      Write_Max7219(i,disp1[g_cnt][i-1]);
    }
    delay(2000);
  }
}
```

# テスト
モノを近づけた時にカウントしつつ音が再生されればOKです
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">モノを近づけると数をカウントしつつ音が再生される装置 <a href="https://t.co/kzLy2WxkRY">pic.twitter.com/kzLy2WxkRY</a></p>&mdash; st (@st17890027) <a href="https://twitter.com/st17890027/status/1212662493241196545?ref_src=twsrc%5Etfw">January 2, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">モノを近づけると数をカウントしつつ音が再生される装置2 <a href="https://t.co/nSPvvEv7Jz">pic.twitter.com/nSPvvEv7Jz</a></p>&mdash; st (@st17890027) <a href="https://twitter.com/st17890027/status/1212724309208092673?ref_src=twsrc%5Etfw">January 2, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

飛んできたピンポン玉を距離センサで検知して、ドラクエのレベルが上がった音を再生することも可能。
距離センサのしきい値(=val)を最適な値に調整すると良いです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ピンポン玉がゴミ箱に入ったらレベルが上がる装置 <a href="https://t.co/6YNMA6evx0">pic.twitter.com/6YNMA6evx0</a></p>&mdash; st (@st17890027) <a href="https://twitter.com/st17890027/status/1213878861567381506?ref_src=twsrc%5Etfw">January 5, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# CodingError対策
DFPlayer Miniの電源(5V)は、電源から直接供給したほうがよさそうです
（arduinoからでは電流がたりない？）

https://stonez56.blogspot.com/2015/03/arduino-dfplayer-mini-mp3-module.html
>* Note: You have to separate DFPlayer Mini Module power from Arduino power
> or you will hear very loud noises (It took me two days to figure out this!)


# 参考
[DFPlayerMini](https://www.amazon.co.jp/gp/product/B01D1D0E7Q/ref=ppx_yo_dt_b_asin_title_o06__o00_s01?ie=UTF8&psc=1)
[VL53L0X Time-of-Flight 距離センサモジュール](https://www.switch-science.com/catalog/2869/)
[ArduinoにDFPlayerMiniを繋いでmp3音楽再生をする](https://qiita.com/seigot/items/719758b66b84698d1f0d)
[距離センサモジュールVL53L0Xをarduinoを使って距離を測る](https://qiita.com/seigot/items/95e34d685605f229b358)