Problem using FHT

Hello everybody,

i'm having troubles using an AVR PIC KY-037 to acquire analog signal to be processed using the FHT library.

I first made a test, serial printing the signal get from the module. I read a base value i can change using the built in potentiometer from 0 to 1023 and a small signal over it. If i scream at the microphone i can have a +-100cnt, that should be enough for a preliminary test.

I used the library as shown:

#define LOG_OUT 0 // use the log output function
#define LIN_OUT 0
#define LIN_OUT8 0
#define OCTAVE 1
#define FHT_N 256
#define SCALE 1
#define OCT_NORM 1
#include <FHT.h>

void setup() {
	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();	
		for (int i = 0 ; i < FHT_N ; i++) { 
			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();
		fht_reorder();
		fht_run(); 
		fht_mag_octave();
		sei();

		Serial.print(fht_oct_out[0]);
		Serial.print(", ");
		Serial.print(fht_oct_out[1]);
		Serial.print(", ");
		Serial.print(fht_oct_out[2]);
		Serial.print(", ");
		Serial.print(fht_oct_out[3]);
		Serial.print(", ");
		Serial.print(fht_oct_out[4]);
		Serial.print(", ");
		Serial.print(fht_oct_out[5]);
		Serial.print(", ");
		Serial.print(fht_oct_out[6]);
		Serial.print(", ");
		Serial.println(fht_oct_out[7]);
	}

}

Here a typical result without OCT_NORM

218, 203, 70, 52, 56, 59, 59, 56
218, 203, 68, 49, 53, 53, 59, 61
218, 203, 70, 49, 50, 56, 56, 60
218, 203, 68, 50, 52, 55, 57, 59
218, 203, 70, 55, 59, 59, 56, 58
218, 203, 71, 53, 61, 62, 58, 58
218, 203, 71, 56, 60, 57, 55, 59
218, 203, 70, 53, 61, 62, 58, 58
218, 203, 70, 49, 59, 58, 60, 59
218, 203, 69, 55, 54, 59, 59, 59
218, 203, 69, 51, 52, 53, 57, 58
218, 203, 74, 55, 57, 57, 55, 61
218, 203, 71, 49, 51, 51, 57, 56
218, 203, 70, 57, 54, 55, 55, 57
218, 203, 70, 53, 56, 56, 56, 58

and here with OCT_NORM

218, 203, 62, 34, 30, 21, 13, 8
218, 203, 61, 37, 25, 19, 16, 8
218, 203, 62, 35, 27, 21, 13, 8
218, 203, 62, 35, 27, 21, 13, 8
218, 203, 63, 30, 25, 16, 13, 8
218, 203, 62, 34, 29, 21, 16, 13
218, 203, 60, 37, 25, 22, 16, 8
218, 203, 63, 35, 29, 21, 13, 8
218, 203, 61, 34, 27, 22, 13, 8
218, 203, 63, 37, 27, 21, 16, 8
218, 203, 61, 33, 27, 22, 16, 8
218, 203, 62, 36, 27, 19, 16, 13
218, 203, 62, 33, 24, 21, 16, 8
218, 203, 61, 33, 28, 21, 13, 0
218, 203, 63, 33, 25, 19, 16, 8
218, 203, 62, 37, 25, 24, 19, 8

I thought i should have small signals (all near 0) because i'm not screaming at the microphone. Why do i have always big numbers?

Thanks

PS: The FHT somehow works: if i remove the offset i can see differences when i Whistle but i have a very noisy signal. Making a frequency test with headset i realized that first two channels doesn't change at all (maybe they are saturated) and other changes but with a lot of noise. I'll try to amplify the signal, or is it better to forget the AVR PIC KY-037 and to make a direct amplification circuit for a jack signal?

You are doing a 256 point FHT but only printing the first 8 bins. Those 8 bins will correspond to frequencies up to about 300Hz (if my math is correct!). If you scream or whistle into the mic, most of the audio energy will be higher than that.
Bin 0 is the DC component and seems to have a lot of the signal's content. Is the range of the KY-037 audio output signal from 0-5V or +/- 2.5V? The code itself does a DC offset correctly but that isn't going to help if the signal at the ADC isn't offset too.

Pete

Sorry for delay but i had no time to test again the project.

I used that functions: info here

  • fht_window(): fht_input[] -> fht_input[]
  • fht_reorder(): fht_input[] -> fht_input[]
  • fht_run(): fht_input[] -> fht_input[]
    the final output is kept in fht_input[], with the 0 -> N/2 bins having the sum of the real and imaginary components, and the N/2 -> N having the difference between the real and imaginary components.
  • fht_run(): fht_output[] ->fht_oct_out[] (Maybe they means fht_input[] ->fht_oct_out[]?)
    The data is represented as an 8b value of 16*log2(sqrt(mag)). There are LOG_N bins, and they are given as follows:

FHT_N = 256 : bins = [0, 1, 2:4, 5:8, 9:16, 17:32, 3:64, 65:128]
FHT_N = 128 : bins = [0, 1, 2:4, 5:8, 9:16, 17:32, 3:64]
[/list]

so i suppose i'm printing the whole results.

I measured the voltage of the KY-037 and i adjusted the potentiometer to get a 2.5V offset. It can't work under 0V because it's powered from arduino.

I made a test traking maximum and minimum analog and the signal was very low (only 100 around the offset) and so i built an amplifier (see circuit) setting the KY-037 offset to 1V. I adjusted the potentiometer to have ~3V on arduino and i tested the signal. Now it saturate if there is a lot of noise but it doesn't with a standard level, i tested with ~+-300 analog.

The behaviour is better but it has the same problem described in the first post. Channel are unstable and overlap each other and only 4 / 8 channels seems to be related to the noise i produce.

I will make a last test with a direct audio connection but i'm starting to think to buy a pi and to set up a i2c connection. (or is there a chip or a module that makes a fht?)

circuit.png

Sorry, I missed your use of fht_mag_octave, so printing the 8 bins is correct. The first two bins are still the DC and very low frequency bins and they still suggest to me that there is a strong DC bias in the signal.
I think your circuit needs to have a capacitor from the potentiometer wiper to the Arduino A0. Without it, there will be a strong DC bias on A0.

Pete

There must be a "strong DC bias" on the ADC input, typically about 2.5V (for a 5V Arduino), because the ADC can't measure negative values. Please post a wiring diagram showing how you have wired the input (hand drawn, not Fritzing).

If the following subtractive offset is not correct, expect large values in the lowest frequency bin.

k -= 0x0200; // form into a signed int

The diagram is in #2.
The subtractive offset is correct once the capacitor is added to the circuit.

Pete

I do not think that the diagram is correct or that the added transistor amplifier will help.

The KY-037 is extremely poorly documented and a search through this forum suggests that several people have experimented with it, but no one has had any success.

The only circuit diagram I've found for it is here (see page 40) and that circuit is obviously not useful as a linear microphone amplifier. It may not be complete as it does not show the A0 output.

I suggest to use a different microphone/amplifier module, such as this one from Sparkfun, which properly biases the output to Vcc/2, for input to the Arduino.

The KY-037 has a potentiometer that fix its output bias. I set it to have a +2.5V when i connected it directly to A0 and i changes it to have +1V when i connected it to the bjt.

To remove all doubts i will connect directly an audio source to a bias and to the bjt. I noticed that in the tutorial they uses the module to read maximum and minimum values and most of FHT implementations uses a direct audio line.

your circuit needs to have a capacitor from the potentiometer wiper to the Arduino A0

I'm wrong (again). All the cap would do is remove any DC bias.

Pete

I made a test, i connected an audio jack directly to the bjt with a bias voltage. I changed the condensor to 1uF to avoid saturation in the ADC. The output remains unstable very unstable...

I'm going to connect my laptop to make a FHT and send it to arduino using an ehernet module

Thank you

Or you could use a properly designed microphone amplifier module, as suggested in reply #6.

I have a question: plotting the fht_input (before fht_window) i see that it's greater than 1023, is it right?

I collected this two sets of data unplugging the jack so basically you can see the bias fluctuation:

plotting analogRead:

622 624 626 624 622 624 623 623
623 625 625 621 626 621 623 625
628 623 624 622 624 622 625 623
623 623 624 626 622 623 623 622
625 624 625 623 623 622 622 625
621 621 623 626 623 623 623 622
624 625 623 623 625 624 623 622
624 625 626 625 622 625 622 623
623 625 622 621 623 622 623 622
621 620 624 623 624 622 622 624
622 623 623 624 623 623 625 626
624 624 625 624 624 622 624 622
623 624 624 621 623 623 623 624
622 622 623 624 624 622 623 623
623 624 623 623 624 625 624 621
624 625 624 623 622 622 625 623
625 622 622 620 623 623 623 623
623 621 624 624 624 622 624 625
623 624 624 623 623 623 623 625
624 623 624 623 621 624 624 628
621 624 622 621 623 626 623 622
621 621 623 626 623 624 623 624
623 625 623 623 624 625 624 623
624 622 624 623 621 622 623 624
622 623 622 621 623 624 623 622
621 620 623 623 622 623 623 624
622 623 623 625 624 622 624 623
623 624 624 623 621 623 625 623
623 625 622 621 624 625 626 622
621 622 626 622 622 623 622 623
623 625 622 624 624 623 623 625
623 623 626 622 623 622 622 624

plotting fht_input

6912 6976 6912 6976 6976 6976 6912 6912
6976 6976 6912 6912 6848 6912 6848 6912
6912 6976 6976 6912 6848 6912 6912 6912
7040 6976 6912 6976 6912 6976 6976 6912
6912 6912 6848 6848 6912 6912 6912 6912
6976 6912 6912 6976 7104 6912 6912 6848
6848 6848 6848 6976 7040 7040 6912 6976
6912 6976 6912 6912 6912 6976 7040 6912
6976 6912 6848 6912 6976 6912 6848 6848
6912 6912 6912 6976 7104 7040 6976 6976
6912 6912 6976 6912 6912 6912 6912 6912
6848 6912 6912 6784 6848 6912 6912 7040
6912 6912 6848 6848 6912 6912 6912 6912
7040 6912 6912 7040 7104 6912 6912 6912
6976 6912 6912 6976 7040 6976 6976 6912
6976 6912 6848 6848 6848 7040 6912 6976
6912 7104 6912 6848 6912 6976 7040 6976
6912 6976 7040 7040 6912 6912 6912 7104
6912 6848 6912 6912 7104 6912 6912 6848
7040 6976 6912 6912 6912 6912 6912 6976
6976 6912 6912 6912 6912 6848 6848 6912
6784 6912 6912 6912 6976 6976 6976 6848
6848 7040 6848 6784 6848 7040 6912 6976
7040 7040 6912 6912 6912 6976 7040 6912
6912 6976 7040 6912 6976 6912 7040 6976
6848 6848 6912 7040 6848 6912 6912 7168
6976 6912 6912 6912 7040 6912 6912 6976
7104 6976 6976 6912 6912 7040 6848 6848
6976 6976 6848 6912 6976 6848 6912 6912
6912 6912 6912 6976 6976 6976 6976 6976
6912 6912 6912 6976 7040 6848 6912 6912
7104 6976 6912 6912 7104 6912 6912 6912

and here the fht_oct_out that is very high in all channels even if the input is flat...

196.00, 180.00, 43.56, 38.70, 45.92, 41.36, 35.00, 26.31

I don't think that the microphone or the audio jack has a problem. Maybe the bjt amplifier is not good enought but a flat signal is wrongly processed by the fht library. In my opionion the problem is in the library but I do not have the skills to understand where and how...

Analog read should be showing numbers around 512. Values of 620+ indicate a strong DC bias on the input which explains why the fht_oct_out gives a high value for the first bin. The second bin presumably has a lot of "leakage" from the first bin.

You should probably modify the FHT to handle the offset you really have as opposed to the one you should ideally have.
Change this:

				k -= 0x0200; // form into a signed int

to this

				k -= 623; // form into a signed int

623 is the average value of the first 160 values from analogRead.

Your problem is that you are giving the FHT library incorrect data. It therefore gives you garbage as a result.
The BJT amplifier is not working well, or at all. As @jremington has said, you should be using a proper audio amplifier.

Pete

el_supremo:
Analog read should be showing numbers around 512. Values of 620+ indicate a strong DC bias on the input which explains why the fht_oct_out gives a high value for the first bin. The second bin presumably has a lot of "leakage" from the first bin.

Your problem is that you are giving the FHT library incorrect data. It therefore gives you garbage as a result.
The BJT amplifier is not working well, or at all. As @jremington has said, you should be using a proper audio amplifier.

I set 620 as offset purposely to avoid signal deformation near 1V due to bjt. I really can't understand why a fft should have leakage or why channels that represents higher frequency should change changing offset.

Changing the manual offset to 623 in the sketch i have:

