Teensy Microphone Module

If you analyze the spectrum in audacity do you see a peak at 172Hz in either of the recordings?

I get a 172Hz peak with the audio board, where it writes to the uSD card 172x a second.

Would you mind posting your sketch for writing the ADC1 input to the uSD card? I'm going to go ahead and order some of your boards for testing.
 
If you analyze the spectrum in audacity do you see a peak at 172Hz in either of the recordings?

I get a 172Hz peak with the audio board, where it writes to the uSD card 172x a second.

Would you mind posting your sketch for writing the ADC1 input to the uSD card? I'm going to go ahead and order some of your boards for testing.
I2S mic spectrum
I2SMic.jpg

Analog mic spectrum
AnalogMic.jpg

Nope - don't see anything like that.

Here is the recorder sketch using the I2S microphone:
Code:
// Record sound as raw data to a SD card, and play it back.
//
// Requires the audio shield:
//   http://www.pjrc.com/store/teensy3_audio.html
//
// Three pushbuttons need to be connected:
//   Record Button: pin 0 to GND
//   Stop Button:   pin 1 to GND
//   Play Button:   pin 2 to GND
//
// This example code is in the public domain.

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputI2S            i2s2;           //xy=105,63
AudioAnalyzePeak         peak1;          //xy=278,108
AudioRecordQueue         queue1;         //xy=281,63
AudioPlaySdRaw           playRaw1;       //xy=302,157
AudioOutputI2S           i2s1;           //xy=470,120
AudioConnection          patchCord1(i2s2, 0, queue1, 0);
AudioConnection          patchCord2(i2s2, 0, peak1, 0);
AudioConnection          patchCord3(playRaw1, 0, i2s1, 0);
AudioConnection          patchCord4(playRaw1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=265,212
// GUItool: end automatically generated code

// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord = Bounce(0, 8);
Bounce buttonStop =   Bounce(1, 8);  // 8 = 8 ms debounce time
Bounce buttonPlay =   Bounce(2, 8);


// which input on the audio shield will be used?
//const int myInput = AUDIO_INPUT_LINEIN;
const int myInput = AUDIO_INPUT_MIC;

// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording, 2=playing

// The file where data is recorded
File frec;

void setup() {
  // Configure the pushbutton pins
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(60);

  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(myInput);
  sgtl5000_1.volume(0.5);

  // Initialize the SD card
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}


void loop() {
  // First, read the buttons
  buttonRecord.update();
  buttonStop.update();
  buttonPlay.update();

  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
  }
  if (buttonStop.fallingEdge()) {
    Serial.println("Stop Button Press");
    if (mode == 1) stopRecording();
    if (mode == 2) stopPlaying();
  }
  if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press");
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
  }

  // If we're playing or recording, carry on...
  if (mode == 1) {
    continueRecording();
  }
  if (mode == 2) {
    continuePlaying();
  }

  // when using a microphone, continuously adjust gain
  if (myInput == AUDIO_INPUT_MIC) adjustMicLevel();
}


void startRecording() {
  Serial.println("startRecording");
  if (SD.exists("RECORD.RAW")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD.RAW");
  }
  frec = SD.open("RECORD.RAW", FILE_WRITE);
  if (frec) {
    queue1.begin();
    mode = 1;
  }
}

void continueRecording() {
  if (queue1.available() >= 2) {
    byte buffer[512];
    // Fetch 2 blocks from the audio library and copy
    // into a 512 byte buffer.  The Arduino SD library
    // is most efficient when full 512 byte sector size
    // writes are used.
    memcpy(buffer, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    memcpy(buffer+256, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    // write all 512 bytes to the SD card
    elapsedMicros usec = 0;
    frec.write(buffer, 512);
    // Uncomment these lines to see how long SD writes
    // are taking.  A pair of audio blocks arrives every
    // 5802 microseconds, so hopefully most of the writes
    // take well under 5802 us.  Some will take more, as
    // the SD library also must write to the FAT tables
    // and the SD card controller manages media erase and
    // wear leveling.  The queue1 object can buffer
    // approximately 301700 us of audio, to allow time
    // for occasional high SD card latency, as long as
    // the average write time is under 5802 us.
    //Serial.print("SD write, us=");
    //Serial.println(usec);
  }
}

void stopRecording() {
  Serial.println("stopRecording");
  queue1.end();
  if (mode == 1) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
    }
    frec.close();
  }
  mode = 0;
}


void startPlaying() {
  Serial.println("startPlaying");
  playRaw1.play("RECORD.RAW");
  mode = 2;
}

void continuePlaying() {
  if (!playRaw1.isPlaying()) {
    playRaw1.stop();
    mode = 0;
  }
}

void stopPlaying() {
  Serial.println("stopPlaying");
  if (mode == 2) playRaw1.stop();
  mode = 0;
}

void adjustMicLevel() {
  // TODO: read the peak1 object and adjust sgtl5000_1.micGain()
  // if anyone gets this working, please submit a github pull request :-)
}

And the sketch for the ADC:
Code:
// Record sound as raw data to a SD card, and play it back.
//
// Requires the audio shield:
//   http://www.pjrc.com/store/teensy3_audio.html
//
// Three pushbuttons need to be connected:
//   Record Button: pin 0 to GND
//   Stop Button:   pin 1 to GND
//   Play Button:   pin 2 to GND
//
// This example code is in the public domain.

#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;  
AudioAnalyzePeak         peak1; 
AudioRecordQueue         queue1;  
AudioPlaySdRaw           playRaw1;  
AudioOutputI2S           i2s1;  
AudioConnection          patchCord1(adc1, 0, queue1, 0);
AudioConnection          patchCord2(adc1, 0, peak1, 0);
AudioConnection          patchCord3(playRaw1, 0, i2s1, 0);
AudioConnection          patchCord4(playRaw1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=265,212
// GUItool: end automatically generated code

// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord = Bounce(0, 8);
Bounce buttonStop =   Bounce(1, 8);  // 8 = 8 ms debounce time
Bounce buttonPlay =   Bounce(2, 8);


// which input on the audio shield will be used?
//const int myInput = AUDIO_INPUT_LINEIN;
const int myInput = AUDIO_INPUT_MIC;

// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording, 2=playing

// The file where data is recorded
File frec;

void setup() {
  // Configure the pushbutton pins
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(60);

  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(myInput);
  sgtl5000_1.volume(0.5);

  // Initialize the SD card
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}


void loop() {
  // First, read the buttons
  buttonRecord.update();
  buttonStop.update();
  buttonPlay.update();

  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
  }
  if (buttonStop.fallingEdge()) {
    Serial.println("Stop Button Press");
    if (mode == 1) stopRecording();
    if (mode == 2) stopPlaying();
  }
  if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press");
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
  }

  // If we're playing or recording, carry on...
  if (mode == 1) {
    continueRecording();
  }
  if (mode == 2) {
    continuePlaying();
  }

  // when using a microphone, continuously adjust gain
  if (myInput == AUDIO_INPUT_MIC) adjustMicLevel();
}


void startRecording() {
  Serial.println("startRecording");
  if (SD.exists("RECORD.RAW")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD.RAW");
  }
  frec = SD.open("RECORD.RAW", FILE_WRITE);
  if (frec) {
    queue1.begin();
    mode = 1;
  }
}

void continueRecording() {
  if (queue1.available() >= 2) {
    byte buffer[512];
    // Fetch 2 blocks from the audio library and copy
    // into a 512 byte buffer.  The Arduino SD library
    // is most efficient when full 512 byte sector size
    // writes are used.
    memcpy(buffer, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    memcpy(buffer+256, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    // write all 512 bytes to the SD card
    elapsedMicros usec = 0;
    frec.write(buffer, 512);
    // Uncomment these lines to see how long SD writes
    // are taking.  A pair of audio blocks arrives every
    // 5802 microseconds, so hopefully most of the writes
    // take well under 5802 us.  Some will take more, as
    // the SD library also must write to the FAT tables
    // and the SD card controller manages media erase and
    // wear leveling.  The queue1 object can buffer
    // approximately 301700 us of audio, to allow time
    // for occasional high SD card latency, as long as
    // the average write time is under 5802 us.
    //Serial.print("SD write, us=");
    //Serial.println(usec);
  }
}

void stopRecording() {
  Serial.println("stopRecording");
  queue1.end();
  if (mode == 1) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
    }
    frec.close();
  }
  mode = 0;
}


void startPlaying() {
  Serial.println("startPlaying");
  playRaw1.play("RECORD.RAW");
  mode = 2;
}

void continuePlaying() {
  if (!playRaw1.isPlaying()) {
    playRaw1.stop();
    mode = 0;
  }
}

void stopPlaying() {
  Serial.println("stopPlaying");
  if (mode == 2) playRaw1.stop();
  mode = 0;
}

void adjustMicLevel() {
  // TODO: read the peak1 object and adjust sgtl5000_1.micGain()
  // if anyone gets this working, please submit a github pull request :-)
}
 
I forgot to mention that I see the peak when I analyze a silent portion of the audio signal. Did you analyze a silent portion?
 
If you analyze the spectrum in audacity do you see a peak at 172Hz in either of the recordings?

I get a 172Hz peak with the audio board, where it writes to the uSD card 172x a second.

Would you mind posting your sketch for writing the ADC1 input to the uSD card? I'm going to go ahead and order some of your boards for testing.

Update: I reran the testing using a little test speaker and white noise. Actually, it's a small wooden box with the speaker mounted on the outside pointing in and a small hole on the other side. This lets me generate sounds inside that chamber without a ton of external influence. Unfortunately, it is a box and has some sharp resonance points plus the speaker is small and I have some acoustic stuffing in there so high notes are damped. But... it is self-consistent so I can compare two mics!

I2S mic running through the Audio Shield with white noise playing in the sound box:
RECORDI.jpg

Analog mic running into ADC, same box and white noise:
RECORDA.jpg
 
I forgot to mention that I see the peak when I analyze a silent portion of the audio signal. Did you analyze a silent portion?

I recorded a few seconds of "silence" from each. No 172Hz component. I can't get a truly silent recording given my wife is watching the Emmys in the other room! A touch more 60Hz noise on the I2S mic.
 
Interesting, maybe it's my wire length on the microphone on the audio board. Are you running off of batteries?
Are you using the uSD card suggested by pjrc? That one arrives tomorrow for me, so I'll test again then.

This is what mine looked like.
teensy172HzSpike.jpg
 
Interesting, maybe it's my wire length on the microphone on the audio board. Are you running off of batteries?
Are you using the uSD card suggested by pjrc? That one arrives tomorrow for me, so I'll test again then.

This is what mine looked like.
View attachment 11557

The signal levels are lower then my set-up - nice low noise floor! Yes, long wires between the Analog Shield and the microphone element will pick-up noise. On my set-up, the mic element is soldered directly to the Shield at a right angle so it points straight off the end. As for the card, I'm using a Sandisk Ultra 32GB SD card.
 
Looks like mine will arrive tomorrow.

Any way to take advantage of the differential ADC inputs (the bottom pads)? Either in the current form, or a future design? My understanding is that it gets a little closer to 16-bit resolution with those pins, with the CMRR.

Also, maybe you would think about doing a microphone board with the uSD card adapter on it with some power stability added.
 
Looks like mine will arrive tomorrow.

Any way to take advantage of the differential ADC inputs (the bottom pads)? Either in the current form, or a future design? My understanding is that it gets a little closer to 16-bit resolution with those pins, with the CMRR.

Also, maybe you would think about doing a microphone board with the uSD card adapter on it with some power stability added.

I hadn't read up on the differential pairs of ADC inputs. Seems interesting. Are you thinking of an conventional microphone input with phantom power and everything?

I'm probably not going to tackle the uSD card reader - I would prefer to keep all digital off the microphone board. I suppose I could keep the connections completely separate but then you might as well have two board.
 
I hadn't read up on the differential pairs of ADC inputs. Seems interesting. Are you thinking of an conventional microphone input with phantom power and everything?

I wasn't thinking of phantom power, just getting better audio quality with low-cost, low-power components.
I tried reading up on how to hook up an electret mic with balanced connections, but didn't find much. I'm not sure what makes sense. The only thing I can think of so far (not in any way a good idea probably), is to have a dummy mic as one of the inputs so that the electrical stuff cancels out. Maybe having shielding would somehow be the other differential input? Just thinking aloud.
Also, I think the differential inputs allows up to 64x gain using the PGA.

I'm probably not going to tackle the uSD card reader - I would prefer to keep all digital off the microphone board. I suppose I could keep the connections completely separate but then you might as well have two board.

Fair enough. I just think the uSD adapter while writing could use some more power stability.
 
Last edited:
I'd love to try these out as I'd like to make a sound-reactive version of my excessive LED staff.

Sadly, I'm in New Zealand and Tindie is telling me that it won't ship these to NZ. Any idea when that might change? Or is there a way around that restriction?
 
I'd love to try these out as I'd like to make a sound-reactive version of my excessive LED staff.

Sadly, I'm in New Zealand and Tindie is telling me that it won't ship these to NZ. Any idea when that might change? Or is there a way around that restriction?

I'd say "Happily, you live in New Zealand!" I've never been there but understand that it's beautiful!!

Tindie wants me to create country-specific profiles in order to add shipping costs to orders based on the ship-to location. Given my lack of experience in this, I originally decided to only create the one profile for the U.S. and wait to see if there was interest from others. Since then, I've had interest from Austria, U.K., Australia, etc.... needless to say, lots of interest across the global! I still don't have a ton of experience in shipping internationally, but the US Postal Service seems to have a decent rate and for all the countries I've checked so far, it's been right around $13.60 to $13.75. Seems to almost be a flat rate for the size of package and weight. I'll create a new profile for New Zealand and expect it to be right around there. Please try again soon!

If others have suggestions on global shipping companies that can beat $13.60-$13.75 for a small bubble envelope of around an ounce, please let me know. The USPS rate does not get me tracking, which would be a great addition.
 
Cheers, I look forward to getting my hands on some and good to hear there's lots of interest.

NZ has relatively sane politics, so I'm not going to complain about the postage.
 
I've been following w/ interest, just placed an order for a couple of boards. I haven't got a particular use for them in mind at the moment, but I'm sure I can come up with something ;)
Thanks for all the hard work, looks great!

Chief
 
Is it possible to record from 2 mics on different ADC inputs and save to sdcard?

I believe the audio board can do this with i2s for line-level input, but maybe that's just for outputting over USB.
 
Is it possible to record from 2 mics on different ADC inputs and save to sdcard?

I believe the audio board can do this with i2s for line-level input, but maybe that's just for outputting over USB.

Yes, I know that I can simultaneous stream two ADC channels to USB and they show up as left & right to Audacity - that's how I test the mics. Stereo recording to a file on the SD Card is something I haven't tried. Hopefully someone can weigh in on this!
 
Hi

If I read the data sheet for the MAX9817 correctly, I see Attack/release values for the AGC of 1/4000 ms/ms. Does that mean that a loud sound is compensated within 1ms (lowering of the gain), but that the auto gain is only raised after a 4000ms lower sound level. Practically: Will a high sound every second lower the auto gain almost immediately so that the high sound is almost at "max", but the gain will be kept "almost the same" on the "silent periode" because there's a high sound very second?
 
I think I understand your question. Yes, mic sounds create an internal voltage that is compared to the voltage on pin 14, TH, or Threshold. When the sound is loud enough, the ACG does reduce the gain in . Table 1 and Table 2 in the datasheet show how you can change the time constants. I used a 0.1uF cap for Cct, and left A/R open. That gives an attack time of 0.24msec and a recovery time of 960msec. So you are correct, a periodic loud sound that comes more frequently then 960msecs will keep the AGC on and the gain minimized.

At the same time, you can short out R1 as shown on the typical application schematic, which has the net effect of trigger the reduced gain all the time! If you don't want the gain changing, just defeat the ACG and you'll have a fixed gain.
 
Hi,
can i still pick up one of you mics? I'm trying to control a led strip via FFT and had the MAX4466 around but as i read now, this won't work properly with the Teensy 3.2.
So i'm really glad if i could get one of your mics :)

However on Tindie this product is retired, so what's the current status?
 
Yes, I ran out of the original batch of 45 and decided to retire the mic modules. The demand was good in the beginning but dropped to about one a month toward the end.
I figured out that I would have to produce around 200 of them to make this work out and it looked like that would give me a 10 year supply! Graph.png
 
Back
Top