Navigation
Your stuff
|
FFT implemented in a microDisclaimer:
FFT - Fast Fourier AlgorithmI do use the Arduino library https://github.com/kosme/arduinoFFT You can install it from the offical Arduino system:
Test and metricsIt is tested on an Arduino MEGA with 8 Mbyte RAM.
Th Arduino program for testing a FFT with 512 samples uses 4337 bytes so if you only have an Arduino UNO I assume you can at most do a 128 pins FFT. Code should be able to run on an ESP32 and similar - but no guarantees as I have not tested it yet. The code - adapted from on of the examples in the library The test code adapted from FFT library examples.
#include "arduinoFFT.h"
/*
testprogram v/ Jens Dalsgaard Nielsen(JDN), Beer license :-)
1. Program samples A0 on an Arduino (tested on an old Mega)
512 samples
200 Hz samplings frequency (same as 5 msec samplæing period)
Analog A0 as input 0-1023
2. Sampling an A0 just with a wire inserted - should give nice 50 Hz noise :-)
3. Let it run after some rounds press reset button and keep it down
Now you can scroll in the terminal window and hopefully se a 50 Hz oin from 50 Hz noise
*/
const uint16_t samples = 512; //JDN64; //This value MUST ALWAYS be a power of 2
const double samplingFrequency = 200; // aka 5
const unsigned long tPer = 5; // == 1/samplingFrequency as usigned long
unsigned long tNext; // for doing tiem correct sampling
// for fft plot with stars etc
double vVal;
const double deltaV = 1; // see use of scaleToMax
double vReal[samples];
double vImag[samples];
/* Create FFT object */
ArduinoFFT<double> FFT = ArduinoFFT<double>(vReal, vImag, samples, samplingFrequency);
#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02
#define SCL_PLOT 0x03
// next added by JDN
#define SCL_FREQ_PLOT 0x10
void setup() {
Serial.begin(115200);
while (!Serial) {
}
tNext = millis() + tPer; // configure for accurate 5 msec sampling
}
// -----------------------------------------
void loop() {
static uint16_t arIndex = 0;
if (tNext <= millis()) {
tNext += tPer;
vReal[arIndex] = analogRead(A0);
vImag[arIndex] = 0.0; //Imaginary part must be zeroed in case of looping to avoid wrong calculations and overflows
arIndex++;
}
if (samples <= arIndex) {
removeDC(vReal, samples); // Arduino ADC is unipolar [0->1023] so with substract DC offset/value
FFT.windowing(FFTWindow::Hamming, FFTDirection::Forward); /* Weigh data */
FFT.compute(FFTDirection::Forward); /* Compute FFT */
FFT.complexToMagnitude(); /* Compute magnitudes */
scaleToMax(vReal, (samples >> 1), 100.0); // for star plot
//PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
PrintVector(vReal, (samples >> 1), SCL_FREQ_PLOT); // plot a vertical FFT :-) with stars :-) by JDN
//JDN AGAIN - we are doing real sampling
delay(1000);
arIndex = 0; // ready to next round
tNext = millis() + tPer;
}
}
//-------------------------------------------------------------
void scaleToMax(double *vData, uint16_t bufferSize, double vMax) //JDN - to remove DC offset due to unipolar ADC
{
double vA = -1000.0;
// find max
for (uint16_t i = 0; i < bufferSize; i++) {
if (vA < vData[i]) {
vA = vData[i];
}
}
vA = vMax / vA;
//scale
for (uint16_t i = 0; i < bufferSize; i++) {
vData[i] *= vA;
}
}
void removeDC(double *vData, uint16_t bufferSize) //JDN - to remove DC offset due to unipolar ADC
{
double sum = 0;
for (uint16_t i = 0; i < bufferSize; i++) {
sum += vData[i];
}
sum /= (double)bufferSize;
for (uint16_t i = 0; i < bufferSize; i++) {
vData[i] -= sum;
}
}
void PrintVector(double *vData, uint16_t bufferSize, uint8_t scaleType) {
for (uint16_t i = 0; i < bufferSize; i++) {
double abscissa;
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;
case SCL_FREQ_PLOT:
abscissa = ((i * 1.0 * samplingFrequency) / samples);
break;
default:;
}
/* Print abscissa value */
if (scaleType != SCL_FREQ_PLOT) {
Serial.print(vData[i], 4);
Serial.print(" ");
Serial.print(abscissa, 6);
if (scaleType == SCL_FREQUENCY) {
Serial.print(" Hz");
}
Serial.println();
} else { // JDN vertical freq plot with dots
Serial.print(abscissa, 4);
Serial.print("-");
vVal = deltaV;
while (vVal < vData[i]) {
Serial.print("-");
vVal += deltaV; // hack for 10bit/1023 full range
}
Serial.print("*");
Serial.println();
}
}
Serial.println();
}
the fft plot
200 Hz sampling 512 pins
A0 ADC on Arduino Mega
a wire attached single ended to A0
just collect noise in my office
which is 50
JDN June 2026
void loop() {
static uint16_t arIndex = 0;
if (tNext <= millis()) {
tNext += tPer;
vReal[arIndex] = analogRead(A0);
vImag[arIndex] = 0.0; //Imaginary part must be zeroed in case of looping to avoid wrong calculations and overflows
arIndex++;
}
if (samples <= arIndex) {
removeDC(vReal, samples); // Arduino ADC is unipolar [0->1023] so with substract DC offset/value
FFT.windowing(FFTWindow::Hamming, FFTDirection::Forward); /* Weigh data */
FFT.compute(FFTDirection::Forward); /* Compute FFT */
FFT.complexToMagnitude(); /* Compute magnitudes */
scaleToMax(vReal, (samples >> 1), 100.0); // for star plot
//PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
PrintVector(vReal, (samples >> 1), SCL_FREQ_PLOT); // plot a vertical FFT :-) with stars :-) by JDN
//JDN AGAIN - we are doing real sampling
delay(1000);
arIndex = 0; // ready to next round
tNext = millis() + tPer;
}
}
0.0000-*
0.3906--*
0.7813-*
1.1719-*
1.5625-*
1.9531-*
2.3438-*
2.7344---*
3.1250----*
3.5156--*
3.9063-*
4.2969-*
4.6875-*
5.0781-*
5.4688-*
5.8594-*
6.2500-*
6.6406-*
7.0313-*
7.4219-*
7.8125-*
8.2031-*
8.5937-*
8.9844-*
9.3750--*
9.7656-*
10.1562-*
10.5469-*
10.9375-*
11.3281-*
11.7187-*
12.1094-*
12.5000-*
12.8906-*
13.2812-*
13.6719-*
14.0625-*
14.4531-*
14.8437-*
15.2344-*
15.6250-*
16.0156-*
16.4062-*
16.7969-*
17.1875-*
17.5781-*
17.9687-*
18.3594-*
18.7500-*
19.1406-*
19.5312-*
19.9219--*
20.3125---*
20.7031--*
21.0937-*
21.4844-*
21.8750-*
22.2656-*
22.6562-*
23.0469-*
23.4375--*
23.8281-*
24.2187-*
24.6094-*
25.0000-*
25.3906-*
25.7812---*
26.1719------*
26.5625--------*
26.9531----*
27.3437-*
27.7344-*
28.1250-*
28.5156-*
28.9062-*
29.2969-*
29.6875-*
30.0781-*
30.4687-*
30.8594-*
31.2500-*
31.6406-*
32.0312-*
32.4219-*
32.8125--*
33.2031-*
33.5937-*
33.9844-*
34.3750-*
34.7656-*
35.1562-*
35.5469-*
35.9375-*
36.3281-*
36.7187-*
37.1094-*
37.5000-*
37.8906-*
38.2812-*
38.6719-*
39.0625-*
39.4531-*
39.8437-*
40.2344-*
40.6250-*
41.0156-*
41.4062-*
41.7969-*
42.1875-*
42.5781-*
42.9687-*
43.3594-*
43.7500--*
44.1406-*
44.5312-*
44.9219-*
45.3125-*
45.7031-*
46.0937-*
46.4844-*
46.8750-*
47.2656-*
47.6562-*
48.0469-*
48.4375-*
48.8281-*
49.2187---*
49.6094-----------------------------------------*
50.0000----------------------------------------------------------------------------------------------------*
50.3906----------------------------------------------------*
50.7812--*
51.1719-*
51.5625-*
51.9531-*
52.3437-*
52.7344-*
53.1250-*
53.5156-*
53.9062-*
54.2969-*
54.6875-*
55.0781-*
55.4687-*
55.8594-*
56.2500--*
56.6406--*
57.0312-*
57.4219-*
57.8125-*
58.2031-*
58.5937-*
58.9844-*
59.3750-*
59.7656-*
60.1562-*
60.5469-*
60.9375-*
61.3281-*
61.7187-*
62.1094-*
62.5000-*
62.8906-*
63.2812-*
63.6719-*
64.0625-*
64.4531-*
64.8438-*
65.2344-*
65.6250-*
66.0156-*
66.4063-*
66.7969--*
67.1875--*
67.5781-*
67.9688-*
68.3594-*
68.7500-*
69.1406-*
69.5313-*
69.9219-*
70.3125-*
70.7031-*
71.0938-*
71.4844-*
71.8750-*
72.2656-*
72.6563-*
73.0469----*
73.4375-------*
73.8281------*
74.2188--*
74.6094-*
75.0000-*
75.3906-*
75.7813-*
76.1719--*
76.5625--*
76.9531-*
77.3438-*
77.7344-*
78.1250-*
78.5156-*
78.9063-*
79.2969--*
79.6875---*
80.0781--*
80.4688-*
80.8594-*
81.2500-*
81.6406-*
82.0313-*
82.4219-*
82.8125-*
83.2031--*
83.5938-*
83.9844-*
84.3750-*
84.7656-*
85.1563-*
85.5469-*
85.9375-*
86.3281-*
86.7188-*
87.1094-*
87.5000-*
87.8906-*
88.2813-*
88.6719-*
89.0625-*
89.4531-*
89.8438-*
90.2344-*
90.6250--*
91.0156-*
91.4063-*
91.7969-*
92.1875-*
92.5781-*
92.9688-*
93.3594-*
93.7500-*
94.1406-*
94.5313-*
94.9219-*
95.3125-*
95.7031-*
96.0938-*
96.4844--*
96.8750----*
97.2656---*
97.6563-*
98.0469-*
98.4375-*
98.8281-*
99.2188-*
99.6094-----------*
the fft plot as numbers
200 Hz sampling 512 pins
A0 ADC on Arduino Mega
a wire attached single ended to A0
just collect noise in my office
which is 50
void loop() {
static uint16_t arIndex = 0;
if (tNext <= millis()) {
tNext += tPer;
vReal[arIndex] = analogRead(A0);
vImag[arIndex] = 0.0; //Imaginary part must be zeroed in case of looping to avoid wrong calculations and overflows
arIndex++;
}
if (samples <= arIndex) {
removeDC(vReal, samples); // Arduino ADC is unipolar [0->1023] so with substract DC offset/value
FFT.windowing(FFTWindow::Hamming, FFTDirection::Forward); /* Weigh data */
FFT.compute(FFTDirection::Forward); /* Compute FFT */
FFT.complexToMagnitude(); /* Compute magnitudes */
scaleToMax(vReal, (samples >> 1), 100.0); // for star plot
PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
//PrintVector(vReal, (samples >> 1), SCL_FREQ_PLOT); // plot a vertical FFT :-) with stars :-) by JDN
//JDN AGAIN - we are doing real sampling
delay(1000);
arIndex = 0; // ready to next round
tNext = millis() + tPer;
}
}
0.9396 0.000000 Hz
1.5982 0.390625 Hz
0.4902 0.781250 Hz
0.2280 1.171875 Hz
0.1557 1.562500 Hz
0.1305 1.953125 Hz
0.0304 2.343750 Hz
0.6505 2.734375 Hz
0.1248 3.125000 Hz
0.4615 3.515625 Hz
0.1279 3.906250 Hz
0.1767 4.296875 Hz
0.1185 4.687500 Hz
0.0407 5.078125 Hz
0.0572 5.468750 Hz
0.1473 5.859375 Hz
0.1867 6.250000 Hz
0.1535 6.640625 Hz
0.0796 7.031250 Hz
0.1415 7.421875 Hz
0.0725 7.812500 Hz
0.0879 8.203125 Hz
0.0742 8.593750 Hz
0.1529 8.984375 Hz
0.0476 9.375000 Hz
0.2047 9.765625 Hz
0.0052 10.156250 Hz
0.0757 10.546875 Hz
0.0547 10.937500 Hz
0.1187 11.328125 Hz
0.0090 11.718750 Hz
0.1379 12.109375 Hz
0.0485 12.500000 Hz
0.1133 12.890625 Hz
0.0294 13.281250 Hz
0.1655 13.671875 Hz
0.0334 14.062500 Hz
0.1526 14.453125 Hz
0.0565 14.843750 Hz
0.0998 15.234375 Hz
0.0652 15.625000 Hz
0.1557 16.015625 Hz
0.0824 16.406250 Hz
0.1433 16.796875 Hz
0.1664 17.187500 Hz
0.1105 17.578125 Hz
0.0287 17.968750 Hz
0.0195 18.359375 Hz
0.1060 18.750000 Hz
0.1178 19.140625 Hz
0.1424 19.531250 Hz
0.3306 19.921875 Hz
0.1163 20.312500 Hz
0.4405 20.703125 Hz
0.0249 21.093750 Hz
0.0791 21.484375 Hz
0.0392 21.875000 Hz
0.1219 22.265625 Hz
0.1010 22.656250 Hz
0.4604 23.046875 Hz
0.5083 23.437500 Hz
0.7084 23.828125 Hz
0.4122 24.218750 Hz
0.2647 24.609375 Hz
0.1843 25.000000 Hz
0.3526 25.390625 Hz
0.4660 25.781250 Hz
1.3857 26.171875 Hz
0.4536 26.562500 Hz
0.8819 26.953125 Hz
0.1846 27.343750 Hz
0.1485 27.734375 Hz
0.1321 28.125000 Hz
0.0222 28.515625 Hz
0.0091 28.906250 Hz
0.2006 29.296875 Hz
0.2231 29.687500 Hz
0.1653 30.078125 Hz
0.0520 30.468750 Hz
0.1325 30.859375 Hz
0.0451 31.250000 Hz
0.0614 31.640625 Hz
0.0540 32.031250 Hz
0.1936 32.421875 Hz
0.0668 32.812500 Hz
0.2469 33.203125 Hz
0.0361 33.593750 Hz
0.0690 33.984375 Hz
0.0535 34.375000 Hz
0.0725 34.765625 Hz
0.0414 35.156250 Hz
0.1056 35.546875 Hz
0.0712 35.937500 Hz
0.1119 36.328125 Hz
0.0369 36.718750 Hz
0.1408 37.109375 Hz
0.0511 37.500000 Hz
0.1071 37.890625 Hz
0.0436 38.281250 Hz
0.1141 38.671875 Hz
0.0621 39.062500 Hz
0.1275 39.453125 Hz
0.0579 39.843750 Hz
0.1404 40.234375 Hz
0.1176 40.625000 Hz
0.0701 41.015625 Hz
0.0095 41.406250 Hz
0.0689 41.796875 Hz
0.0982 42.187500 Hz
0.0784 42.578125 Hz
0.0842 42.968750 Hz
0.2421 43.359375 Hz
0.0716 43.750000 Hz
0.3179 44.140625 Hz
0.0066 44.531250 Hz
0.0839 44.921875 Hz
0.0604 45.312500 Hz
0.1641 45.703125 Hz
0.0379 46.093750 Hz
0.1928 46.484375 Hz
0.2396 46.875000 Hz
0.3054 47.265625 Hz
0.0672 47.656250 Hz
0.1560 48.046875 Hz
0.0785 48.437500 Hz
0.4322 48.828125 Hz
0.9150 49.218750 Hz
44.6512 49.609375 Hz
100.0000 50.000000 Hz
44.4224 50.390625 Hz
0.4491 50.781250 Hz
0.1410 51.171875 Hz
0.0984 51.562500 Hz
0.0394 51.953125 Hz
0.0548 52.343750 Hz
0.3239 52.734375 Hz
0.3364 53.125000 Hz
0.2747 53.515625 Hz
0.0956 53.906250 Hz
0.1410 54.296875 Hz
0.0253 54.687500 Hz
0.0521 55.078125 Hz
0.0937 55.468750 Hz
0.2335 55.859375 Hz
0.0989 56.250000 Hz
0.3071 56.640625 Hz
0.0130 57.031250 Hz
0.1076 57.421875 Hz
0.0574 57.812500 Hz
0.0858 58.203125 Hz
0.0211 58.593750 Hz
0.1236 58.984375 Hz
0.0961 59.375000 Hz
0.0873 59.765625 Hz
0.0177 60.156250 Hz
0.1700 60.546875 Hz
0.0183 60.937500 Hz
0.1004 61.328125 Hz
0.0506 61.718750 Hz
0.1742 62.109375 Hz
0.0826 62.500000 Hz
0.1695 62.890625 Hz
0.0421 63.281250 Hz
0.0968 63.671875 Hz
0.1032 64.062500 Hz
0.0875 64.453125 Hz
0.0179 64.843750 Hz
0.0824 65.234375 Hz
0.0869 65.625000 Hz
0.1433 66.015625 Hz
0.0301 66.406250 Hz
0.1919 66.796875 Hz
0.1046 67.187500 Hz
0.2353 67.578125 Hz
0.0580 67.968750 Hz
0.0589 68.359375 Hz
0.0552 68.750000 Hz
0.1354 69.140625 Hz
0.0823 69.531250 Hz
0.1857 69.921875 Hz
0.1873 70.312500 Hz
0.1638 70.703125 Hz
0.0767 71.093750 Hz
0.0601 71.484375 Hz
0.1258 71.875000 Hz
0.1599 72.265625 Hz
0.0656 72.656250 Hz
0.9328 73.046875 Hz
0.8287 73.437500 Hz
0.7940 73.828125 Hz
0.3547 74.218750 Hz
0.4114 74.609375 Hz
0.1109 75.000000 Hz
0.0962 75.390625 Hz
0.3110 75.781250 Hz
0.7782 76.171875 Hz
0.5996 76.562500 Hz
0.5611 76.953125 Hz
0.0438 77.343750 Hz
0.1244 77.734375 Hz
0.1128 78.125000 Hz
0.0701 78.515625 Hz
0.1041 78.906250 Hz
0.2432 79.296875 Hz
0.1878 79.687500 Hz
0.4049 80.078125 Hz
0.0434 80.468750 Hz
0.1196 80.859375 Hz
0.0696 81.250000 Hz
0.0484 81.640625 Hz
0.0176 82.031250 Hz
0.0854 82.421875 Hz
0.1199 82.812500 Hz
0.1138 83.203125 Hz
0.0549 83.593750 Hz
0.1868 83.984375 Hz
0.0608 84.375000 Hz
0.0905 84.765625 Hz
0.0447 85.156250 Hz
0.1874 85.546875 Hz
0.1055 85.937500 Hz
0.1264 86.328125 Hz
0.0463 86.718750 Hz
0.1241 87.109375 Hz
0.0914 87.500000 Hz
0.0689 87.890625 Hz
0.0576 88.281250 Hz
0.0649 88.671875 Hz
0.0624 89.062500 Hz
0.1075 89.453125 Hz
0.0372 89.843750 Hz
0.1319 90.234375 Hz
0.0851 90.625000 Hz
0.2311 91.015625 Hz
0.0313 91.406250 Hz
0.0545 91.796875 Hz
0.0412 92.187500 Hz
0.1460 92.578125 Hz
0.0669 92.968750 Hz
0.1323 93.359375 Hz
0.1795 93.750000 Hz
0.1110 94.140625 Hz
0.0214 94.531250 Hz
0.0244 94.921875 Hz
0.0865 95.312500 Hz
0.1084 95.703125 Hz
0.1008 96.093750 Hz
0.6042 96.484375 Hz
0.3281 96.875000 Hz
0.3959 97.265625 Hz
0.1542 97.656250 Hz
0.1235 98.046875 Hz
0.1199 98.437500 Hz
0.1739 98.828125 Hz
0.5043 99.218750 Hz
10.1530 99.609375 Hz
CodeIts all here included a copy of the fft library Src folder list: here Jens As ususal no guarantee given for whatsoever
THE BEER-WARE LICENSE
I did write this file. As long as you retain this notice you can do whatever you want with this stuff on these pages. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return :-) (C) JensD credit for license this goes to the beer-ware creator Page created by human - no AI involved
|