Using MEMS microphones with Teensy 3.x--help

Status
Not open for further replies.

onehorse

Well-known member
I want to use an array (>=2) of MEMS digital microphones like these to try out "echo location" using frequencies near the Helmholtz resonant 18 KHz. The circuit diagram shows the L/R input going to a CODEC. Most of the CODEC chips I have looked at are gigantic and support hi-fi audio output. That's overkill for me. I just want to take the signal(s) and do some FFT operations on them looking for differential doppler shifts to get a bearing. So some questions:

1) Is there some easier, smaller decoding I can do with the Teensy 3.x by itself or in concert with a small smd chip, and

2) What is the best way to generate an 18 kHz narrow band signal? Can I just use the same MEMS microphone as a "speaker", i.e., sound generator?

I am looking for very small form factor solutions.

This is all new to me so any suggestions are welcome!
 
The microphone that you linked to is a digital microphone using pulse density modulation. I don't have any experience using this kind of microphone, but you may be able to connect the digital output directly to the Teensy and do the conversion in software. If you found an I2S format digital microphone, you could connect it up to the I2S interface built into the Teensy microcontroller and not have to do as much software work.

The teensy 3.x also has a bunch of analog inputs, which could all be connected to analog microphones, probably best using the PGAs in the 3.1 for more mic gain.

The easiest way to get started would probably be to use the audio board and a pair of analog microphones.

Regarding #2, the best way to generate a 18kHz tone is probably to use either the Teensy 3.1 DAC (or PWM) connected to a small piezo element or small speaker (something like this might work). You will not be able to use the microphone as a speaker, because they generally have integrated gain stages that prevent you from directly controlling the diaphragm and actually generating a sound (even if you could, you probably couldn't get a usable signal out of a mems mic because of the tiny diaphragm size).

Again, the easiest way to get started would be to use the audio board output connected to the speaker/piezo element.

The audio library already has tone generation and FFTs built in, so that may be a good place to start, make a prototype, and then explore other options.
 
Thanks for the reply. In the meantime I started looking at this Invensense microphone, which I should be able to use by simply piping the I2S output directly into the Teensy or Edison, which I am also using. I found some small smd speakers from Knowles which could be used to send the sound trains. For my application, the Adafruit speaker is too gigantic. I want appallingly small!

So it looks like I can build a transmitter and responder with small add-on boards mounted on two Teensy 3.1s. I would prefer top mounted microphones and will probably need help with the DAC/PWM sound generation as well as the FFT but I think I have all the pieces to put a hardware prototype together. When I do, I will share the results...
 
Two other questions:

Which pins are home to the 3-pin I2S port on the Teensy 3.1. That is, if I have data, clock, and word select signals coming from a microphone array, where do I put them? Can the port accept 1V8 input or am I limited to 3V3 on input?

If I get the I2S data to the Teensy 3.1 at the proper ports, is there an I2S library to support reading the data like the Wire.h or i2c_t3.h libraries for I2C? Is this the Audio library?

I want to design a little add-on board for these MEMS microphones to test them and want to know how to hook them up preparatory to the design.

Thanks for the help!
 
I took a quick look at the mk20dx ref manual, and it looks like there are at least 2 options for the I2S pins. You can take a look there and decide which set to use, or go off the locations that are used for the audio board.

I don't know of any I2S library besides the code that is used in audio library, but reading from and writing to the I2S interface is dead simple once it's setup. It uses FIFOs for both input and output, and the easiest way that I've found to work with it (the audio library does the same) is to set the FIFO watermark up to trigger an ISR, and then read the samples during the ISR. You can use the audio library setup code as a starting point: https://github.com/PaulStoffregen/Audio/blob/master/output_i2s.cpp
 
If I get the I2S data to the Teensy 3.1 at the proper ports, is there an I2S library to support reading the data like the Wire.h or i2c_t3.h libraries for I2C? Is this the Audio library?

Well, in theory you'd use this object in the audio lib.

http://www.pjrc.com/teensy/gui/?info=AudioInputI2Sslave

But in practice, the I2S slave objects are basically untested at this time. The audio shield uses the master mode ones.

https://github.com/PaulStoffregen/Audio/issues/74

I'd put the odds of it actually working at maybe 50-50. Actually, the waveforms on page 12 of that sensor's datasheet show 64 clocks per LRCLK cycle. I believe we're currently using 32 for master mode. So maybe the odds are lower than 50%.

Eventually, if I2S slave mode is ever going to be reliable and well tested, someone's going to need to go first and be an early adopter. It's likely to be painful.
 
Pain is my middle name!

I'll build the hardware, make a few attempts to get I2S slave mode to work and then likely ask for help.

In order to get the hardware right I would like to understand which Teensy 3.1 pins correspond to the three wire I2S signals Serial Data, Clock, and Word Select. In the very old thread these were identified as Teensy pins 9, 4, and 3 IIRC. Can these be any PWM pins or are there specific I2S ports configured on the Teensy that ought to be used, just like I2C uses only specific ports?
 
Last edited:
From your link it looks like pin 9 is the clock, pin 13 is the data io, and pin 23 is the word sample pin. Are there alternative pins for any of these? Ideally I would like a group of pins close enought together to allow a small add-on board design. How about 9, 13, and 10?
 
Hi Onehorse,

I see that you didn't get a response about the teensy pin matchup with your mems specs, but I would be very keen to know if you were successful in your guess of which goes to which?

I am also interested in the possibility of connecting a MEMS digital microphone to the Teensy. I would think you could also just use the digital pins and use digitalRead to grock the PWM modulation, but maybe there is an already set library in I2S that makes the software a LOT easier, as you all mentioned...
 
These I2S digital microphones work directly with the Teensy 3.X and the output can be captured via Serial.write directly to a file on the pc for replay using Audacity etc.
 
I noticed those, but it seems that I then also have to buy a Wolfson wm8731 chip/codec to even run most of the example code. I see one non-codec example but it's not super clear to me what I gain and loose by not using an extra (or onboard) codec. Now thinking about just using a analog MEMS and using up cycles on the Teensy's ADC.
Again, not super clear what I gain or loose in terms of performance of one choice over another. I might want to buffer the data a little to transmit over wifi, I am guessing that this is when DMA might become important...
 
That's the whole point of the I2S digital microphone, no codec required. The sketch s a hack from one written for the Wolfson codec, it just collects the serial data into buffers and outputs the data via Serial.write or serial.print if you want to look at the bytes on the serial monitor (not very interesting). The point of a digital I2S mic is that the data is in a standard format that doesn't require a codec to decode.
 
Again, not super clear what I gain or loose in terms of performance of one choice over another.

Teensy on-chip ADC gives you about 12-13 bits performance, plus 3-4 bits of noise. For strong signals, it's not bad, but the audio quality is certainly not as good using a proper codec.

Likewise, the DAC pin gives 12 bits. For casual listening, the quality is pretty decent, but again not as good as a dedicated codec chip.
 
Eventually, if I2S slave mode is ever going to be reliable and well tested, someone's going to need to go first and be an early adopter. It's likely to be painful.

Paul, would it work to connect two teensys (one output, one input?) if yes, i could try (& bugfix if nessary) in 2-3 weeks.
I have no other I2S output.
 
Likewise, the DAC pin gives 12 bits. For casual listening, the quality is pretty decent, but again not as good as a dedicated codec chip.

The audio quality of the internal DAC can be considerably improved by doing some oversampling. I'm currently fiddling around with the DAC being fed from its ring buffer, configured to a size of 2 x n registers, where n is the oversampling rate. Thus, the hardware allows to do up to 8 x oversampling since there are 16 registers. Using the PDB to trigger the DAC output at (sampling rate x n) allows the DAC to output n values from one half of the buffer without consuming CPU resources, while the other half is filled with new interpolated values from the polyphase oversampling filter.

8 x oversampling can be done at a 48kHz audio rate, but then, the oversampling filter uses up to 70% of the CPU time. But that gives a virtual 15bit resolution and a simple 2nd order Butterworth low pass filter in Sallen-Key technology with a 3dB corner frequency of 24kHz is enough to clean the output signal.

By trying to push everything at its limits, I found out that 6 x oversampling at 96kHz which makes a 576kHz DAC conversion rate is still possible with the Teensy 3.2
 
No dithering, at least for the moment, since the result sounds ok for me.

Edit: I wonder if there isn't "automatic" dithering when scaling and offsetting the signed 16bit audio data to the unsigned 12bit DAC values...
 
Last edited:
I'm pretty sure dithering requires adding a small signal before discarding the lower bits.

4X oversampling with noise shaped dither is on my wish list... of stuff I'd love to do if only there were a *lot* more hours in every day!
 
I will dive deeper into that dithering issue, and when you find the time to work on that, I'd be happy to share my code with you, Paul, so that you can integrate it into the audio library or wherever you want.

Edit: Studied. Will try add optional TPF dither when I find a very quick! way to generate random numbers between -15 and 15

Edit: Found perhaps. Needs testing.
 
Last edited:
Thanks :) I'll do it.

I was just checking my (I2S slave) code:
all you need is conditionally set the FSD bit on (R/TCR4) register

for receiver:
Code:
	if(isMaster)
		I2S0_RCR4 |= I2S_RCR4_FSD;
all other parameters on clock generation (I2S0_MCR, I2S0_MDR, I2S0_RCR2,I2S0_TCR2) are ignored in slave mode (so you can also set them)

hope this helps
 
I was just checking my (I2S slave) code:
all you need is conditionally set the FSD bit on (R/TCR4) register

for receiver:
Code:
	if(isMaster)
		I2S0_RCR4 |= I2S_RCR4_FSD;
all other parameters on clock generation (I2S0_MCR, I2S0_MDR, I2S0_RCR2,I2S0_TCR2) are ignored in slave mode (so you can also set them)

hope this helps

Has there been success with I2S slave mode on the Teensy?

Chip
 
Status
Not open for further replies.
Back
Top