arduino FHT

Hello, I'm running fht library on my arduino and spectrum analizer works great using 38.5k sample rate this version uses only one ADC channel, but for my project I want to make some microcontroller based device whose sampling rate would be 10 ksample, and it will use 2 or 3 ADC channels.

I'm asking this question, because I don't know how to change frequency and sampling rate values.

Thank you in advance, here is the linkh ttp://wiki.openmusiclabs.com/wiki/ArduinoFHT

You will have to write your own data input routine and call the functions in the FHT library as appropriate. You can follow the example provided in the "examples" folder of the Open Music Labs FHT library, namely fht_adc.pde.

As I understand I need to read each analog pin (for ex. 0 to 2) independently process this data and then output ? I.e do the following routine for every analog input?
And if I want to lower sampling rate and frequency spectrum (from 18.5 to 4/5khz?)
and what about square wave input ?

The data from each analog input must be processed independently, however the inputs can be sampled at (nearly) the same time, if you have enough memory for the data arrays.

To lower the sampling rate, study the example and insert a delay as needed.

What about square waves -- is there a question?

Yes, that's the question, can this library used as square wave analyzer @ <20 kHz?

You can analyze any waveform, as long as the maximum frequency present in the waveform is less than 1/2 the sampling frequency. For a square wave, that is never true, so you will see false peaks due to aliasing.

A good antialiasing filter with a hard cutoff of no more than 1/2 the sample frequency is always recommended if you want to avoid such artifacts.

OK, thank you very much.
I'm bit confused, how can I read adc1 and 2, after I read adc0, I mean code?

There are up to 8 ADC channels, assigned to different pins and you have to select the appropriate one before doing the conversion. You can either select the appropriate channel and read in an array of values from that channel, or step through the channels and convert one value from each channel.

For the fastest sampling you need to do direct port manipulation. The ADC section of the processor data sheet explains all of this in great detail, but unfortunately it is difficult to read. If you wish to start by modifying someone else's code, like the OpenMusicLabs example, you will still need to consult the data sheet in order to understand all the steps involved.

I've read the details, and as I understand I choose ADC channels using admux, and read them using arch and adcl bytes, but when I assign admux register to read second channel on atmega328 nothing valuable happens, and please if you can, just give me some example.

when i assign ADMUX = 0b010000001; this means that i use ADC1 but, finally ADCL and ADCH register processing gives me ADC0 value. i cant understand why ?

giorgi111-111:
when i assign ADMUX = 0b010000001; this means that i use ADC1 ...

Checking it against the description of register ADMUX in the datasheet:

  • Bit 7 = 1, Bit 6 = 0: This combination selects reference mode 2, which is described in the datasheet as, "reserved." I don't know how the reference will behave, but it's likely that it won't do what you expect.
  • [Edit: Delete this, because it's incorrect] Bit 0 = 1: This selects ADC channel 0, not ADC channel 1.

So, it's not surprising that it doesn't tell you about ADC channel 1. Maybe that's what you used, or maybe you copied it wrong.

If you want help, you should probably post some code. You should tell us what you expected, and tell us what happened instead. Your code should be a small sketch that illustrates the problem, rather than long stretches of code that are largely irrelevant to your question.

Bit 0 = 1: This selects ADC channel 0, not ADC channel 1.

That is not correct. MUX3...0, the lower 4 bits of ADMUX, select ADC channel 0-8, where values of 0 = channel 0, 1 = channel 1, 7 = channel 7, 8 = temperature sensor and >8 are reserved.

Here is how the OpenMusicLabs fht_adc.pde example initializes the ADC:

 ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0

The "4" in the upper nibble selects AREF to be AVCC and ADLAR = 0 (data are right adjusted).
To choose channel 1, set ADMUX = 0x41;

As the author of the OpenMusicLabs pages discusses, it is a good idea to turn off the digital inputs associated with each channel, to reduce noise.

jremington:

Bit 0 = 1:

That is not correct. MUX3...0, the lower 4 bits of ADMUX, select ADC channel 0-8, ...

Indeed, that is not correct. Edited the original post, using strikeout to leave a trail.

Thanks.

0x41 = 0b01000001; right? So I think that it will give me same result bit I'll try it out. I use open music's lab code. Thank you very Mich for your response. I'll write my results down.

void setup()
{
  Serial.begin(115200);
  TIMSK0 = 0; 
  ADCSRA = 0xe5; 
  ADMUX = 0x40; // use adc0
  //when i change DAMUX = 0x41; //use adc1
  //same results are coming as in adc0
  DIDR0 = 0x01; 
}

void loop()
{
  while(index == 1)
  {
    T = micros();
    cli();
    while(!(ADCSRA & 0x10));
    ADCSRA = 0xf5; 
    int k = ADCL;
    k = (ADCH<<8) + k;
    data[0] = k;
    sei();
data[0] = k;

All of your measurements are being stored in data[0]. Use an index instead of 0.

0 is index, if I read k variable I have same results

The problem is, you are not studying the example. Because you won't do that, your code does not work.

Again, here is how it works in the fht_adc.pde example:

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
    }

i think my mistake is that i didn't convert values Accordingly?

but if it works for adc0 why now for adc1 ?

The code you posted doesn't work properly for either ADC0 or ADC1.

I think that it works for adc0 because I tested out voltage divider and it gave me true value.

Can you tell me why it doesn't work? I would be very thankful