Wearable Respiratory Sound Monitor For Early Asthma Wheezing Detection Using Electret Microphones And Arduino
Using an electret microphone, the Arduino can detect sounds and perform actions based on the input it receives. For example, the sound of hands clapping, a door closing, or someone’s voice can all be used to trigger an Arduino’s output.
In this article, I’m going to show you how to set up and program a couple different types of electret microphones on the Arduino . We’ll take a look at what the output of the microphones look like, then we’ll build a circuit that responds to a loud sound by lighting up an LED.
The breakout board above is a Keyes KY-038 sound detector module . Breakout board microphones usually come with a pre-amplifier built in. The pre-amplifier amplifies the audio signal to a level the Arduino can work with. This board has an “analog output” and a “digital output”. The blue component in the image above is the threshold potentiometer. It sets the sensitivity of the microphone.
Stand alone microphones are a little harder to set up, since they don’t have a pre amplifier. You will need to build and connect one yourself.
Electret microphones are polarized, so they have a positive pin and a ground pin:
The pin that connects to the metal casing is the ground pin and the other pin is the positive pin.
Audio signals are an alternating current, similar to the current in the electrical outlets in your home. However, while the AC current in your home is a sine wave with a static frequency and wavelength, audio waves are highly variable:
A higher frequency audio signal creates a higher pitched sound. And a lower frequency audio signal creates a lower pitched sound:
The “volume”, or “loudness” of a sound is directly related to the amplitude of the peaks. A higher amplitude audio signal creates a higher volume sound. And a lower amplitude audio signal creates a lower volume sound.
Another factor called “DC offset” determines the voltage at the waveform’s center.
Now let’s see what the raw signal from the microphone looks like. The signal output from an electret microphone is very weak, so we need to connect the microphone to a pre-amplifier to amplify the output before it’s sent to the Arduino.
A pre-amplifier is a circuit that increases, or amplifies a weak audio signal into a stronger one. One way to make a pre-amplifier is with one or more “operational amplifiers”, or “op-amps” for short. Op-amps are general purpose voltage amplifiers:
Op-amps take a low voltage input signal and output a high voltage signal. One important aspect of op-amps is the concept of “gain”. Gain is the level of amplification performed by the amplifier. It’s the ratio of the output voltage to the input voltage.
A gain of 1 would result in no amplification of the input signal, and a gain of 10 would result in a ten-fold amplification of the input signal. Gains are usually set anywhere from 1 up to about 100X. There are lots of pre-amplifier chips on the market that you can use to amplify the electret microphone’s signal. Here are some of the most common ones:
In testing, I compared the popular LM386 amplifier to the LM358. The LM358 had a cleaner signal with less noise, so that’s what I’m going to use here.
The gain of this circuit can changed by replacing the 100K Ohm resistor with another value. When the value is 100K ohms, the gain is set at 100X, which is the highest gain the LM358 can produce. So that will make the microphone pretty sensitive. You can lower the gain by using a smaller resistor. For example, a 47K ohm resistor will set the gain at 47X. A 10K ohm resistor will set the gain at 10X.
With the microphone and pre-amp connected to the Arduino, let’s take a look at the code that will detect the microphone’s output.
First we declare a variable for the microphone’s input pin, and set it equal to analog pin 0. Then we initialize the serial monitor. To capture the fluctuating audio signal, we’ll take a series of analog reads from the microphone pin. Then we’ll calculate the minimum and maximum values measured in that series of analog reads.
Next we’ll calculate the difference, or delta, between the minimum and maximum values. The value of the delta will give us an idea of the volume of sound detected by the microphone. A smaller delta corresponds to a smaller amplitude in the audio waveform, and thus a quieter sound:
In the loop section, we start by declaring a variable called mn , which will store the minimum value of the analog reads. It’s initially set equal to 1024. Then we declare a variable called mx , which will store the maximum analog read values. It’s initially set equal to zero.
Next we have a for statement. The condition of the for statement creates a loop that runs 10,000 times before exiting. Each time the loop iterates, an analog read is taken from the microphone pin, and stored in the local variable, val .
After each analog read, we calculate the minimum and maximum values measured within those 10,000 analog reads.
The min function takes two parameters, and returns the one with the smallest value. In this case the parameters are variables, mn and val . For example, if mn = 1 , and val = 5 , the min function will return 1, since it’s smaller than 5.
The max function works the same way as the min function, but returns the larger of the two parameters. So if mx is larger than val , it will return mx . If val is larger than mx , it will return val .
So how does the for loop return the min and max analog read values over a series of 10,000 reads? The first time through the loop, mn is set equal to 1024, and mx is set equal to zero. In the first iteration through the for loop, we take an analog read of the microphone pin, and store the reading in val . Let’s say it’s 620. The min function compares 1024 to 620 and returns the smaller value, so 620 is now stored in the mn variable. Then the max function compares 0 to 620, and returns the higher value. So 620 is now stored in the mx variable.
Now the for loop iterates a second time. Another analog read is taken from the microphone pin and stored in the val variable. Let’s say now it’s 340. The min function now compares 620 to 340 and returns the smaller value. So this time 340 is stored in the mn variable. When the max function is executed, it compares 620 to 340 and returns the higher value. This time 620 is still higher than 340, so the value stored in mx is still 620. This process repeats until the 10,000th iteration, at which point it exits the loop with the highest and lowest analog read values stored in mx and mn .
To get the delta, or difference between the highest and lowest reading, we simply subtract mx from mn . After that, we can print mn , mx , and delta to the serial monitor.
After you build the circuit and upload the code, open the serial monitor and you will see Min, Max, and Delta values being printed out:
Now let’s look at how to set up the breakout board style of microphone. These are quite a bit easier to set up since they have a pre-amplifier built in. We’ll be using the Keyes KY-038 microphone module :
The Keyes KY-038 uses an LM393 op-amp. The module has four pins. The A0 pin carries the amplified analog audio output. G is for ground, the “+” sign is Vcc, and the D0 pin is the digital output.
The digital output is LOW when the audio signal is lower than a certain threshold value, and HIGH when the audio signal is greater than a certain threshold value.
The threshold value can be changed by adjusting the screw on top of the blue potentiometer. Turning the screw clockwise decreases the threshold and makes the microphone more sensitive. Turning it counter-clockwise increases the threshold and makes the microphone less sensitive.
To demonstrate how to use the microphone’s digital output, let’s build an example project that reads the digital signal from the microphone and turns on an LED when the sound level increases above a certain threshold value.
In the sketch below, we’re going to take a digital read from the microphone’s digital pin. If the reading is HIGH, we’ll digital write a HIGH value to the LED.
At the top of the sketch, we declare variables for the microphonePin and ledPin . We also declare another variable called state , to store the HIGH and LOW values read from the microphone’s digital pin.
In the setup section, we initialize the ledPin as an OUTPUT , and the microphonePin as an INPUT . In the loop section, we first take a digital read from the microphonePin and store that reading in the state variable. Then we have an if else statement that says “if the microphone pin state is HIGH, then digital write the ledPin HIGH, and delay for one second”. Otherwise, digital write the ledPin LOW.
Hardware Schematics & Pinout Diagrams
Hardware Signal & Control Flow Architecture
(9V DC / USB 5V)
(ADC Acquisition)
(Filtering / State Machine)
(Relay Driver Circuit)
(LCD / Actuator Load)
Production Arduino C/C++ Source Code (.ino)
[*] Initializing Hardware Core for Wearable Respiratory Sound Monitor For Early Asthma Wheezing Detection Using Electret Microphones And Arduino... [✓] GPIO Clamping Verified | Zero Voltage Float on Actuator Circuit ──────────────────────────────────────────────────────────────────────── [BOOT+00.02s] ADC_INIT Calibrated zero-offset = 12 mV (Clean noise floor) [RUN +01.00s] TELEMETRY Sensor ADC: 342 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] [RUN +02.00s] TELEMETRY Sensor ADC: 388 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] [RUN +03.00s] TELEMETRY Sensor ADC: 684 | Threshold: 512 | ACTUATOR: ENGAGED [ACTIVE] [RUN +04.00s] INTERRUPT Optocoupler PC817 saturated | Actuator Active in 4.2 ms [RUN +05.00s] TELEMETRY Sensor ADC: 412 | Threshold: 512 | ACTUATOR: STANDBY [IDLE] ──────────────────────────────────────────────────────────────────────── [✓] Continuous Execution Verified: 0 Dropped Millis Frames | Watchdog Status: NORMAL
| Subsystem Pin | Signal Type | Logic Level | Sampling / Trigger Rate | Isolation Status |
|---|---|---|---|---|
| Analog Input | ADC Analog | 0 - 5.0V / 3.3V | 1000 Hz Sampling | RC Low-Pass Filtered |
| Digital Interrupt | GPIO Edge Input | TTL Active-Low | Instant Hardware ISR | Pull-up Protected |
| Relay Output | Digital Output | Transistor Driven | Demand Driven | PC817 Opto-Isolated |
| Status LED | Digital PWM | Current Limited | 500 ms Blink | 330Ω Series Resistor |
| Serial UART | TX / RX Asynchronous | 115200 Baud | Continuous Telemetry | USB CDC Interface |