no idea how this was coded
Do you have a question? Looks like a spectrum analyzer to me. There is an FFT library for Arduino. You can ask whoever uploaded the video.
It looks very nice and I wanted to do a similar thing so I looked at the ESP_FFT-VU.h code from Scott Marley but it fails with this error when I try to verify it:
c:/users/.../appdata/local/arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld.exe: section .stack_dummy VMA [20007b00,20007eff] overlaps section .heap VMA [20005b38,20007b37]
collect2.exe: error: ld returned 1 exit status
exit status 1
Compilation error: exit status 1
The FFT code can be found here:
I assume the code does not make provision for the R4 WiFi yet. I am using a Windows 10 64bit machine with Arduino IDE 2.2.1. I can upload other projects to the R4 WiFi. Any ideas how I can get past this issue?
A few years ago I tried to use an FFT with an Arduino with no success. I ended up using the MSGEQ7 chip and everything went smoothly with it.
Hello, could you point out the tutorials used to make this, or share the code that was used?
Thanks!
Alright, I put together some code that does something similar to the above videos. I used the information from the following sources to put this together.
Video Referenced: https://www.youtube.com/watch?v=Mgh2WblO5_c&ab_channel=ScottMarley
And the respective github page: GitHub - s-marley/ESP32_FFT_VU: A spectrum analyzer VU meter for the ESP32 and a FastLED matrix
I'm not saying this is the best or most efficient way of doing this, but it's how I accomplished a similar result.
#include <arduinoFFT.h>
#include <Arduino_LED_Matrix.h>
#define SAMPLES 256 // Must be a power of 2
#define SAMPLING_FREQ 20000 // Hz, must be 40000 or less due to ADC conversion time. Determines maximum frequency that can be analysed by the FFT Fmax=sampleF/2.
#define AUDIO_IN_PIN 0 // Signal in on this pin (same as A0 or Analog 0)
#define NUM_BANDS 12 // To change this, you will need to change the bunch of if statements describing the mapping from bins to bands
#define NOISE 100 // Used as a crude noise filter, values below this are ignored
ArduinoLEDMatrix matrix;
uint8_t frame[8][12] = {0};
// Sampling and FFT stuff
unsigned int sampling_period_us;
byte peak[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // The length of these arrays must be >= NUM_BANDS
int bandValues[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
double vReal[SAMPLES];
double vImag[SAMPLES];
unsigned long newTime;
ArduinoFFT<double> FFT = ArduinoFFT<double>(vReal, vImag, SAMPLES, SAMPLING_FREQ); //This was changed from the orig
// Was: arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
// Recomended use case is: ArduinoFFT<float> FFT = ArduinoFFT<float>(vReal, vImag, SAMPLES, SAMPLING_FREQ);
double NN;
int HH = 128;
void setup() {
Serial.begin(115200);
matrix.begin();
sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQ));
}
void loop() {
// Reset bandValues[]
for (int i = 0; i<NUM_BANDS; i++){
bandValues[i] = 0;
}
// Sample the audio pin
for (int i = 0; i < SAMPLES; i++) {
newTime = micros();
vReal[i] = analogRead(AUDIO_IN_PIN); // A conversion takes about 9.7uS on an ESP32
vImag[i] = 0;
while ((micros() - newTime) < sampling_period_us) { /* chill */ }
}
// Compute FFT
FFT.dcRemoval(); // Was: FFT.DCRemoval();
FFT.windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD); // Was: FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.compute(FFT_FORWARD); // Was: FFT.Compute(FFT_FORWARD);
FFT.complexToMagnitude(); // Was: FFT.ComplexToMagnitude();
// Analyse FFT results
for (int i = 2; i < (SAMPLES/2); i++){ // Don't use sample 0 and only first SAMPLES/2 are usable. Each array element represents a frequency bin and its value the amplitude.
if (vReal[i] > NOISE) { // Add a crude noise filter
if (i<=2 ) bandValues[0] += (int)vReal[i]; NN = (int)((bandValues[0]/2)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][11] = true;} for (int x=NN;x<8;x++){frame[x][11] = false;}
if (i>2 && i<=3 ) bandValues[1] += (int)vReal[i]; NN = (int)((bandValues[1]/2)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][10] = true;} for (int x=NN;x<8;x++){frame[x][10] = false;}
if (i>3 && i<=4 ) bandValues[2] += (int)vReal[i]; NN = (int)((bandValues[2]/2)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][9] = true;} for (int x=NN;x<8;x++){frame[x][9] = false;}
if (i>4 && i<=6 ) bandValues[3] += (int)vReal[i]; NN = (int)((bandValues[3]/2)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][8] = true;} for (int x=NN;x<8;x++){frame[x][8] = false;}
if (i>6 && i<=9 ) bandValues[4] += (int)vReal[i]; NN = (int)((bandValues[4]/3)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][7] = true;} for (int x=NN;x<8;x++){frame[x][7] = false;}
if (i>9 && i<=13 ) bandValues[5] += (int)vReal[i]; NN = (int)((bandValues[5]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][6] = true;} for (int x=NN;x<8;x++){frame[x][6] = false;}
if (i>13 && i<=20 ) bandValues[6] += (int)vReal[i]; NN = (int)((bandValues[6]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][5] = true;} for (int x=NN;x<8;x++){frame[x][5] = false;}
if (i>20 && i<=30 ) bandValues[7] += (int)vReal[i]; NN = (int)((bandValues[7]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][4] = true;} for (int x=NN;x<8;x++){frame[x][4] = false;}
if (i>30 && i<=46 ) bandValues[8] += (int)vReal[i]; NN = (int)((bandValues[8]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][3] = true;} for (int x=NN;x<8;x++){frame[x][3] = false;}
if (i>46 && i<=70 ) bandValues[9] += (int)vReal[i]; NN = (int)((bandValues[9]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][2] = true;} for (int x=NN;x<8;x++){frame[x][2] = false;}
if (i>70 && i<=106 ) bandValues[10] += (int)vReal[i]; NN = (int)((bandValues[10]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][1] = true;} for (int x=NN;x<8;x++){frame[x][1] = false;}
if (i>106 ) bandValues[11] += (int)vReal[i]; NN = (int)((bandValues[11]/4)/HH)+1; if (NN > 8) NN = 8; for (int x=0;x<NN;x++){frame[x][0] = true;} for (int x=NN;x<8;x++){frame[x][0] = false;}
matrix.renderBitmap(frame, 8, 12);
}
}
}
The spreadsheet that s-marley put together was particularly helpful regarding the bands. The microphone I am using had a 100Hz-10KHz range so your values will vary depending on your audio source. In this case I am just using the analog read in.
I hope this might be useful to someone else as a "getting started" approach to using and making an FFT meter with the Arduino Uno R4 LED Matrix.