I've been working on a VFO project on the arduino IDE working with the clasic bluepill STM32, and im very proud of my badly coded project, im not the best with code one function i would like to implement is a spectrograph and with the FFT library this is kinda posible but how would you speed up this code? not because i want an sdr but just because im reaching the limits of my knowledge.
#include "SPI.h"
#include "Adafruit_ILI9341.h"
#include "arduinoFFT.h"
// Definición de pines
#define TFT_CS PA4
#define TFT_DC PB1
#define TFT_RST PB0
#define CHANNEL PA3
// Definiciones FFT
#define TFT_WIDTH 640
#define TFT_HEIGHT 80
#define GRAPH_TOP_MARGIN 4
#define GRAPH_BOTTOM_MARGIN 4
Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);
arduinoFFT FFT;
unsigned int sampling_period_us;
const uint16_t samples = 512;
double vReal[samples];
double vImag[samples];
void setup() {
// Inicialización del TFT y elementos visuales
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
// Definición de la frecuencia de muestreo para la FFT
sampling_period_us = round(1000000 * (1.0 / 100000)); // Ajusta según sea necesario
// Otras inicializaciones...
}
void loop() {
// Llamada a la función para realizar la FFT y dibujar la gráfica
performFFTAndDrawGraph(0, 150);
}
void performFFTAndDrawGraph(int xOffset, int yOffset) {
unsigned long microseconds = micros();
// Toma de muestras del ADC
for (int i = 0; i < samples; i++) {
vReal[i] = analogRead(CHANNEL);
vImag[i] = 0;
while (micros() - microseconds < sampling_period_us) {
}
microseconds += sampling_period_us;
}
// Configuración y cálculos de la FFT
FFT = arduinoFFT(vReal, vImag, samples, 100000);
FFT.Windowing(FFT_WIN_TYP_RECTANGLE, FFT_FORWARD);
FFT.Compute(FFT_FORWARD);
FFT.ComplexToMagnitude();
// Eliminación de las 3 primeras magnitudes
//vReal[0] = 0;
//vReal[1] = 0;
// Configuración de los márgenes y dimensiones del gráfico
int graphWidth = TFT_WIDTH;
int graphHeight = TFT_HEIGHT - GRAPH_TOP_MARGIN - GRAPH_BOTTOM_MARGIN;
int startX = xOffset;
int startY = GRAPH_TOP_MARGIN + graphHeight + yOffset;
// Calcula el ancho de cada barra en el gráfico
float barWidth = 1;
// Encuentra el valor máximo en los datos de la FFT y su índice
int maxMagnitude = 0.0;
int maxIndex = 0;
for (int i = 0; i < samples / 2; i++) {
if (vReal[i] > maxMagnitude) {
maxMagnitude = vReal[i];
maxIndex = i;
}
}
if (maxMagnitude < 5000) {
maxMagnitude = 5000;
}
// Calcula la frecuencia correspondiente al índice del pico máximo
float frequency = (maxIndex * 1.0) / (sampling_period_us * 1e-6 * samples);
// Dibujo de las barras de la gráfica
for (int i = 0; i < samples / 2; i++) {
int barHeight = static_cast<int>((vReal[i] / maxMagnitude) * graphHeight);
int x = startX + static_cast<int>(i * barWidth);
int y1 = startY - barHeight;
tft.drawFastVLine(x, yOffset + 2, 73, ILI9341_BLACK);
tft.drawFastVLine(x, y1, barHeight, ILI9341_GREEN);
}
// Muestra el pico máximo y su frecuencia
tft.setCursor(10, 10);
tft.print("Pico Maximo: ");
tft.fillRect(80, 10, 50, 10, ILI9341_BLACK);
tft.print(maxMagnitude);
tft.setCursor(120, 10);
tft.print(" en Frecuencia: ");
tft.fillRect(200, 10, 70, 10, ILI9341_BLACK);
tft.print(frequency);
tft.print(" Hz");
}
this is a simple "spectrum analyzer" that i have managed to make run to 100000ks/s, so i can recognize a 50khz signal, but if want to deal with the other signals coming from a radio like audio level batery voltage, current consuption swr measurements i think i need some faster code or another MCU, does anyone have experience doing something like this?
github
Here's a picture of the radio


