3

I am wondering if it is possible to attach a microphone to an Arduino board and make the Arduino recognize a volume peak in a specific range of frequencies.

I want it to detect a specific peak (for example 0,1 dB) in the range of 1000 hz to 5000 hz.

0

3 Answers 3

1

You can filter the signal and look at the power that lies within the frequency range you are interested about. You could use an FFT for that, but it is quite computationally expensive. If you go for the FFT, you would probably end up sampling the mic in small bursts (a few milliseconds sampled every few tens of milliseconds), as the Arduino would spend most of its time processing the data.

A better option is probably to work in the time domain, rather than the frequency domain. If you do not need to know exactly how much power lies in each frequency bin, and are only interested in the total power within the window of interest, then the FFT is computing too much stuff you do not need. A less computationally expensive option would be to run the samples through a digital band pass filter tailored to the band you want. You can then compute the power from the output of the filter and low-pass it:

raw_sample = sample_the_microphone_somehow();
filtered_signal = bandpass_filter(raw_sample);
instantaneous_power = filtered_signal * filtered_signal:
smoothed_power = low_pass_filter(instantaneous_power);

But you would still need a beefy Arduino if you want to be able to acquire and process the samples at a reasonable rate: at least twice the highest frequency that comes out of the microphone.

A still better option could be to do the filtering in the analog domain, before the signal reaches the Arduino. If you can at least remove the frequency components above 5 kHz, then the Arduino would only need to sample at 10 kS/s, and run a digital high pass filter to remove the part of the signal below 1 kHz. This should be easy enough even for an AVR-based Arduino.

For the implementation of the filters, you may want to try this online filter builder

1

An alternative to the FFT is the Goertzel algorithm. It is intended to only detect a single frequency, so may not suit your purpose of working with a range.

But it may be more practical and require less intensive processing. Although intended to only detect a single frequency, it will of course give results near a given frequency, depending on the sampling rates and detection thresholds.

I have previously used an Arduino Goertzel algorithm library, but there doesn't appear to be anything available through the Library Manager at the moment; a web search shows some hits though.

The beauty of the Goertzel algorithm is that it only needs to keep a small amount of data in memory, so may have some benefit on smaller processors over more data intensive techniques like FFT.

I would try implementing one or more Goertzel detectors across your range (eg one at 3kHz or two at 2kHz and 4kHz) to see if they are sensitive enough.

0

You could sample the sound from the microphone and then apply a Fast Fourier Transformation (FFT).

An FFT lets you decompose a sequence of samples into components of different frequencies, usually into "buckets" that each have a small frequency band. You can then have a look at these buckets to see if there is a peak in a specific frequency range.

There are several examples and libraries for this on Arduinos, like EasyFFT and arduinoFFT.

PS. Edgar Bonet's answer is better; I may have become a bit lazy at coming up with computationally efficient ways of doing things because of my using "beefy" Arduinos exclusively.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.