最終更新日
記事公開日

ESP32で特定の音を検知(サウンドセンサー)

今回はESP32-DevKitCを使って、特定の音を検知するサンプルコードを紹介します。

「音に反応して、動く装置を作りたい」

「特定の音だけに反応するプログラムを組みたい」

という方、ぜひ参考にしてみて下さい。

「音の大きさ」と「音の長さ」が条件に一致した場合のみ、LEDが点灯します。

目次

使用パーツ

配線・回路図

ESP32とサウンドセンサーの配線・回路図
ESP32とサウンドセンサーの配線写真

プログラム

// サウンドセンサーに使用するPin
int sensor_pin = 15;

// 音検知を示すLEDに使用するPin
int led_pin = 19;

void setup() {

  // センサーに使用するPinを入力に設定
  pinMode(sensor_pin, INPUT);

  // LEDに使用するPinを出力に設定
  pinMode(led_pin, OUTPUT);

  // シリアルモニタの通信速度
  Serial.begin(115200);

}

// 稼働時間
unsigned long uptime;

// 音の始まりから終わりまでの総時間
int high_time;

// 無音時間
int low_time;

// 音の終わりと判断するための無音時間(us)
int limit_time = 1000000;

// 音が鳴り続いていることを示すフラグ
int high_state = 0;

// 無音を継続しているときのフラグ
int low_state = 0;

// 音の起点となった時間を記録
int rise_point;

// 音の終点となりそうな時間を記録
int fall_point;

// センサーの値
int sensor_val;

void loop() {

  // マイコンの稼働時間(us)
  uptime = micros();

  // センサーの値を読み取る
  sensor_val =  digitalRead(sensor_pin);

  // 音が鳴っている(センサーの値がHIGH)
  if (sensor_val == 1) {

    // 無音信号の継続フラグ:OFF
    low_state = 0;

    // 音の起点(信号の立ち上がり)の場合
    if (high_state == 0) {

      // 音の起点となる時間を記録
      rise_point = uptime;

      // 有音信号の継続フラグ:ON
      high_state = 1;

    }
    
 // 音が鳴っていない(センサーの値がLOW)
  } else {

    // 無音の起点(信号の立ち下がり)の場合
    if (low_state == 0) {

      // 無音の起点となる時間を記録
      fall_point = uptime;

      // 無音信号の継続フラグ:ON
      low_state = 1;

    // 無音が継続されている(信号の途中)場合
    } else {

      // 無音時間を計測(稼働時間 - 無音の起点時間)
      low_time = uptime - fall_point;

      // 音の終わりと判断した場合
      if (low_time > limit_time) {

        // ずっと無音状態だったときは処理しない
        if (high_state) {

          // 音の始まりから終わりまでの総時間を算出
          high_time = uptime - rise_point - limit_time;

          // 音の長さが範囲内のときにLEDを点灯
          if (high_time > 3000000 && high_time < 4000000) {
            
            Serial.print(high_time);
            Serial.println(" hit!");
            digitalWrite(led_pin,HIGH);
            
          } else {
            
            Serial.println(high_time);
            digitalWrite(led_pin,LOW);
            
          }

          // 総時間をリセット
          high_time = 0;
          
        }

        // 一つの音の読み取り終了
        low_time = 0;
        rise_point = 0;
        high_state = 0;
        fall_point = uptime;
        low_state = 0;
        
      }
    }
  }
}

技術解説

さらに詳しく解説していきます。

サウンドセンサーについて

サウンドセンサーは、基板上のマイクで「音の強さ」を読み取っています。

音を検知すると「HIGH」、音がない場合は「LOW」を出力します。

大きい音のときはパルス幅が広く、小さい音のときはパルス幅が狭いです。

サウンドセンサのパルス信号

※簡略化した波形の例です。実際にはもっと細かなパルスの組み合わせで構成されています。

音の解析・特定について

サウンドセンサーからの信号を繰り返し読み取り、音データの取り込みを行っています。

音の特定には、以下の2つの要素を使用しています。

  1. 音の大きさ(感度)
  2. 音の長さ

音の大きさ(感度)

感度は、サウンドセンサー上にあるボリュームで調整します。

  • 左に回す → 感度が下がる(大きい音しか拾わない)
  • 右に回す → 感度が上がる(小さい音も拾う)

※「开关指示」のLEDが消えないように調整してください。

サウンドセンサの感度調整

「音が聞こえた」という事だけを検知する場合は、この感度だけでも十分です。

しかし感度だけでは、特定の音を検知することは難しくなります。

例えば、感度では小さい音だけを検知することはできません(感度を上げると、大きい音も拾ってしまう)

音の長さ

音が鳴ると、そのタイミングを記録。

その後、1秒以上無音が続いたタイミングを音の終わりとして判定し、一つの音の長さを計測しています。

これで特定の音だけを見分ける精度を高めています。

ArduinoIDEのシリアルモニタ出力画面

※シリアルモニタに一音の長さ(us)が出力されます。

もちろん、同じ長さの音であれば誤検知してしまうのですが、検知範囲を狭く設定することで、さらに精度を上げることが可能です。

注意点

同じ音でも、距離が遠くなれば、サウンドセンサーから送られてくるデータは変わってきます。

よって、動くモノの音を検知するのは難しいです。

特定の音と一致させる場合には、設置する場所を固定しておく必要があります。

※追記※

誤検知を減らすために、「音の長さ」だけでなく「サウンドセンサからのパルスがHIGHのときの総時間を」も検知対象に加えました↓

【ESP32】特定の音が鳴ったらLINEで通知する

この記事のURLをコピー

メールアドレスは公開されませんのでご安心ください。また、* が付いている欄は必須項目となります。

内容に問題なければ、下記の「コメントを送信する」ボタンを押してください。

関連情報

運営者プロフィール
コダマ

職業はIT系フリーランス。過去、電子配線業務の経験が10年ある為、はんだづけも得意です。宮崎県在住、30代・2児の父親。

カテゴリー