-448 -448 -384 -320 -512 -256 -448 -448
-512 -512 -320 -512 -448 -512 -512 -512
-448 -256 -384 -256 -448 -320 -384 -256
-256 -448 -448 -384 -512 -512 -512 -384
-256 -384 -256 -448 -384 -512 -448 -256
-448 -384 -192 -384 -384 -448 -384 -256
-448 -320 -448 -384 -512 -256 -448 -384
-384 -320 -448 -384 -512 -384 -512 -320
-512 -384 -448 -256 -384 -320 -384 -320
-320 -448 -448 -448 -448 -448 -384 -384
-384 -512 -384 -256 -512 -384 -256 -448
-256 -512 -320 -448 -320 -320 -384 -448
-384 -256 -448 -256 -512 -384 -448 -384
-512 -320 -384 -384 -192 -384 -384 -448
-384 -512 -512 -448 -320 -384 -256 -448
-256 -320 -384 -448 -384 -384 -512 -448
-512 -256 -448 -448 -448 -384 -512 -512
-256 -512 -448 -512 -448 -320 -256 -256
-448 -256 -512 -320 -320 -448 -256 -448
-384 -384 -448 -448 -448 -320 -448 -320
-320 -512 -320 -448 -512 -256 -512 -320
-384 -448 -256 -384 -320 -320 -384 -448
-448 -384 -256 -384 -384 -512 -384 -192
-512 -448 -320 -512 -320 -512 -512 -384
-448 -320 -448 -384 -320 -512 -448 -384
-512 -320 -512 -320 -256 -512 -256 -256
-512 -384 -512 -384 -256 -512 -448 -448
-320 -256 -448 -448 -192 -384 -448 -512
-384 -256 -448 -448 -256 -448 -448 -512
-512 -320 -448 -512 -256 -448 -384 -384
-512 -256 -192 -384 -320 -512 -384 -192
-448 -512 -512 -448 -192 -448 -512 -512

130.29, 113.67, 38.91, 37.76, 39.13, 34.74, 33.30, 39.97

changing to 619 i have:

0 -64 0 -128 -192 -64 0 0
64 64 64 -128 0 0 -128 64
64 128 -128 0 0 64 -128 -64
64 0 -64 -128 0 0 192 -64
0 0 64 0 64 -128 64 0
0 -128 -64 -128 -64 -64 128 -192
128 0 192 64 64 -64 64 64
128 -64 0 0 0 192 0 0
0 -64 64 64 64 64 -128 64
0 128 64 -128 -128 -128 0 0
-64 -64 128 64 64 0 0 0
64 128 64 64 -128 -64 -64 128
0 0 -128 -256 0 0 64 -128
0 -128 64 128 64 128 -64 64
0 128 0 0 64 -64 64 0
0 64 -128 64 0 64 0 -128
0 -64 0 64 0 64 -128 128
64 -64 64 -128 64 64 64 64
-192 0 64 0 64 -128 0 64
0 64 -128 -128 192 64 128 -128
0 128 0 0 -64 -64 128 0
0 -128 -64 64 -64 -64 64 -128
0 128 -128 -64 -64 0 128 -64
-64 64 0 0 64 -192 -64 64
-64 0 -128 0 128 -64 0 128
0 0 0 -64 64 -64 -64 128
64 0 0 -64 64 128 -64 0
0 0 64 -128 0 192 -64 -64
-64 0 64 -192 -64 64 -128 0
192 64 0 0 64 128 -64 -64
192 0 -64 -64 0 64 -128 -64
0 -64 0 0 0 128 -128 -64

32.02, 40.81, 36.23, 36.83, 38.33, 31.86, 35.93, 35.66

Changing the value of 1 points gives very strong differences in the result.

I also have a TL072CP to try to amplify the audio signal, but probably the only way to make it work is to buy the microphone you mentioned. And which chip should i buy to amplify a standard audio signal?

Changing the value of 1 points

You changed it by 4 which will be amplified by a factor of 64 by the statement "k <<= 6;"
The fact that the average changes from one run to the next suggests that the input circuit to the ADC is not very stable. That is only going to make life even more difficult.

I really can't understand why a fft should have leakage

You'll have to read up on "FFT spectral leakage" but it's a fact of life when using the FFT.

or why channels that represents higher frequency should change changing offset

I don't understand this but I think the answer is "they don't".

BTW. What is the overall purpose of using the FHT? You say you want to "acquire analog signal to be processed using the FHT library". Why? What are you going to do with the FHT output assuming that it is working?

Pete

I'm going to do graphic effects with leds and pwm...

will i have a more stable results using an OP-AMP to amplify the signal?

You won't have correct results until you use a proper amplifier.

please define "proper amplifier" and why a TL072CP is not proper. Which spec is too low to amplify the signal well?

The TL072CP would work well, provided it is used correctly. However, it is a very, very old design and generally requires bipolar power supplies. Post your circuit diagram.

For the bipolar power supplies isn't enought to put a 0-5V capactior big enough? (now i have a 47uF)

For the layout i thought to use this schematic, get from the board you mentioned at sparkfun.

Honestly i don't understand the utiltiy of the capacitor near R3 (if OP AMP has a very big input impedance that zone should be DC-only)

Only another question before wiring: i will reduce the R4 R5 by a factor 10, will it introduce noises or something else?

Thanks you all for patience :slight_smile: