ref: a48d4e0b1330a34e32f56a6d4a65c77eca84f655
src/libs/arduinoFFT-develop/Examples/FFT_speedup/FFT_speedup.ino
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
/* Example of use of the FFT libray to compute FFT for a signal sampled through the ADC with speedup through different arduinoFFT options. Based on examples/FFT_03/FFT_03.ino Copyright (C) 2020 Bim Overbohm (header-only, template, speed improvements) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ // There are two speedup options for some of the FFT code: // Define this to use reciprocal multiplication for division and some more speedups that might decrease precision //#define FFT_SPEED_OVER_PRECISION // Define this to use a low-precision square root approximation instead of the regular sqrt() call // This might only work for specific use cases, but is significantly faster. Only works for ArduinoFFT<float>. //#define FFT_SQRT_APPROXIMATION #include "arduinoFFT.h" /* These values can be changed in order to evaluate the functions */ #define CHANNEL A0 const uint16_t samples = 64; //This value MUST ALWAYS be a power of 2 const float samplingFrequency = 100; //Hz, must be less than 10000 due to ADC unsigned int sampling_period_us; unsigned long microseconds; /* These are the input and output vectors Input vectors receive computed results from FFT */ float vReal[samples]; float vImag[samples]; /* Allocate space for FFT window weighing factors, so they are calculated only the first time windowing() is called. If you don't do this, a lot of calculations are necessary, depending on the window function. */ float weighingFactors[samples]; /* Create FFT object with weighing factor storage */ ArduinoFFT<float> FFT = ArduinoFFT<float>(vReal, vImag, samples, samplingFrequency, weighingFactors); #define SCL_INDEX 0x00 #define SCL_TIME 0x01 #define SCL_FREQUENCY 0x02 #define SCL_PLOT 0x03 void setup() { sampling_period_us = round(1000000*(1.0/samplingFrequency)); Serial.begin(115200); Serial.println("Ready"); } void loop() { /*SAMPLING*/ microseconds = micros(); for(int i=0; i<samples; i++) { vReal[i] = analogRead(CHANNEL); vImag[i] = 0; while(micros() - microseconds < sampling_period_us){ //empty loop } microseconds += sampling_period_us; } /* Print the results of the sampling according to time */ Serial.println("Data:"); PrintVector(vReal, samples, SCL_TIME); FFT.windowing(FFTWindow::Hamming, FFTDirection::Forward); /* Weigh data */ Serial.println("Weighed data:"); PrintVector(vReal, samples, SCL_TIME); FFT.compute(FFTDirection::Forward); /* Compute FFT */ Serial.println("Computed Real values:"); PrintVector(vReal, samples, SCL_INDEX); Serial.println("Computed Imaginary values:"); PrintVector(vImag, samples, SCL_INDEX); FFT.complexToMagnitude(); /* Compute magnitudes */ Serial.println("Computed magnitudes:"); PrintVector(vReal, (samples >> 1), SCL_FREQUENCY); float x = FFT.majorPeak(); Serial.println(x, 6); //Print out what frequency is the most dominant. while(1); /* Run Once */ // delay(2000); /* Repeat after delay */ } void PrintVector(float *vData, uint16_t bufferSize, uint8_t scaleType) { for (uint16_t i = 0; i < bufferSize; i++) { float abscissa; /* Print abscissa value */ switch (scaleType) { case SCL_INDEX: abscissa = (i * 1.0); break; case SCL_TIME: abscissa = ((i * 1.0) / samplingFrequency); break; case SCL_FREQUENCY: abscissa = ((i * 1.0 * samplingFrequency) / samples); break; } Serial.print(abscissa, 6); if(scaleType==SCL_FREQUENCY) Serial.print("Hz"); Serial.print(" "); Serial.println(vData[i], 4); } Serial.println(); } |