Time Difference between Two Microphones

Hello everyone,

I'm dealing with a project, where I use 2 different microphones. I need to measure the time difference of receivement of data between two mics, via using Arduino. As the subject is sound, naturally the time difference is about microseconds. I have tried various Micros and PulseIn codes to obtain a result, but I have failed every time.

The sensors are wired to digital pins, Can you help me figure out how to obtain a reliable and accurate result?

Post your code. Don't forget your code tags.

What is the nature of the noise? If it isn't an impulse noise and you are looking for a phase difference, that will be more complex.

Before you can measure the arrival time difference between two audio signals, you have to make absolutely sure that you can detect the arrival of a single signal, and determine precisely when that signal actually arrives. That is difficult to do unless the sound is very loud and distinctive, like a sharp bang.

You probably can't expect much useful help on this forum unless you take more time to describe the actual experiment. Describe the sound, the microphone and associated circuitry and what you have done so far (including code) to determine whether you are actually detecting the sound of interest.

jremington:
Before you can measure the arrival time difference between two audio signals, you have to make absolutely sure that you can detect the arrival of a single signal, and determine precisely when that signal actually arrives. That is difficult to do unless the sound is very loud and distinctive, like a sharp bang.

You probably can't expect much useful help on this forum unless you take more time to describe the actual experiment. Describe the sound, the microphone and associated circuitry and what you have done so far (including code) to determine whether you are actually detecting the sound of interest.

That is an even better statement than mine. Do that.

the time difference is about microseconds. I have tried various Micros and PulseIn codes to obtain a result, but I have failed every time.

Microseconds intervals to measure (with some precision) is usually done with a free running oscillator (ie 50MHz) and a flip-flop, AND gate and a binary counter.

The mike1 pulse sets the f-f, the gate opens for the oscillator pulses to be passed into the counter.

Then a pulse on mike2 resets the f-f, the gate closes and the oscillator pulses stop to pass into the counter.

Then you read the content of the counter.

A time difference of 10usecs shows 500 pulses then.

PS: If you are keen on electronics you may consider this design:
http://forum.arduino.cc/index.php?topic=120220.0
It includes everything you need, the counter is 32bit long, and the stuff can count up to 100Mhz fast (so 10usecs time difference gives you a 1000 reading). Or, otherwise, 1 count gives you 3micrometers of microphones position difference..

jremington:
You probably can't expect much useful help on this forum unless you take more time to describe the actual experiment. Describe the sound, the microphone and associated circuitry and what you have done so far (including code) to determine whether you are actually detecting the sound of interest.

#include <FreqCount.h>  
#include <math.h>



volatile unsigned long firstPulseTime;  
volatile unsigned long lastPulseTime;   
volatile unsigned long numPulses;
unsigned long currentTime = 0;
unsigned long pastTime = 0;
unsigned long value;

double x;
double y;
float ab;
double w;
double a,b,c,d,e,f,g,h,k;
double xb;
unsigned long timePassed, timePassed2, timePassed1;


int servo = 8;
int angle;
int pwm;


void isr()                           
{                                    
  unsigned long now = micros();
  if (numPulses == 1)
  {
    firstPulseTime = now;
  }
  else
  {
    lastPulseTime = now;
  }
  ++numPulses;
}

void setup() {
  
  
  xb = 5.65;
  x = 100;
  
  FreqCount.begin(1000);  
  pinMode(3, OUTPUT);     
  analogWrite(3, 128);
  pinMode(servo, OUTPUT);
  Serial.begin(57600);
   

}


float readFrequency(unsigned int sampleTime) 
{                                          
  numPulses = 0;                     
  attachInterrupt(0, isr, RISING);    
  delay(sampleTime);
  detachInterrupt(0);
  return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime);
}


void servoPulse (int servo, int angle)
{
  pwm = (angle*11) + 500;      
  digitalWrite(servo, HIGH);
  delayMicroseconds(pwm);
  digitalWrite(servo, LOW);
  delay(50);                  
}



