In dit artikel onderzoeken we wat er komt kijken bij het uitvoeren van een complexe wiskundige berekening zoals FFT op een ESP32 development board, weliswaar met wat hulp van een bibliotheek, een Pmod I2S2-module, en een speciaal programma hiervoor.

De fouriertransformatie is een van de belangrijke instrumenten bij signaalverwerking om een signaal van het tijddomein naar het frequentiedomein te transformeren. Elk signaal met willekeurige vorm kan worden weergegeven door een oneindige som van sinus- en cosinus-golfvormen. De Fouriertransformatie wordt toegepast bij analoge signalen om de diverse componenten binnen deze reeksen te vinden. Het resultaat is het frequentiespectrum van het analoge ingangssignaal waaruit elk van de frequentie- en amplitudewaarden kan worden berekend.

De Discrete Fouriertransformatie (DFT) is een transformatie die vergelijkbaar is met de Fouriertransformatie, maar die wordt toegepast bij digitale signalen. De DFT is dus de discrete versie van de originele Fouriertransformatie. De snelle Fouriertransformatie (Fast Fourier Transform, FFT) is een algoritme dat wordt gebruikt om de DFT snel en efficiënt te berekenen. FFT is dus een implementatie van DFT met bijna identieke resultaten, maar dan veel sneller en efficiënter.

Zowel DFT als FFT zijn complexe rekenprocessen, die goede wiskundekennis vereisen om ze te begrijpen. Hoewel er verschillende FFT-algoritmen bestaan, is een van de meest gebruikte ontwikkeld door Cooley-Tukey, een algoritme van het ‘verdeel-en-heers’ type. Dit algoritme splitst de DFT op in kleinere stukken.
 


Opmerking van de redactie: dit artikel (230623-03is een deel van het 254 pagina’s tellende boek “Practical Audio DSP Projects with the ESP32” (Elektor 2023). Het is aangepast en enigszins bewerkt om te voldoen aan de redactionele normen en pagina-indeling van Elektor Magazine. Auteur en redactie hebben de tekst naar eer en geweten bewerkt, en zijn graag bereid om eventuele vragen te beantwoorden. 


Waarom FFT? Practical Audio DSP

Het FFT-algoritme is dermate efficiënt en snel dat het met de meeste microcontroller-systemen kan worden geïmplementeerd. Het stelt ons in staat om te zien welke frequenties aanwezig zijn in een digitaal signaal, en ook welke van deze frequenties de overheersende zijn. In een FFT-display is de frequentie op de horizontale as en de amplitude op de verticale as te zien. Er wordt een grafiek van één of meer pieken getoond.

Een hoge piek geeft een frequentie aan die overheerst in het ingangssignaal. De meest dominante piek vertegenwoordigt de grondtoon van het ingangssignaal. De andere pieken zijn de harmonischen, die voorkomen bij veelvouden van de grondtoon.

Indien het ingangssignaal een sinus is, dan is er maar één piek, en wel met dezelfde frequentie als het ingangssignaal. Indien het ingangssignaal een blokgolf is, dan is er een aantal pieken met afnemende amplitude te zien bij verschillende frequenties. Het FFT-algoritme werkt met een eindig aantal monsters van het ingangssignaal (de lengte genoemd), die veelvouden van twee moeten zijn (bijvoorbeeld 32, 64, 128, 256 enzovoort). Over het algemeen geldt: hoe meer monsters, hoe langzamer het algoritme en ook hoe meer rekenkracht er nodig is, omdat er meer gerekend moet worden. Meer monsters zullen echter wel nauwkeurigere resultaten opleveren.

In dit artikel zullen we een FFT-programma ontwikkelen met behulp van Phil Pschatzmann’s Arduino Audio Tools bibliotheek, die is gebaseerd op de AudioRealFFT-klasse. De resultaten worden weergegeven in de seriële monitor, met frequentie, amplitude en de muzieknoot die overeenkomt met deze frequentie. Meer details zijn te vinden op een speciale webpagina .

Aan de slag met de FFT van een ingangssignaal

In dit project wordt gebruik gemaakt van de Pmod I2S20module, die goedkoop en goed verkrijgbaar is bij verschillende leveranciers. Een signaal (sinus, blok of een andere golfvorm) wordt op de ingangspoort (blauwe connector) aangelegd. De grondtoon, amplitude, en de muzikale toon die zich het dichtst bij deze frequentie bevindt worden allemaal weergegeven in de seriële monitor. Het doel van dit project is om te laten zien hoe de Arduino Audio Tools bibliotheek gebruikt kan worden voor een FFT-applicatie die draait op een ESP32. Het development board dat in het bovengenoemde boek wordt gebruikt is de Espressif ESP32-WROOM-32D (figuur 1). Deze is breadboard-compatibel en heeft afmetingen van 5 × 27,9 mm.
 

ESP32-WROOM, FFT on an ESP32
Figuur 1. Het Espressif ESP32-WROOM-32D
development board.

Figuur 2 toont het schema van dit project. De Pmod I2S2-module krijgt audiosignalen van de PCSGU250-signaalgenerator (of een gelijkwaardige generator die je bij de hand hebt). Vergeet niet dat, hoewel alleen het ADC-gedeelte van de Pmod I2S2 wordt gebruikt, de aansluitingen voor zowel de ADC als de DAC in het schema zijn aangegeven. Het programma verwerkt de samples van het ingangssignaal en geeft de resultaten weer in de seriële monitor.
 

Figure 2 fft.png
Figuur 2. Het schema van het project.

Listing 1 toont het FFT-programma. Dit programma is opgenomen in een software-archief dat het boek Practical Audio DSP Projects with the ESP32 ondersteunt. De bundel kan gratis worden gedownload van de sectie ‘Boeken’ op de website van de Elektor Store . Eenmaal op de webpagina van dit boek ga je naar ‘Downloads’ voor de Software_Practical Audio DSP Projects with the ESP32 (een .zip-bestand van 62 MB); sla dit bestand op je systeem op. Pak het archief uit en zoek het FFT.ino-programma in het materiaal bij hoofdstuk 14.

Listing 1. Programma om FFT uit te voeren op de ESP32.
/***************************************************************
 *           FAST FOURIER TRANSFORM
 *           ======================
 *
 * This program uses the Arduino Audio Tools library to display
 * the FFT components of an input signal.
 *
 * Author : Dogan Ibrahim
 * Program: FFT
 * Date   : May, 2023
 *
 * (This program is a modified version of the program developed
 *  by Phil Pschatzmann)
 ***************************************************************/
#include "AudioTools.h"
#include "AudioLibs/AudioRealFFT.h"

uint16_t sample_rate=44100;
uint8_t channels = 2;
I2SStream in;
AudioRealFFT fft;
StreamCopy copier(fft, in);

//
// Display fft result on Serial Monitor
//
void fftResult(AudioFFTBase &fft)
{
    float diff;
    auto result = fft.result();
    if (result.magnitude>100)
    {
        Serial.print(result.frequency);
        Serial.print(" ");
        Serial.print(result.magnitude);  
        Serial.print(" => ");
        Serial.print(result.frequencyAsNote(diff));
        Serial.print( " diff: ");
        Serial.println(diff);
    }
}

void setup(void)
{
  Serial.begin(115200);
 
//
// Configure in stream
//
  auto configin = in.defaultConfig(RX_MODE);
  configin.sample_rate = sample_rate;
  configin.channels = channels;
  configin.bits_per_sample = 16;
  configin.i2s_format = I2S_STD_FORMAT;
  configin.is_master = true;
  configin.port_no = 0;
  configin.pin_ws = 15;                        // LRCK
  configin.pin_bck = 14;                       // SCLK
  configin.pin_data = 22;                      // SDOUT
  configin.pin_mck = 0;
  in.begin(configin);

//
// Configure FFT
//
  auto tcfg = fft.defaultConfig();
  tcfg.length = 8192;
  tcfg.channels = channels;
  tcfg.sample_rate = sample_rate;
  tcfg.bits_per_sample = 16;
  tcfg.callback = &fftResult;
  fft.begin(tcfg);
}

//
// Copy input signal to fft
//
void loop()
{
  copier.copy();
}

Aan het begin van het programma zijn de headerbestanden AudioTools.h en AudioLibs/AudioRealFFT.h opgenomen. Ook worden de streams fft en in gedefinieerd. Binnen de setup()-functie wordt de I2S-stream in (in RX_MODE) geconfigureerd door de ESP32 GPIO-poorten op te geven waarop deze is aangesloten. Ook wordt de FFT geconfigureerd door de lengte (length) in te stellen op 8192 samples. De callback-functie krijgt de name fftResult door, zodat de FFT-resultaten in deze functie beschikbaar zijn. De functie fftResult() geeft dan de frequentie, de amplitude, en de muziektoon weer die het dichtst bij deze frequentie ligt, samen met het verschil tussen de twee frequenties .
 

Sample output of the program
Figuur 3. Voorbeeld van de uitvoer van het programma in de seriële monitor.

De voorbeeld-uitvoer is te zien in figuur 3, waarbij de invoer een sinus was met een frequentie van 440 Hz. Dus.. is dat ‘fast’ of niet?


Vragen of opmerkingen?

 

Hebt u technische vragen of opmerkingen naar aanleiding van dit artikel? Stuur een e-mail naar de auteur via d.ibrahim@btinternet.com of naar de redactie van Elektor via redactie@elektor.com.

Inschrijven
Schrijf u in voor tag alert e-mails over Elektor Books!