Obsah:

EasyFFT: Rýchla Fourierova transformácia (FFT) pre Arduino: 6 krokov
EasyFFT: Rýchla Fourierova transformácia (FFT) pre Arduino: 6 krokov

Video: EasyFFT: Rýchla Fourierova transformácia (FFT) pre Arduino: 6 krokov

Video: EasyFFT: Rýchla Fourierova transformácia (FFT) pre Arduino: 6 krokov
Video: Fourierova transformácia na osciloskope 2024, Septembra
Anonim
Image
Image

Meranie frekvencie zo zachyteného signálu môže byť náročná úloha, najmä na Arduine, pretože má nižší výpočtový výkon. K dispozícii sú metódy na zachytenie prechodu nulou, kde je frekvencia zachytená skontrolovaním, koľkokrát signál prekročí nulové čiary v danom čase. Takáto metóda nemusí fungovať, ak je signál kombináciou rôznych frekvencií.

To sa nejako ťažko kóduje, ak nie ste z takého pozadia. Ale keďže je to drotár, tento kód môže byť veľmi užitočný pre rôzne projekty súvisiace s hudbou a analýzou signálu. Motívom tohto projektu bolo pripraviť kód, ktorý je možné ľahko implementovať na Arduine bez toho, aby ste sa dostali do pozadia.

Tento projekt nevysvetľuje fungovanie FFT, ale vysvetľuje aplikáciu funkcie FFT. Rovnaký postup je vysvetlený aj v priloženom videu.

Ak vás zaujíma iba aplikácia kódu, a nie jeho vysvetlenie. Môžete priamo prejsť na krok č. 3.

Krok 1: Úvod do frekvenčnej transformácie

Úvod do frekvenčnej transformácie
Úvod do frekvenčnej transformácie
Úvod do frekvenčnej transformácie
Úvod do frekvenčnej transformácie

Každý signál môže byť zložený z kombinácie rôznych sínusových vĺn. Akýkoľvek časový signál môže byť teda tiež zobrazený ako kombinácia rôznych sínusov rôznych amplitúd.

Pokúsil som sa vysvetliť fungovanie DFT (diskrétna Fourierova transformácia) v jednom z predchádzajúcich inštrukcií (https://www.instructables.com/id/Arduino-Frequency…). Tieto metódy sú extrémne pomalé pre každú aplikáciu v reálnom čase. čím je takmer zbytočný.

Na obrázku je znázornený signál, ktorý je kombináciou dvoch frekvencií f2 a f5. Tento signál je vynásobený testovacími sínusovými vlnami hodnôt f1 až f5.

Matematicky je možné ukázať, že -súhrn násobenia dvoch harmonických súborov údajov s rôznou frekvenciou má tendenciu k nule (vyšší počet údajov môže viesť k výsledku cesta). V našom prípade, ak má tieto dve násobiace frekvencie rovnakú (alebo veľmi blízku) frekvenciu, súčet násobenia je nenulové číslo.

Ak je teda náš signál vynásobený f1, súčet násobenia bude nulový (pre skutočnú aplikáciu blízky nule). podobné je to pre f3, f4. Avšak pre hodnotu nebude výstup f2 a f5 nulový, ale výrazne vyšší ako ostatné hodnoty.

Tu je signál testovaný s 5 frekvenciami, takže signál je potrebné vynásobiť piatimi frekvenciami. Taký intenzívny výpočet trvá dlhšie. Matematicky sa ukazuje, že na N počet vzoriek je potrebné N*N komplexné násobenie.

Krok 2: Rýchla Fourierova transformácia

James Cooley a John Tukey vyvinuli algoritmus FFT na urýchlenie výpočtu DFT. Tento algoritmus je tiež považovaný za jeden z najdôležitejších algoritmov 20. storočia. Rozdeľuje signál na nepárnu a párnu sekvenčnú časť, čím sa znižuje počet požadovaných výpočtov. Jeho použitím je možné celkové požadované komplexné násobenie znížiť na NlogN. čo je výrazné zlepšenie.

Na podrobné porozumenie matematiky za FFT môžete použiť nižšie uvedené odkazy, na ktoré som odkazoval pri písaní kódu:

1.

2.

3.

4.

Krok 3: Vysvetlenie kódu

1. Rýchly sínus a kosínus:

Výpočet FFT preberá hodnotu rôznych sínusov a kosínusov viackrát. Vstavaná funkcia Arduina nie je dostatočne rýchla a na poskytnutie požadovanej hodnoty potrebuje veľa času. Vďaka tomu je kód výrazne pomalší (zdvojnásobí čas pre 64 vzoriek). Aby sa zabránilo tomuto problému, hodnota sínusu pre 0 až 90 stupňov je uložená ako násobok 255. Tým sa eliminuje potreba používať ukladanie čísel ako float a môžeme ho uložiť ako bajt, ktorý zaberá 1/4 miesto na Arduine. Sine_data musí byť vložený navrch kódu, aby bol deklarovaný ako globálna premenná.

Okrem sine_data je pole s názvom f_peaks vyhlásené za globálnu premennú. Po každom spustení funkcie FFT sa toto pole aktualizuje. Kde f_peaks [0] je najdominantnejšia frekvencia a ďalšie hodnoty v zostupnom poradí.

byte sine_data [91] = {0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255}; float f_peaks [5];

Pretože máme uloženú hodnotu sínusu pre 0 až 90 stupňov, je možné vypočítať akúkoľvek hodnotu sínusu alebo kosínu. Nasleduje prvé kolo čísla s nulovou desatinnou čiarkou a návratová hodnota z uložených údajov. táto metóda potrebuje iba jedno plávajúce delenie. Toto môže byť ďalej znížené priamym ukladaním hodnôt sínusu (nie 255 násobkov). ale to zaberá vysokú pamäť na Arduine.

Použitie vyššie uvedeného postupu znižuje presnosť, ale zvyšuje rýchlosť. Pri 64 bodoch dáva výhodu 8 ms a pri 128 bodoch dáva výhodu 20 ms.

Krok 4: Vysvetlenie kódu: Funkcia FFT

FFT je možné vykonať iba pre veľkosť vzorky 2, 4, 8, 16, 32, 64 a tak ďalej. ak hodnota nie je 2^n, potom bude brať spodnú stranu hodnoty. Ak napríklad zvolíme veľkosť vzorky 70, bude brať do úvahy iba prvých 64 vzoriek a vynechá zvyšok.

Vždy sa odporúča mať veľkosť vzorky 2^n. čo môže byť:

2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …

Dva plaváky out_r a out_im zaberú veľké množstvo pamäte. pre Arduino nano nebude fungovať pre vzorky vyššie ako 128 (a v niektorých prípadoch 128) kvôli nedostatku dostupnej pamäte.

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

int a, c1, f, o, x; a = N; for (int i = 0; i <12; i ++) // výpočet úrovní {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // vstup pre sekvenovanie float out_r [data [o] = {}; // skutočná časť transformácie float out_im [data [o] = {}; // imaginárna časť transformácie

Ďalší tok je nasledujúci:

1. Kód generuje trochu obrátené poradie pre danú veľkosť vzorky (podrobnosti o bitovom obrátení o referenciách: krok 2)

2. Vstupné údaje zoradené podľa vygenerovanej objednávky, 3. Vykonané FFT

4. Vypočítaná amplitúda komplexného čísla, 5. Piky sú detekované a usporiadané zostupne

6. výsledky sú dostupné z f_peaks.

[na prístup k iným údajom (okrem špičkovej frekvencie) by mal byť kód upravený tak, aby bolo možné lokálnu premennú skopírovať do niektorej preddefinovanej globálnej premennej]

Krok 5: Testovanie kódu

Testovanie kódu
Testovanie kódu
Testovanie kódu
Testovanie kódu

Ako vstup je uvedená vzorová vlna trojuholníka. pre túto vlnu je vzorkovacia frekvencia 10 Hz a samotná frekvencia vlny je 1,25 Hz.

Ako je zrejmé z hrubého výstupu, hodnota sa zhoduje s FFT vypočítaným Scilabom. tieto hodnoty však nie sú úplne rovnaké ako my s nízkou presnosťou, ale rýchlejšie sínusové vlny.

Vo výstupnom frekvenčnom poli je frekvencia poľa 1,25 a 3,75. nie je potrebné zakaždým získať presnú hodnotu. zvyčajne sa tieto čísla nazývajú frekvenčné zásobníky. takže výstupná hodnota môže byť kdekoľvek v rámci špecifikovaných zásobníkov.

Rýchlosť:

pre Arduino nano to trvá:

16 bodov: 4 ms32 bodov: 10 ms 64 bodov: 26 ms 128 bodov: 53 ms

Krok 6: Záver

Tento kód FFT je možné použiť v aplikáciách v reálnom čase. Dokončenie výpočtu trvá približne 30 ms. Jeho rozlíšenie je však obmedzené počtom vzoriek. Počet vzorky je obmedzený pamäťou Arduino. Použitím Arduino Mega alebo iných výkonnejších dosiek je možné zlepšiť presnosť.

ak máte akékoľvek otázky, návrhy alebo opravy, kľudne napíšte.

Aktualizácia (2/5/21)

Aktualizácie: // ----------------------------- Funkcia FFT --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Dátový typ N sa zmenil na Integer (existujúci bajt) tak, aby podporoval veľkosť vzorky> 255. Ak je veľkosť vzorky <= 128, mal by sa použiť typ bajtu.

Odporúča: