Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Miguel A LOPEZ-MONZON
Published

Triangulation of Sound

Imagine having the ability to detect a specific sound and triangulate its exact location.

IntermediateShowcase (no instructions)Over 3 days3,352
Triangulation of Sound

Things used in this project

Hardware components

Argon
Particle Argon
×1
Microphone Amplifier Breakout
Adafruit Microphone Amplifier Breakout
×3
LED Strip, NeoPixel Digital RGB
LED Strip, NeoPixel Digital RGB
×1
Adafruit MicroSD card breakout board+
×1

Software apps and online services

Visual Studio Code Extension for Arduino
Microsoft Visual Studio Code Extension for Arduino
Fritzing

Story

Read more

Schematics

Fritzing Diagram

Schematic

PowerPoint Presentation

Discusses the functionality of the project and what the components are being used for.

Code

Triangulation of Sound/Capstone Project

C/C++
/*
 * Project: Capstone_Project
 * Description: Triangulating sound to find precise location
 * Author:  Miguel Lopez
 * Date: 8/27/20
 */

#include <JsonParserGeneratorRk.h>
#include <neopixel.h>
#include <SPI.h>
#include <SdFat.h>

#define PIXEL_PIN A4
#define PIXEL_PIN2 A3
#define PIXEL_COUNT 31
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel pixelX(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
Adafruit_NeoPixel pixelY(PIXEL_COUNT, PIXEL_PIN2, PIXEL_TYPE);

const int chipSelect = SS;

#define FILE_BASE_NAME "Data"

SdFat sd;
SdFile file;

const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[13] = FILE_BASE_NAME "00.csv";

int micro1 = A0, micro2 = A1, micro3 = A2;  //Microphone analog inputs
int val1, val2, val3;                       //AnalogRead values
int T1 = 0, T2 = 0, T3 = 0;                 //Timing of sound for each microphone
int threshold = 3700;                       //Threshold that picks up loud sounds

int i;                                      //Variable for for loop
const int arraySize = 1024;                 //Size of the array
float soundWaveArray[1024][2];              //Two dimensional array capturing timestamp and soundwave
int lastTime;                               //Timestamp

float A, B;                                 //Getting A and B values from micros to seconds and multiplying by speed of sound             

float a, b, c;                              //Values for Quadratic Formula  
float T;                                    //Quadratic Formula
float X, Y;                                 //Position of Sound

float locationX, locationY;                   //Utilizing map-function to displah location using neopixels like on a quadrant
float pointX, pointY;
float longitude, latitude;

// setup() runs once, when the device is first turned on.
void setup() {
  // Put initialization like pinMode and begin functions here.
  Serial.begin(9600);

  pixelX.begin();
  pixelY.begin();
  pixelX.clear();
  pixelY.clear();

  pinMode(micro1, INPUT);
  pinMode(micro2, INPUT);
  pinMode(micro3, INPUT);

  if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) 
  {
    sd.initErrorHalt();  
  }

  if (BASE_NAME_SIZE > 6) 
  {
    Serial.println("FILE_BASE_NAME too long");
    while(1);
  }
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.
  showLocationWithNeopixels();
}

void simpleSoundTest()
{
  getMicrophoneValues();
   if(val1 > threshold || val2 > threshold || val3 > threshold)
   {
     Serial.printf("mic1 = %i | mic2 = %i | mic3 = %i | Time = %i\n",val1,val2,val3);
   }
}

void getTimingOfSound()
{
  delay(2000);
  T1 = 0;
  T2 = 0;
  T3 = 0;
  Serial.println("waiting for sound");
  while((T1 == 0) || (T2 == 0) || (T3 == 0))
  {
    getMicrophoneValues();
    if((T1 == 0) && (val1 > threshold))
    {
      T1 = micros();
    }
    if((T2 == 0) && (val2 > threshold))
    {
      T2 = micros();
    }
    if((T3 == 0) && (val3 > threshold))
    {
      T3 = micros();
    }
  }
  Serial.printf("T1 = %i | T2 = %i | T3 = %i\n",T1, T2, T3);
}

void getMicrophoneValues()
{
  val1 = analogRead(micro1);
  val2 = analogRead(micro2);
  val3 = analogRead(micro3);
  //Serial.printf("Microphone 1 = %i | Microphone 2 = %i | Microphone 3 = %i\n", val1, val2, val3);
}

void getTriangulationOfSound()
{
  getTimingOfSound();
  A = ((T2 - T1)/1000000.0)*343;               
  B = ((T3 - T1)/1000000.0)*343;             
  a = (sq(A) + sq(B)-1);            
  b = (((sq(A)-1)*A) + ((sq(B)-1)*B));      
  c = (sq(sq(A)-1)/4) + (sq(sq(B)-1)/4);  
  T = ((-b-sqrt(sq(b)-(4*a*c)))/(2*a)); 
  X = -((A*T) + ((sq(A)-1)/2));
  Y = -((B*T) + ((sq(B)-1)/2));
  Serial.printf("A = %0.6f | B = %0.6f\n", A, B);
  Serial.printf("T = %0.2f\n", T);
  Serial.printf("X = %0.2f | Y = %0.2f\n", X, Y);
  Serial.printf("a = %0.2f | b = %0.2f | c = %0.2f\n",a,b,c);
}

void showLocationWithNeopixels()
{
  recordLongitudeLatitudeData(longitude, latitude);
  getTriangulationOfSound();
  SDCard();
  pointX = X;
  locationX = map(pointX, 0.0, 1.0, 0.0, 31.0);
  longitude = map(pointX, 0.0, 1.0, -106.65136, -106.6496);
  pixelX.clear();
  pixelX.setPixelColor(locationX,255,0,0);
  pixelX.show();

  pointY = Y;
  locationY = map(pointY, 0.0, 1.0, 0.0, 31.0);
  latitude = map(pointX, 0.0, 1.0, 35.0866796, 35.088413);
  pixelY.clear();
  pixelY.setPixelColor(locationY,0,0,255);
  pixelY.show();
}

void recordLongitudeLatitudeData(float longitude, float latitude)
{
  JsonWriterStatic<256> jw;
  {
    JsonWriterAutoObject obj(&jw);

    jw.insertKeyValue("Longitude", longitude);
    jw.insertKeyValue("Latitude", latitude);
  }
  Particle.publish("Noise",jw.getBuffer(), PRIVATE);
  Serial.printf("Longitude: %0.7f| Latitude: %0.7f\n", longitude, latitude);
}

void soundWaveCapture()
{
  if(val1 > threshold)
  {
    for(i =0 ; i < arraySize ; i++)
    {
      while(micros()-lastTime < 500)
      {
        //do nothing
      }
      lastTime = micros();
      getMicrophoneValues();
      soundWaveArray[i][1] = val1;
    }
  }
}

void SDCard()
{
  Serial.printf("Starting Data Logging \n");

  while (sd.exists(fileName)) 
  {
    if (fileName[BASE_NAME_SIZE + 1] != '9') 
    {
      fileName[BASE_NAME_SIZE + 1]++;
    } 
    else if (fileName[BASE_NAME_SIZE] != '9') 
    {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } 
    else 
    {
      Serial.println("Can't create file name");
      while(1);
    }
  }

  if (!file.open(fileName, O_WRONLY | O_CREAT | O_EXCL)) 
  {
    Serial.println("file.open");
  }
  Serial.printf("Logging to: %s \n",fileName);

  //For Loop here for array capturing sound
  if(val1 > threshold)
  {
    for(i = 0 ; i < arraySize ; i++)
    {
      while(micros()-lastTime < 500)
      {
        //do nothing
      }
      lastTime = micros();
      getMicrophoneValues();
      soundWaveArray[i][0] = micros()/1000000.0;
      soundWaveArray[i][1] = val1;
    }
  }
  for(i = 0; i < arraySize; i++)
  {
    file.printf("%0.8f , %0.2f\n",soundWaveArray[i][0], soundWaveArray[i][1]);
  }
  file.close();
  Serial.printf("Done \n");
  delay(2000);
  Serial.printf("Ready for next data log \n");
}

Credits

Miguel A LOPEZ-MONZON
3 projects • 6 followers
My name is Miguel Lopez, I am a student at the IoT Bootcamp in New Mexico which focuses on implementing smart devices to the real world.
Contact

Comments

Please log in or sign up to comment.