3

I want to make a simple circuit which returns the time/delay between two, consecutive loud sounds (i.e, a mic reading of ~600) coming from a speaker. I have set up and ADMP 401 microphone for this purpose. How do I measure the time it takes for this application?

  • Why can't you use millis() for this? – Ignacio Vazquez-Abrams Apr 15 '14 at 5:08
  • 1
    Do you know how to wire up and detect the sound from the microphone using the Arduino? – jippie Apr 15 '14 at 5:09
  • What is the time precision you need? – jfpoilpret Apr 15 '14 at 5:23
  • @jippie: yes, I have done so successfully – shortstheory Apr 15 '14 at 6:01
  • @jfpoilpret: I need time precision of the order of 10^-6 secs. Of course, smaller is better :) – shortstheory Apr 15 '14 at 6:02
2

Your question is probably not as simple as it may seem.

One approach I would use if I was to address this same problem would consist in:

  1. converting the analog output of the mike into a digital value (based on a threshold to determine)
  2. connect this digital signal to one Arduino pin that can trigger an interrupt when its level changes

Let's first start with the easy part: Arduino program.

Let's say we have a digital signal that raises to 1 as soon as a sound of too high amplitude is captured by the mike; it shall stay 1 as long as the sound does not reduce amplitude enough. We will connect this signal to Arduino pin 3; then we can use attachInterrupt() to have a function called whenever this pon level raises to 1:

volatile static bool started = false;
volatile static unsigned long timing = 0;
volatile static bool finished = false;

void loud() {
    if (started) {
        timing = micros() - timing;
        started = false;
        finished = true;
    } else {
        timing = micros();
        started = true;
        finished = false;
    }
}

void setup() {
    pinMode(3, INPUT);
    attachInterrupt(1, loud, RAISE);
}

void loop() {
    if (finished) {
        // Do something with timing
    }
}

Now the hardest part: electronics!

A first issue we have to deal with is related to the fact that the raw mike signal will have same wave shape as the sound it captures, this wave has a frequency that can vary between 10Hz (bass) and 20KHz (treble).

Indeed, if we convert the mike analog output to a logical value (1 when the analog value is above a threshold we'll call Vt, 0 when it is under Vt) fast enough, then, if the environmental sound as an amplitude above Vt, the logical input connected to your Arduino will oscillate at the same frequency as the sound! This would make our efforts pointless as you would measure the period of the sound wave instead of the elapsed time between two distinct sound bursts.

That means that we should probably first "smoothen" the analog sound signal in order to avoid disturbance of its frequency.

Hence point 1 will have to deal with these 2 aspects:

  • smoothen analog input value
  • compare smoothened value with Vt threshold and provide a logical value from this comparison

Comparison can rather easily be performed by an op-amp used as a comparator.

However, the main difficulty you may have with an op-amp is the need for a symetric voltage supply (e.g. +5V/-5V) although it is possible to use a single supply but that raises further limitations (outside the scope of my answer).

Smoothening the signal is potentially more complex, although it can be done with a simple capacitor, because smoothening the signal generally means weakening it, thus you would lose the initial amplitude of the sound signal.

So how can we deal with that?

A Schmitt trigger is probably a good solution for this problem but further experiment will be needed to confirm that.

| improve this answer | |
  • Thanks for the answer. Well the ADMP 401 already has an amp of sorts, so is a separate op-amp required? Would an op amp like this one work: protocentral.com/breakout-boards/… ? – shortstheory Apr 27 '14 at 2:41
  • The ADMP 401 uses an Op Amp as a signal amplifier not as a comparator, so you will still need an additional Op Amp mounted as a comparator. There are plenty of Op Amps available and cheap; I think the LM 358 chip (sparkfun.com/products/9456) should fit your purpose; this one only requires a single supply (between 3V and 32V). – jfpoilpret Apr 27 '14 at 6:37
1

When you mentions "loud sounds (i.e, a mic reading of ~600)" I'm guessing that means you've successfully connected the mic to an ADC input and you are referring to analog readings, right? (If not you may need to clarify). I won't worry about scaling or offset biasing the inputs, assuming you have that part down and you can test the Analog input to detect loudness.

If your Arduino can be dedicated to making this measurement (ie: doesn't need to do anything else while doing it), then the simplest solution might be a loop comparing the ADC input with some threshold you have determined, and using micros() to check the time different. The micros() function has only 4 uS resolution, but the loop time will add more time than that anyway, and actually the limited bandwidth of your audio signals (speaker and mic both) will make any microsecond level measurement suspect anyway. So the simple loop might be as accurate as you need.

For example:

const int THRESHOLD = 600; // adjust
const int MINDELAY = 1000;  // adjust

long 
takeMeasurement() {
    while(analogRead(A4) < THRESHOLD); // wait for first trigger
    long start = micros();
    delayMicroseconds(MINDELAY); // let first noise die down
    while(analogRead(A4) < THRESHOLD); // wait for second trigger
    return micros() - start;
}

You would call this function when you were ready to take a measurement. To keep the loop time short (when it's waiting for a loud sound), it has no timeout, so it won't return until it does detect two loud sounds. Depending on your need, you might need to change that and have an escape from the loops. There are several ways that might be done:

  • test for micros() exceeding some timeout within the loop

  • decrement a counter in the loop and exit if it goes to zero (or if the sound is detected)

  • test a flag (volatile byte) in the loop, which gets set by a timer interrrupt

Which is best depends on other aspects of your overall design.

| improve this answer | |
  • Yes, that is correct, I'll try this out the next time I start messing with my arduino :) – shortstheory Apr 26 '14 at 7:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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