void loop() {
   
   
   if (FreqCount.available()) {              
    unsigned long count = FreqCount.read();
    float freq = readFrequency(1000);  
           

    
  
  if (freq == 0 && count==0){ 
    
   pastTime    = currentTime; 
   currentTime = micros();    

 
    if (freq > 0 && count == 0){   

    timePassed1 = (currentTime - pastTime - 1000000);   
    }
    
    else if (count > 0 && freq == 0 ){

    timePassed2 = (currentTime - pastTime - 1000000);
    

    }
    
    timePassed = timePassed2 - timePassed1;
    
    if(timePassed > 0){
    
    
    ab = (343.2*timePassed/10000);
    y = xb * xb;
    w = ab * ab;
    a = x * x;
    b = w/4;
    c = 4*y;
    d = c/w;
    e = d - 1;
    f = a*e;
    g = sqrt (b - y + f);
    h = atan2 (g, x);
    k = h*180/PI;
    
    for (angle = 180; angle >= (k); angle +=5)  {
    servoPulse(servo, angle);  }    

    
    }
    
     else if (timePassed < 0){
     
    timePassed = timePassed1 - timePassed2;
    ab = (343.2*timePassed/10000);
    y = xb * xb;
    w = ab * ab;
    a = x * x;
    b = w/4;
    c = 4*y;
    d = c/w;
    e = d - 1;
    f = a*e;
    g = sqrt (b - y + f);
    h = atan2 (g, x);
    k = h*180/PI;    
    
    for (angle = 0; angle <= (180 - k); angle +=5)  {
    servoPulse(servo, angle);  }    
    
    
     }
  }
  delay(1000);
    
    freq = 0;
    count = 0;
}
}

This is the code. What I'm trying to achieve here is to reset the measurement as zero at the beginning of the loop and then obtain the time difference by starting the time count when one of the mics are high and stop when the other one becomes high, too. It may sound too basic (it doesn't work anyway) and the logic behind may be wrong.

The sound I'm dealing with is continuous not impulse, which makes everything much more complex. The letter variables belong to the TDOA algorithm that is supposed to give the result as an angle if the time difference is found at the start. My intention is to direct the servo to the source of the sound by using that result and also still keep measuring the frequency.

The mics I'm using are MEMS microphone boards(link of the datasheet https://www.sparkfun.com/datasheets/Components/General/SPM0404HE5H.pdf), so no additional gain amplifiers are included to the circuit. The circuit is a simple one, containing two microphones only, not even a single resistor or an opamp. I'm using Arduino Due. But I have an extra Arduino Leo if number of timers or anything else would be insufficient when Due used.

That's the case. Please help on this issue. My graduation completely depends on that. I can give more information about the project if needed.

You may be interested in this post, which measures the phase difference for a particular tone, between two microphones. The author claims about 1 degree accuracy http://coolarduino.wordpress.com/2012/10/01/sound-localization/

The higher the response of the microphone into the ultrasonic range the better the
time resolution you can expect - the datasheet isn't great, it doesn't show the frequency
response above 10kHz (there's clearly a resonance up there somewhere too, maybe into
the ultrasonic range even).

I presume you have some sort of zero-crossing detector to generate the digital signal?
The quality of that circuitry is key to the time accuracy, it needs to be symmetrical and
stable.

In order to eliminate any impedance variations with frequency you'd be best working
with a fixed frequency throughout - and not near any resonances in the acoustic system.
The amplitude also needs to be kept constant as far as possible as amplitude and phase
will interact in a real-world microphone I suspect (well its another possible error you
would have to at least characterise during calibration to see if it mattered).

The ISR should read the hardware in a timer directly, not rely on micros(), in
order to eliminate a possible source of jitter. You need to turn off the other interrupts
in the system (timer0 overflow basically). You would set the timer up to clock at maximum
speed - timer1 is an obvious choice as its 16 bit so shouldn't encounter wrap-around issues
as often as an 8-bit counter.

It using a board with a ceramic resonator to clock the microcontroller consider replacing
it with a quartz crystal and load capacitors.

jremington:
You may be interested in this post, which measures the phase difference for a particular tone, between two microphones. The author claims about 1 degree accuracy http://coolarduino.wordpress.com/2012/10/01/sound-localization/

I already tried the same code with the same circuit but it still failed somehow. After that, I tried some variations on the code and the circuit, couldn't succeed again. I don't know where did I go wrong, but it doesn't work for me.

MarkT:
The higher the response of the microphone into the ultrasonic range the better the
time resolution you can expect - the datasheet isn't great, it doesn't show the frequency
response above 10kHz (there's clearly a resonance up there somewhere too, maybe into
the ultrasonic range even).

I presume you have some sort of zero-crossing detector to generate the digital signal?
The quality of that circuitry is key to the time accuracy, it needs to be symmetrical and
stable.

I'm not trying to measure extremely high frequencies, so stability for values between 0-4000 Hz is enough in my case.

If I understood you right, my signals are not artificially and intendedly created, they are natural sounds like a song, or human voice, etc. Those voices are continous; to reset the measurement to zero, I added a code of defining frequency variables as zero at the beginning of the loop before reading a frequency value again. However it's highly possible that this is not really sensible because I couldn't reach my goal. I guess at this point, the time difference is not enough for me and I need to figure out how to find phase delay between two signals.

Simply recognizing natural sounds and defining a "time of arrival" are both very, very difficult tasks even if you are well versed in analog electronics and signal processing algorithms. You have given yourself an extremely challenging problem to solve. If your graduation depends on the solution, good luck!

I would pick a more straightforward problem for a graduation project.

I'm considering to use two different Arduinos: one Due and one Leo, separately. On Due, I can successfully obtain a precise frequency value by both mics, so no problem at frequency measurement. I'm thinking about finding the phase delay on Leo. I just don't know how to do.

If you want to measure the phase difference of two continual natural sound signals you may sample the both signals (channels) at the same sampling rate, ie 10kHz, fill in two buffers, ie 1ksamples each, and simply do the cross correlation between the channels - that is a pure math. You can get the phase diff then. Simply search "cross-correlation phase difference"

Cross-correlation is what the author did in the link already posted (and tried by the OP): https://coolarduino.wordpress.com/2012/10/01/sound-localization/

Sorry, overlooked that..

I could not make much sense out of the microphone data sheet that you posted, so I think what you need to do is make sure that you have a good, clean signal from the microphones -- with amplitude changes of a VOLT or so when the sound of interest is present. If you have access to an oscilloscope, use it. If possible, post a picture of the signal.

You will probably need an amplifier and possibly also a low pass filter between the microphone and the Arduino input. Your chances of successfully analyzing a clean, strong signal are fantastically better than analyzing a weak, noisy signal.Just being able to correctly identify a frequency is not strong evidence that your signal is clean and strong.

How do you propose the read the output of the microphone you posted a link to, without an opamp ?

How are you getting on with the project? I am doing something similar, if you have finished it can you please send my your or code? If not, let's exchange emails and try to find a solution together :slight_smile:

Hi- I haven't read all posts, hope I'm not 'reinventing the wheel'.....
One possible approach, would be to run each mic thru a gain amp,
goal being output between 0 - 5 vdc for sound input into either mic.
Then run each amp output to a comparator, giving either a 0V or
5V signal for no sound/ sound. Run each comparator output to a
hc86 XOR gate (each gate has two inputs), one hc86 input hooked
directly to comparator output, other hc86 input having a small
capacitor (perhaps 0.1 uF) to gnd, and resistor to comparator out.
This circuit essentially 'splits' each comparator output into two
signals, slightly delaying one. The result is a positive going comparator
output signal yields a brief pulse from the HC86. Overall effect is
for leading edge of sound signal, a brief digital pulse is generated
for each mic. (might also need a flip-flop, i.e. HC74, in circuit to
prevent repetitive pulses from a sound: use HC86 out to set HC74.
Run HC86 output, and -Q HC74 to AND gate. AND gate out is
single pulse/ sound. Reset HC74 before next sound). Then use
these digital pulses to start and stop a counter, and read counter
for sound delay mic 1 to mic 2. Much of this could be done in
software on Arduino processor.

Hope this helps a little.

Stan Smale (SESMD)
stanleysmd@gmail.com