あなたが実際に望むのは、音の強さを測定することです。これは
あなたが読んだサンプルを単に平均化するよりもはるかに関わっています。私
数週間前にこれを正確に行うプログラムを書いています。
音の強さを測定し、その測定値を
シリアルポート。それはあなたがかもしれないかなり短いプログラム(43行のコード)です
あなたのニーズに適応することができるので、私は今GitHubの要点としてそれを共有しています:
sound-meter.ino
これをリンク専用の回答にしないために、私は
プログラムの内部の働き、そして音を測定する理論
Arduinoでの強さ。しかし、まずここに免責条項を入れておきます。
「実際の」騒音レベルメーターは、
いくつかの規格では、絶対レベルに較正する必要があります。
このプログラムは、どの周波数でも校正されていない読み取り値のみを提供します
アナログハードウェアの応答です。
シグナルコンディショニング
Four measuring sound on an Arduino, you obviously need a microphone,
but you also need some kind of interface circuit between the microphone
and the Arduino. The purpose of the interface is to “condition the
signal”, i.e. to make sure the Arduino gets a voltage in the proper
range for it's analog-to-digital converter (ADC). It's typically an
op-amp based circuit that provides some amplification and also adds a DC
bias to avoid clipping the negative side of each oscillation. Ideally,
the DC bias should be around Vcc/2, i.e. 2.5 V on an Arduino Uno.
この SparkFunマイクをご覧ください
ブレークアウトの例
そのような回路を構築することができます(「回路図」をクリックしてください)。
ADCサンプリング
Once you have a properly conditioned analog signal, you have to sample
it fast enough to catch all its spectral content. The Nyquist–Shannon
sampling
theorem
tells us the sampling rate should be at least twice the highest
frequency in the signal. For audio signals, sampling rates of the order
of 8 kS/s (kilosamples per second) are typical of low quality,
telephone-like applications, whereas high quality audio would run at
44.1 to 48 kS/s.
The ADC of the Arduino Uno, in its default configuration, takes
104 µs to convert one sample. If you just call analogRead()
in a
tight loop, this gives a sampling rate of about 9.6 kS/s, which is
fine for this kind of application, unless we have to measure noise above
4.8 kHz. The problem with this approach is that analogRead()
is a
blocking function. Calling it in a tight loop means the program will
spend most of its time just waiting for the ADC. If you do anything else
in the loop, not only will the sampling rate be lowered, it will also
become unsteady, which is generally not desirable.
In order to avoid blocking the CPU, we have to forgo analogRead()
, and
instead get our hands dirty with low-level configuration of the ADC. The
ADC of the Arduino Uno offers a so-called “free running mode”, which is
well suited for this kind of application. In this mode, the ADC starts a
new conversion as soon as the previous one is done, ensuring a very
consistent sampling rate of 9.6 kS/s. It can also trigger an
interrupt after each conversion, in order for the interrupt service
routine to retrieve and process the sample. See the datasheet of the
ATmega328P
for details on configuring the ADC.
DCバイアスの除去
デジタル化されたサンプルを入手したら、最初に削除する
インターフェイス回路によって追加されたDCバイアス。バイアスが
安定していて(実験によって決定されるかもしれない)、これは
定数を減算する。それが知られていない場合は、
カットオフ付きのデジタルローパスフィルタでサンプルを実行する
関心のある範囲よりも低い周波数である。 aの出力を減算する
ローパスフィルタは基本的にハイパスフィルタを構築しています。として
代替、数値導関数(連続
サンプル)を粗ハイパスフィルタとして使用することができる。しかし、これは
ハイエンド方向の検出感度をバイアスする
スペクトラム。検出したいノイズと
バックグラウンドノイズの場合、これはアプリケーションで許容される可能性があります。
私が共有しているプログラムでは、私はDCバイアスが分かっていると仮定します。
dc_offset
定数をプログラムの先頭に追加します。
瞬時強度
DCバイアスを除去した状態での信号は、
マイクが選んだ音。ちょうどそれを平均化するのは魅力的かもしれない
そのまま。しかし、これは肯定的な変動
信号の負の値がキャンセルされます。
この問題を解決するためのいくつかのオプションがあります。私たちはピークを迎えることができた
平均の代わりに検出するか、または絶対値をとることができます
平均化する前に。最も一般的な選択肢はおそらく
サンプルの四角。実数の2乗は常に
これは、平均化問題を回避する。しかし、広場にも
より深い物理的意味:これは、音に比例します
強度、すなわち
音波によって運ばれるエネルギー。
ローパスフィルタ
The intensity computed above is a very fast varying quantity. If the
signal is a simple tone of constant frequency and volume, the
瞬時強度 fluctuates between zero and some maximum at
twice the tone frequency. In order to recover the “constant volume”
property of the sound, we need to perform some sort of averaging or, in
other words, we need a ローパスフィルタ.
There are many ways to implement a digital ローパスフィルタ. The most
intuitive may be to group the samples into batches, and then compute the
average of each batch. However, this is neither the best nor the most
efficient to implement. When I need a quick and simple low pass filter,
I generally use an exponential moving
average.
This is the discrete-time equivalent of an analog RC filter, and it can
be implemented very efficiently by remembering the previous output and
updating it as
output += input - output/N;
where, for efficiency reasons, N should be a power of two. The filter's
time constant is N/fs, where fs is the sampling
frequency. In the program I use N = 256, which makes the
division virtually free. This gives a time constant of 26.6 ms. You
can tune the time constant to your needs simply by changing N, but make
sure it is still a power of two.
デシメーション
If you only want to trigger an event when the sound intensity exceeds a
defined level, you may not need this. But if you have other processing
to do with those measurements, it is probably not useful to process more
than one intensity reading per time constant of the previous filter.
That's why the program has a デシメーション step. This is simply the ISR
periodically signaling the main program that an intensity reading is
available. Notice that, since the sample count is an 8-bit variable, it
automatically counts modulo 256. If you want to increase the デシメーション
factor, you should make sample_count
wider and mask out the bits you
do not need.