Turinys:

„EasyFFT“: greita Furjė transformacija (FFT), skirta „Arduino“: 6 žingsniai
„EasyFFT“: greita Furjė transformacija (FFT), skirta „Arduino“: 6 žingsniai

Video: „EasyFFT“: greita Furjė transformacija (FFT), skirta „Arduino“: 6 žingsniai

Video: „EasyFFT“: greita Furjė transformacija (FFT), skirta „Arduino“: 6 žingsniai
Video: QuickFFT: High Speed FFT for Arduino 2024, Lapkritis
Anonim
Image
Image

Dažnio matavimas iš užfiksuoto signalo gali būti sunki užduotis, ypač naudojant „Arduino“, nes jis turi mažesnę skaičiavimo galią. Yra metodų, kaip užfiksuoti nulinį kirtimą, kai dažnis fiksuojamas patikrinus, kiek kartų signalas per nustatytą laiką kerta nulines linijas. Toks metodas gali neveikti, kai signalas yra įvairių dažnių derinys.

Tai kažkaip sunku koduoti, jei nesate iš tokios aplinkos. Tačiau būdamas meistras šis kodas gali būti labai naudingas įvairiems projektams, susijusiems su muzika, signalų analize. Šio projekto motyvas buvo parengti kodą, kurį būtų lengva įdiegti „Arduino“, nesigilinant į jo foną.

Šis projektas nepaaiškina FFT veikimo, bet paaiškina FFT funkcijos taikymą. Tas pats procesas taip pat paaiškinamas pridėtame vaizdo įraše.

Jei jus domina tik kodo taikymas, o ne jo paaiškinimas. Galite pereiti tiesiai prie 3 veiksmo.

1 žingsnis: įvadas į dažnio transformaciją

Įvadas į dažnio transformaciją
Įvadas į dažnio transformaciją
Įvadas į dažnio transformaciją
Įvadas į dažnio transformaciją

Bet kokį signalą gali sudaryti įvairių sinusoidinių bangų derinys. Taigi bet koks laiko signalas taip pat gali būti rodomas kaip įvairių amplitudžių įvairių sinusų derinys.

