Satura rādītājs:

EasyFFT: ātra Furjē transformācija (FFT) Arduino: 6 soļi
EasyFFT: ātra Furjē transformācija (FFT) Arduino: 6 soļi

Video: EasyFFT: ātra Furjē transformācija (FFT) Arduino: 6 soļi

Video: EasyFFT: ātra Furjē transformācija (FFT) Arduino: 6 soļi
Video: Анализатор THD для бедняков измеряет THD мостового синусоидального генератора Wien 2024, Septembris
Anonim
Image
Image

Frekvences mērīšana no uztvertā signāla var būt grūts uzdevums, īpaši Arduino, jo tam ir zemāka skaitļošanas jauda. Ir pieejamas metodes nulles šķērsošanas uztveršanai, kad frekvenci uztver, pārbaudot, cik reizes signāls noteiktā laikā šķērso nulles līnijas. Šāda metode var nedarboties, ja signāls ir dažādu frekvenču kombinācija.

To kaut kā ir grūti kodēt, ja neesat no šādas fona. Bet, būdams gudrinieks, šis kods var būt ļoti noderīgs dažādiem projektiem, kas saistīti ar mūziku, signālu analīzi. Šī projekta motīvs bija sagatavot kodu, kuru ir viegli ieviest Arduino, nenonākot tā fonā.

Šis projekts nepaskaidro FFT darbību, bet izskaidro FFT funkcijas pielietojumu. Tas pats process ir izskaidrots arī pievienotajā video.

Ja jūs interesē tikai koda pielietošana, nevis tā skaidrojums. Jūs varat pāriet tieši uz 3. darbību.

1. darbība. Ievads frekvenču pārveidē

Ievads frekvenču pārveidē
Ievads frekvenču pārveidē
Ievads frekvenču pārveidē
Ievads frekvenču pārveidē

Jebkurš signāls var sastāvēt no dažādu sinusoidālu viļņu kombinācijas. Tātad jebkuru uz laiku balstītu signālu var parādīt arī kā dažādu amplitūdas dažādu sinusu kombināciju.

Es mēģināju izskaidrot DFT (diskrētās Furjē transformācijas) darbību vienā no iepriekšējiem norādījumiem (https://www.instructables.com/id/Arduino-Frequency…). Šīs metodes ir ārkārtīgi lēnas jebkurai reāllaika lietojumprogrammai. kas padara to gandrīz bezjēdzīgu.

Attēlā tiek parādīts signāls, kas ir divu frekvenču f2 un f5 kombinācija. Šo signālu reizina ar testa sinusa viļņiem, kuru vērtības ir no f1 līdz f5.

Matemātiski var pierādīt, ka divu harmonisku datu kopu, kurām ir atšķirīga frekvence, reizināšanas summai ir tendence uz nulli (lielāks datu skaits var izraisīt mīklas rezultātu). Mūsu gadījumā, ja šīm divām reizināšanas frekvencēm ir vienāda (vai ļoti tuva) frekvence, reizināšanas summa ir skaitlis, kas nav nulle.

Tātad, ja mūsu signāls tiek reizināts ar f1, reizināšanas summa būs nulle (reālai lietošanai gandrīz līdz nullei). līdzīgi ir f3, f4. Tomēr attiecībā uz vērtību f2 un f5 izlaide nebūs nulle, bet ievērojami augstāka nekā pārējās vērtības.

Šeit signāls tiek pārbaudīts ar 5 frekvencēm, tāpēc signāls jāreizina ar piecām frekvencēm. Šāds intensīvs aprēķins prasa ilgāku laiku. Matemātiski ir parādīts, ka N paraugu skaitam ir nepieciešama N*N kompleksa reizināšana.

2. solis: ātra Furjē transformācija

Lai padarītu DFT aprēķināšanu ātrāku, FFT algoritmu izstrādāja Džeimss Kūlijs un Džons Tukijs. Šis algoritms tiek uzskatīts arī par vienu no vissvarīgākajiem 20. gadsimta algoritmiem. Tas sadala signālu nepāra un vienmērīgā secībā, kas samazina vajadzīgo aprēķinu skaitu. Izmantojot to, kopējo nepieciešamo kompleksu reizināšanu var samazināt līdz NlogN. kas ir būtisks uzlabojums.

Lai detalizēti izprastu FFT matemātiku, varat atsaukties uz atsaucēm, uz kurām es atsaucos, rakstot kodu:

1.

2.

3.

4.

3. darbība: koda skaidrojums

1. Ātrs sinuss un kosinuss:

Aprēķins FFT vairākas reizes ņem dažādu sinusa un kosinusa vērtību. Arduino iebūvētā funkcija nav pietiekami ātra, un vajadzīgās vērtības nodrošināšana prasa daudz laika. Kas padara kodu ievērojami lēnāku (dubultojas laiks 64 paraugiem). Lai novērstu šo problēmu, sinusa vērtība no 0 līdz 90 grādiem tiek saglabāta kā 255. reizinājums. Šādi rīkojoties, vairs nebūs nepieciešams izmantot skaitļus kā pludiņu, un mēs varam to saglabāt kā baitu, kas Arduino aizņem 1/4 vietu. Sine_data ir jāielīmē koda augšdaļā, lai to pasludinātu par globālu mainīgo.

Papildus sine_data masīvs ar nosaukumu f_peaks tika deklarēts kā globāls mainīgais. Pēc katras FFT funkcijas palaišanas šis masīvs tiek atjaunināts. Kur f_runas [0] ir dominējošā frekvence un turpmākās vērtības dilstošā secībā.

baits 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}; pludiņš f_peaks [5];

Tā kā esam saglabājuši sinusa vērtību no 0 līdz 90 grādiem, var aprēķināt jebkuru sinusa vai kosinusa vērtību. Zemāk darbojas skaitļa pirmā kārta līdz nullei aiz komata un atgriež vērtību no saglabātajiem datiem. šai metodei nepieciešams tikai viens peldošs sadalījums. To var vēl vairāk samazināt, tieši saglabājot sinusa vērtības (nevis 255 vairākas). bet tas ēd augstu atmiņu Arduino.

Iepriekš minētās procedūras izmantošana samazina precizitāti, bet uzlabo ātrumu. Par 64 punktiem tas dod 8 ms priekšrocības un par 128 punktiem - 20 ms.

4. solis: koda skaidrojums: FFT funkcija

FFT var veikt tikai parauga lielumam 2, 4, 8, 16, 32, 64 un tā tālāk. ja vērtība nav 2^n, tad tā aizņems vērtības apakšējo pusi. Piemēram, ja mēs izvēlamies izlases lielumu 70, tas ņems vērā tikai pirmos 64 paraugus un izlaidīs atpūtu.

Vienmēr ieteicams, lai izlases lielums būtu 2^n. kas var būt:

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

Divi pludiņi out_r un out_im aizņems lielu atmiņas apjomu. Arduino nano nedarbosies paraugiem, kas ir lielāki par 128 (un dažos gadījumos 128), jo trūkst atmiņas.

neparakstīti int dati [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

int a, c1, f, o, x; a = N; par (int i = 0; i <12; i ++) // līmeņu aprēķināšanu {if (dati <= a) {o = i;}} int in_ps [dati [o] = {}; // ievades secība float out_r [dati [o] = {}; // reālā transformācijas daļa float out_im [dati [o] = {}; // iztēles daļa transformācijas

Turpmākā plūsma ir šāda:

1. Kods ģenerē mazliet apgrieztu secību noteiktam izlases lielumam (informācija par bitu apgriešanu atsaucēs: 2. darbība)

2. Ievades dati sakārtoti atbilstoši ģenerētajam pasūtījumam, 3. Veikta FFT

4. Aprēķinātā kompleksa skaitļa amplitūda, 5. Pīķi tiek konstatēti un sakārtoti dilstošā secībā

6. rezultātiem var piekļūt no f_peaks.

[lai piekļūtu citiem datiem (izņemot maksimālo frekvenci), kods ir jāmaina, lai vietējo mainīgo varētu nokopēt uz kādu iepriekš noteiktu globālo mainīgo]

5. darbība: koda pārbaude

Koda pārbaude
Koda pārbaude
Koda pārbaude
Koda pārbaude

Trīsstūra viļņa paraugs tiek ievadīts kā ievade. šim viļņam paraugu ņemšanas frekvence ir 10 Hz, un pati viļņa frekvence ir 1,25 Hz.

Kā redzams no neapstrādātas produkcijas, vērtība atbilst Scilab aprēķinātajai FFT. tomēr šīs vērtības nav tieši tādas pašas kā zemā precizitāte, bet ātrāks sinusoidālais vilnis.

Izejas frekvenču masīvā frekvence ir 1,25 un 3,75. nav nepieciešams katru reizi iegūt precīzu vērtību. Parasti šos skaitļus sauc par frekvenču tvertnēm. tāpēc izvades vērtība var būt jebkur noteiktās tvertnēs.

Ātrums:

Arduino nano nepieciešams:

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

6. darbība. Secinājums

Šo FFT kodu var izmantot reāllaika lietojumprogrammās. Tā kā aprēķina pabeigšana prasa apmēram 30 ms. Tomēr tā izšķirtspēju ierobežo vairāki paraugi. Parauga skaitu ierobežo Arduino atmiņa. Izmantojot Arduino Mega vai citu augstākas veiktspējas dēļa precizitāti, to var uzlabot.

ja jums ir kādi jautājumi, ieteikumi vai labojumi, lūdzu, komentējiet.

Atjauninājums (21.05.21.)

Atjauninājumi: // ----------------------------- FFT funkcija --------------- ------------------------------- // float FFT (int in , int N, float Frequency)

N datu tips ir mainīts uz veselu skaitli (esošs baits), lai atbalstītu> 255 izlases lielumu. Ja izlases lielums ir <= 128, jāizmanto baitu datu tips.

Ieteicams: