Help with using Teensy 4.1 to make an ANC headset.

As the tile says I am currently trying to use a teensy 4.1 to make an ANC headset. So far I have wired up one ear and all the components are working (I am using the Adafruit I2S MEMS Microphone Breakout - SPH0645LM4H for the inputs and the Adafruit I2S 3W Class D Amplifier Breakout - MAX98357A as the output) and I have written code to implement an adaptive filter with an LMS algorithm to do the noise cancelling. The problem is when I try to run my code after a few seconds the teensy disconnects from my computer, reconnects and then restarts the code again and I'm not sure what is happening or how to fix it, so I'm looking on any suggestions on what to do. I have attached a pic of my wiring and the pasted the code below. Thanks for any responses in advance :).

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2SQuad        i2s_quad1;      //xy=244,138
AudioAmplifier           amp1;           //xy=434,111
AudioAmplifier           amp2;           //xy=434,162
AudioRecordQueue         queue1;         //xy=580,111
AudioRecordQueue         queue2;         //xy=581,163
AudioPlayQueue           queue3;         //xy=630,370
AudioOutputI2S2          i2s2_1;         //xy=810,341
AudioOutputUSB           usb1;           //xy=810,402
AudioConnection          patchCord1(i2s_quad1, 0, amp1, 0);
AudioConnection          patchCord2(i2s_quad1, 2, amp2, 0);
AudioConnection          patchCord3(amp1, queue1);
AudioConnection          patchCord4(amp2, queue2);
AudioConnection          patchCord5(queue3, 0, i2s2_1, 0);
AudioConnection          patchCord6(queue3, 0, i2s2_1, 1);
AudioConnection          patchCord7(queue3, 0, usb1, 1);
AudioConnection          patchCord8(queue3, 0, usb1, 0);
// GUItool: end automatically generated code


#include <deque>


const int L = 128;
const double mu = 0.01;
const double vol = 10;

const int BufLen = 128; //Number of samples in  each buffer round


std::deque<int16_t> x(L*2, 0);

double w[L] = {}; //Initalise filter coefficents to be 0


void setup() {
  // put your setup code here, to run once:

  Serial.begin(38400);
  while (!Serial) {
    ; // wait for serial port to connect.
  }
  Serial.println("Serial connection established.");

  AudioMemory(500);

  queue1.begin();

  amp1.gain(vol);//Set volume of mic inputs
  amp2.gain(vol);
}



void loop() {
  //Serial.println("ANC in process...");
 
  if (queue1.available() > 0){
    int16_t* xBuf = queue1.readBuffer();
    int16_t* RBuf = queue2.readBuffer();
    queue1.freeBuffer();
    queue2.freeBuffer();
    for(int n=0; n<BufLen; n++){
      x.push_back(xBuf[n]);
      x.pop_front();
    }
   
    int16_t yBuf[BufLen] = {};
    for(int n=0; n<BufLen; n++){
      yBuf[n] = 0;//Doubley making suer output sample starts at 0
      for(int i=0; i<(L-1); i++){
        yBuf[n] += w[i]*x[n+L-i];
        //Serial.println("Were in");
      }
      float e = -RBuf[n]; //Calculating error signal, for no want silence so error signal is just -reference signal.
      Serial.println(e);
      for(int i=0; i<L; i++){
        //Serial.println("Were in AGAIN");
        w[i] += mu*e*x[n+L-i];
      }
    }
    queue3.play(yBuf, BufLen);
  }



}
Teensy 4.1 ANC Wiring Pic.png
 
@IWantYourCookies: I would suggesst that you add a line to your setup() function something like this (which will wait for a maximum of 3 seconds for the serial monitor to be connected, then proceed): while (!Serial && millis() < 3000) {}.

Then, add the following code in the setup() function, right after the while (!Serial && millis() < 3000) {} line, which will print out any crash information:

Code:
if (CrashReport) {
   Serial.print(CrashReport);
}

Note that, if a crash occurs, the crash information will be printed in the SerialMonitor, so in this case you'll want to open the SerialMonitor from the Arduino IDE to view the crash information. The report will include an address where the crash was recorded. Paul has also created a CrashReport() <webpage> with useful details. You can also check the entry in the unofficial Teensy wiki <here> for links to descriptions of where to find the addr2line utility for both the old (1.8.x) & new (2.3.x) Arduino IDE, as well as detailed descriptions of how to use it.

Good luck & let us know what you find . . .

Mark J Culross
KD5RXT
 
A few observations…
  • You never begin() queue2, so RBuf will be nullptr, and reading it will crash the Teensy. Look up CrashReport and how to use it…
  • it appears that x will never have anything in it, as you immediately take out everything you put in. Indexing any element will probably crash the Teensy
  • You shouldn’t free what you’ve read from a queue until you’ve finished processing it
 
A few observations…
  • You never begin() queue2, so RBuf will be nullptr, and reading it will crash the Teensy. Look up CrashReport and how to use it…
  • it appears that x will never have anything in it, as you immediately take out everything you put in. Indexing any element will probably crash the Teensy
  • You shouldn’t free what you’ve read from a queue until you’ve finished processing it
@IWantYourCookies: I would suggesst that you add a line to your setup() function something like this (which will wait for a maximum of 3 seconds for the serial monitor to be connected, then proceed): while (!Serial && millis() < 3000) {}.

Then, add the following code in the setup() function, right after the while (!Serial && millis() < 3000) {} line, which will print out any crash information:

Code:
if (CrashReport) {
   Serial.print(CrashReport);
}

Note that, if a crash occurs, the crash information will be printed in the SerialMonitor, so in this case you'll want to open the SerialMonitor from the Arduino IDE to view the crash information. The report will include an address where the crash was recorded. Paul has also created a CrashReport() <webpage> with useful details. You can also check the entry in the unofficial Teensy wiki <here> for links to descriptions of where to find the addr2line utility for both the old (1.8.x) & new (2.3.x) Arduino IDE, as well as detailed descriptions of how to use it.

Good luck & let us know what you find . . .

Mark J Culross
KD5RXT

Hey, thank you guys for the responses, I implemented your suggestions and they stopped the teensy from crashing. After that I was testing my lms algorithm and I realised all my error values were massive, this turned out to be because the i2s mic I was using for those values (RBuf in the code) only outputs super high values, with an average output of around -1700, the microphone works and sounds fine but these values are throwing off my algorithm, especially because the other i2s microphone I am using only has an offset of roughly -0.4. I'm not sure what to do about this, I dont know why that microphone has a massive offset and how to fix it, I was thinking of normalising both signals but I gon't know how to do that without knowing the range of the outputs, I would expect both of them to have a range of -32768 to +33768 since they are supposed to ouput 16bit but that can't be the case with the mic with an offset of -1700 right? Any advice on how to deal with this? I have put the updated code below if needed:

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2SQuad        i2s_quad1;      //xy=244,138
AudioAmplifier           amp1;           //xy=434,111
AudioAmplifier           amp2;           //xy=434,162
AudioRecordQueue         queue1;         //xy=580,111
AudioRecordQueue         queue2;         //xy=581,163
AudioPlayQueue           queue3;         //xy=630,370
AudioOutputI2S2          i2s2_1;         //xy=810,341
AudioOutputUSB           usb1;           //xy=810,402
AudioConnection          patchCord1(i2s_quad1, 0, amp1, 0);
AudioConnection          patchCord2(i2s_quad1, 2, amp2, 0);
AudioConnection          patchCord3(amp1, queue1);
AudioConnection          patchCord4(amp2, queue2);
AudioConnection          patchCord5(queue3, 0, i2s2_1, 0);
AudioConnection          patchCord6(queue3, 0, i2s2_1, 1);
AudioConnection          patchCord7(queue3, 0, usb1, 1);
AudioConnection          patchCord8(queue3, 0, usb1, 0);
// GUItool: end automatically generated code


#include <deque>


const int L = 128;
const double mu = 0.01;
const double vol = 10;

const int BufLen = 128; //Number of samples in  each buffer round


std::deque<int16_t> x(L*2, 0);

double w[L] = {}; //Initalise filter coefficents to be 0


void setup() {
  // put your setup code here, to run once:

  Serial.begin(38400);
  while (!Serial) {
    ; // wait for serial port to connect.
  }
  Serial.println("Serial connection established.");

  if (CrashReport) {
   Serial.print(CrashReport);
  }

  AudioMemory(500);

  queue1.begin();
  queue2.begin();

  amp1.gain(vol);//Set volume of mic inputs
  amp2.gain(vol);
}



void loop() {
  //Serial.println("ANC in process...");
 
  if (queue1.available() > 0){
    int16_t* xBuf = queue1.readBuffer();
    int16_t* RBuf = queue2.readBuffer();
    for(int n=0; n<BufLen; n++){
      x.push_back(xBuf[n]);
      x.pop_front();
    }
    
    int16_t yBuf[BufLen] = {};
    for(int n=0; n<BufLen; n++){
      yBuf[n] = 0;//Doubley making suer output sample starts at 0
      for(int i=0; i<(L-1); i++){
        yBuf[n] += w[i]*x[n+L-i];
        //Serial.println("Were in");
      }
      float e = -RBuf[n]; //Calculating error signal, for no want silence so error signal is just -reference signal.
      Serial.println(RBuf[64]);
      for(int i=0; i<L; i++){
        //Serial.println("Were in AGAIN");
        w[i] += mu*e*x[n+L-i];
      }
    }
    //Serial.println(x[127]);
    queue3.play(yBuf, BufLen);
    queue1.freeBuffer();
    queue2.freeBuffer();
  }



}
 
Back
Top