- 最終更新日
- 記事公開日
ESP32で特定の音を検知(サウンドセンサー)
今回はESP32-DevKitCを使って、特定の音を検知するサンプルコードを紹介します。
「音に反応して、動く装置を作りたい」
「特定の音だけに反応するプログラムを組みたい」
という方、ぜひ参考にしてみて下さい。
「音の大きさ」と「音の長さ」が条件に一致した場合のみ、LEDが点灯します。
目次
使用パーツ
配線・回路図
プログラム
// サウンドセンサーに使用する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つの要素を使用しています。
- 音の大きさ(感度)
- 音の長さ
音の大きさ(感度)
感度は、サウンドセンサー上にあるボリュームで調整します。
- 左に回す → 感度が下がる(大きい音しか拾わない)
- 右に回す → 感度が上がる(小さい音も拾う)
※「开关指示」のLEDが消えないように調整してください。
「音が聞こえた」という事だけを検知する場合は、この感度だけでも十分です。
しかし感度だけでは、特定の音を検知することは難しくなります。
例えば、感度では小さい音だけを検知することはできません(感度を上げると、大きい音も拾ってしまう)
音の長さ
音が鳴ると、そのタイミングを記録。
その後、1秒以上無音が続いたタイミングを音の終わりとして判定し、一つの音の長さを計測しています。
これで特定の音だけを見分ける精度を高めています。
※シリアルモニタに一音の長さ(us)が出力されます。
もちろん、同じ長さの音であれば誤検知してしまうのですが、検知範囲を狭く設定することで、さらに精度を上げることが可能です。
注意点
同じ音でも、距離が遠くなれば、サウンドセンサーから送られてくるデータは変わってきます。
よって、動くモノの音を検知するのは難しいです。
特定の音と一致させる場合には、設置する場所を固定しておく必要があります。
※追記※
誤検知を減らすために、「音の長さ」だけでなく「サウンドセンサからのパルスがHIGHのときの総時間を」も検知対象に加えました↓