Problems in Arduino FFT and Data sampling

Hi everyone,

I am working on data processing with FFT. I have some doubts about fft size and adc data memory. Hopefully may get some bits of help, thanks.

I am designing a spectrum analyzer by reading analog from ADC and processed by Arduino with fft to convert time-domain signals to frequency domain signals. I have searched for many materials but still cannot solve my problems.

Let review what I understood (I am not sure is it correct, please correct me if I am wrong),

  1. Sampling frequency must larger than 2x signal frequency by Nyquist sampling theorem.
  2. High Sampling frequency would get a better resolution of the frequency bins.
  3. High Sampling frequency means need more memory to store sampling points of the signal.
  4. Sampling points(N) must be a power of 2 integers (N=64, 128, 256, etc).
  5. Numbers of frequency bins is the same as numbers of sampling points(N)
  6. The sampling frequency is fixed in the design
  7. FFT size is fixed in the design

Let talk about my problems. Since I may use arduino or FPGA as my data processor, so the highest sampling frequency is not a limitation for me. My FPGA can sample data with high-speed ADC up to 32MHz. Both FPGA and arduino would make me encounter some similar problems but I think it would easier to understand and discuss with Arduino.

Assume I am using constant 20kHz sampling frequency to sample Sinewave signal frequency in a range from 10Hz to 10kHz. The size of the fft is chosen to use 64.

Q1.
Is the fft process after captured the entire cycle of the signal?? or it is a continuous procedure to process each sample data at the time it received ??

/*SAMPLING*/
  for(int i=0; i<SAMPLES; i++)
  {
    useconds_sampling = micros();
  
    vReal[i] = analogRead(analogpin);
    vImag[i] = 0;
  
    while(micros() < (useconds_sampling + sampling_period_us)){
      //wait...
    }
  }  
 
  /*FFT*/
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

Q2.
When I sampling 10kHz signal with 20kHz, lt would only obtain 2 points per cycle in the 10kHz Sinewave signal.
How it would fit into a size of 64 fft? Is it process fft after captured 32 cycles of signal??

Q3.
When I sampling 10Hz signal with 20kHz, lt would obtain 2000 points per cycle in the 10Hz Sinewave signal.
How it would fit into a size of 64 fft? The size of fft is not enough for all points. A more extreme case with a sampling frequency 32MHz, total 3.2MHz data points are collected. How to fit the memory and the fft??

Q4. The numbers of sampling points must be the power of 2(N=64, 128, 256, etc). Is it true only in Arduino?? or also true in all data sampling??

Q5.
The number of samples is fixed, the Sampling frequency is fixed, fft size is fixed. How to process all difference frequencies ?? Why is it needed to be power of 2??

The complete code is referred to the follow website.
https://www.norwegiancreations.com/2019/03/arduino-fft-pt-2-improving-the-hardware-for-real-time-analysis/

Thank you for all of your help.

shyuenaa:
Hi everyone,

I am working on data processing with FFT. I have some doubts about fft size and adc data memory. Hopefully may get some bits of help, thanks.

I am designing a spectrum analyzer by reading analog from ADC and processed by Arduino with fft to convert time-domain signals to frequency domain signals. I have searched for many materials but still cannot solve my problems.

Let review what I understood (I am not sure is it correct, please correct me if I am wrong),

  1. Sampling frequency must larger than 2x signal frequency by Nyquist sampling theorem.

yes

  1. High Sampling frequency would get a better resolution of the frequency bins.

no, more bins and lower sampling frequency give more resolution. Each bin is Fs/N in bandwidth, so decreasing Fs or increasing N will give a narrower bandwidth per bin

  1. High Sampling frequency means need more memory to store sampling points of the signal.

No, larger N needs more memory, N samples in fact

  1. Sampling points(N) must be a power of 2 integers (N=64, 128, 256, etc).

In general no, any integer can be used, but for simple FFT libraries this is a requirement, and certainly on a small microcontroller you'll only see PoT FFTs.

  1. Numbers of frequency bins is the same as numbers of sampling points(N)

Yes, including the negative frequency bins (if they don't interest you, there are N/2 useful bins)

  1. The sampling frequency is fixed in the design

Its just the rate of sampling, should be easy to change, upto some maximum

  1. FFT size is fixed in the design

Why?

Let talk about my problems. Since I may use arduino or FPGA as my data processor, so the highest sampling frequency is not a limitation for me. My FPGA can sample data with high-speed ADC up to 32MHz. Both FPGA and arduino would make me encounter some similar problems but I think it would easier to understand and discuss with Arduino.

Assume I am using constant 20kHz sampling frequency to sample Sinewave signal frequency in a range from 10Hz to 10kHz. The size of the fft is chosen to use 64.

Q1.
Is the fft process after captured the entire cycle of the signal?? or it is a continuous procedure to process each sample data at the time it received ??

Entire block of N samples is required before any processing can be done

Q2.
When I sampling 10kHz signal with 20kHz, lt would only obtain 2 points per cycle in the 10kHz Sinewave signal.
How it would fit into a size of 64 fft? Is it process fft after captured 32 cycles of signal??

You can't sample 10kHz at 20kSPS, that violates Nyquist. You stated this in point 1.

Q3.
When I sampling 10Hz signal with 20kHz, lt would obtain 2000 points per cycle in the 10Hz Sinewave signal.

yes

How it would fit into a size of 64 fft?

It doesn't, you'd need at least 2048 point FFT. 20kSPS with N=64 gives a frequency resolution of 20000/64 = 312.5Hz, 10Hz is effectively DC compared to that.

The size of fft is not enough for all points. A more extreme case with a sampling frequency 32MHz, total 3.2MHz data points are collected. How to fit the memory and the fft??

Use a device with enough memory...

Q4. The numbers of sampling points must be the power of 2(N=64, 128, 256, etc). Is it true only in Arduino?? or also true in all data sampling??

I answered this above

Q5.
The number of samples is fixed, the Sampling frequency is fixed, fft size is fixed. How to process all difference frequencies ??

What are you asking? What do you mean by difference frequency in this context?

Why is it needed to be power of 2??

I answered this above - its much much simpler/smaller code for PoT. The full libraries for arbitrary sized FFT would not fit on a smalll microcontroller

The complete code is referred to the follow website.
Arduino FFT pt. 2: Improving the Hardware for Real-time Analysis – Norwegian Creations

Thank you for all of your help.

MarkT: Thanks for your help. You really help me clear some of my doubts. However, I still have some follow up questions and few points not quit understand.

Quote
2. High Sampling frequency would get a better resolution of the frequency bins.

no, more bins and lower sampling frequency give more resolution. Each bin is Fs/N in bandwidth, so decreasing Fs or increasing N will give a narrower bandwidth per bin

Can you explain more?? Is it true if using a higher sampling rate to sample a signal would have more sampling points per cycle?? is more sampling points means more frequency bins??

Quote
3. High Sampling frequency means need more memory to store sampling points of the signal.

No, larger N needs more memory, N samples in fact

Memory is related to the size of fft but not the sampled data??

Quote
6. The sampling frequency is fixed in the design

Its just the rate of sampling, should be easy to change, upto some maximum

Like in my case, the signal changes from 10Hz to 10kHz. The sample rate should remain unchanged, right??

Quote
7. FFT size is fixed in the design

Why?

I saw all the examples used a fix size of fft in their codes. The size should be static but no dynamic. Is it true??

Quote
Q2.
When I sampling 10kHz signal with 20kHz, lt would only obtain 2 points per cycle in the 10kHz Sinewave signal.
How it would fit into a size of 64 fft? Is it process fft after captured 32 cycles of signal??

You can't sample 10kHz at 20kSPS, that violates Nyquist. You stated this in point 1.

In this case, fs is 2x fsignal. Why would it violates Nyquist??

Follow-up Questions
As you said,

Entire block of N samples is required before any processing can be done

If I am using the same sampling rate to sample two different frequencies: 10Hz and 10Khz.

  1. The number of sample points would not be the same since the sampling rate is fixed.
  2. The memory size to store an entire cycle of these two data is not the same.
  3. FFT would not always able to input the entire cycle of the sampled data

eg. fs=100kHz, fft size =64

For data1 with f=10kHz,
The number of points received after ADC would be 10 points per cycle. A memory would store 6.4 cycles of data1 samples (6.4 cycles x 10 points per cycle = 64). After 64 samples are stored, the whole block would pass to fft to process.

For data2 with f=10Hz,
The number of points received after ADC would be 10k points per cycle. If using the same memory, 10k data points cannot fits into a memory size of 64. A memory with size 10k is needed to store the entire cycle for data2. Then the memory size would not be the same as data1. Also, a fft has size of 10k to fit data2. How does it work ??

shyuenaa:

no, more bins and lower sampling frequency give more resolution. Each bin is Fs/N in bandwidth, so decreasing Fs or increasing N will give a narrower bandwidth per bin

Can you explain more?? Is it true if using a higher sampling rate to sample a signal would have more sampling points per cycle?? is more sampling points means more frequency bins??

Not really, each bin has a bandwidth of Fs/N, so that N/2 bins have Fs/2 total bandwidth, the Nyquist limit. This is easy to see from the time taken - N samples take N/Fs seconds to gather, so that the lowest frequency representable is the reciprocal of this.

  1. High Sampling frequency means need more memory to store sampling points of the signal.

No, larger N needs more memory, N samples in fact

Memory is related to the size of fft but not the sampled data??

Of course, you gather N samples, process them, repeat.

  1. The sampling frequency is fixed in the design

Its just the rate of sampling, should be easy to change, upto some maximum

Like in my case, the signal changes from 10Hz to 10kHz. The sample rate should remain unchanged, right??

Ah, you are confusing "fixed in the design" with "constant for one run". Its very common to be able to sample at different rates, but yes for a given signal you sample at a constant rate for its duration.

  1. FFT size is fixed in the design

Why?

I saw all the examples used a fix size of fft in their codes. The size should be static but no dynamic. Is it true??

No. Its whatever you want, subject to available memory. You can fix it if you want, but larger FFTs run slower so you might want to trade that off against other factors.

Q2.
When I sampling 10kHz signal with 20kHz, lt would only obtain 2 points per cycle in the 10kHz Sinewave signal.
How it would fit into a size of 64 fft? Is it process fft after captured 32 cycles of signal??

You can't sample 10kHz at 20kSPS, that violates Nyquist. You stated this in point 1.

In this case, fs is 2x fsignal. Why would it violates Nyquist??

You said: "1. Sampling frequency must larger than 2x signal frequency by Nyquist sampling theorem."
It must be strictly larger, not the same. And to avoid a very intricate anti-aliasing filter you'd never normally go higher than 40% of the sample rate, 8kHz would be a practical limit for 20kSPS, still requiring a pretty advanced anti-alias filter.

Follow-up Questions
As you said,

Entire block of N samples is required before any processing can be done

If I am using the same sampling rate to sample two different frequencies: 10Hz and 10Khz.

Then you need at least a sample rate of 25kSPS, preferrably 40kSPS in fact, and N >= 4000

  1. The number of sample points would not be the same since the sampling rate is fixed.

It has to be if you are processing multiple components of one signal.

  1. The memory size to store an entire cycle of these two data is not the same.

It has to be

  1. FFT would not always able to input the entire cycle of the sampled data

It has to contain at least one cycle, preferably more, of the lowest frequency of interest, or it falls below
the resolution of a bin.

eg. fs=100kHz, fft size =64

For data1 with f=10kHz,
The number of points received after ADC would be 10 points per cycle. A memory would store 6.4 cycles of data1 samples (6.4 cycles x 10 points per cycle = 64). After 64 samples are stored, the whole block would pass to fft to process.

For data2 with f=10Hz,
The number of points received after ADC would be 10k points per cycle. If using the same memory, 10k data points cannot fits into a memory size of 64. A memory with size 10k is needed to store the entire cycle for data2. Then the memory size would not be the same as data1. Also, a fft has size of 10k to fit data2. How does it work ??

If you want to look at different signals in different runs you are free to chose the values of Fs and N appropriate to each instance.

BTW its important to understand the need for (and implications of) FFT windows for spectrum analysis.
Its also important to understand aliasing in sampled systems - you normally require a steep anti-aliasing low-pass filter before sampling to avoid frequency aliasing. This filter has to match the Nyquist frequency.

MarkT: Thanks for your reply. I think I need to do more review in the topic of data processing. Do you have recommendations materials for me?

you normally require a steep anti-aliasing low-pass filter before sampling to avoid frequency aliasing.

Just so that's clear - "Before sampling" means you need an analog filter of the ADC.

People who make audio spectrum analyzer effects often get-away with a simple RC filter, or no filter, because the high-frequency components in audio are usually lower in amplitude and that makes the aliasing lower-level and you can still get a reasonably-good visual effect.

shyuenaa:
MarkT: Thanks for your reply. I think I need to do more review in the topic of data processing. Do you have recommendations materials for me?

It's hard to recommend educational material on digital signal processing without knowing something about your background. That said, it helps to play around with the concepts and parameters, as MarkT discussed up thread, in an interactive/visual programming environment.

My current tool of choice would be Anaconda Python, but Matlab (if available to you) or Gnu Octave are good as well.

DVDdoug:
Just so that's clear - "Before sampling" means you need an analog filter of the ADC.

Well, perhaps.

It you oversample beyond twice the maximum unwanted frequency present in your source you can digitally low-pass filter before applying the FFT (or do a bigger FFT and not use the higher frequencies). However that doesn't remove aliased noise.

MrMark:
It's hard to recommend educational material on digital signal processing without knowing something about your background.

I'd second that - some treatments are much more mathematical than others, some are more practical.

Appreciate for MarkT, DVDdoug and MrMark`s rely.

I think I am a bit confused about the relation between "Sampling rate", "Number of sampled data", "memory for sampled data", "memory for fft", "fft size" and "Number of frequency bins" and "BW of frequency bin".

Can you guys explain the relations with few examples?? Thanks a lot.

From MarkT answers, I understand

  1. ("fft size" /2) is the "Number of frequency bins".
  2. "BW of frequency bin" is (fs/"fft size").

but I am still confusing the relations in these terms "Sampling rate", "Number of sampled data", "memory for sampled data", "memory for fft", "fft size".

Is "Number of sampled data", "memory for sampled data", "memory for fft", "fft size" are the same thing ??

Let`s say, I have two sinewave signals 10Hz and 10kHz . What is the procedure to process these signals??
First, the signals are sampled by some sampling rate (assume 40kSPS and would remain unchanged all the time) in ADC with RC filters.
Then........

Thanks all you guys .

Also,

"Number of sampled data" is related to "Sampling rate" or "fft size"??

Thanks

Please forgive my bad drawing.

The two pic in the attachments illustrates one of my doubts. Two signals with different frequencies are sampled with the same sample rate with a sampling interval of Ts and a size of 8 FFT.

For the higher frequency case, about 2.5 cycles signal is passed to fft to process. Then recall from above, passing more cycles ("sampled data") to fft can have a better "Bandwidth of frequency bins" and more "number of bins".

My doubt is in the lower frequency case. As the pic shows, with the same Ts and "size of fft". The fft cannot process the entire cycle of the lower frequency signal. It has to either lower the "sampling rate" or increase "fft size" to fit the entire signal.

If this is true, then it means "sampling rate" and "fft size" is dynamic. I understand both "sampling rate" and "fft size" can be changed as wanted like the oscilloscope we use in lab. However, this circumstance only suitable if we know the frequency of the signal. How to dynamically change "sampling rate" and "fft size" without knowing the signal frequency??

shyuenaa:
Let`s say, I have two sinewave signals 10Hz and 10kHz . What is the procedure to process these signals??
First, the signals are sampled by some sampling rate (assume 40kSPS and would remain unchanged all the time) in ADC with RC filters.

Taking my own Python prototyping advice from post #6, your scenario, and the relationships from MarkT's posts:

import numpy as np 
import matplotlib.pyplot as plt 

Fs = 40e3       # Sample Frequency in Hz
Ts = 1/Fs       # Sample interval in seconds

binSize = int(5)   # desired FFT bin size in Hz
samples = int(Fs/binSize)   # Number of samples to get desired resolution
print("Samples = {}".format(samples))
T = np.linspace(0, (samples-1)*Ts, samples) # vector time of sample
binFreq = np.linspace(0, (samples-1)*binSize, samples)  # vector FFT bin freqs

# Generate signal with 10 Hz and 10,000 Hz sine waves
sig = np.sin(2*np.pi*10*T) + np.sin(2*np.pi*10e3*T)

# Plot FFT of signal
plt.figure(1)
plt.plot(binFreq, np.abs(np.fft.fft(sig)))
plt.grid(axis='both')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude')

produces this:

fftExample.png

Note what is important is not so much my implementation of this specific example case, but the process of creating an implementation from some set of requirements.

fftExample.png