Go Down

Topic: FHT whistle detection (Read 4608 times) previous topic - next topic

SomethingClever

Hi guys,

Objective:
To detect whistling.

Hardware:
  • Arduino Yun
  • Electret Microphone Amplifier - MAX4466 with Adjustable Gain
Wiring:
  • Vcc -> 3.3v
  • Ground -> ground
  • Output -> A0
Library:
OpenMusicLabs FHT

Question:
I have read many, many forum threads about the FHT and the FFT, but some of them I do not understand, and many of them does not really give an answer, but just ends with OP going silent or finding a tweak that helped his individual project.

I need to be able do detect a human whistle, or at least just sounds around a high pitched frequency.

When I run the code (posted below), I get the same output every time, which of course tells me something is wrong. I have read that disabling the window function helps this problem, but I have also read that this function must be kept.

Can someone give me something to work from as I am completely lost where to begin? Right now I understand that the output is a collection of bins, each representing a frequency range, and the integer shows the amplitude of that range - is that correct?

Code:
Code: [Select]
/*
fht_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fht library.
it takes in data on ADC0 (Analog0) and processes them
with the fht. the data is sent out over the serial
port at 115.2kb.
*/

#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht

#include <FHT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  //TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while (1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while (!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    sei();
    Serial.println("start");
    for (int i = 0; i < FHT_N / 2; i++)
    {
      Serial.println(fht_log_out[i]);
    }
    Serial.flush();
  }
}


Output:
Code: [Select]
start
232
216
80
60
47
42
38
32
33
19
27
27
19
19
19
19
8
19
19
27
16
19
19
19
19
19
19
16
19
19
19
19
0
8
8
16
16
0
19
19
19
19
19
19
16
19
19
16
0
16
19
8
19
8
8
19
19
0
19
19
0
19
8
0
8
0
8
0
0
0
0
0
0
0
8
8
0
8
0
0
0
0
19
0
0
0
0
0
0
0
0
19
16
0
8
8
0
0
0
0
0
16
0
0
0
0
0
0
16
8
0
0
8
0
0
0
0
8
8
0
0
0
8
0
8
0
19
0

jremington

Quote
I need to be able do detect a human whistle, or at least just sounds around a high pitched frequency.
That is surprisingly difficult to do. The FFT or FHT just tell you what RANGES of frequencies at what amplitudes are present in a small audio sample.

To detect a particular sound, you must first clearly define it, and the term "human whistle" covers an extremely large range of possible sounds. Furthermore most sounds have high frequency components.

To start, you need to spend quite a bit of time analyzing various sounds that you are likely to encounter, until you can come up with some scheme to detect the one of interest.

SomethingClever

Okay, I see. I once thought this was going to be the easy part of the project.. :)

Anyway, then lets just say I want to detect when there is a high frequency sound at a certain amplitude. I guess that is a start?

jremington


tmd3

When I run the code (posted below), I get the same output every time, which of course tells me something is wrong.
Before you spend too much time and energy fretting about the output of the FHT, you should probably verify that your input has meaning.  

When I run your code with the sole modification that I set the analog input uniformly to zero, I get exactly the output that you posted.  When I turn off the windowing function, I get an output that shows a high value in the first bin, and zeros thereafter - again, just what I'd expect.  That suggests that your Arduino finds a zero every time it reads the ADC.

Try printing the contents of the array fft_input[], after the acquisition is complete, and before any further processing.

A schematic of your analog input circuit, including the microphone, would help.  Can you post one?

Grumpy_Mike

A human whistle is remarkably like a sin wave and should be easy to detect.
Being a hardware sort of person then I would use a simple UM3763 and have done.

jremington

Quote
I would use a simple UM3763 and have done.
And where might you buy one?

Grumpy_Mike

#7
Aug 03, 2015, 07:15 pm Last Edit: Aug 03, 2015, 07:18 pm by Grumpy_Mike
Got a bag of them in my component draw.  :)

You could always use on of these:-
http://uk.farnell.com/texas-instruments/lm567cn-nopb/tone-decoder-dip-8/dp/1496187

SomethingClever

@jremington

Good question! :)

@tmd3

I will get back to you about the schematic. But ground is to ground, vcc is to 3.3, out is to A0. Nothing else is connected at all.

When I loop through the fht_input array every value is "-10496".

@Grumpy_Mike

The tone decoder chip you linked to, which different parts of hardware will I need to get that working as a whistle detector?

Grumpy_Mike

Quote
which different parts of hardware will I need to get that working as a whistle detector?
What do you mean?
You will put your microphone output into that chip and it will output a logic level when it detects the sound. Down load the data sheet and read it.

SomethingClever

#10
Aug 04, 2015, 12:02 am Last Edit: Aug 04, 2015, 01:30 am by SomethingClever
Ah okay. I have just seen another chip where I needed a bunch of other hardware.

Well, that seems to be the solution then? :)

Edit: Does it matter if the chip is called    LM567CN or LM567CN/NOPB? Because then I found it at a local dealer.

Edit2: What I meant when saying hardware was resistors, capacitors and so on. I only have a very basic understanding of electronics and circuits, and after reading the data sheet three times I am still lost.

tmd3

#11
Aug 04, 2015, 03:15 am Last Edit: Aug 04, 2015, 02:31 pm by tmd3
... ground is to ground, vcc is to 3.3, out is to A0. Nothing else is connected at all.
I'll read between the lines and guess that you're using this device.  Based on the documentation, that's how you hook it up.
Quote
When I loop through the fht_input array every value is "-10496".
A uniform value of -10946 for fht_input[] didn't yield the results you showed in the original post.  To get that output, the input must be uniformly -32768, negative full scale for an int, corresponding to an analog input voltage of zero.  Here's a bit of the output that a uniform -10946 yields:
Code: [Select]
start
206
190
56
45
38
27
19

Similar to the posted results, but lower in magnitude.

A uniform value of -10946 for fht_input[] suggests that you're getting an analog reading of 348, corresponding to an input voltage of about 1.7V - supiciously close to 1.65V, which is 3.3V/2.  That's about what you should be getting from the Adafruit device, if the microphone output is zero - corresponding to VCC/2.  Maybe it's quiet when you run the test, or maybe it's just kind of quiet, and the gain is dialed all the way down.

I'd suggest whistling at the microphone from a few inches away while you run the test program to print the values of fht_input.  If that yields nothing, try turning the gain potentiometer to the other end, and testing again.  Note that you'll want to whistle for several seconds, at least until you see output, in order to be sure that there was sound while the ADC was taking readings.

[Edit:  Delete stray text]

Grumpy_Mike

The suffix in an IC is normally something to do with the package, it should say what in the data sheet. The NOPB is normaly when it is a lead free part ( no Pb - no lead ).
Yes you have to put resistors and capacitors round in order to define what the frequency you detect actually is.

SomethingClever

@tmd3

Yes, that is the device I got. I should have put a link in post #1.

I have tried replicating the output from yesterday, but now I just get -1xxxx in every output the first time, and then it slowly progresses towards -32768. I have tried reassembling everything, changing the microphone (I have two similar), adjusting the gain, using 5v instead, and nothing works.

All of a sudden my computer could not recognize the Arduino, and just said it was an unknown device. I tried uploading another sketch through wifi, and when that was loaded the computer recognized the Arduino and assigned it another port. I don't know what the heck is going on.

Now whenever I upload the sketch below and run it, my computer can't recognize the Yun.

Code: [Select]

/*
fht_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fht library.
it takes in data on ADC0 (Analog0) and processes them
with the fht. the data is sent out over the serial
port at 115.2kb.
*/

#define LOG_OUT 1 // use the log output function
#define FHT_N 256 // set to 256 point fht

#include <FHT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  //TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while (1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples
      while (!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fht_input[i] = k; // put real data into bins
    }
    Serial.println("start");
    for (int i = 0; i < FHT_N / 2; i++)
    {
      Serial.println(fht_input[i]);
    }
    Serial.flush();
    fht_window(); // window the data for better frequency response
    fht_reorder(); // reorder the data before doing the fht
    fht_run(); // process the data in the fht
    fht_mag_log(); // take the output of the fht
    sei();
    
  }
}



@Grumpy_Mike

I see, thank you.

The problem is that I simply don't understand how to assemble everything in the right way and what the different components do. This project is a part of a small university cause, and the whistle detection part of the prototype is a really, really small part of everything which I have spend waaay too much time on, and I simply don't have the time to get into how the circuit works, as I lack a lot of knowledge about the basics.

If you can tell me what components to buy and how to assemble them, I would be very grateful!

jremington

#14
Aug 04, 2015, 05:17 pm Last Edit: Aug 04, 2015, 05:23 pm by jremington
Buy an LM567 tone detector module here. http://indo-ware.com/produk-2459-sound-frequency-sensor-module-sound-activation-lm567.html

Or follow these instructions: http://www.scary-terry.com/more_stuff/tonedet/tonedet.htm

If you want to continue with the microphone module you have, and actually learn something, here is a tutorial from Adafruit on sound detection: https://learn.adafruit.com/fft-fun-with-fourier-transforms

Go Up