Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turned your code into a Class / library #1

Open
MichielfromNL opened this issue May 13, 2021 · 10 comments
Open

Turned your code into a Class / library #1

MichielfromNL opened this issue May 13, 2021 · 10 comments

Comments

@MichielfromNL
Copy link

MichielfromNL commented May 13, 2021

Hi,
I was using ArduinoFFT sofar, and found your code when I was looking for a faster FFT for my project.
Which worked fine, super!

I spend a few hours today to turn it into a class, added some functions to make it work just like ArduinoFFT and made it a tad more "user friendly". the zip installs as an arduino library
Best regards,
Michiel

ESPfft.zip

#define FFT_N       2048  // Must be a power of 2
#define SAMPLEFREQ  218   //

//#define TOTAL_TIME  9.391904 //The time in which data was captured. This is equal to FFT_N/sampling_freq

float fft_input[FFT_N];
float fft_output[FFT_N];

#include "ESP32_fft.h" // include the library
#include "fft_signal.h"

// class
ESP_fft FFT(FFT_N, SAMPLEFREQ, FFT_REAL, FFT_FORWARD, fft_input, fft_output);

void setup() {
 Serial.begin(115200); // use the serial port
 while (!Serial);
 Serial.println("Hello. FFT test");
 for (int k = 0 ; k < FFT_N ; k++)
   fft_input[k] = (float)fft_signal[k];

 long int t1 = micros();
 // Execute transformation
 FFT.removeDC();
 FFT.hammingWindow();
 FFT.execute();
 FFT.complexToMagnitude();
 long int t2 = micros();
 //FFT.print();
 Serial.print("Time taken: ");Serial.print((t2-t1)*1.0/1000);Serial.println(" milliseconds!");
 
 // Print the output
 Serial.println();
 /*Multiply the magnitude of the DC component with (1/FFT_N) to obtain the DC component*/
 Serial.printf("DC component : %f g\n", (fft_output[0])/FFT_N);  // DC is at [0]

 Serial.printf("Fundamental Freq : %f Hz\t Mag: %f g\n", FFT.majorPeakFreq(), (FFT.majorPeak()/10000)*2/FFT_N);
 for (int i=0; i< 10; i++) {
   Serial.printf("%f:%f\n", FFT.frequency(i),fft_output[i]);
 }
 
}

void loop() {
 
}```
@yash-sanghvi
Copy link
Owner

This is excellent @MichielfromNL. Thanks for the efforts. I'll add the links to this post of yours in the Readme, and also in the Medium tutorial on FFT onboard ESP32.

@citamrac
Copy link

citamrac commented Jun 22, 2021

I have tried this out with a frequency sweep , generated from my computer and input via my ESP32's ADC, and it seems that no matter the input frequency, only the highest frequency bins have the strongest peaks

@sanghvi-yash
Copy link
Collaborator

Can you share some more details on the input and output and also share code snippets?

@Shnagarsheth
Copy link

Thank you making it a Library; unfortunetly, I am receving errors for constructor. As I am not a master of C++ can you please help me with this

Error while Compiling

In file included from lib\ESPfft\ESP32_fft.cpp:31:0:
lib\ESPfft\ESP32_fft.h: In constructor 'ESP_fft::ESP_fft(int, int, fft_type_t, fft_direction_t, float*, float*)':
lib\ESPfft\ESP32_fft.h:75:19: error: 'ESP_fft::_direction' will be initialized after [-Werror=reorder]
   fft_direction_t _direction;     // forward or backward
                   ^
lib\ESPfft\ESP32_fft.h:71:19: error:   'float* ESP_fft::_input' [-Werror=reorder]
   float        *  _input;         // pointer to input buffer
                   ^
lib\ESPfft\ESP32_fft.cpp:37:1: error:   when initialized here [-Werror=reorder]
 ESP_fft::ESP_fft(int size, int samplefreq,fft_type_t type, fft_direction_t direction, float input[], float output[]) :      
 ^
cc1plus.exe: some warnings being treated as errors

@MichielfromNL
Copy link
Author

Thank you making it a Library; unfortunetly, I am receving errors for constructor. As I am not a master of C++ can you please help me with this

I suspect the compiler flag [-Werror=reorder] triggers , because the order of class variables in the header file is not exactly as the order of the initaliser list in the constructor.
I don't have the possibility here to test the fix, but you may want to try changing the order of variables in the ESP_fft.h:

It is now:
private:
int _size; // FFT size
int _samplefreq;
float _binwidth; // freq per bin
float * _input; // pointer to input buffer
float * _output; // pointer to output buffer
float * _twiddle_factors; // pointer to buffer holding twiddle factors
fft_type_t _type; // real or complex
fft_direction_t _direction; // forward or backward
unsigned int _flags; // FFT flags
float _max_mag = 0;
float _fundamental_freq = 0;

Change it into:

private:
int _size; // FFT size
int _samplefreq;
fft_type_t _type; // real or complex
fft_direction_t _direction; // forward or backward
float * _input; // pointer to input buffer
float * _output; // pointer to output buffer
float * _twiddle_factors; // pointer to buffer holding twiddle factors
float _binwidth; // freq per bin
unsigned int _flags; // FFT flags
float _max_mag = 0;
float _fundamental_freq = 0;

Hope this helps

@Shnagarsheth
Copy link

Thank you for your prompt reply. It worked; no compilation Error now.

@be-engineer
Copy link

be-engineer commented Mar 9, 2022

Nice job, great!
By the way,can I use directly output value to show in LCD? Does the output value represent the amplitude of the corresponding frequency?

@Spartrap
Copy link

Spartrap commented Aug 2, 2022

@MichielfromNL thank you for your effort to make this code more object-oriented, it's very much appreciated.

OTOH, I believe there is a mistake in the definition of the _binwidth member (and consequently, the output of the frequency() method is likely wrong):
_binwidth = (float)_samplefreq/(_size/2.0);

I believe it should read simply "(float) samplefreq /_size;", as only half the sampling frequency bandwidth is available (Nyquist theorem), so the 2.0 gets simplified away..
Best regards.

@diplab-projects
Copy link

diplab-projects commented Aug 6, 2022

@MichielfromNL thank you very much for your effort.

FYI, there is a problem in the implementation of the function complexToMagnitude. After calculating _max_mag and _fundamental_freq, these values will never be updated if the new values aren't bigger.

I fixed locally this behavior by resetting them in each call of complexToMagnitude.

https://gist.github.com/diplab-projects/8551fa44b44abf5a35ec8a16681761fa


Oh, and BTW:

OTOH, I believe there is a mistake in the definition of the _binwidth member (and consequently, the output of the frequency() method is likely wrong): _binwidth = (float)_samplefreq/(_size/2.0);

I believe it should read simply "(float) samplefreq /_size;", as only half the sampling frequency bandwidth is available (Nyquist theorem), so the 2.0 gets simplified away.. Best regards.

You are absolutely right. I tested this with real data, and the frequency will be doubled.

@DanieljVargas
Copy link

Can anyone give a snippet or some help to use the library with input in ADC? Im trying to use it with current and voltage sensors so I can get the amplitudes of the harmonics. But it isnt working right. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants