Kazalo:

EasyFFT: Hitra Fourierjeva transformacija (FFT) za Arduino: 6 korakov
EasyFFT: Hitra Fourierjeva transformacija (FFT) za Arduino: 6 korakov

Video: EasyFFT: Hitra Fourierjeva transformacija (FFT) za Arduino: 6 korakov

Video: EasyFFT: Hitra Fourierjeva transformacija (FFT) za Arduino: 6 korakov
Video: Тренинг по обучению основам дебатного искусства в форматах игр АПФ и БПФ 2024, September
Anonim
Image
Image

Merjenje frekvence iz zajetega signala je lahko težka naloga, zlasti na Arduinu, saj ima manjšo računsko moč. Na voljo so načini za zajemanje ničelnega prehoda, pri katerem se frekvenca zajame s preverjanjem, kolikokrat signal prečka ničelne črte v danem času. Ta metoda morda ne bo delovala, če je signal kombinacija različnih frekvenc.

To je nekako težko kodirati, če niste iz takega ozadja. Toda kot odpravljalka kode je lahko zelo koristna za različne projekte, povezane z glasbo, analizo signalov. Motiv tega projekta je bil pripraviti kodo, ki je enostavna za izvedbo na Arduinu, ne da bi pri tem prišla v ozadje.

Ta projekt ne razlaga delovanja FFT, ampak razlaga uporabo funkcije FFT. Enak postopek je razložen tudi v priloženem videoposnetku.

Če vas zanima samo uporaba kode in ne razlaga le -te. Lahko preskočite neposredno na korak 3.

1. korak: Uvod v frekvenčno transformacijo

Uvod v frekvenčno transformacijo
Uvod v frekvenčno transformacijo
Uvod v frekvenčno transformacijo
Uvod v frekvenčno transformacijo

Vsak signal je lahko sestavljen iz kombinacije različnih sinusnih valov. Tako se lahko vsak časovno odvisen signal prikaže tudi kot kombinacija različnih sinusov različnih amplitud.

Poskušal sem razložiti delovanje DFT (diskretna Fourierjeva pretvorba) v enem od prejšnjih navodil (https://www.instructables.com/id/Arduino-Frequency…). Te metode so zelo počasne za vsako aplikacijo v realnem času. zaradi česar je skoraj neuporaben.

Na sliki je prikazan signal, ki je kombinacija dveh frekvenc f2 in f5. Ta signal se pomnoži s preskusnimi sinusnimi valovi vrednosti od f1 do f5.

Matematično je mogoče prikazati, da -povzetek množenja dveh harmoničnih nizov podatkov z različno frekvenco teži k nič (večje število podatkov lahko privede do testa). V našem primeru, če imata ti dve frekvenci množenja enako (ali zelo blizu) frekvenco, je vsota množenja različno od nič.

Torej, če naš signal pomnožimo s f1, bo seštevek množenja nič (blizu nič za resnično uporabo). podobno velja za f3, f4. Vendar za vrednost izhod f2 in f5 ne bo nič, ampak bistveno višji od preostalih vrednosti.

Tu se signal preskusi s 5 frekvencami, zato ga je treba pomnožiti s petimi frekvencami. Tako intenziven izračun traja dlje. Matematično je prikazano, da je za N število vzorcev potrebno kompleksno množenje N*N.

2. korak: Hitra Fourierjeva transformacija

Za hitrejši izračun DFT sta algoritem FFT razvila James Cooley in John Tukey. Ta algoritem velja tudi za enega najpomembnejših algoritmov 20. stoletja. Signal razdeli na lih in sodo zaporeden del, zaradi česar je število zahtevanih izračunov manjše. Z njegovo uporabo se lahko skupno zahtevano kompleksno množenje zmanjša na NlogN. kar je pomemben napredek.

Za podrobnejše razumevanje matematike, ki stoji za FFT, se lahko sklicujete na spodnje reference, ki sem jih omenil pri pisanju kode:

1.

2.

3.

4.

3. korak: Razlaga kode

1. Hitri sinus in kosinus:

Izračun FFT večkrat vzame vrednost različnih sinusov in kosinusov. Vgrajena funkcija Arduina ni dovolj hitra in potrebuje kar nekaj časa, da zagotovi zahtevano vrednost. Zaradi tega se koda bistveno upočasni (podvoji čas za 64 vzorcev). Če želite odpraviti to težavo, je vrednost sinusov za 0 do 90 stopinj shranjena kot večkratnik 255. S tem boste odpravili potrebo po shranjevanju številk kot float in jih lahko shranimo kot bajt, ki zavzame 1/4 prostora na Arduinu. Sine_data je treba prilepiti na vrh kode, da jo razglasi za globalno spremenljivko.

Poleg sine_data je polje, imenovano f_peaks , deklarirano kot globalna spremenljivka. Po vsakem zagonu funkcije FFT se ta niz posodobi. Kjer je f_peaks [0] najbolj prevladujoča frekvenca in nadaljnje vrednosti v padajočem vrstnem redu.

bajt 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];

