If I Upload this code:
#include <arduinoFFT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "math.h"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define IN_PIN A0 // Mic read pin
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C // 0x3C for 128x64
#define SAMPLES 64 //N for N-point FFT
#define SAMPLING_FREQUENCY 20000 //Fs, Make sure satisifies Nyquist Criteria
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
unsigned int sampling_period_us; //Time period
unsigned long microseconds; //for storing Time
double vReal[SAMPLES];
double vImag[SAMPLES];
arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQUENCY);
void setup() {
Serial.begin(115200);
pinMode(IN_PIN, INPUT);
//SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY)); //Time period is inverse of Frequency
display.clearDisplay();
text_displayer("0kHz", 0, 0, 1);
text_displayer("5kHz", 54, 0, 1);
text_displayer("10kHz", 94, 0, 1);
text_invert_displayer("audioFFT ", 0, 56, 1);
text_displayer("313hz/u", 85, 56, 1);
}
void loop() {
//Reading 64 samples at Fs frequency
for(int i = 0; i < SAMPLES; i += 1){
microseconds = micros();
vReal[i] = analogRead(IN_PIN);
vImag[i] = 0;
while(micros()-microseconds < sampling_period_us){}
}
FFT.DCRemoval();
FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(FFT_FORWARD);
FFT.ComplexToMagnitude();
//Finding Max frequency in FFT result for Normalization
int peak = 0.0;
for(int i = 0; i < SAMPLES; i += 1){
if( peak < vReal[i] ){
peak = vReal[i];
}
}
//Displaying (N/2) bins as Final result
double invPeak = 44.0/(peak*1.0);
display.fillRect(0, 7, 127, 48, BLACK);
for(int j = 0; j < SAMPLES; j += 1){
display.fillRect(j*4, (56.0-(vReal[j]*invPeak)), 3, (vReal[j]*invPeak), WHITE);
}
display.display();
delay(1);
}
//Function for displaying Text on OLED display
void text_displayer(String text, int x, int y, int s){
display.setTextSize(s);
display.setTextColor(WHITE);
display.setCursor(x, y);
display.println(text);
display.display();
}
//Function for displaying InverseBackground Text on OLED display
void text_invert_displayer(String text, int x, int y, int s){
display.setTextSize(s);
display.setTextColor(BLACK, WHITE);
display.setCursor(x, y);
display.println(text);
display.display();
}
I obtain this message in Serial Monitor:
SSD1306 allocation failed
SSD1306 allocation failed
...
But if I use this code:
//Libraries
#include <Wire.h> //IDE Standard
#include <Adafruit_GFX.h> //Adafruit GFX https://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h> //Adafruit SSD1306 https://github.com/adafruit/Adafruit_SSD1306
#include <fix_fft.h> //https://www.arduinolibraries.info/libraries/fix_fft
const byte audioIn = A0; //Define analog pin for FFT
char re[128], im[128]; //Real and Imaginary FFT result arrays
byte yaxis = 63; //OLED y-axis drawing boundary limit
byte xaxis = 0; //OLED x-axis limit
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire,-1);
void setup()
{
Wire.begin(); //I2C Master
pinMode(audioIn,INPUT); //Set A0 as analog input pin
analogReference(DEFAULT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextColor(WHITE);
display.clearDisplay();
display.display();
}
/*
The FFT real/imaginary data are stored in a char data type as a signed -128 to 127 number
This allows a waveform to swing centered around a 0 reference data point
The ADC returns data between 0-1023 so it is scaled to fit within a char by dividing by 4 and subtracting 128.
eg (0 / 4) - 128 = -128 and (1023 / 4) - 128 = 127
*/
void loop()
{
for (byte i = 0; i < 128; i++) //Read 128 analog input samples from ADC
{
int sample = analogRead(audioIn);
re[i] = (sample >> 2) - 128; // sample / 4 - 128; //Scale the samples to fit within a char variable
im[i] = 0; //There are no imaginary samples associated with the time domain so set to 0
}
fix_fft(re, im, 7, 0); //Send the samples for FFT conversion, returning the real/imaginary results in the same arrays
display_spectrum();
display.display();
delay(1);
}
/*
For a 16 MHz Arduino the ADC clock is set to 16 MHz/128 = 125 KHz. Each conversion in AVR takes 13 ADC clocks so 125 KHz /13 = 9615 Hz.
The data array will contain frequency bin data in locations 0..127 for samples up to the sampling frequency of approx. 9 KHz
Each frequency bin will represent a center frequency of approximately (9 KHz / 128 samples) = 70 Hz
Due to Nyquist sampling requirements, we can only consider sampled frequency data up to (sampling rate / 2) or (9 KHz / 2) = 4.5 KHz
Therefore we only acknowledge the first 64 frequency bins [0..63] = [0..4.5KHz]
*/
void text_displayer(String text, int x, int y, int s){
display.setTextSize(s);
display.setTextColor(WHITE);
display.setCursor(x, y);
display.println(text);
//display.display();
}
//Function for displaying InverseBackground Text on OLED display
void text_invert_displayer(String text, int x, int y, int s){
display.setTextSize(s);
display.setTextColor(BLACK, WHITE);
display.setCursor(x, y);
display.println(text);
//display.display();
}
void display_spectrum()
{
display.clearDisplay();
int yOffset = 12;
for (byte i = 1; i < 64; i++)
{
int dat = sqrt(re[i] * re[i] + im[i] * im[i]); //Frequency magnitude is the square root of the sum of the squares of the real and imaginary parts of a vector
if (dat >= 63 ) dat = 63;
display.drawLine(i * 2, yaxis - yOffset, i * 2, yaxis - dat - yOffset, WHITE);// draw bars for each frequency bin from 70 Hz to 4.5 KHz
}
// display.setTextSize(2);
// display.setCursor(16,8);
// display.print("SPECTRUM");
text_displayer("0kHz", 0, 0, 1);
text_displayer("5kHz", 104, 0, 1);
text_invert_displayer("audioFFT", 0, 56, 1);
display.display();
}
It all works!
However, in my opinion, the implementation of the arduinoFFT.h library is easier than the implementation of the fix_fft.h library. Is there any way to fix this so that I can use the arduinoFFT library? Thank you all