Waterfall graph speed
Posted: Sat Dec 02, 2023 5:27 pm
Hello everyone, im new to the forum and still learning about the esp32.
Im using a esp32 wroom to make a simple vfo/panadapter for radios that i make, my goal is to create an opensource pcb for this purpose, however im running into a speed problem.
I'm runing a simple code for a waterfall graph which is done by reading an adc channel and computing the fft of the read values, then the esp32 displays the values on a tft display (spi ili9486 320x480) running at 80mhz but the update speed seems to be really slow like 7-10hz and that's just for the waterfall graph, i did something similar but without the waterfall for a previous project involving a stm32 and that ran a bit faster, https://github.com/gcrcien/STM32_VFO, im coding all this in the arduino IDE.
Has any of you guys done a similar project that can give hints on how to accelerate this project? I'm new to the esp32 but i have read that dma is a way to accelerate the spi lcd refresh rate, but im lost with this.
[Codebox]#include "arduinoFFT.h"
#include "SPI.h"
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
#define CHANNEL 34
#define TFT_WIDTH 480
#define TFT_HEIGHT 100
#define GRAPH_TOP_MARGIN 4
#define GRAPH_BOTTOM_MARGIN 4
#define BLACK 0x0000
#define GREEN 0x07E0
arduinoFFT FFT;
const uint16_t samples = 128;
const double samplingFrequency = 10000;
double vReal[samples];
double vImag[samples];
#define NUM_WATERFALL_ROWS 90
float waterfallData[NUM_WATERFALL_ROWS][128] = {0};
void performFFTAndDrawGraph(int xOffset, int yOffset);
void setup() {
//SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
tft.init();
tft.invertDisplay(0);
tft.fillScreen(BLACK);
tft.setRotation(1);
}
void loop() {
performFFTAndDrawGraph(0, 0);
}
void performFFTAndDrawGraph(int xOffset, int yOffset) {
// Capturar datos de entrada
for (int i = 0; i < samples; i++) {
vReal = analogRead(34);
vImag = 0;
}
// Realizar FFT
FFT = arduinoFFT(vReal, vImag, samples, samplingFrequency);
FFT.Windowing(FFT_WIN_TYP_RECTANGLE, FFT_FORWARD);
FFT.Compute(FFT_FORWARD);
FFT.ComplexToMagnitude();
// Solo mapear los datos de entrada antes de almacenarlos en el array waterfall
for (int col = 0; col < 128; ++col) {
int mappedValue = map(vReal[col], 0, 5000, 0, 128); // Solo mapear a un rango de 0 a 255
waterfallData[NUM_WATERFALL_ROWS - 1][col] = mappedValue;
}
// Actualizar datos de waterfall
for (int row = 0; row < NUM_WATERFALL_ROWS - 1; ++row) {
for (int col = 0; col < 128; ++col) {
waterfallData[row][col] = waterfallData[row + 1][col];
}
}
// Dibujar el waterfall en la pantalla
for (int row = 0; row < NUM_WATERFALL_ROWS; ++row) {
for (int col = 0; col < 128; ++col) {
int intensity = waterfallData[row][col];
int color = intensity; // El color ahora está en el rango de 0 a 255
tft.drawPixel(col + xOffset, TFT_HEIGHT - 1 - row + yOffset + 80, color);
}
}
}[/Codebox]
Im using a esp32 wroom to make a simple vfo/panadapter for radios that i make, my goal is to create an opensource pcb for this purpose, however im running into a speed problem.
I'm runing a simple code for a waterfall graph which is done by reading an adc channel and computing the fft of the read values, then the esp32 displays the values on a tft display (spi ili9486 320x480) running at 80mhz but the update speed seems to be really slow like 7-10hz and that's just for the waterfall graph, i did something similar but without the waterfall for a previous project involving a stm32 and that ran a bit faster, https://github.com/gcrcien/STM32_VFO, im coding all this in the arduino IDE.
Has any of you guys done a similar project that can give hints on how to accelerate this project? I'm new to the esp32 but i have read that dma is a way to accelerate the spi lcd refresh rate, but im lost with this.
[Codebox]#include "arduinoFFT.h"
#include "SPI.h"
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
#define CHANNEL 34
#define TFT_WIDTH 480
#define TFT_HEIGHT 100
#define GRAPH_TOP_MARGIN 4
#define GRAPH_BOTTOM_MARGIN 4
#define BLACK 0x0000
#define GREEN 0x07E0
arduinoFFT FFT;
const uint16_t samples = 128;
const double samplingFrequency = 10000;
double vReal[samples];
double vImag[samples];
#define NUM_WATERFALL_ROWS 90
float waterfallData[NUM_WATERFALL_ROWS][128] = {0};
void performFFTAndDrawGraph(int xOffset, int yOffset);
void setup() {
//SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
tft.init();
tft.invertDisplay(0);
tft.fillScreen(BLACK);
tft.setRotation(1);
}
void loop() {
performFFTAndDrawGraph(0, 0);
}
void performFFTAndDrawGraph(int xOffset, int yOffset) {
// Capturar datos de entrada
for (int i = 0; i < samples; i++) {
vReal = analogRead(34);
vImag = 0;
}
// Realizar FFT
FFT = arduinoFFT(vReal, vImag, samples, samplingFrequency);
FFT.Windowing(FFT_WIN_TYP_RECTANGLE, FFT_FORWARD);
FFT.Compute(FFT_FORWARD);
FFT.ComplexToMagnitude();
// Solo mapear los datos de entrada antes de almacenarlos en el array waterfall
for (int col = 0; col < 128; ++col) {
int mappedValue = map(vReal[col], 0, 5000, 0, 128); // Solo mapear a un rango de 0 a 255
waterfallData[NUM_WATERFALL_ROWS - 1][col] = mappedValue;
}
// Actualizar datos de waterfall
for (int row = 0; row < NUM_WATERFALL_ROWS - 1; ++row) {
for (int col = 0; col < 128; ++col) {
waterfallData[row][col] = waterfallData[row + 1][col];
}
}
// Dibujar el waterfall en la pantalla
for (int row = 0; row < NUM_WATERFALL_ROWS; ++row) {
for (int col = 0; col < 128; ++col) {
int intensity = waterfallData[row][col];
int color = intensity; // El color ahora está en el rango de 0 a 255
tft.drawPixel(col + xOffset, TFT_HEIGHT - 1 - row + yOffset + 80, color);
}
}
}[/Codebox]