Ker imamo shranjeno vrednost sinusa za 0 do 90 stopinj, lahko izračunamo katero koli vrednost sinusa ali kosinusa. Spodaj deluje prvi krog števila na decimalno vejico nič in vrnjena vrednost iz shranjenih podatkov. ta metoda potrebuje le eno plavajočo delitev. To lahko dodatno zmanjšamo z neposrednim shranjevanjem vrednosti sinusov (ne 255 večkratnikov). vendar to na Arduinu poje veliko spomina.

Z uporabo zgornjega postopka se zmanjša natančnost, vendar izboljša hitrost. Za 64 točk daje prednost 8 ms, za 128 točk pa prednost 20 ms.

4. korak: Pojasnilo kode: funkcija FFT

FFT je mogoče izvesti samo za velikost vzorca 2, 4, 8, 16, 32, 64 itd. če vrednost ni 2^n, potem vzame spodnjo stran vrednosti. Na primer, če izberemo velikost vzorca 70, bo upošteval le prvih 64 vzorcev in izpustil ostalo.

Vedno je priporočljivo imeti vzorec 2^n. kar je lahko:

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

Dva plavajoča out_r in out_im bosta zajela veliko pomnilnika. ker Arduino nano ne bo deloval za vzorce, večje od 128 (in v nekaterih primerih 128) zaradi pomanjkanja razpoložljivega pomnilnika.

podpisani int podatki [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 ++) // izračun ravni {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // vnos za zaporedje float out_r [data [o] = {}; // dejanski del transformacije float out_im [data [o] = {}; // imaginarni del preoblikovanja

Nadaljnji tok je naslednji:

1. Koda ustvari malo obrnjen vrstni red za dano velikost vzorca (podrobnosti o obrnitvi bitov na referencah: korak 2)

2. Vhodni podatki, razvrščeni po generiranem naročilu, 3. Izveden FFT

4. Izračunana amplituda kompleksnega števila, 5. Vrhovi se zaznajo in razvrstijo po padajočem vrstnem redu

6. Do rezultatov lahko dostopate iz f_peaks.

[za dostop do drugih podatkov (razen najvišje frekvence) je treba kodo spremeniti, tako da je mogoče lokalno spremenljivko kopirati v neko vnaprej določeno globalno spremenljivko]

5. korak: Preizkusite kodo

Testiranje kode
Testiranje kode
Testiranje kode
Testiranje kode

Vhodni vzorec je trikotni val. frekvenca vzorčenja tega vala je 10 Hz, frekvenca samega vala pa 1,25 Hz.

Kot je razvidno iz surove proizvodnje, se vrednost ujema s FFT, ki ga izračuna Scilab. vendar te vrednosti niso povsem enake kot pri nas z nizko natančnostjo, ampak hitrejši sinusni val.

V izhodni frekvenčni matriki sta frekvenci 1,25 in 3,75. ni treba vsakič dobiti natančne vrednosti. Običajno se te številke imenujejo frekvenčni sprejemniki. zato je lahko izhodna vrednost kjer koli v določenih posodah.

Hitrost:

za Arduino nano je potrebno:

16 točk: 4 ms32 točk: 10 ms 64 točk: 26 ms 128 točk: 53 ms

6. korak: Zaključek

To kodo FFT je mogoče uporabiti v aplikacijah v realnem času. Ker za dokončanje izračuna traja približno 30 ms. Vendar je njegova ločljivost omejena s številnimi vzorci. Število vzorcev je omejeno s pomnilnikom Arduino. Z uporabo Arduino Mega ali katere koli druge zmogljivosti plošče lahko izboljšate natančnost.

če imate kakršna koli vprašanja, predloge ali popravke, komentirajte.

Posodobitev (2/5/21)

Posodobitve: // ----------------------------- Funkcija FFT --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

Podatkovni tip N se je spremenil v Integer (obstoječi bajt), da podpira> 255 velikosti vzorca. Če je velikost vzorca <= 128, je treba uporabiti podatkovni tip bajtov.

Priporočena: