Time division Multiplexing(TDM) for multilateration(TDOA) using mics from invensense

Status
Not open for further replies.
Could this TDM input be used to capture 6 guitar pickups, and send them each to their own FFT1024 object in the Audio Library?
@graydetroit might be able to use that.
 
Last edited:
Well, I'm not sure. The TDM object works for my application because the microphones I am using are configured to put out a TDM signal. TDM is best suited for sending audio data from many inputs down one line and in a way that the data can be separated on the other end. I think Paul has developed a board for collecting multiple mic inputs that can be used with the audio library. But this is the wrong place to ask about the TDM object for your application. you can get much better help if you start your own thread in the project guidance category.

my apologies, I see from reading your recent posts you were asking for someone else's application. Still I'm not sure how to interface the guitar pickups and use the TDM object. @graydetroit could use the mics im using instead of pickups but I'm not sure he would want to do that.
 
Last edited:
Running 6 simultaneous FFT 1024 will require some trickery. You'll need to schedule things so each CPU intensive FFT operation is done in a different 128 sample update slot. There are 8 of those updates per 1024 samples, so this should be possible. But if you just put 6 of the regular FFT1024 objects into your design, they could (and probably will) end up trying to do the CPU intensive work during the same update.
 
Hmmm,

I imagine the Teensy 3.6 would be better suited.
I also assume from your post that simply calling available() for each FFT one at a time would not solve the problem.
Is the problem that an FFT is in "case 7:" in the code when another FFT gets to that same case - and that a conflict might cause a delay for sampling or another critically-timed interrupt?

If that's the case, could a global "busy flag" allow only one FFT at a time to run "case 7:", and others would simply wait?
 
By the way, I noticed that the code I had last posted had made the whole collection of data backwards (earliest data at the end and newest data at the beginning) so I'll post my updated code for others.
Code:
#include <Audio.h>

AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);



int16_t* queue1DataA;
int16_t* queue2DataA;
int16_t* queue3DataA;
int16_t* queue4DataA;
int16_t* queue5DataA;
int16_t* queue6DataA;
int16_t* queue7DataA;
int16_t* queue8DataA;
int16_t* queue9DataA;
int16_t* queue10DataA;
int16_t* queue1DataB;
int16_t* queue2DataB;
int16_t* queue3DataB;
int16_t* queue4DataB;
int16_t* queue5DataB;
int16_t* queue6DataB;
int16_t* queue7DataB;
int16_t* queue8DataB;
int16_t* queue9DataB;
int16_t* queue10DataB;
int16_t* queue1DataC;
int16_t* queue2DataC;
int16_t* queue3DataC;
int16_t* queue4DataC;
int16_t* queue5DataC;
int16_t* queue6DataC;
int16_t* queue7DataC;
int16_t* queue8DataC;
int16_t* queue9DataC;
int16_t* queue10DataC;

int16_t* queue1DataD;
int16_t* queue2DataD;
int16_t* queue3DataD;
int16_t* queue4DataD;
int16_t* queue5DataD;
int16_t* queue6DataD;
int16_t* queue7DataD;
int16_t* queue8DataD;
int16_t* queue9DataD;
int16_t* queue10DataD;

int16_t* queue1DataE;
int16_t* queue2DataE;
int16_t* queue3DataE;
int16_t* queue4DataE;
int16_t* queue5DataE;
int16_t* queue6DataE;
int16_t* queue7DataE;
int16_t* queue8DataE;
int16_t* queue9DataE;
int16_t* queue10DataE;

int16_t* queue1DataF;
int16_t* queue2DataF;
int16_t* queue3DataF;
int16_t* queue4DataF;
int16_t* queue5DataF;
int16_t* queue6DataF;
int16_t* queue7DataF;
int16_t* queue8DataF;
int16_t* queue9DataF;
int16_t* queue10DataF;

int16_t* queue1DataG;
int16_t* queue2DataG;
int16_t* queue3DataG;
int16_t* queue4DataG;
int16_t* queue5DataG;
int16_t* queue6DataG;
int16_t* queue7DataG;
int16_t* queue8DataG;
int16_t* queue9DataG;
int16_t* queue10DataG;

int16_t* queue1DataH;
int16_t* queue2DataH;
int16_t* queue3DataH;
int16_t* queue4DataH;
int16_t* queue5DataH;
int16_t* queue6DataH;
int16_t* queue7DataH;
int16_t* queue8DataH;
int16_t* queue9DataH;
int16_t* queue10DataH;

int16_t* queue1DataI;
int16_t* queue2DataI;
int16_t* queue3DataI;
int16_t* queue4DataI;
int16_t* queue5DataI;
int16_t* queue6DataI;
int16_t* queue7DataI;
int16_t* queue8DataI;
int16_t* queue9DataI;
int16_t* queue10DataI;

int16_t* queue1DataJ;
int16_t* queue2DataJ;
int16_t* queue3DataJ;
int16_t* queue4DataJ;
int16_t* queue5DataJ;
int16_t* queue6DataJ;
int16_t* queue7DataJ;
int16_t* queue8DataJ;
int16_t* queue9DataJ;
int16_t* queue10DataJ;

int sig1;
int sig2;
int sig3;
int sig4;
int sig5;
int thresh = 50000;
int rowCounter;
int mic1[2176];
int mic2[2176];
int mic3[2176];
int mic4[2176];
int mic5[2176];
bool tripped = false;
int rowPrinter=0; 



void setup() {
  Serial.begin(9600);

  AudioMemory(512);
  
  // put your setup code here, to run once:
  rowPrinter=0;
  queue1.begin();
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();
}
 


void printMics(int sendex)
{  
  for (int i = 0; i < sendex; i++)
  {
    rowPrinter++;
    sig1 = mic1[i];
    sig2 = mic2[i];
    sig3 = mic3[i];
    sig4 = mic4[i];
    sig5 = mic5[i];
    Serial.print(rowPrinter);
    if(sig1>=10 || sig1<=-10)
    {
      if(sig1>=100 || sig1<=-100)
      {
        if(sig1>=1000 || sig1<=-1000)
        {
          if(sig1>=10000 || sig1<=-10000)
          {
            if(sig1>=100000 || sig1<=-100000)
            {
              if(sig1>=1000000 || sig1<=-1000000)
              {
                if(sig1>=10000000 || sig1<=-10000000)
                {
                  Serial.print(", ");
                }
                else
                {
                  Serial.print(",  ");
                }
              }
              else
              {
                Serial.print(",  ");
              }
              
            }
            else
            {
              Serial.print(",   ");
            }
          }
          else
          {
            Serial.print(",    ");
          }
        }
        else
        {
          Serial.print(",     ");
        }
      }
      else
      {
        Serial.print(",      ");
      }
        
    }
    else
    {
      Serial.print(",       ");
    }
    if(sig1>0)
      {
        Serial.print(" ");
      }
    Serial.print(sig1);
    if(sig2>=10 || sig2<=-10)
    {
      if(sig2>=100 || sig2<=-100)
      {
        if(sig2>=1000 || sig2<=-1000)
        {
          if(sig2>=10000 || sig2<=-10000)
          {
            if(sig2>=100000 || sig2<=-100000)
            {
              if(sig2>=1000000 || sig2<=-1000000)
              {
                if(sig2>=10000000 || sig2<=-10000000)
                {
                  Serial.print(", ");
                }
                else
                {
                  Serial.print(",  ");
                }
              }
              else
              {
                Serial.print(",  ");
              }
              
            }
            else
            {
              Serial.print(",   ");
            }
          }
          else
          {
            Serial.print(",    ");
          }
        }
        else
        {
          Serial.print(",     ");
        }
      }
      else
      {
        Serial.print(",      ");
      }
      
    }
    else
    {
      Serial.print(",       ");
    }
    if(sig1>0)
      {
        Serial.print(" ");
      }
      
    Serial.print(sig2);
    if(sig3>=10 || sig3<=-10)
    {
      if(sig3>=100 || sig3<=-100)
      {
        if(sig3>=1000 || sig3<=-1000)
        {
          if(sig3>=10000 || sig3<=-10000)
          {
            if(sig3>=100000 || sig3<=-100000)
            {
              if(sig3>=1000000 || sig3<=-1000000)
              {
                if(sig3>=10000000 || sig3<=-10000000)
                {
                  Serial.print(", ");
                }
                else
                {
                  Serial.print(",  ");
                }
              }
              else
              {
                Serial.print(",  ");
              }
              
            }
            else
            {
              Serial.print(",   ");
            }
          }
          else
          {
            Serial.print(",    ");
          }
        }
        else
        {
          Serial.print(",     ");
        }
      }
      else
      {
        Serial.print(",      ");
      }
      
    }
    else
    {
      Serial.print(",       ");
    }
    if(sig1>0)
      {
        Serial.print(" ");
      }
      
    Serial.print(sig3);
    if(sig4>=10 || sig4<=-10)
    {
      if(sig4>=100 || sig4<=-100)
      {
        if(sig4>=1000 || sig4<=-1000)
        {
          if(sig4>=10000 || sig4<=-10000)
          {
            if(sig4>=100000 || sig4<=-100000)
            {
              if(sig4>=1000000 || sig4<=-1000000)
              {
                if(sig4>=10000000 || sig4<=-10000000)
                {
                  Serial.print(", ");
                }
                else
                {
                  Serial.print(",  ");
                }
              }
              else
              {
                Serial.print(",  ");
              }
              
            }
            else
            {
              Serial.print(",   ");
            }
          }
          else
          {
            Serial.print(",    ");
          }
        }
        else
        {
          Serial.print(",     ");
        }
      }
      else
      {
        Serial.print(",      ");
      }
      
    }
    else
    {
      Serial.print(",       ");
    }
    if(sig1>0)
      {
        Serial.print(" ");
      }
      
    Serial.print(sig4);
    if(sig5>=10 || sig5<=-10)
    {
      if(sig5>=100 || sig5<=-100)
      {
        if(sig5>=1000 || sig5<=-1000)
        {
          if(sig5>=10000 || sig5<=-10000)
          {
            if(sig5>=100000 || sig5<=-100000)
            {
              if(sig5>=1000000 || sig5<=-1000000)
              {
                if(sig5>=10000000 || sig5<=-10000000)
                {
                  Serial.print(", ");
                }
                else
                {
                  Serial.print(",  ");
                }
              }
              else
              {
                Serial.print(",  ");
              }
              
            }
            else
            {
              Serial.print(",   ");
            }
          }
          else
          {
            Serial.print(",    ");
          }
        }
        else
        {
          Serial.print(",     ");
        }
      }
      else
      {
        Serial.print(",      ");
      }
      
    }
    else
    {
      Serial.print(",       ");
    }
    if(sig1>0)
      {
        Serial.print(" ");
      }
      
    Serial.print(sig5);
    Serial.print(", ");
    Serial.println(i);
    delay(1);
    
  }
  
}
void loop() {
  // put your main code here, to run repeatedly:
  if (queue1.available()>9 && queue2.available()>9 && queue3.available()>9 && queue4.available()>9 && queue5.available()>9 && queue6.available()>9 && queue7.available()>9 && queue8.available()>9 && queue9.available()>9 && queue10.available()>9)
  {
    
    queue1.end();
    queue2.end();
    queue3.end();
    queue4.end();
    queue5.end();
    queue6.end();
    queue7.end();
    queue8.end();
    queue9.end();
    queue10.end();

    queue1DataA = queue1.readBuffer();
    queue2DataA = queue2.readBuffer();
    queue3DataA = queue3.readBuffer();
    queue4DataA = queue4.readBuffer();
    queue5DataA = queue5.readBuffer();
    queue6DataA = queue6.readBuffer();
    queue7DataA = queue7.readBuffer();
    queue8DataA = queue8.readBuffer();
    queue9DataA = queue9.readBuffer();
    queue10DataA = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();


    queue1DataB = queue1.readBuffer();
    queue2DataB = queue2.readBuffer();
    queue3DataB = queue3.readBuffer();
    queue4DataB = queue4.readBuffer();
    queue5DataB = queue5.readBuffer();
    queue6DataB = queue6.readBuffer();
    queue7DataB = queue7.readBuffer();
    queue8DataB = queue8.readBuffer();
    queue9DataB = queue9.readBuffer();
    queue10DataB = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    queue1DataC = queue1.readBuffer();
    queue2DataC = queue2.readBuffer();
    queue3DataC = queue3.readBuffer();
    queue4DataC = queue4.readBuffer();
    queue5DataC = queue5.readBuffer();
    queue6DataC = queue6.readBuffer();
    queue7DataC = queue7.readBuffer();
    queue8DataC = queue8.readBuffer();
    queue9DataC = queue9.readBuffer();
    queue10DataC = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    queue1DataD = queue1.readBuffer();
    queue2DataD = queue2.readBuffer();
    queue3DataD = queue3.readBuffer();
    queue4DataD = queue4.readBuffer();
    queue5DataD = queue5.readBuffer();
    queue6DataD = queue6.readBuffer();
    queue7DataD = queue7.readBuffer();
    queue8DataD = queue8.readBuffer();
    queue9DataD = queue9.readBuffer();
    queue10DataD = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    queue1DataE = queue1.readBuffer();
    queue2DataE = queue2.readBuffer();
    queue3DataE = queue3.readBuffer();
    queue4DataE = queue4.readBuffer();
    queue5DataE = queue5.readBuffer();
    queue6DataE = queue6.readBuffer();
    queue7DataE = queue7.readBuffer();
    queue8DataE = queue8.readBuffer();
    queue9DataE = queue9.readBuffer();
    queue10DataE = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

     queue1DataF = queue1.readBuffer();
    queue2DataF = queue2.readBuffer();
    queue3DataF = queue3.readBuffer();
    queue4DataF = queue4.readBuffer();
    queue5DataF = queue5.readBuffer();
    queue6DataF = queue6.readBuffer();
    queue7DataF = queue7.readBuffer();
    queue8DataF = queue8.readBuffer();
    queue9DataF = queue9.readBuffer();
    queue10DataF = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    queue1DataG = queue1.readBuffer();
    queue2DataG = queue2.readBuffer();
    queue3DataG = queue3.readBuffer();
    queue4DataG = queue4.readBuffer();
    queue5DataG = queue5.readBuffer();
    queue6DataG = queue6.readBuffer();
    queue7DataG = queue7.readBuffer();
    queue8DataG = queue8.readBuffer();
    queue9DataG = queue9.readBuffer();
    queue10DataG = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    queue1DataH = queue1.readBuffer();
    queue2DataH = queue2.readBuffer();
    queue3DataH = queue3.readBuffer();
    queue4DataH = queue4.readBuffer();
    queue5DataH = queue5.readBuffer();
    queue6DataH = queue6.readBuffer();
    queue7DataH = queue7.readBuffer();
    queue8DataH = queue8.readBuffer();
    queue9DataH = queue9.readBuffer();
    queue10DataH = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    queue1DataI = queue1.readBuffer();
    queue2DataI = queue2.readBuffer();
    queue3DataI = queue3.readBuffer();
    queue4DataI = queue4.readBuffer();
    queue5DataI = queue5.readBuffer();
    queue6DataI = queue6.readBuffer();
    queue7DataI = queue7.readBuffer();
    queue8DataI = queue8.readBuffer();
    queue9DataI = queue9.readBuffer();
    queue10DataI = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();
        
    queue1DataJ = queue1.readBuffer();
    queue2DataJ = queue2.readBuffer();
    queue3DataJ = queue3.readBuffer();
    queue4DataJ = queue4.readBuffer();
    queue5DataJ = queue5.readBuffer();
    queue6DataJ = queue6.readBuffer();
    queue7DataJ = queue7.readBuffer();
    queue8DataJ = queue8.readBuffer();
    queue9DataJ = queue9.readBuffer();
    queue10DataJ = queue10.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    queue3.freeBuffer();
    queue4.freeBuffer();
    queue5.freeBuffer();
    queue6.freeBuffer();
    queue7.freeBuffer();
    queue8.freeBuffer();
    queue9.freeBuffer();
    queue10.freeBuffer();

    
    
    
    
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataA[i] << 8) + (queue2DataA[i] >> 8);
      sig2 = (queue3DataA[i] << 8) + (queue4DataA[i] >> 8);
      sig3 = (queue5DataA[i] << 8) + (queue6DataA[i] >> 8);
      sig4 = (queue7DataA[i] << 8) + (queue8DataA[i] >> 8);
      sig5 = (queue9DataA[i] << 8) + (queue10DataA[i] >> 8);

      mic1[i]=sig1;
      mic2[i]=sig2;
      mic3[i]=sig3;
      mic4[i]=sig4;
      mic5[i]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataB[i] << 8) + (queue2DataB[i] >> 8);
      sig2 = (queue3DataB[i] << 8) + (queue4DataB[i] >> 8);
      sig3 = (queue5DataB[i] << 8) + (queue6DataB[i] >> 8);
      sig4 = (queue7DataB[i] << 8) + (queue8DataB[i] >> 8);
      sig5 = (queue9DataB[i] << 8) + (queue10DataB[i] >> 8);

      mic1[i+128]=sig1;
      mic2[i+128]=sig2;
      mic3[i+128]=sig3;
      mic4[i+128]=sig4;
      mic5[i+128]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataC[i] << 8) + (queue2DataC[i] >> 8);
      sig2 = (queue3DataC[i] << 8) + (queue4DataC[i] >> 8);
      sig3 = (queue5DataC[i] << 8) + (queue6DataC[i] >> 8);
      sig4 = (queue7DataC[i] << 8) + (queue8DataC[i] >> 8);
      sig5 = (queue9DataC[i] << 8) + (queue10DataC[i] >> 8);

      mic1[i+256]=sig1;
      mic2[i+256]=sig2;
      mic3[i+256]=sig3;
      mic4[i+256]=sig4;
      mic5[i+256]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataD[i] << 8) + (queue2DataD[i] >> 8);
      sig2 = (queue3DataD[i] << 8) + (queue4DataD[i] >> 8);
      sig3 = (queue5DataD[i] << 8) + (queue6DataD[i] >> 8);
      sig4 = (queue7DataD[i] << 8) + (queue8DataD[i] >> 8);
      sig5 = (queue9DataD[i] << 8) + (queue10DataD[i] >> 8);

      mic1[i+384]=sig1;
      mic2[i+384]=sig2;
      mic3[i+384]=sig3;
      mic4[i+384]=sig4;
      mic5[i+384]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataE[i] << 8) + (queue2DataE[i] >> 8);
      sig2 = (queue3DataE[i] << 8) + (queue4DataE[i] >> 8);
      sig3 = (queue5DataE[i] << 8) + (queue6DataE[i] >> 8);
      sig4 = (queue7DataE[i] << 8) + (queue8DataE[i] >> 8);
      sig5 = (queue9DataE[i] << 8) + (queue10DataE[i] >> 8);

      mic1[i+512]=sig1;
      mic2[i+512]=sig2;
      mic3[i+512]=sig3;
      mic4[i+512]=sig4;
      mic5[i+512]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataF[i] << 8) + (queue2DataF[i] >> 8);
      sig2 = (queue3DataF[i] << 8) + (queue4DataF[i] >> 8);
      sig3 = (queue5DataF[i] << 8) + (queue6DataF[i] >> 8);
      sig4 = (queue7DataF[i] << 8) + (queue8DataF[i] >> 8);
      sig5 = (queue9DataF[i] << 8) + (queue10DataF[i] >> 8);

      mic1[i+640]=sig1;
      mic2[i+640]=sig2;
      mic3[i+640]=sig3;
      mic4[i+640]=sig4;
      mic5[i+640]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataG[i] << 8) + (queue2DataG[i] >> 8);
      sig2 = (queue3DataG[i] << 8) + (queue4DataG[i] >> 8);
      sig3 = (queue5DataG[i] << 8) + (queue6DataG[i] >> 8);
      sig4 = (queue7DataG[i] << 8) + (queue8DataG[i] >> 8);
      sig5 = (queue9DataG[i] << 8) + (queue10DataG[i] >> 8);

      mic1[i+768]=sig1;
      mic2[i+768]=sig2;
      mic3[i+768]=sig3;
      mic4[i+768]=sig4;
      mic5[i+768]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataH[i] << 8) + (queue2DataH[i] >> 8);
      sig2 = (queue3DataH[i] << 8) + (queue4DataH[i] >> 8);
      sig3 = (queue5DataH[i] << 8) + (queue6DataH[i] >> 8);
      sig4 = (queue7DataH[i] << 8) + (queue8DataH[i] >> 8);
      sig5 = (queue9DataH[i] << 8) + (queue10DataH[i] >> 8);

      mic1[i+896]=sig1;
      mic2[i+896]=sig2;
      mic3[i+896]=sig3;
      mic4[i+896]=sig4;
      mic5[i+896]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataI[i] << 8) + (queue2DataI[i] >> 8);
      sig2 = (queue3DataI[i] << 8) + (queue4DataI[i] >> 8);
      sig3 = (queue5DataI[i] << 8) + (queue6DataI[i] >> 8);
      sig4 = (queue7DataI[i] << 8) + (queue8DataI[i] >> 8);
      sig5 = (queue9DataI[i] << 8) + (queue10DataI[i] >> 8);

      mic1[i+1024]=sig1;
      mic2[i+1024]=sig2;
      mic3[i+1024]=sig3;
      mic4[i+1024]=sig4;
      mic5[i+1024]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    for (int i = 0; i < 128; i++)
    {   

      sig1 = (queue1DataJ[i] << 8) + (queue2DataJ[i] >> 8);
      sig2 = (queue3DataJ[i] << 8) + (queue4DataJ[i] >> 8);
      sig3 = (queue5DataJ[i] << 8) + (queue6DataJ[i] >> 8);
      sig4 = (queue7DataJ[i] << 8) + (queue8DataJ[i] >> 8);
      sig5 = (queue9DataJ[i] << 8) + (queue10DataJ[i] >> 8);

      mic1[i+1152]=sig1;
      mic2[i+1152]=sig2;
      mic3[i+1152]=sig3;
      mic4[i+1152]=sig4;
      mic5[i+1152]=sig5;
      
      if (!tripped && ((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)))
      {
        tripped = true;
      } 
      rowCounter++; 
    }
    
    

    if(tripped)
    {
      printMics(rowCounter);
      tripped = false;
    }
    rowCounter=0;
    
    queue1.clear();
    queue2.clear();
    queue3.clear();
    queue4.clear();
    queue5.clear();
    queue6.clear();
    queue7.clear();
    queue8.clear();
    queue9.clear();
    queue10.clear();
    
    
    queue1.begin();
    queue2.begin();
    queue3.begin();
    queue4.begin();
    queue5.begin();
    queue6.begin();
    queue7.begin();
    queue8.begin();
    queue9.begin();
    queue10.begin();
    
  }
  if (Serial.available())
  {
    if (Serial.read() == '0') 
    {
      rowPrinter=0;
    }
    
  }
}

this code collects 1280 data points from 5 mics, checks each mic to see if it has crossed a threshold, then it prints that data to the serial monitor(if the threshold was crossed), the first column is the sample number (this can increment above 1280 but there will be a gap of missing time between chunks of data),
the 5 middle columns are the 24 bit sample data, and the last column is the index of each sample. if you type a '0' into the serial monitor it will reset the sample number.
 
Last edited:
I built the microphone array and I have started to collect data. I've been using the data to locate the sound source. Here is a plot of the microphone array:
position 2.png
The array is in the shape of a tetrahedron with one at the center. the red triangle is the speaker's measured location, and the blue dot is what the algorithm reports for the sound's origin (using the signal delays between the mics). It was only 3 cm off at 2 meters away. I have some more adjustments to make for optimization but so far this is excellent. Thank you so much guys, I couldn't have done it without you.
Paul, the Audio library is awesome and it works well with the ICS-52000 mics. Thank you for an awesome microcontroller and even more awesome support.
 
I originally started this project for fun, I was getting too obsessed, so my wife told me to stop. I needed one more lab class to finish my physics undergraduate degree, I found a class called fundamentals of measurement and instrumentation. For the last half of the semester they allowed us to do a self directed experiment, so the microphone array was back on! I have recently finished characterizing the microphone array and wrote a report about it. here is a preview:
ReportPreview.png
and here is a link to this paper:
https://drive.google.com/file/d/1EK8QcsiJBpGliD8YHm8h3E1lpIwYGkYZ/view?usp=sharing.
Thank you all for your help. This was a fun project.
 
Nice work,
I only wanted to correct Andersen (the work you quote in your write-up) and others wo claim the same. You do not NEED 5 sensors but only 4 to obtain a linear set of equations. With 4 sensors you can form up to 6 independent sensor pairs and time delays and therefore easily obtain a solution for the 4 unknowns (x,y,z,R).
 
I believe you are correct, I can visualize it now. It would be good for me to reevaluate the math anyway. Thank you.
 
I only wanted to correct Andersen (the work you quote in your write-up) and others wo claim the same. You do not NEED 5 sensors but only 4 to obtain a linear set of equations. With 4 sensors you can form up to 6 independent sensor pairs and time delays and therefore easily obtain a solution for the 4 unknowns (x,y,z,R).
Sorry, I have to correct myself: for estimating 3-d distance (localization) you need 5 Sensors for a linear set of equations as said by Andersen. For estimating 3-d direction yo need only four sensors. Andersen talks about localization with widely distributed sensors and not direction finding. So he is correct.
Only excuse is that tetrahedral arrays, as shown in your write-up, are typically used for direction finding. However, they can be used for close-by localization. All depends on the distance of the source from the sensor array. However, all my applications use tetrahedral arrays for direction finding and not close-by localization, so I was somewhat biased.
 
Sorry, I have to correct myself: for estimating 3-d distance (localization) you need 5 Sensors for a linear set of equations as said by Andersen. For estimating 3-d direction yo need only four sensors. Andersen talks about localization with widely distributed sensors and not direction finding. So he is correct.
Only excuse is that tetrahedral arrays, as shown in your write-up, are typically used for direction finding. However, they can be used for close-by localization. All depends on the distance of the source from the sensor array. However, all my applications use tetrahedral arrays for direction finding and not close-by localization, so I was somewhat biased.

HI WMXZ,

Some one has successfully connected the ICS52000 with Teensy 3.6 .

Dreggory was not using the NW-AUD-ICS52000 notWired.co Breakout Board,
but connecting to the ICS52000 directly.

A great good news. :cool:

I will try to fellow Dreggory' work.
 
I tried 3 different NW-AUD-ICS52000 boards. all with the same result: noise only.
As I have actually no need for multi-mic system, I put notWired.co boards back into storage.

Maybe i can try my luck with I2S.
What is the maximum number of i2s microphones, such as the ICS43434, can the Teensy 4.1 connect with?:confused:
 
Maybe i can try my luck with I2S.
What is the maximum number of i2s microphones, such as the ICS43434, can the Teensy 4.1 connect with?:confused:

Unfortunately, ICS43434 is true I2S with L/R signal, so, I guess, you can only connect two per data line. on Teensy 4.1 you then can connect 8 mics on the t4 .1 data input lines.
 
Unfortunately, ICS43434 is true I2S with L/R signal, so, I guess, you can only connect two per data line. on Teensy 4.1 you then can connect 8 mics on the t4 .1 data input lines.

That is a sad news. we need to use 64 or more microphone at the same time.

Can you have a try of the ICS52000 microphone directly rather than using the the notwird board? :confused:
dreggory have successfully use the microphone directly.
 
That is a sad news. we need to use 64 or more microphone at the same time.

Can you have a try of the ICS52000 microphone directly rather than using the the notwird board? :confused:
dreggory have successfully use the microphone directly.

I have no single ICS52000 and on travel for the next 3 weeks.
 
this suggestion didn't work but I am intrigued, the % has always confused me. but I got the code working nicely, here it is for all who care:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>


// GUItool: begin automatically generated code
AudioInputTDM            tdm1;           //xy=172,228
AudioRecordQueue         queue9;         //xy=428,202
AudioRecordQueue         queue7;         //xy=430,159
AudioRecordQueue         queue5;         //xy=434,117
AudioRecordQueue         queue1;         //xy=439,34
AudioRecordQueue         queue3;         //xy=439,78
AudioRecordQueue         queue6;         //xy=554,118
AudioRecordQueue         queue8;         //xy=554,159
AudioRecordQueue         queue10;        //xy=554,201
AudioRecordQueue         queue2;         //xy=559,35
AudioRecordQueue         queue4;         //xy=559,77
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
AudioConnection          patchCord5(tdm1, 4, queue5, 0);
AudioConnection          patchCord6(tdm1, 5, queue6, 0);
AudioConnection          patchCord7(tdm1, 6, queue7, 0);
AudioConnection          patchCord8(tdm1, 7, queue8, 0);
AudioConnection          patchCord9(tdm1, 8, queue9, 0);
AudioConnection          patchCord10(tdm1, 9, queue10, 0);


// GUItool: end automatically generated code


int16_t* spot1 ; //I might know what I'm doing now... a little bit(thanks Paul, mlu, WMXZ and tni) - Greg
int16_t* spot2 ;
int16_t* spot3 ;
int16_t* spot4 ; 
int16_t* spot5 ; 
int16_t* spot6 ;
int16_t* spot7 ;
int16_t* spot8 ;
int16_t* spot9 ; 
int16_t* spot10 ;
int sig1;
int sig2;
int sig3;
int sig4;
int sig5;
bool sp1 = false;
bool sp2 = false;
bool sp3 = false;
bool sp4 = false;
bool sp5 = false;
bool sp6 = false;
bool sp7 = false;
bool sp8 = false;
bool sp9 = false;
bool sp10 = false;
bool tripped = false;
bool filling = false;
bool historyArrayFull = false;
long thresh=50000;
long lastThresh;
long mic1[30];
long mic2[30];
long mic3[30];
long mic4[30];
long mic5[30];
long sendMics[128][5];
byte ndex=0;
byte sendex=30;
byte i=0;
byte indexWrap;
byte indexTailLength;
int datacount = -1;

int16_t dummybuffer[128];   /* Holds dummy values if a queuebuffer is not found */

void setup() 
{
  // << nothing before the first delay will be printed to the serial
  Serial.begin(9600);
  
  AudioMemory(256);
  queue1.begin();//I thought I should enable 
  queue2.begin();
  queue3.begin();
  queue4.begin();
  queue5.begin();
  queue6.begin();
  queue7.begin();
  queue8.begin();
  queue9.begin();
  queue10.begin();

  for (int k=0; k<128; k++) dummybuffer[k] = -1; /* dummybuffer in case read from queue fails */
}

void loop() 
{

  if((queue1.available() > 0)&&(datacount == -1)) /* Buffers are empty and queues have new data */
  {
    spot1=queue1.readBuffer(); 
    spot2=queue2.readBuffer(); 
    spot3=queue3.readBuffer(); 
    spot4=queue4.readBuffer(); 
    spot5=queue5.readBuffer(); 
    spot6=queue6.readBuffer(); 
    spot7=queue7.readBuffer(); 
    spot8=queue8.readBuffer(); 
    spot9=queue9.readBuffer(); 
    spot10=queue10.readBuffer(); 

    /* Here we can check that there is actually a block available in every queue, this shouldnt happen but will show up in output data */
    if (spot1==NULL) spot1 = dummybuffer;
    if (spot2==NULL) spot2 = dummybuffer;
    if (spot3==NULL) spot3 = dummybuffer;
    if (spot4==NULL) spot4 = dummybuffer;
    if (spot5==NULL) spot5 = dummybuffer;
    if (spot6==NULL) spot6 = dummybuffer;
    if (spot7==NULL) spot7 = dummybuffer;
    if (spot8==NULL) spot8 = dummybuffer;
    if (spot9==NULL) spot9 = dummybuffer;
    if (spot10==NULL) spot10 = dummybuffer;
    
    datacount = 128;
  }

  if (datacount>0)  /* Data in buffers to process, read next i of samples from buffers */
  {
    sig1 = spot1[128-datacount]*256 + spot2[128-datacount]/256;
    sig2 = spot3[128-datacount]*256 + spot4[128-datacount]/256;
    sig3 = spot5[128-datacount]*256 + spot6[128-datacount]/256;
    sig4 = spot7[128-datacount]*256 + spot8[128-datacount]/256;
    sig5 = spot9[128-datacount]*256 + spot10[128-datacount]/256;
    datacount--;

    if (filling)
    {
      sendMics[sendex][0]=sig1;
      sendMics[sendex][1]=sig2;
      sendMics[sendex][2]=sig3;
      sendMics[sendex][3]=sig4;
      sendMics[sendex][4]=sig5;
      sendex++;
    }
    else
    {
      mic1[ndex]=sig1;
      mic2[ndex]=sig2;
      mic3[ndex]=sig3;
      mic4[ndex]=sig4;
      mic5[ndex]=sig5;
      ndex++;
    }

  }
  else return;           /* No data has been processed so return */

  if(datacount == 0)     /* Buffers has been fully read, free them */
  {
    queue1.freeBuffer(); 
    queue2.freeBuffer(); 
    queue3.freeBuffer(); 
    queue4.freeBuffer(); 
    queue5.freeBuffer(); 
    queue6.freeBuffer(); 
    queue7.freeBuffer(); 
    queue8.freeBuffer(); 
    queue9.freeBuffer(); 
    queue10.freeBuffer(); 

    datacount = -1;
  }

  /* If we arrive here a new row of samples has been read, now process this row */

  if(ndex>=30)
  {
    ndex=0;
  }

  
  if (((sig1 >= thresh || sig1 <= -thresh) || (sig2 >= thresh || sig2 <= -thresh) || (sig3 >= thresh || sig3 <= -thresh) || (sig4 >= thresh || sig4 <= -thresh) || (sig5 >= thresh || sig5 <= -thresh)) && !filling)
  {
    tripped = true;
  }
  else
  {
    if (lastThresh>thresh)
    {
      //Serial.println(thresh);
      lastThresh=thresh;
    }
    
  }
  if (tripped)
  {  
      indexWrap = ndex;  //indexWrap is the indice of the oldest value in the "history arrays" (mic1,mic2,...)
      indexTailLength = 29-ndex;  //the remaining number of indices(if any) in the history arrays.
      filling = true;
      tripped = false;
  }
  if (filling)
  {
    if(sendex > 127)
    {
        queue1.end();//I thought I should disable while it takes it's time filling and printing the final array.  
        queue2.end();
        queue3.end();
        queue4.end();
        queue5.end();
        queue6.end();
        queue7.end();
        queue8.end();
        queue9.end();
        queue10.end();
        for (i=0; i <= indexTailLength; i++)
        {
          sendMics[i][0]=mic1[i+indexWrap];
          sendMics[i][1]=mic2[i+indexWrap];
          sendMics[i][2]=mic3[i+indexWrap];
          sendMics[i][3]=mic4[i+indexWrap];
          sendMics[i][4]=mic5[i+indexWrap];
        }
        for (i = 0; i <= indexWrap-1; i++)
        {
          sendMics[i+indexTailLength+1][0]=mic1[i];
          sendMics[i+indexTailLength+1][1]=mic2[i];
          sendMics[i+indexTailLength+1][2]=mic3[i];
          sendMics[i+indexTailLength+1][3]=mic4[i];
          sendMics[i+indexTailLength+1][4]=mic5[i];
        }
        filling=false;
        sendex=30;
        Serial.printf("indexWrap = %d",indexWrap);
        Serial.println();
        for (i = 0; i < 128; i++)
        {
          Serial.print(i);
          Serial.print(" ");
          for(int j=0; j<5; j++)
          {
            Serial.print(sendMics[i][j]);
            Serial.print(" ");
            delay(1);
          }
          Serial.println();
        }
        queue1.begin();//I thought I should enable 
        queue2.begin();
        queue3.begin();
        queue4.begin();
        queue5.begin();
        queue6.begin();
        queue7.begin();
        queue8.begin();
        queue9.begin();
        queue10.begin();
    }
  }  

}
and here are two examples of nice sinusoids at 1500Hz.
View attachment 10597
View attachment 10598
Thank you so much guys! I think I can do something with this now. But now I'm seriously considering processing the time shift using the Teensy, instead of the Raspberry pi (even though I already have some python code waiting to process samples (FYI these pictures are from where the mics are sitting on my desk spaced less than 30 cm apart, I'm going to try and space them 60cm apart.)

as a bonus here is the matlab code I wrote to simulate the possibility of interpolating between samples by using a spline fit, it turns out you can at least interpolate 208 times between points:

Code:
%MATLAB CODE (not C++)

decay=0.005;  %how fast the chirp decays this has an effect on accuracy of time delay(fit all of the wave in the window)
shift=-0.00035479;%simulated time shift
w=2*pi;      %normalization period
a=3.3;       %amplitude of first wave
b=2.8;       %amplitude of second wave
t=-.04:0.000021:.04;%range and 1/sampling frequency
phase=0;     %initial phase
f0=200;      %starting lower frequency
f1=3000;     %final upper frequency
T=.05;       %time to sweep frequency
k=(f1/f0)^(1/T);
snr=65;%signal to noise ratio in dBA



s1=a*sin(phase+((f0*w*((k).^(t)-1))/log(k))).*exp(-((t)/decay).^2);
s1n=awgn(s1,snr);
s2=b*sin(phase+((f0*w*((k).^(t+shift)-1))/log(k))).*exp(-((t+shift)/decay).^2);
s2n=awgn(s2,snr);
format long

figure
plot(t,s2n,'o',t,s1n,'o')
hold on
% [r,lag]=xcorr(s1n,s2n);%the time shift if only using sample rate for discrete shifting
% [~,I] = max(abs(r));
% lagDiff = lag(I)
% timeDiff = lagDiff/48000.0

time =-.04:0.00000001:.04;%may have to get creative with finding the bounds for the final application
p1 = interp1(t,s1n,time,'spline');%linear interpolation will never be better than original sampling speed
p2 = interp1(t,s2n,time,'spline');
plot(time,p1,time,p2)
hold off
[r2,lag2] = xcorr(p1,p2);%time shift after interpolation
[~,I2] = max(abs(r2));
lagDiff2 = lag2(I2);
timeDiff2 = lagDiff2/100000000
I was seeing if I could get a better time shift resolution(where I have, Dt +- dt, and I wanted a smaller dt) this simulation worked and I was able to meet my benchmark requirements it calculates the shift in .10 seconds and i get a dt of 0.0000001 and occasionally better. but it may require some tricky signal processing tricks. I'm just wondering if there is a way if I can write a spline fitting function with the Teensy, then over sample that fit and with the over sampled points do a cross correlation? or as someone once told me, I should do the cross correlation and then find the maximum of the correlation after spine fitting and over sampling the cross correlation.
Anyway, thank you so much for the help you guys have given me. this has been by far my best forum experience.

We have been trying to connectin the ICS52000 microphone with Teensy 3.6, but have no success.
We are lost .

Could you please share a detailed photo of your hardware connection between the ICS52000 microphone with Teensy 3.6,
and the code that you make the figure with three sine waves.
 
Status
Not open for further replies.
Back
Top