Inhoudsopgave:

QuickFFT: High Speed FFT voor Arduino - Ajarnpa
QuickFFT: High Speed FFT voor Arduino - Ajarnpa

Video: QuickFFT: High Speed FFT voor Arduino - Ajarnpa

Video: QuickFFT: High Speed FFT voor Arduino - Ajarnpa
Video: QuickFFT: High Speed FFT for Arduino 2024, Juni-
Anonim
QuickFFT: High Speed FFT voor Arduino
QuickFFT: High Speed FFT voor Arduino

Typische Arduino heeft beperkte RAM en verwerkingskracht, en FFT is een rekenintensief proces. Voor veel real-time toepassingen is de enige vereiste om frequentie met maximale amplitude te krijgen of om frequentiepieken te detecteren.

In een van mijn instructables heb ik een code voor FFT voorbereid die hier te vinden is: EasyFFT

Deze code was in staat om FFT van maximaal 128 samples uit te voeren op Arduino nano. Een hoger samplenummer dan dit is niet mogelijk vanwege het beperkte geheugen van Arduino. Ik heb de functie een beetje aangepast om de snelheid te verbeteren en het geheugenverbruik te verminderen. Deze aanpassing stelt Arduino in staat om FFT vijf keer sneller uit te voeren en verbruikt bijna de helft van het geheugen. Deze Instructable heeft geen betrekking op de werking van FFT, referenties ervoor zijn te vinden op EasyFFT.

Stap 1: Werken

Werken
Werken
Werken
Werken
Werken
Werken
Werken
Werken

De typische FFT-functie is aangepast om de snelheid met minder nauwkeurigheid te verbeteren. Zoals in de afbeelding te zien is, moet een testsignaal worden vermenigvuldigd met sinus- of cosinusgolfvormen. Deze waarden kunnen tussen 0 en 1 liggen, dus drijvende vermenigvuldiging is een must. in Arduino is zwevende vermenigvuldiging traag in vergelijking met bewerkingen met gehele getallen.

In deze functie wordt de sinus/cosinusgolf vervangen door een blokgolf. We moeten namelijk een testsignaal vermenigvuldigen met een blokgolf die de waarde 0, 1 of -1 kan hebben. Daarom kunnen we zwevende vermenigvuldiging vervangen door gewoon geheel getal optellen of aftrekken. Voor Arduino is integer optellen of aftrekken ongeveer 5 keer sneller. Dit maakt het oplossen ongeveer 5 keer sneller.

Door deze wijziging kunnen nu frequentie bin-waarden worden opgeslagen als een geheel getal (dat voorheen float was) en krijgen we nog een voordeel van een lager geheugenverbruik. In Arduino Nano verbruikt int 2 bytes geheugen, terwijl float 4 bytes geheugen verbruikt. Dankzij dit voordeel in de nieuwe code kunnen we FFT uitvoeren voor bijna 256 samples (voorheen 128 samples).

In Normal FFT moesten we de sinuswaarde opslaan om sneller een oplossing te maken. In een nieuwe functie, omdat we geen sinus/cosinus-waarden meer nodig hebben, kunnen we deze elimineren en wat geheugen besparen.

Implementatie:

Het implementeren van deze functie is eenvoudig. We kunnen de functie eenvoudig kopiëren aan het einde van de code. Deze functie kan worden uitgevoerd met het onderstaande commando:

float f= Q_FFT(data, 256, 100);In functie Q_FFT, data: deze term is een array met signaalwaarden, de aanbevolen steekproefomvang is 2, 4, 8, 32, 64, 128, 256, 512, … en verder. als de steekproefomvang niet bij deze waarden hoort, wordt deze afgekapt naar de dichtstbijzijnde lagere kant van de waarden. als de steekproefomvang bijvoorbeeld 75 is, wordt FFT uitgevoerd voor 64 aantallen steekproeven. Het maximale aantal steekproefgroottes wordt beperkt door het beschikbare RAM-geheugen op Arduino.

De tweede term specificeert het aantal samples in een array en de laatste term is de samplefrequentie in Hz.

Stap 2: Coderen

In dit gedeelte wordt de wijziging uitgelegd die in de EasyFFT-code is aangebracht en waarmee rekening moet worden gehouden bij het aanbrengen van wijzigingen in de code, 1. Zoals eerder uitgelegd, worden hier gehele getallen gebruikt om FFT uit te voeren. Int in Arduino is een 16-bits getal en kan waarden bevatten van -32768 tot 32768. wanneer de waarde van deze int dit bereik overschrijdt, veroorzaakt dit het probleem. om dit probleem te elimineren na ooit niveauberekening. als een van de waarden 15000 overschrijdt, worden volledige arrays gedeeld door 100. Dit voorkomt dat de int overloopt.

2. Amplitudeberekening: om de amplitude te berekenen, moeten het reële en imaginaire deel worden gekwadrateerd en de vierkantswortel van de som. kwadrateren en de vierkantswortel van de functie kost tijd. om het proces sneller te maken, zal deze code eenvoudig enkele van de grootheden van echte en imaginaire delen doen. Dit is zeker minder nauwkeurig en kan in sommige gevallen tot de verkeerde conclusie leiden. u kunt ervoor kiezen om terug te keren naar de normale methode voor het berekenen van de grootte, maar het zal meer tijd kosten en u moet ook een regeling treffen om deze getallen op te slaan.

3. Deze code heeft geen module voor meervoudige piekdetectie. Het kiest gewoon de waarde met maximale amplitude (exclusief het eerste getal dat DC-offset is). Als je meerdere pieken nodig hebt, kun je de EasyFFT-code raadplegen en hier de vereiste wijzigingen aanbrengen. In dat geval moet een array/variabele ook als globale variabele worden gedeclareerd.

4. De functie bevat de volgende regel:

unsigned int Pow2[13]={1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

het declareren van de bovenstaande variabelen als een globale variabele (plakken aan het begin van de code) zal bij elke uitvoering ergens 1 milliseconde tijd besparen.

5. In tegenstelling tot de EasyFFT-functie, waar de top 5 pieken werden opgeslagen in de vooraf gedefinieerde array. Deze functie retourneert een float-waarde. deze waarde vertegenwoordigt de frequentie met maximale amplitude in Hz. Dus de weergave van code ziet er ongeveer zo uit.

float f= Q_FFT(data, 256, 100);

6. Piekdetectie: zodra een frequentie met maximale amplitude is gevonden, gebruikt deze functie een frequentieamplitude net ervoor en erna om de nauwkeurige resultaten te berekenen. De amplitude die in deze berekening wordt gebruikt, is ook de som van de modulus (niet de vierkantswortel van de kwadratensom)

als Fn de frequentie met maximale amplitude is, kan de frequentie worden berekend met de onderstaande formule.

Werkelijke F= (A n-1 *Fn-1 + An-1 *Fn-1 + An-1 *Fn-1) / (An-1+An+An+1)

waarbij An de amplitude van n de frequentie is en Fn-1 de frequentiewaarde is.

Stap 3: Resultaten:

Resultaten
Resultaten
Resultaten
Resultaten

De oplostijd wordt weergegeven in de bovenstaande afbeeldingsvergelijking met EasyFFT. Snelheid ervan getoond met de vergelijking.

Voor voorbeeldgegevens met 3 sinusoïdale golven met verschillende frequenties wordt getoond. Het resultaat van QuickFFT wordt vergeleken met Scilab-uitvoer. Zoals we in de afbeelding kunnen zien, komen 3 pieken met maximale amplitude overeen met de Scilab-uitvoer. De uitvoer bevat echter veel ruis, wat voor sommige toepassingen misleidend kan zijn. Het is dus aan te raden om de code goed te controleren voordat u deze op uw aanvraag toepast.

Ik hoop dat je deze code nuttig vond voor je project. In het geval van een vraag of suggestie, gelieve commentaar te geven.

Aanbevolen: