Teensy 3.2 and a simple amplified mic... how to use AudioAnalyzeNoteFrequency?

Status
Not open for further replies.

teoeva

Member
I'll be back on the forum after a few weeks . I bought a Teensy 3.2 and I watched the video " Teensy Audio Tutorial " , but I still have some doubts about how to get what I'm trying to do for several weeks ( yes, I know ... shame on me ; ) )

What I'm trying to do is to get the frequency of a particular sound ( we can compare it to the note produced by a guitar string ) listening to the sounds directly from an amplified microphone connected to the teensy .

THIS (http://electropit.com/index.php/2015/12/20/fc-109-max9812-microphone-amplifier-module/) is the microphone.

I tried it with a software spectrum analyzer , and the noise level seems acceptable to me . The note appears quite distinct ( always in the range of 200 to 950 Hz ) and very well separated ( also as amplitude) from any harmonics (usually they have a couple ).


I did not buy the audio shield , because I thought I connect the microphone output directly to ADC . This is the first question that I was born : for this type of application I can do without the sound shield ? I can directly connect the ADC output and work on what I read ?


I designed it using this simple scheme audio system design tool

sdfghjk.JPG


I'm on the right track ?


the detection of the note is a fundamental part of a project that I'm developing ... without your help I'm afraid of not being able to get what I'm looking for weeks ...
 
It's certainly possible, though the it's nosier to use a straight adc input as per your example above. Starting point is examples->audio->anylsis->fft

The example assumes the audio shield, but a quick swap of the input assignment to have ADC1 as per your example (export to a text editor and pull the needed lines into the example), and patch cord to the FFT in place of the one from AudioInputI2s and it should be working.

Note in the example there is a commented sine wave source you can swap in as a test of the output, and you will need to power your mic from 3.3V to avoid clipping issues.

If you are doubting the microphone see the peak detect example for a more basic function test.
 
Looks like you're on the right track.

If things don't all "just work", I'd recommend putting the dac object into your design and wire the adc to the dac. Connect amplified computer speakers to the DAC pin (ideally with a 10 uF capacitor in series, but most speakers block DC at their inputs anyway). Then you'll be able to hear the audio.

If that doesn't work, try modifying one of the examples like SamplerPlayer or PlaySynthMusic to output to the dac instead of i2s. That will let you test your speaker connection. Then when you know that's good, you can use it to listen to the adc to hear if Teensy is receiving your sounds.
 
Last edited:
The audio shield does help isolate problems. I started with an electret mic and the circuit recommended in the audio library's adc object. It was finicky. The audio shield can use the same mic, but eliminates the need for the resistor/capacitor circuit.
It also eliminates the need to use the dac, having a headphone jack built in for output.
This allowed me to focus on the Notefreq and FFT usage, and get my pitch-detection working.
I likely won't need the audio shield in any 'final' design, but it sure helped in the early process.
 
Plugged the FC-109 amplified mic

FC-109 ------------ TEENSY 3.2

VCC <----------> 3.3V
GND <----------> GND
OUT <----------> D15


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

// GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=470,269
AudioAnalyzeNoteFrequency notefreq1;      //xy=765,284
AudioConnection          patchCord1(adc1, notefreq1);
// GUItool: end automatically generated code

void setup() {
    AudioMemory(30);
    /*
     *  Initialize the yin algorithm's absolute
     *  threshold, this is good number.
     */
    notefreq1.begin(.15);
    pinMode(LED_BUILTIN, OUTPUT);

}

void loop() {
    // read back fundamental frequency
    if (notefreq1.available()) {
        float note = notefreq1.read();
        float prob = notefreq1.probability();
        Serial.printf("Note: %3.2f | Probability: %.2f\n", note, prob);
    }
}

it works perfectly for my purpose!
With probability i can take the most accurate frequency.

Thank you very much Paul, Gremlin and David!!!!
 
[MOVED TO A NEW THREAD] --> https://forum.pjrc.com/threads/33740-Issue-Audio-Library-and-NOKIA-5510-LCD-Monitor-can-they-work-together?p=100598#post100598


:rolleyes:

---------------------------------------------------

Here we are again.
ok, now i'm able to detect the main frequency with probability percentage! Great!
The next step of my project is to show these data on a Nokia 5510 LCD Screen, which i used i'm many arduino project without problem.
I testes it on my teensy 3.2 and it works properly. Then i've tried to use it with audio library and... i found some issues.

When i try to use AudioLibrary, i.e. this part

Code:
 // GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=470,269
AudioAnalyzeNoteFrequency notefreq1;      //xy=765,284
AudioConnection          patchCord1(adc1, notefreq1);
// GUItool: end automatically generated code

in a simple sketch that shows on lcd the value of a resistor keyboard, if THAT part of code is uncommented nothing seems to work, if i comment it i’m able to read values on my lcd… can you help me?

here’s the code (with that part commented…)… you can see also the LCD’s connection. The resistor keyboard is plugged to A0 (D14), mic on A1 (D15).

Code:
#include <Audio.h>



/*  
 // GUItool: begin automatically generated code
AudioInputAnalog         adc1;           //xy=470,269
AudioAnalyzeNoteFrequency notefreq1;      //xy=765,284
AudioConnection          patchCord1(adc1, notefreq1);
// GUItool: end automatically generated code
*/



#define PIN_SCE   7  // LCD CS  .... Pin 3
#define PIN_RESET 6  // LCD RST .... Pin 1
#define PIN_DC    5  // LCD Dat/Com. Pin 5
#define PIN_SDIN  4  // LCD SPIDat . Pin 6
#define PIN_SCLK  8 // LCD SPIClk . Pin 4   
// LCD Gnd .... Pin 2
// LCD Vcc .... Pin 8
// LCD Vlcd ... Pin 7

#define LCD_C     LOW
#define LCD_D     HIGH

#define LCD_X     84
#define LCD_Y     48
#define LCD_CMD   0




int sensorPin = A0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup()
{

   // AudioMemory(30);
    /*
     *  Initialize the yin algorithm's absolute
     *  threshold, this is good number.
     */
    //notefreq1.begin(.15);
    //pinMode(LED_BUILTIN, OUTPUT);

  
    //inizializzazione SD card1
    LcdInitialise();
    LcdClear();
    
    gotoXY(0,0);
    LcdString("TEST");
    gotoXY(10,2);
    LcdString("TEST1");
    delay(3000);
    LcdClear();


    
    
}

void loop()
{



  sensorValue = analogRead(sensorPin);    
//Serial.println(sensorValue);    

    gotoXY(0,0);
  LcdString("KEY");

  char c1[6]; // buffer 
  dtostrf(sensorValue, 1, 1, c1); 
  gotoXY(10,1);
  LcdString(c1);
  }



  static const byte ASCII[][5] =
{
 {0x00, 0x00, 0x00, 0x00, 0x00} // 20  
,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 !
,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 "
,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 #
,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $
,{0x23, 0x13, 0x08, 0x64, 0x62} // 25 %
,{0x36, 0x49, 0x55, 0x22, 0x50} // 26 &
,{0x00, 0x05, 0x03, 0x00, 0x00} // 27 '
,{0x00, 0x1c, 0x22, 0x41, 0x00} // 28 (
,{0x00, 0x41, 0x22, 0x1c, 0x00} // 29 )
,{0x14, 0x08, 0x3e, 0x08, 0x14} // 2a *
,{0x08, 0x08, 0x3e, 0x08, 0x08} // 2b +
,{0x00, 0x50, 0x30, 0x00, 0x00} // 2c ,
,{0x08, 0x08, 0x08, 0x08, 0x08} // 2d -
,{0x00, 0x60, 0x60, 0x00, 0x00} // 2e .
,{0x20, 0x10, 0x08, 0x04, 0x02} // 2f /
,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 30 0
,{0x00, 0x42, 0x7f, 0x40, 0x00} // 31 1
,{0x42, 0x61, 0x51, 0x49, 0x46} // 32 2
,{0x21, 0x41, 0x45, 0x4b, 0x31} // 33 3
,{0x18, 0x14, 0x12, 0x7f, 0x10} // 34 4
,{0x27, 0x45, 0x45, 0x45, 0x39} // 35 5
,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 36 6
,{0x01, 0x71, 0x09, 0x05, 0x03} // 37 7
,{0x36, 0x49, 0x49, 0x49, 0x36} // 38 8
,{0x06, 0x49, 0x49, 0x29, 0x1e} // 39 9
,{0x00, 0x36, 0x36, 0x00, 0x00} // 3a :
,{0x00, 0x56, 0x36, 0x00, 0x00} // 3b ;
,{0x08, 0x14, 0x22, 0x41, 0x00} // 3c <
,{0x14, 0x14, 0x14, 0x14, 0x14} // 3d =
,{0x00, 0x41, 0x22, 0x14, 0x08} // 3e >
,{0x02, 0x01, 0x51, 0x09, 0x06} // 3f ?
,{0x32, 0x49, 0x79, 0x41, 0x3e} // 40 @
,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 41 A
,{0x7f, 0x49, 0x49, 0x49, 0x36} // 42 B
,{0x3e, 0x41, 0x41, 0x41, 0x22} // 43 C
,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 44 D
,{0x7f, 0x49, 0x49, 0x49, 0x41} // 45 E
,{0x7f, 0x09, 0x09, 0x09, 0x01} // 46 F
,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 47 G
,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 48 H
,{0x00, 0x41, 0x7f, 0x41, 0x00} // 49 I
,{0x20, 0x40, 0x41, 0x3f, 0x01} // 4a J
,{0x7f, 0x08, 0x14, 0x22, 0x41} // 4b K
,{0x7f, 0x40, 0x40, 0x40, 0x40} // 4c L
,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 4d M
,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 4e N
,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 4f O
,{0x7f, 0x09, 0x09, 0x09, 0x06} // 50 P
,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 51 Q
,{0x7f, 0x09, 0x19, 0x29, 0x46} // 52 R
,{0x46, 0x49, 0x49, 0x49, 0x31} // 53 S
,{0x01, 0x01, 0x7f, 0x01, 0x01} // 54 T
,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 55 U
,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 56 V
,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 57 W
,{0x63, 0x14, 0x08, 0x14, 0x63} // 58 X
,{0x07, 0x08, 0x70, 0x08, 0x07} // 59 Y
,{0x61, 0x51, 0x49, 0x45, 0x43} // 5a Z
,{0x00, 0x7f, 0x41, 0x41, 0x00} // 5b [
,{0x02, 0x04, 0x08, 0x10, 0x20} // 5c ¥
,{0x00, 0x41, 0x41, 0x7f, 0x00} // 5d ]
,{0x04, 0x02, 0x01, 0x02, 0x04} // 5e ^
,{0x40, 0x40, 0x40, 0x40, 0x40} // 5f _
,{0x00, 0x01, 0x02, 0x04, 0x00} // 60 `
,{0x20, 0x54, 0x54, 0x54, 0x78} // 61 a
,{0x7f, 0x48, 0x44, 0x44, 0x38} // 62 b
,{0x38, 0x44, 0x44, 0x44, 0x20} // 63 c
,{0x38, 0x44, 0x44, 0x48, 0x7f} // 64 d
,{0x38, 0x54, 0x54, 0x54, 0x18} // 65 e
,{0x08, 0x7e, 0x09, 0x01, 0x02} // 66 f
,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 67 g
,{0x7f, 0x08, 0x04, 0x04, 0x78} // 68 h
,{0x00, 0x44, 0x7d, 0x40, 0x00} // 69 i
,{0x20, 0x40, 0x44, 0x3d, 0x00} // 6a j 
,{0x7f, 0x10, 0x28, 0x44, 0x00} // 6b k
,{0x00, 0x41, 0x7f, 0x40, 0x00} // 6c l
,{0x7c, 0x04, 0x18, 0x04, 0x78} // 6d m
,{0x7c, 0x08, 0x04, 0x04, 0x78} // 6e n
,{0x38, 0x44, 0x44, 0x44, 0x38} // 6f o
,{0x7c, 0x14, 0x14, 0x14, 0x08} // 70 p
,{0x08, 0x14, 0x14, 0x18, 0x7c} // 71 q
,{0x7c, 0x08, 0x04, 0x04, 0x08} // 72 r
,{0x48, 0x54, 0x54, 0x54, 0x20} // 73 s
,{0x04, 0x3f, 0x44, 0x40, 0x20} // 74 t
,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 75 u
,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 76 v
,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 77 w
,{0x44, 0x28, 0x10, 0x28, 0x44} // 78 x
,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 79 y
,{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
,{0x00, 0x08, 0x36, 0x41, 0x00} // 7b {
,{0x00, 0x00, 0x7f, 0x00, 0x00} // 7c |
,{0x00, 0x41, 0x36, 0x08, 0x00} // 7d }
,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ←
,{0x00, 0x06, 0x09, 0x09, 0x06} // 7f →
};




void LcdCharacter(char character)
{
  LcdWrite(LCD_D, 0x00);
  for (int index = 0; index < 5; index++)
  {
    LcdWrite(LCD_D, ASCII[character - 0x20][index]);
  }
  LcdWrite(LCD_D, 0x00);
}

void LcdClear(void)
{
  for (int index = 0; index < LCD_X * LCD_Y / 8; index++)
  {
    LcdWrite(LCD_D, 0x00);
  }
}

void LcdInitialise(void)
{
  pinMode(PIN_SCE,   OUTPUT);
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC,    OUTPUT);
  pinMode(PIN_SDIN,  OUTPUT);
  pinMode(PIN_SCLK,  OUTPUT);

  digitalWrite(PIN_RESET, LOW);
 // delay(1);
  digitalWrite(PIN_RESET, HIGH);

  LcdWrite( LCD_CMD, 0x21 );  // LCD Extended Commands.
  LcdWrite( LCD_CMD, 0xBf );  // Set LCD Vop (Contrast). //B1
  LcdWrite( LCD_CMD, 0x04 );  // Set Temp coefficent. //0x04
  LcdWrite( LCD_CMD, 0x14 );  // LCD bias mode 1:48. //0x13
  LcdWrite( LCD_CMD, 0x0C );  // LCD in normal mode. 0x0d for inverse
  LcdWrite(LCD_C, 0x20);
  LcdWrite(LCD_C, 0x0C);
}

void LcdString(char *characters)
{
  while (*characters)
  {
    LcdCharacter(*characters++);
  }
}

void LcdWrite(byte dc, byte data)
{
  digitalWrite(PIN_DC, dc);
  digitalWrite(PIN_SCE, LOW);
  shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
  digitalWrite(PIN_SCE, HIGH);
}

// gotoXY routine to position cursor 
// x - range: 0 to 84
// y - range: 0 to 5

void gotoXY(int x, int y)
{
  LcdWrite( 0, 0x80 | x);  // Column.
  LcdWrite( 0, 0x40 | y);  // Row.  

}



void drawLine(void)
{
  unsigned char  j;  
   for(j=0; j<84; j++) // top
  {
          gotoXY (j,0);
    LcdWrite (1,0x01);
  }   
  for(j=0; j<84; j++) //Bottom
  {
          gotoXY (j,5);
    LcdWrite (1,0x80);
  }   

  for(j=0; j<6; j++) // Right
  {
          gotoXY (83,j);
    LcdWrite (1,0xff);
  }   
  for(j=0; j<6; j++) // Left
  {
          gotoXY (0,j);
    LcdWrite (1,0xff);
  }

}
 
Last edited:
Status
Not open for further replies.
Back
Top