Ide 2.3.2, arduinoFFT, is not working

Upgraded to the new ide. Tried to compile a code that was previously good. FFT.DCRemoval(); Error, FFT not recognized. Reloaded "arduinoFFT.h" but problem persists.
Tried <arduinoFFT.h> same error. Any suggestions? Code is for Audio Analyzer 32 Bands, ESP32, TFT1.8" Display.

Suggestion: post the code, using code tags. And the complete error message(s), also using code tags.

 Filename: ESP32_TFT_Display_32_Bands_Mono_ASA.ino
  This code works just fine
  Using: ESP32 with 1.8" TFT Display (128 x 160) and ArduinoFFT() for 32 bands Audio Frequency Analyzer with Sprites
  This file is to be used for 13 Channels of Audio Spectrum Analyzers in PCB Board
  In the file TFT_eSPI/User_Setup_Select.h
  comment this line: #include <user_Setup.h>
  uncommnet this line: #include <User_Setups/Setup47_ST7735.h>
  On Setup47 change the height to 160 and use Blacktab
   
  Revision date: October 17, 2023    
*/
#include <driver/i2s.h>
#include <driver/adc.h>  // Needed to get to adc1_get_raw()
#include <WiFi.h>        // Nedded to dislable WiFi
#include <complex.h>
#include <math.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#include "arduinoFFT.h"

const i2s_port_t I2S_PORT = I2S_NUM_0;

arduinoFFT FFT = arduinoFFT();

#define SAMPLES 1024  // Must be a power of 2
#define SAMPLING_FREQUENCY 44100
#define NOISE 300
#define NUM_BANDS 32
#define COEF 100

#define audioinputPin 36

TFT_eSPI tft = TFT_eSPI();  // For 1.8" ST7735 TFT Display

// Define Sprites
TFT_eSprite asa = TFT_eSprite(&tft);
TFT_eSprite spectrum = TFT_eSprite(&tft);
TFT_eSprite freq = TFT_eSprite(&tft);

// Sprites height assignments
uint16_t asa_sprite_height = 10;
uint16_t spectrum_sprite_height = 108;
uint16_t freq_sprite_height = 10;

struct eqBand {
  const char* freqname;
  uint16_t amplitude;
  int peak;
  int lastpeak;
  uint16_t lastval;
  unsigned long lastmeasured;
};

eqBand audiospectrum[NUM_BANDS] = {
  //Adjust the amplitude values to fit your audio input level
  { "45",  200, 0, 0, 0, 0 },
  { "90",  200, 0, 0, 0, 0 },
  { "130", 200, 0, 0, 0, 0 },
  { "180", 200, 0, 0, 0, 0 },
  { "220", 200, 0, 0, 0, 0 },
  { "260", 200, 0, 0, 0, 0 },
  { "310", 200, 0, 0, 0, 0 },
  { "350", 200, 0, 0, 0, 0 },
  { "390", 200, 0, 0, 0, 0 },
  { "440", 200, 0, 0, 0, 0 },
  { "480", 200, 0, 0, 0, 0 },
  { "525", 200, 0, 0, 0, 0 },
  { "650", 200, 0, 0, 0, 0 },
  { "825", 200, 0, 0, 0, 0 },
  { "1K",  200, 0, 0, 0, 0 },
  { "1K3", 200, 0, 0, 0, 0 },
  { "1K6", 200, 0, 0, 0, 0 },
  { "2K05",200, 0, 0, 0, 0 },
  { "2K5", 200, 0, 0, 0, 0 },
  { "3K",  200, 0, 0, 0, 0 },
  { "4K",  200, 0, 0, 0, 0 },
  { "5125",200, 0, 0, 0, 0 },
  { "6250",200, 0, 0, 0, 0 },
  { "9125",200, 0, 0, 0, 0 },
  { "12K", 200, 0, 0, 0, 0 },
  { "13K", 200, 0, 0, 0, 0 },
  { "14K", 200, 0, 0, 0, 0 },
  { "15K", 200, 0, 0, 0, 0 },
  { "16K", 200, 0, 0, 0, 0 },
  { "16K5",200, 0, 0, 0, 0 },
  { "17K", 200, 0, 0, 0, 0 },
  { "17K5",200, 0, 0, 0, 0 }
};

byte getBand(int i) {
  if (i <= 2) return 0;                //   45Hz
  if (i > 2 && i <= 3) return 1;       //   90Hz
  if (i > 3 && i <= 4) return 2;       //  130Hz
  if (i > 4 && i <= 5) return 3;       //  180Hz
  if (i > 5 && i <= 8) return 4;       //  220Hz
  if (i > 8 && i <= 9) return 5;       //  260Hz
  if (i > 9 && i <= 10) return 6;      //  310Hz
  if (i > 10 && i <= 12) return 7;     //  350Hz
  if (i > 12 && i <= 14) return 8;     //  390Hz
  if (i > 14 && i <= 16) return 9;     //  440Hz
  if (i > 16 && i <= 18) return 10;    //  480Hz
  if (i > 18 && i <= 20) return 11;    //  525Hz
  if (i > 20 && i <= 22) return 12;    //  650Hz
  if (i > 22 && i <= 25) return 13;    //  825Hz
  if (i > 25 && i <= 30) return 14;    //   1KHz
  if (i > 30 && i <= 40) return 15;    //  1K3Hz
  if (i > 40 && i <= 50) return 16;    //  1K6Hz
  if (i > 50 && i <= 60) return 17;    // 2K05Hz
  if (i > 60 && i <= 75) return 18;    //  2K5Hz
  if (i > 75 && i <= 110) return 19;   //   3KHz
  if (i > 110 && i <= 120) return 20;  //   4KHz
  if (i > 120 && i <= 140) return 21;  // 5125Hz
  if (i > 140 && i <= 150) return 22;  // 6250Hz
  if (i > 150 && i <= 170) return 23;  // 9125Hz
  if (i > 170 && i <= 190) return 24;  //  12KHz
  if (i > 190 && i <= 210) return 25;  //  13KHz
  if (i > 210 && i <= 240) return 26;  //  14KHz
  if (i > 240 && i <= 260) return 27;  //  15KHz
  if (i > 260 && i <= 280) return 28;  //  16KHz
  if (i > 280 && i <= 290) return 29;  // 16K5Hz
  if (i > 290 && i <= 300) return 30;  //  17KHz
  if (i > 300 && i <= 315) return 31;  // 17K5Hz
  return 32;
}

unsigned long sampling_period_us;
unsigned long microseconds;
double vReal[SAMPLES];
double vImag[SAMPLES];

unsigned long newTime, oldTime;
uint16_t width = 160;   // width for spectrum sprite
uint16_t height = 108;  // height for spectrum sprite
uint8_t bands = 32;
uint8_t bands_width = floor(width / bands);
uint8_t bands_pad = bands_width - 2;
uint16_t colormap[255];  // color palette for the band meter (pre-fill in setup)
byte peak[SAMPLES] = {0};
bool adcread = false;    // use adc raw or analogread

void displayBand(int band, int dsize) {
  uint16_t hpos = bands_width * band;
  int dmax = 98; // To leave space for text max-amp
  if (dsize > height) {
    dsize = height;
  }
  if (dsize < audiospectrum[band].lastval) {
    // lower value, delete some lines
    spectrum.fillRect(hpos, height - audiospectrum[band].lastval, bands_pad, audiospectrum[band].lastval - dsize, TFT_GREEN);
  }
  if (dsize > dmax) dsize = dmax;
  for (int s = 0; s <= dsize; s = s + 4) {
    spectrum.drawFastHLine(hpos, height - s, bands_pad, colormap[height - s]);
  }
  if (dsize > audiospectrum[band].peak) {
    audiospectrum[band].peak = dsize;
  }
  audiospectrum[band].lastval = dsize;
  audiospectrum[band].lastmeasured = millis();
}

void displayMaxAmplitudeFrequency()
  {
    int maxAmplitude = 0;
    int maxAmplitudeIndex = 0;

    // Find the band with the maximum amplitude
    for (int i = 0; i < bands; i++)
    {
      if (audiospectrum[i].lastval > maxAmplitude)
      {
        maxAmplitude = audiospectrum[i].lastval;
        maxAmplitudeIndex = i;
     }
   }
    // Display the frequency with the maximum amplitude   
    spectrum.setTextSize(1);
    spectrum.setTextColor(TFT_YELLOW);
    String maxAmplitudeFrequency = "Freq(Max_Amp): " + String(audiospectrum[maxAmplitudeIndex].freqname) + " (" + String(maxAmplitude) + ")";
    spectrum.drawString(maxAmplitudeFrequency, 10, 2, 1);    
  }

void setup() {
  WiFi.mode(WIFI_MODE_NULL);
  Serial.begin(115200);
  adc1_config_width(ADC_WIDTH_BIT_12);
  adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
  // adc1_config_channel_atten(ADC1_CHANNEL_1, ADC_ATTEN_DB_11);

  // Initialize the I2S interface
  i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLING_FREQUENCY,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 4,
    .dma_buf_len = SAMPLES,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  const i2s_pin_config_t pin_config = {
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = 36
  };

  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);

  tft.init();
  tft.fillScreen(TFT_BLACK);
  tft.setRotation(3);

  // Create Sprites
  asa.createSprite(width, asa_sprite_height);
  spectrum.createSprite(width, spectrum_sprite_height);
  freq.createSprite(width, freq_sprite_height);

  //Set Sprite Text Colors
  asa.setTextColor(TFT_YELLOW, TFT_BLACK);
  spectrum.setTextColor(TFT_RED, TFT_BLACK);
  freq.setTextColor(TFT_YELLOW, TFT_BLACK);

  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
  delay(2000);

  for (uint8_t i = 0; i < height; i++) {
    colormap[i] = spectrum.color565(height - i * .5, i * 1.1, 0);
  }
}

void loop() {
  asa.fillSprite(TFT_BLACK);
  asa.setTextSize(1);
  asa.drawString("Audio Spectrum Analyzer", 10, 0, 1);
  asa.pushSprite(0, 0);

  spectrum.fillSprite(TFT_BLACK);
  spectrum.drawFastVLine(1, 10, 107, TFT_WHITE);
  spectrum.drawFastHLine(1, 107, 156, TFT_WHITE);

  int32_t sample[SAMPLES];
  size_t bytes_read;

  i2s_read(I2S_NUM_0, &sample, SAMPLES, &bytes_read, portMAX_DELAY);
  
  for (int i = 0; i < SAMPLES; i++) {
    newTime = micros() - oldTime;
    oldTime = newTime;
    if (adcread) {
      vReal[i] = adc1_get_raw(ADC1_CHANNEL_0);
      delayMicroseconds(20);
    } else {
      vReal[i] = analogRead(audioinputPin);  // A conversion takes about 1uS on an ESP32
    }
    vImag[i] = 0;
    while (micros() < (newTime + sampling_period_us)) { /* do nothing to wait */ }
  }
  // Compute the FFT
  FFT.DCRemoval();
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

  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 and its value the amplitude.
    if (vReal[i] > NOISE) {
      // Add a crude noise filter, 10 x amplitude or more
      byte bandNum = getBand(i);
      if (bandNum != 32) {
        displayBand(bandNum, (int)vReal[i] / audiospectrum[bandNum].amplitude);
      }
    }
  }

  long vnow = millis();

  for (byte band = 0; band <= 31; band++) {
    // auto decay every 50ms on low activity bands, changing this to 30ms
    if (vnow - audiospectrum[band].lastmeasured > 50) {
      displayBand(band, audiospectrum[band].lastval > 4 ? audiospectrum[band].lastval - 4 : 0);
    }
    if (audiospectrum[band].peak > 0) {
      audiospectrum[band].peak -= 2;
      if (audiospectrum[band].peak <= 0) {
        audiospectrum[band].peak = 0;
      }
    }

    // only draw if peak changed
    if (audiospectrum[band].lastpeak != audiospectrum[band].peak) {
      // delete last peak
      spectrum.drawFastHLine(bands_width * band, height - audiospectrum[band].lastpeak, bands_pad, TFT_RED);
      audiospectrum[band].lastpeak = audiospectrum[band].peak;
      spectrum.drawFastHLine(bands_width * band, height - audiospectrum[band].peak, bands_pad, colormap[height - audiospectrum[band].peak]);
    }
  }

  // Call the function to display the frequency with the maximum amplitude
  displayMaxAmplitudeFrequency();  

  spectrum.pushSprite(0, 10);  

  freq.fillSprite(TFT_BLACK);
  freq.setTextSize(1);
  freq.drawString(" 50 .1k .5k 1k  2k 17.5Khz", 0, 0, 1);
  freq.pushSprite(0, 118);

}  // End of loop


````C:\Users\Juan Acevedo\Documents\Arduino\ESP32_TFT_Display_32_Bands_Mono_ASA\ESP32_TFT_Display_32_Bands_Mono_ASA.ino:25:1: error: 'arduinoFFT' does not name a type; did you mean 'ArduinoFFT'?
   25 | arduinoFFT FFT = arduinoFFT();
      | ^~~~~~~~~~
      | ArduinoFFT
C:\Users\Juan Acevedo\Documents\Arduino\ESP32_TFT_Display_32_Bands_Mono_ASA\ESP32_TFT_Display_32_Bands_Mono_ASA.ino: In function 'void setup()':
C:\Users\Juan Acevedo\Documents\Arduino\ESP32_TFT_Display_32_Bands_Mono_ASA\ESP32_TFT_Display_32_Bands_Mono_ASA.ino:188:21: error: 'ADC_WIDTH_BIT_12' was not declared in this scope; did you mean 'ADC_WIDTH_BIT_13'?
  188 |   adc1_config_width(ADC_WIDTH_BIT_12);
      |                     ^~~~~~~~~~~~~~~~
      |                     ADC_WIDTH_BIT_13
C:\Users\Juan Acevedo\Documents\Arduino\ESP32_TFT_Display_32_Bands_Mono_ASA\ESP32_TFT_Display_32_Bands_Mono_ASA.ino: In function 'void loop()':
C:\Users\Juan Acevedo\Documents\Arduino\ESP32_TFT_Display_32_Bands_Mono_ASA\ESP32_TFT_Display_32_Bands_Mono_ASA.ino:264:3: error: 'FFT' was not declared in this scope
  264 |   FFT.DCRemoval();
      |   ^~~
Multiple libraries were found for "WiFi.h"
  Used: C:\Users\Juan Acevedo\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.0.1\libraries\WiFi
  Not used: C:\Users\Juan Acevedo\Documents\Arduino\libraries\WiFiEspAT
exit status 1

Compilation error: 'arduinoFFT' does not name a type; did you mean 'ArduinoFFT'?`


The photo shows the code working on the previous ide version.

Would it make sense to post the code that is actually causing the problem, along with the complete error messages?

What I am trying to resolve is why it does not compile with the new Arduino ide2.3.2 Apparently there is some incompatibility with the "arduinoFFT.h" library on this new ide version..

If you can't seem to post the complete error messages, how can you expect help?

Hi @jacv2.

There was a breaking change to the API of the "arduinoFFT" library's at the 2.0.0 release:

https://github.com/kosme/arduinoFFT/wiki/api

Migrating from versions prior to 2.0

  • The object name is now capitalized and the constructor requires a floating-point data type, e.g. "ArduinoFFT" instead of "arduinoFFT".
  • All function names are camelCase case now (start with lower-case character), e.g. "windowing()" instead of "Windowing()".

Your sketch was written for use with version 1.x of the library, but you have installed version 2.x of the library. This is the cause of the error.

I'll describe the two possible solutions. You can pick whichever one you prefer.

Install compatible version of arduinoFFT

Since you know your sketch was working with the older version of the library, it will work once again if you install that version of the library. You can do that by using the Arduino IDE Library Manager:

  1. Select Sketch > Include Library > Manage Libraries... from the Arduino IDE menus to open the "Library Manager" view in the left side panel.
  2. Type arduinoFFT in the "Filter your search..." field.
  3. Scroll down through the list of libraries until you see the "arduinoFFT" entry.
  4. You will see a drop-down version menu at the bottom of the entry. Select "1.6.2" from the menu.
  5. Click the "INSTALL" button at the bottom of the entry.
  6. Wait for the installation process to finish, as indicated by a notification at the bottom right corner of the Arduino IDE window:

    ⓘ Successfully installed library ...

Arduino IDE will periodically display a notification that offers to update the library for you:

Updates are available for some of your libraries.

If you click the "INSTALL MANUALLY" button in the notification, a list of each of the libraries that have available updates will be shown in the Arduino IDE Library Manager. It is generally a good idea to keep your libraries updated since the updates might provide important enhancements or bug fixes. So you should look through the list and update other libraries if appropriate, but you should avoid accepting the update for the "arduinoFFT" library.

Port sketch to new API

It might be that some valuable enhancements and/or fixes have been made (or will be made in future releases) to the "arduinoFFT" library since the time of the library's last 1.x release. You can only get access to those if you update your sketch code to use the new API.

Fortunately, the library developer provided very nice documentation of the API, which would make that task much more pleasant:

If you give it a try and have any questions or problems along the way, you can come back here an make a post with a detailed description of the updated situation and the forum helpers will provide assistance.

The error codes are posted after the // End of loop.
It seems I have a more basic problem. I tried some very basic code and all I got was a blank screen. I put another spare ESP32 with the old code and it works. So, my wired connections are ok. I cannot find a simple example of basic working code for the ESP32 with ide2.3.2, like "Hello world". Sorry, I am 83 years old with limited sw knowledge.

Sorry, I missed that.

As noted above, Arduino LLC broke all previously existing code using the ArduinoFFT library by imposing an arbitrary new naming convention, requiring you to make a few minor spelling changes.

After installing a new library, it is a good idea to test it with your setup by running one of the built-in examples in that library.

The "TFT_eSPI" library you are using for your display is quite challenging to use. You must edit the library code files to configure the library for your specific display and connections to the board:

https://github.com/Bodmer/TFT_eSPI#:~:text=The%20screen%20controller%2C%20interface%20pins%20and%20library%20configuration%20settings%20must%20be%20defined%20inside%20the%20library.

You will lose all that configuration every time you update to a new version of the library, or if you make a fresh installation of the library on a different computer. Upgrading the Arduino IDE application won't interfere with the library since the library is installed to a separate location from Arduino IDE. But you might have seen a notification in Arduino IDE about an available update for your libraries and accepted that update.

I see you were very wise and documented the necessary configuration for the library:

Please open that User_Setup_Select.h file in a text editor to see if the configuration you describe there is still in place.

I sympathize. I am often frustrated to find that, even though a library includes examples demonstrating various advanced applications of the library, they don't provide a minimal "hello world" demo. That is the case with this TFT_eSPI library.

The library example sketch available from the File > Examples > TFT_eSPI > 160x128 > TFT_Print_Test menu in Arduino IDE is probably the closest thing to a "Hello, world!" provided by the library developers.

It was not Arduino LLC. This is a library created by a community member. The Arduino company does not have any involvement in the development of the library.

Apologies. Your post failed to state the originator of the change and my assumption was unwarranted.

1 Like

I double checked TFT_eSPI pin assignments and ran the clock example and it displayed just fine on the TFT display. On arduinoFFT, I changed all those capital letters but still just get a blank screen. I ran various of the arduinoFFT examples and they show ok on the serial monitor. I think I am missing some basic change that even when the code compiles ok I only get a blank screen.
As time permits I will continue playing around with this...

I was finally able to fix the code. (ChatGPT makes so many mistakes!) It now works with ide 2.3.2 and arduinoFFT2.0.2. I had to delete the i2s, adc functionality to simplify the code. It still fails the tone generator test in that very high frequencies come back from right to left. Also, in a pink noise test the frequency amplitudes slopes from left to right. To me it means that the FFT is not very accurate. One day I might do it using analog filters (opamps). I have the manual from my Altec/HP 8050A Analyzer that will give a +-1dB accuracy. I think it will improve on the 10Bands Analog by Donner's in that it uses an RMS Detector and some pots to trim values. For now, I consider this request closed. Thanks to all that responded to my inquiry.

Great work on fixing the code! Thanks for taking the time to post an update.

Regards,
Per

That suggests that you are not using the FFT algorithm correctly. There are many pitfalls to be aware of, especially when applied to measured data (use of incorrect sampling frequency, aliasing due to improper low pass filtering of the input data, etc.).

It is easy to check the mathematical accuracy of the code with calculated input data, and in my hands, ArduinoFFT returns the expected result, to within the expected roundoff error.

Well, the code I used was taken from Donner's ASA and after it was working ok, I asked ChatGPT to optimize it and it did, but really there was no difference in the code just explaining it. I suppose when Donner's decided to do a 10-band analog ASA was it because he was not happy with the FFT version?

This is part of a comment from Mark Donner to a question I asked. About a month ago.
" ... in the coming weeks i will release a new analyzer. Different fft algorithm And bluetooth as audio source….. that one is a lot more accurate in high and low"