PDA

View Full Version : Teensy 3.1 FFT Adafruit AGC Electret Microphone - first two bins not zeroing out



ksumrall
07-05-2016, 04:23 AM
Hello,

I'm working on a light to music project and stuck getting a reliable spectrum.

I'm using a Teensy 3.1 and an Adafruit AGC Electrit Microphone (https://www.adafruit.com/product/1713).
I'm running the teensy through USB for now so that I can use the serial monitor ro view results.
My code is as follows:


// FFT Test
//
// Compute a 1024 point Fast Fourier Transform (spectrum analysis)
// on audio connected to an adafruit AGC Electret Microphone MAX9814
// https://www.adafruit.com/product/1713
//
// The 512 bins are calculated into 32 bins.
//

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

#define debug

const unsigned int matrix_width = 32;
const unsigned int matrix_height = 256;

// These parameters adjust the vertical thresholds
const float maxLevel = 0.4; // 1.0 = max, lower is more "sensitive"
const float dynamicRange = 40.0; // total range to display, in decibels
const float linearBlend = 0.3; // useful range is 0 to 0.7

// Create the Audio components. These should be created in the
// order data flows, inputs/sources -> processing -> outputs
AudioInputAnalog adc1(A2);
AudioAnalyzeFFT1024 myFFT;
AudioConnection patchCord1(adc1, myFFT);

// This array specifies how many of the FFT frequency bins to use for each horizontal pixel.
// Because humans hear in octaves, and FFT bins are linear, the low frequencies
// use a small number of bins, higher frequencies use more.
const int lowerFFTBins[] = {0,1,2,3,4,5,6,8,10,12,15,18,22,27,32,38,45,53,63, 74,87,102,119,138,160,186,216,250,289,334,385,444} ;
const int upperFFTBins[] = {0,1,2,3,4,5,7,9,11,14,17,21,26,31,37,44,52,62,73, 86,101,118,137,159,185,215,249,288,333,384,443,511 };
float thresholdVertical[matrix_height];
float thresholdVert[matrix_height];

void setup() {
analogReadAveraging(4);
AudioMemory(12);

// compute the vertical thresholds before starting
computeVerticalLevels();

for(unsigned int j = 0; j < matrix_height; j++) {
thresholdVert[j] = thresholdVertical[matrix_height-j-1];
}

myFFT.windowFunction(AudioWindowHanning1024);
}

void loop() {
float level;
int maxY;

if (myFFT.available()) {
#ifdef debug
Serial.print("FFT: ");
#else
Serial.write(255);
#endif
float bar[60];
int index = 2;
for (int x = 0; x < matrix_width; x++) {
level = myFFT.read(lowerFFTBins[x], upperFFTBins[x]);
maxY = 0;
for(int y = 0; y < matrix_height; y++){
if(level >= thresholdVert[y]){
maxY = y;
}
}
#ifdef debug
Serial.print(maxY);
Serial.print(" ");
#else
Serial.write(maxY);
#endif
}
#ifdef debug
Serial.println();
#endif

delay(20);
}
}

// Run once from setup, the compute the vertical levels
void computeVerticalLevels() {
unsigned int y;
float n, logLevel, linearLevel;

for (y=0; y < matrix_height; y++) {
n = (float)y / (float)(matrix_height - 1);
logLevel = pow10f(n * -1.0 * (dynamicRange / 20.0));
linearLevel = 1.0 - n;
linearLevel = linearLevel * linearBlend;
logLevel = logLevel * (1.0 - linearBlend);
thresholdVertical[y] = (logLevel + linearLevel) * maxLevel;
}
}


The results look good for all but the first two bands. The first two bands seem to latch on to the maximum value experienced...


FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FFT: 24 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


Those first two bands keep latching onto the max value experienced. What's interesting is that I do see them show lower values as there is sound being calculated, but when it goes quiet, they appear in their 'latched' state.
I remember seeing some example code of Paul's where he skipped the first two bins. That makes me wonder if I should do the same and move on with just 30 bins.

*EDIT*
The scale of the values is 0 - 255
I have seen through the course of one song a the first two bins reading 248 and 196 respectively during silence. While the song is playing, the first bins seem to show properly fluctuating levels.

defragster
07-05-2016, 04:30 AM
I was seeing something similar intermittently on my Sparkfun mic breakout and thought the mic was giving an odd value - Then I got distracted doing other stuff first and never got back to it.

One ran fine for days on my downstairs desktop I could see when I breathed or clicked my mouse - then it started acting oddly . . .

DerekR
07-05-2016, 10:04 AM
By any chance is there a small dc offset on your mic input that accounts for bins 0 & 1? Bin 0 is the dc level, and that will be "smeared" into 1 by the Hanning window function.

ksumrall
07-05-2016, 01:47 PM
There is a 1.25 dc offset with a 1Vpp swing. That will leave at least a 0.25V value. I'm sure that has some influence on the values, but I don't see how that would cause the values in those two bins only to continually rise and latch during silence.

B.Jacquot
07-05-2016, 07:44 PM
...continually rise ... during silence.

(Ellepsis mine)

That sounds like it could be a side effect of the AGC.

Does the time it takes change if you pull the A/D pin to ground or VCC?

ksumrall
07-09-2016, 06:59 PM
B.Jacquot -
I have just created a video to demonstrate my observations - https://youtu.be/TQP7IqIM3zI.
I tried a microphone without AGC which produced better results. Here's a link (http://www.ebay.com/itm/262404489457?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT) to the mic on ebay.
I think it does have something to do with AGC, but not sure what. Electronics is hard.
Until I have a better understanding of what is happening, I'll either use the mic without AGC or use the mic with AGC and ignore the first two bins.
Any thoughts?