Bandžiau paaiškinti DFT (diskrečio Furjė transformacijos) veikimą viename iš ankstesnių nurodymų (https://www.instructables.com/id/Arduino-Frequency…). Šie metodai yra labai lėti bet kuriai realaus laiko programai. dėl to jis beveik nenaudingas.

Paveikslėlyje rodomas signalas, sudarytas iš dviejų dažnių f2 ir f5. Šis signalas padauginamas iš bandomųjų sinusinių bangų, kurių vertės yra nuo f1 iki f5.

Matematiškai galima parodyti, kad dviejų skirtingų dažnių harmoninių duomenų rinkinio daugybos suma yra lygi nuliui (didesnis duomenų skaičius gali lemti tešlos rezultatą). Mūsų atveju, jei šie du daugybos dažniai turi tą patį (arba labai artimą) dažnį, dauginimo suma yra ne nulinis skaičius.

Taigi, jei mūsų signalas padauginamas iš f1, daugybos suma bus lygi nuliui (beveik nulis realiam pritaikymui). panašiai yra f3, f4. Tačiau vertės atveju f2 ir f5 išvestis nebus lygi nuliui, bet žymiai didesnė už likusias vertes.

Čia signalas išbandomas 5 dažniais, todėl signalą reikia padauginti iš penkių dažnių. Toks intensyvus skaičiavimas užtrunka ilgiau. Matematiškai parodyta, kad N mėginių skaičiui reikia N*N kompleksinio daugybos.

2 žingsnis: greita Furjė transformacija

Norėdami greičiau apskaičiuoti DFT, FFT algoritmą sukūrė Jamesas Cooley ir Johnas Tukey. Šis algoritmas taip pat laikomas vienu iš svarbiausių XX a. Jis padalija signalą į nelyginę ir lyginę seką, todėl reikiami skaičiavimai yra mažesni. Naudojant jį, visą reikiamą kompleksinį dauginimą galima sumažinti iki NlogN. kas yra reikšmingas pagerėjimas.

Galite išsamiau suprasti FFT matematiką:

1.

2.

3.

4.

3 žingsnis: kodo paaiškinimas

1. Greitas sinusas ir kosinusas:

Skaičiavimas FFT kelis kartus įvertina įvairių sinusų ir kosinusų reikšmes. Integruota „Arduino“funkcija nėra pakankamai greita ir reikalauja daug laiko, kol pateikiama reikiama vertė. Dėl to kodas žymiai sulėtėja (64 pavyzdžių laikas padvigubėja). Norėdami išspręsti šią problemą, sinuso vertė nuo 0 iki 90 laipsnių yra saugoma kaip 255. Kartu tai padarius, nebereikės naudoti skaičiaus saugojimo kaip plūdės, ir mes galime jį išsaugoti kaip baitą, kuris užima 1/4 vietos „Arduino“. Sine_data turi būti įklijuotas kodo viršuje, kad būtų paskelbtas kaip visuotinis kintamasis.

Be sine_data, masyvas, vadinamas f_peaks , paskelbtas pasauliniu kintamuoju. Po kiekvieno FFT funkcijos paleidimo šis masyvas atnaujinamas. Kur f_peaks [0] yra dominuojantis dažnis ir tolesnės vertės mažėjančia tvarka.

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

Turėdami sinuso vertę nuo 0 iki 90 laipsnių, galima apskaičiuoti bet kokią sinuso ar kosinuso vertę. Žemiau veikia pirmasis skaičiaus turas iki nulio po kablelio ir grąžinama iš saugomų duomenų vertė. šiam metodui reikia tik vieno plūduriuojančio padalijimo. Tai galima dar labiau sumažinti tiesiogiai įrašant sinusines reikšmes (ne 255 kartotines). bet tai suvalgo didelę atmintį „Arduino“.

Naudojant aukščiau aprašytą procedūrą, sumažėja tikslumas, tačiau padidėja greitis. Už 64 taškus tai suteikia 8 ms pranašumą, o už 128 taškus - 20 ms.

4 žingsnis: kodo paaiškinimas: FFT funkcija

FFT galima atlikti tik tada, kai imties dydis yra 2, 4, 8, 16, 32, 64 ir pan. jei reikšmė nėra 2^n, tada ji užims apatinę vertės pusę. Pavyzdžiui, jei pasirenkame 70 imties dydį, tai bus atsižvelgiama tik į pirmuosius 64 mėginius ir praleidžiama poilsio dalis.

Visada rekomenduojama, kad imties dydis būtų 2^n. kuris gali būti:

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

Du plūdės out_r ir out_im užims daug atminties. „Arduino nano“neveiks, kai mėginiai yra didesni nei 128 (o kai kuriais atvejais - 128), nes trūksta atminties.

nepasirašyti int duomenys [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 ++) // lygių apskaičiavimas {if (duomenys <= a) {o = i;}} int in_ps [duomenys [o] = {}; // sekos sekos įvestis float out_r [duomenys [o] = {}; // tikroji transformacijos dalis float out_im [duomenys [o] = {}; // įsivaizduojama transformacijos dalis

Tolesnis srautas yra toks:

1. Kodas sukuria šiek tiek atvirkštinę nurodyto dydžio imties tvarką (informacija apie bitų keitimą nuorodose: 2 veiksmas)

2. Įvesties duomenys užsakomi pagal sugeneruotą užsakymą, 3. Atliktas FFT

4. Apskaičiuoto kompleksinio skaičiaus amplitudė, 5. Didžiausios dalys aptinkamos ir išdėstomos mažėjančia tvarka

6. rezultatus galima pasiekti iš f_peaks.

[norint pasiekti kitus duomenis (išskyrus didžiausią dažnį), kodas turėtų būti pakeistas, kad vietinį kintamąjį būtų galima nukopijuoti į tam tikrą iš anksto nustatytą visuotinį kintamąjį]

5 žingsnis: išbandykite kodą

Kodo testavimas
Kodo testavimas
Kodo testavimas
Kodo testavimas

Kaip įvestis pateikiama pavyzdinė trikampio banga. šios bangos mėginių ėmimo dažnis yra 10 Hz, o pats bangos dažnis - 1,25 Hz.

Kaip galima parodyti iš neapdorotos produkcijos, vertė sutampa su „Scilab“apskaičiuotu FFT. tačiau šios vertės nėra visiškai tokios pačios, kaip ir žemo tikslumo, bet greitesnės sinusinės bangos.

Išėjimo dažnių masyvo dažnis yra 1,25 ir 3,75. nebūtina kiekvieną kartą gauti tikslios vertės. paprastai šie skaičiai vadinami dažnio dėžės. todėl išvesties vertė gali būti bet kurioje nurodytų dėžių vietoje.

Greitis:

„Arduino nano“reikia:

16 taškų: 4ms32 taškai: 10ms 64 taškai: 26ms 128 taškai: 53ms

6 žingsnis: Išvada

Šis FFT kodas gali būti naudojamas realaus laiko programose. Skaičiavimui atlikti reikia apie 30 ms. Tačiau jo skiriamąją gebą riboja keletas mėginių. Pavyzdžio skaičių riboja „Arduino“atmintis. Naudojant „Arduino Mega“ar kitą didesnio našumo plokštės tikslumą galima pagerinti.

jei turite klausimų, pasiūlymų ar pataisymų, nedvejodami komentuokite.

Atnaujinti (2/5/21)

Atnaujinimai: // ----------------------------- FFT funkcija --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

N duomenų tipas pakeistas į sveiką skaičių (esamas baitas), kad būtų palaikomas> 255 imties dydis. Jei imties dydis yra <= 128, reikia naudoti baitų duomenų tipą.

Rekomenduojamas: