Sound Triangulation with 3 Microphones

I am currently busy with a project and urgently need help in the right direction. I am a total newbie so please bear with me. I am trying to develop a device to triangulate a sound source. The final project will have multiple sensors the same as the the one I am busy with. The final triangulation will be done by the combined data from 2 or more sensors. The current sensor will only provide a compass bearing to the detected sound.

I have three microphones in an equal triangle formation, each spaced 1 meter apart. I numbered them 1 to 3 with number 1 at the point which will point north 0/360 degrees, number 2 at 120 degrees and three at 240 degrees. they are connected to Analog input pins 1,2 and 3 on an Arduino Mega 2560. Incorporated in this design is also a DS18B20 Thermometer to calculate the correct speed of sound at any given time. Please see the attached Fritzing image for the current setup.

I have used FASTADC as to do faster analog reads (currently reading at 18 microseconds). When the threshold of a microphone is exceeded, I check the remaining mics for a 2nd detection from where the bearing can be calculated.

I will probably add sound analyzing at a later stage, maybe on another microprocessor.

As I said, I am a newbie, please have a look at the code and give me comments on how to improve on the coding and design. When connecting an Xbee I realized that the analog Read values are pushed up quite a lot, normal quiet environment reads will be in the range of 500 to 600, with the Xbee they are pushed to 900 or more. Is it an issue with power distribution or something affecting the RX/TX ports on the Arduino?

Below is my current working code version

#include <OneWire.h>
#include <DallasTemperature.h>

// Detection Order Vars
int S1; // Var to hold 1st detection Mic number
int S2; // Var to hold 2nd detection Mic number

// Analog Read Values
int sensorCheck; // Var to hold Audio Value
int sensorValue1; // Var to hold detected Audio Value of Mic 1
int sensorValue2; // Var to hold detected Audio Value of Mic 2
int sensorValue3; // Var to hold detected Audio Value of Mic 3

// Timing Vars
double detectTime; // Var for detection time out
double time1; // Var to hold 1st detection time, time when 1st mic exceeded the set threshold
double time2; // Var to hold 2nd detection time, time when 2nd mic exceeded the set threshold


// Timing Calculation Vars
double calculatedMS1; // 2nd detection time - 1st detection time micro second value
double calculatedSeconds1= 0.0000000000; // Var to convert microseconds to seconds for angle calculation of 1st detection

// Distance, angle and bearing vars
double DistA = 0; // Calculated sound wave distance between 1st mic detection and 2nd mic detection in meter
double BearingResult1 =0; // Bearing result from 1st detection
double FinalBearing1 =0; // Adjusted and final compass bearing of 1st detection


// Constant Values
double LengthOfSide = 1; // Constant for Mic Array triangle side value in meter
double RadToDegrees = (360/(2*3.1415)); // Radians to degrees function
double temp =0; // Var to hold current temeprature Deg Celsius
double SpeedOfSound = 0; // Var to hold calculated speed of sound value for angle calculation
int micThreshold = 600; // Detection Threshold

// DS18B20 Temperature Sensor defined
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Fast ADC defined
#define FASTADC 1

// Fast ADC defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

 
void setup()
{
Serial.begin(57600);
sensors.begin();
}

void loop()
{
// Zero All Variables

// Analaog read vars
sensorValue1 =0;
sensorValue2 =0;
sensorValue3 =0;
sensorCheck =0;

// Timing Vars
detectTime =0;
time1=0;
time2=0;
calculatedMS1 = 0;
calculatedSeconds1=0;


// Distance, angle and bearing vars
DistA = 0;
BearingResult1 = 0;
FinalBearing1 = 0;

sensors.requestTemperatures(); // get current Temp
Serial.print("Current Temperature: "); 
Serial.println(sensors.getTempCByIndex(0)); // print current temp
Serial.println("Waiting...................."); // show we are ready for detection

// Set the ADC for fast clock speed (18 microsecond per analogRead)
#if FASTADC
  // set prescale to 16
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;
#endif
 
 // Start the detection Sequence
 
 // Check Mic 1
 //------------------------------
 while (sensorCheck<micThreshold)
 {
  sensorCheck =0;
  sensorCheck = analogRead(1);
  if (sensorCheck>=micThreshold){ // Check If Mic 1 exceeded the threshold, save S1 Var to 1, time1 to current micros()
    time1= micros();
    sensorValue1 = sensorCheck;
    sensorCheck=0; // Reset sensorCheck Var
    S1=1;
    while (sensorValue1>micThreshold && sensorCheck<micThreshold){ 
      detectTime = micros()-time1;
      if (detectTime >5880) // check if 1st detection is timed out 1 - 
      { 
          NoDetect();
      }
      sensorCheck =0;
      sensorCheck = analogRead(2);
      if (sensorCheck>=micThreshold){ // While Mic 1 exceed threshold is true Check If Mic 2 exceeded the threshold
        time2= micros();
        sensorValue2 = sensorCheck;
        sensorCheck =0;
        S2=2;
        Action();
        }
      }
      sensorCheck =0;
      sensorCheck = analogRead(3);
      if (sensorCheck>=micThreshold){ // While Mic 1 exceed threshold is true Check If Mic 3 exceeded the threshold
        time2= micros();
        sensorValue3 = sensorCheck;
        sensorCheck =0;
        S2=3;
        Action();
      }  
    }

 // Check Mic 2
 //------------------------------
  sensorCheck =0; 
  sensorCheck = analogRead(2);
  if (sensorCheck>=micThreshold){ // Check If Mic 2 exceeded the threshold, save S1 Var to 2, time1 to current micros()
     time1= micros();
     sensorValue2 = sensorCheck;
     sensorCheck=0;
     S1=2;
     while (sensorValue2>micThreshold && sensorCheck<micThreshold){
     detectTime = micros()-time1;
     if (detectTime >5880)// check if 1st detection is timed out 2 - 
     {
       NoDetect();
     }
      sensorCheck =0;
      sensorCheck = analogRead(1);
      if (sensorCheck>=micThreshold){ // While Mic 2 exceed threshold is true Check If Mic 1 exceeded the threshold
        time2= micros();
        sensorValue1 = sensorCheck;
        sensorCheck =0;
        S2=1;
        Action();
      }
      sensorCheck =0;
      sensorCheck = analogRead(3);
      if (sensorCheck>=micThreshold){ // While Mic 2 exceed threshold is true Check If Mic 3 exceeded the threshold
        time2= micros();
        sensorValue3 = sensorCheck;
        sensorCheck =0;
        S2=3;
        Action();
      }  
    }
  }
  
 // Check Mic 3
 //------------------------------
  sensorCheck =0;
  sensorCheck = analogRead(3);
  if (sensorCheck>=micThreshold){ // Check If Mic 3 exceeded the threshold, save S1 Var to 3, time1 to current micros()
     time1= micros();
     sensorValue3 = sensorCheck;
     sensorCheck=0;
     S1=3;
     while (sensorValue3>micThreshold && sensorCheck<micThreshold){ 
     detectTime = micros()-time1;
     if (detectTime >5880)// check if 1st detection is timed out 3 - 
     {
         NoDetect();
     }
      sensorCheck =0;
      sensorCheck = analogRead(1);
      if (sensorCheck>=micThreshold){ // While Mic 3 exceed threshold is true Check If Mic 1 exceeded the threshold
        time2= micros();
        sensorValue1 = sensorCheck;
        sensorCheck =0;
        S2=1;
        Action();
      }
      sensorCheck =0;
      sensorCheck = analogRead(2);
      if (sensorCheck>=micThreshold){ // While Mic 3 exceed threshold is true Check If Mic 2 exceeded the threshold
        time2= micros();
        sensorValue2 = sensorCheck;
        sensorCheck =0;
        S2=2;
        Action();
      }  
    }
  }
 }
}

void Action()
{
sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0);
SpeedOfSound = (331.3 + (.606*temp));
// Do 1st Triangulation between 1st and 2nd detection
calculatedMS1 = time2 - time1;
calculatedSeconds1=calculatedMS1 / 1000000;
DistA=(calculatedSeconds1 * SpeedOfSound);
BearingResult1 = (acos(DistA / LengthOfSide)*RadToDegrees)-30;
 if (S1==1 && S2==2){
 FinalBearing1 = 0 + BearingResult1;
 }
 if (S1==1 && S2==3){
 FinalBearing1 = 360 - BearingResult1;
 }
 if (S1==2 && S2==1){
 FinalBearing1 = 120 - BearingResult1;
 }
 if (S1==2 && S2==3){
 FinalBearing1 = 120 + BearingResult1;
 }
 if (S1==3 && S2==1){
 FinalBearing1 = 240 + BearingResult1;
 }
 if (S1==3 && S2==2){
 FinalBearing1 = 240 - BearingResult1;
 }
Serial.print("Mics");
Serial.print(S1);
Serial.print("-");
Serial.print(S2);
Serial.print("; Seconds between detections:");
Serial.print(calculatedSeconds1,10);
Serial.print("; Measured Distance:");
Serial.print(DistA,10);
Serial.print("; Calculated Bearing:");
Serial.print(BearingResult1,2);
Serial.print("; Compass Bearing:");
Serial.println(FinalBearing1,2);
sensorCheck=0;
delay(1000);
loop();
}

void NoDetect()
{
Serial.println("Not enough detection data, detection timed-out. At least 2 of the 3 microphones must detect the event");
loop();
}

Untitled Sketch 2_bb.svg|0x0

1 Like

PetrusBotha:
When connecting an Xbee I realized that the analog Read values are pushed up quite a lot, normal quiet environment reads will be in the range of 500 to 600, with the Xbee they are pushed to 900 or more. Is it an issue with power distribution or something affecting the RX/TX ports on the Arduino?

Probably RF noise intruding on your analog circuitry. To test this, temporarily replace the microphones with resistors (or switch them off, if they are switchable) then check your values with and without Xbee.

Attention to your analog ground path could help here, as might using sheilded cable to connect the mics if you aren't already. Also, capacitive low-pass filtering to get rid of high frequency hash may help.

With no information on your circuitry there's no way to judge where the analog noise might be coming from.

MarkT:
With no information on your circuitry there's no way to judge where the analog noise might be coming from.

(check the attachment to the original post, for the wiring)

I suggest you take the Vxx and Gnd for the Xbee from different pins (the ones at either the end of the 36-pin conector would be suitable) rather than running them to the breadboard where your analog circuitry is.

Depending on the microphones, you might need some sort of preamp between them and the analog inputs.

Nantonos:

MarkT:
With no information on your circuitry there's no way to judge where the analog noise might be coming from.

(check the attachment to the original post, for the wiring)

Well that (apparently) tells me only that you are using some sort of microphone module, not a microphone directly - is there information on that unit?

Secondly you seem to be running logic signals well away from the ground connection - all logic signals (being super-fast) ought ideally to run close to a ground line to keep stray inductance under control and to provide a return-path for the transients (otherwise you force that return path to be any near-by wire) - bundle the power supply and signal wires to the Xbee together for instance. And keep them fairly short.

I am using the sparkfun electret breakout board for sound collection which has a 100x opamp, and have not paid any attention to shielding, that might sort the issue, the xbee is a 900mhz Pro uFL. I will also power the xbee from another rail to see if it improves.

I had some success doing it some months back.
Check out rural hacker: Arduino MicLoc or an Acoustic Location System

I really didn't have time to publish code/schematics, but hope to do soon...

Just to post a follow up, you might be interested in checking rural hacker: MicLoc out.
I planned to release the schematics and code earlier, but I had no time on my hands.
Maybe it can still be of some help for your project.

Cheers,
kripthor