Go Down

### Topic: Help using ArduinoFFT (Read 15639 times)previous topic - next topic

#### el_supremo #15
##### Jul 26, 2013, 05:31 pm
Quote
the 0th frequency is the most dominant, and the 128th frequency is the least dominant

No, that's not it at all. As g_u_e_s_t has explained, each bin represents a range of frequencies. The 0th bin has the amplitude of the zero frequency (DC) component of the signal. The next bin will have the amplitude of frequencies around 150Hz, then 300Hz etc. up to the 127th bin with the amplitude of frequencies around 19050Hz.
If you want to know the frequency with the highest amplitude you would have to search the array to find the highest amplitude and then the index of that entry multiplied by 150 gives its frequency.

Pete
Don't send me technical questions via Private Message.

#### g_u_e_s_t #16
##### Jul 26, 2013, 06:53 pm
to find the highest amplitude, you can go through and check each value, saving the largest you have found.  for example:

Code: [Select]
`int j = 0;int k;for (int i = 0; i < FHT_N/2; i++) {  if (fht_log_out[i] > j) {    j = fht_log_out[i];    k = i;  }}Serial.println(k);`

again, this just gives you the bin number. you will need to multiply by 150 to get the frequency.

#### austincb90 #17
##### Jul 26, 2013, 09:09 pm
Arvis . Perfect thank you. Rock on

#### austincb90 #18
##### Jul 26, 2013, 09:28 pm
el_supremo:
Thanksyou this clarified a fundamental  misunderstanding i had with the code i.e. bins vs actual frequency.

#### austincb90 #19
##### Jul 26, 2013, 09:42 pm
g_u_e_s_t: thanks very much for taking the time to post the code.

very much appreciated.

#### austincb90 #20
##### Jul 26, 2013, 10:31 pmLast Edit: Jul 26, 2013, 10:45 pm by austincb90 Reason: 1
The highest amplitude bin code seems to be working now ( thank you g_u_e_s_t)

I believe my only remaining issue is that I need to reduce the bin increment size.
I am using is to detect the frequency of a strobing  light, and  since a strobing light at all realistic frequencies will likely fall below 150hz, thus all frequencies will lie in bin 0 and I am unable to see any differentiation among the different strobe frequencies.  and for clarity is again shown below:
Code: [Select]
`/*fht_adc.pdeguest openmusiclabs.com 9.5.12example sketch for testing the fht library.it takes in data on ADC0 (Analog0) and processes themwith the fht. the data is sent out over the serialport at 115.2kb.  there is a pure data patch forvisualizing the data.*/#define LOG_OUT 1 // use the log output function#define FHT_N 256 // set to 256 point fht#include <FHT.h> // include the libraryvoid 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.write(255); // send a start byte    Serial.println("here starts the list");   int j = 0;int k;for (int i = 0; i < FHT_N/2; i++) {  if (fht_log_out[i] > j) {    j = fht_log_out[i];    k = i;  }}Serial.println(k);    Serial.flush();  }}`

TLDR: how do i reduce the size of my bins? , perhaps so that each bin is ideally only 2hz instead of 150 hz.

Again I have extreme gratitude to those of you who have  helped me

#### g_u_e_s_t #21
##### Jul 27, 2013, 03:00 am
there are only 2 ways to reduce the bin size: 1. increase the number of bins, 2. decrease the sampling frequency.  since you are already using FHT_N = 256, you can't go any higher in terms of number of bins.  but, since you don't care about frequencies above 150Hz, you can easily drop the sampling rate.  that is done with ADCSRA.  the last 3 bits set the rate.  if you set it to 7, the slowest rate, you get /128.  so sampling frequency is 16MHz/128/13 = 9.6kHz, and each bin is therefore 37Hz.  this is probably not slow enough for your application, so you will have to set up the ADC another way.  one way is to setup a timer to trigger the ADC, and another is to use a delay loop.  the delay loop is easier, so i will show that.

Code: [Select]
`void setup() {  Serial.begin(115200); // use the serial port/*  dont do any of this, especially the TIMSK0 business     also got rid of cli() and sei() below as analogRead might need the interrupts?  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    for (int i = 0 ; i < FHT_N ; i++) { // save 256 samples      fht_input[i] = analogRead(0); // put real data into bins      delay(1); // delay 1ms betwee samples    }    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    Serial.write(255); // send a start byte    Serial.println("here starts the list");   int j = 0;int k;for (int i = 0; i < FHT_N/2; i++) {  if (fht_log_out[i] > j) {    j = fht_log_out[i];    k = i;  }}Serial.println(k);    Serial.flush();  }}`

this will take a sample every 1ms, so 1kHz sampling rate, and therefore 4Hz bin size.  on the down side, it takes 256ms to get a full set of samples, so its slower, but this is a neccessary  tradeoff.  to get finer resolution, you have to take longer.

#### austincb90 #22
##### Jul 27, 2013, 04:01 am
wow , thank you so much g_u_e_s_t. I want to genuinely thank you for your generosity in helping me.
the monitor is certainly responding. the code uploads perfectly. Especially as a beginner, I would still be stuck at square 1 without your help. Thank you!

Something still seems to be amiss . Just so i am sure i understand, a bin value of "0" corresponds to 0-4hz, and a bin value of "1" corresponds to 4-8 hz correct?

Strangely, in a blackened room with the photresistor covered a value of 1 is displayed. when i subject to the photoresistor to a strobe of 8 hz pretty consistently displays a value of "0". And as soon as the strobe is cutoff, the monitor proceeds to display 1's. Occasionly while the strobe is on perhaps every 5th value may read "1" and about every 20th value correctly displays a "2" , although the strobe light frequency goes unchanged. Im definitely puzzled.

Again I cant thank you enough g_u_e_s_t

#### g_u_e_s_t #23
##### Jul 27, 2013, 08:07 am
a lot of how it works depends upon your signal coming in, and what the circuit is like.  bins 0, 1, and probably 2 as well have a lot of the DC signal in them (bin 0 because it is DC, and the other ones because there is a bit bleed).  you can either filter your signal to minimize the amount of DC coming in, or just ignore those bins.  for example, if you know the lowest frequency you will probably see is 4Hz, dont bother checking bin 0 or bin 1 in the max checking loop.  start with i = 2.

for very slow things, often measuring the time between signals is easier and more accurate.  you could put your photoresistor through a gain circuit, so that its mostly all on (5v) when there is light, and mostly all off (0v) when there is no light.  you then just monitor the pin, and when it goes high, you start counting.  you then wait for it to go low, and go high again, and then stop counting.  the time it took between high transitions is the period, and the frequency is just 1/period.

#### Arvis #24
##### Jul 28, 2013, 08:09 pm
btw I'm making this together with a LED matrix using 4 shift registers 74hc595.

Is there any way that
Code: [Select]
`    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();`
This part could somehow make one line of LEDs (one pin of a shift register) being constantly set to HIGH, even when the latch pin is LOW?
Without that part of the code my LED matrix functions normally^ but then I can't get the frequency/amplitude data.

#### g_u_e_s_t #25
##### Jul 28, 2013, 10:13 pm
its most likely the interrupt stuff, which isnt really necessary.  try it without it and see what happens

Code: [Select]
`    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`

#### Arvis #26
##### Jul 28, 2013, 10:43 pm
Nothing changes.
I've noticed that the problem is reduced (not solved however - one line is still brighter than the others, just not as much) by setting
#define FHT_N 256 to #define FHT_N 16

#### g_u_e_s_t #27
##### Jul 29, 2013, 05:38 am
can you post the rest of your code?  the FHT takes a while to run, so its probably messing up the timing on when the LEDs are set.

#### Arvis #28
##### Jul 29, 2013, 02:03 pm
Sure, here is the code:
http://pastebin.com/sJhK5j40

#### g_u_e_s_t #29
##### Jul 29, 2013, 07:58 pm
it looks like the way you set how long an LED is on for, is by the amount of time it takes to run 8 clock() functions.  the reason why the last row is brighter than the rest, is because it also has to run the fht() function, so it takes much longer.  the easiest fix, is to put in 1 more row, which is a blank row, and write it out to the LEDs.  that way all of your data rows will be on for the same time, and then there will be a blank row (which you can not see) which will be on for longer.

Go Up