Բովանդակություն:

EasyFFT. Արագ Fourier Transform (FFT) Arduino- ի համար. 6 քայլ
EasyFFT. Արագ Fourier Transform (FFT) Arduino- ի համար. 6 քայլ

Video: EasyFFT. Արագ Fourier Transform (FFT) Arduino- ի համար. 6 քայլ

Video: EasyFFT. Արագ Fourier Transform (FFT) Arduino- ի համար. 6 քայլ
Video: EasyFFT: Fast Fourier Transform (FFT) for Arduino 2024, Նոյեմբեր
Anonim
Image
Image

Գրավված ազդանշանից հաճախականության չափումը կարող է բարդ խնդիր լինել, հատկապես Arduino- ում, քանի որ այն ունի ավելի ցածր հաշվարկային հզորություն: Գոյություն ունեն զրոյական հատման ֆիքսման մեթոդներ, որտեղ հաճախականությունը ֆիքսվում է `ստուգելով, թե քանի անգամ է ազդանշանը հատում զրոյական գծեր տվյալ ժամանակահատվածում: Նման մեթոդը կարող է չաշխատել, երբ ազդանշանը տարբեր հաճախականությունների համադրություն է:

Սա ինչ -որ կերպ դժվար է կոդավորել, եթե դուք նման ծագումից չեք: Բայց լինելով կեղծարար, այս կոդը կարող է շատ օգտակար լինել երաժշտության, ազդանշանների վերլուծության հետ կապված տարբեր նախագծերի համար: Այս նախագծի շարժառիթն էր պատրաստել այնպիսի կոդ, որը հեշտ է իրականացնել Arduino- ում ՝ առանց դրա հետին պլան մտնելու:

Այս նախագիծը չի բացատրում FFT- ի աշխատանքը, այլ բացատրում է FFT գործառույթի կիրառումը: Նույն գործընթացը բացատրվում է նաև կից տեսանյութում:

Եթե ձեզ հետաքրքրում է միայն կոդի կիրառումը, այլ ոչ թե դրա բացատրությունը: Դուք կարող եք ուղղակիորեն անցնել թիվ 3 քայլին:

Քայլ 1. Հաճախականության փոխակերպման ներածություն

Հաճախականության փոխակերպման ներածություն
Հաճախականության փոխակերպման ներածություն
Հաճախականության փոխակերպման ներածություն
Հաճախականության փոխակերպման ներածություն

Signalանկացած ազդանշան կարող է կազմված լինել տարբեր սինուսոիդային ալիքների համակցությունից: Այսպիսով, ժամանակի վրա հիմնված ցանկացած ազդանշան կարող է ցուցադրվել նաև որպես տարբեր ամպլիտուդների տարբեր սինուսների համադրություն:

Ես փորձեցի բացատրել DFT- ի (Ֆուրիեի առանձին փոխակերպում) աշխատանքը նախորդ հրահանգներից մեկում (https://www.instructables.com/id/Arduino-Frequency…): Այս մեթոդները չափազանց դանդաղ են իրական ժամանակի ցանկացած ծրագրի համար: ինչը գրեթե անօգուտ է դարձնում:

Պատկերում ցուցադրվում է ազդանշան, որը երկու հաճախականությունների համադրություն է f2 և f5: Այս ազդանշանը բազմապատկվում է f1- ից f5 արժեքների փորձնական սինուս ալիքներով:

Մաթեմատիկորեն կարելի է ցույց տալ, որ տարբեր հաճախականությամբ երկու ներդաշնակ տվյալների հավաքածուի բազմապատկումը ձգտում է զրոյի (տվյալների ավելի մեծ քանակը կարող է հանգեցնել հարվածի արդյունքի): Մեր դեպքում, եթե այս երկու բազմապատկման հաճախականություններն ունեն նույն (կամ շատ մոտ) հաճախականությունը, ապա բազմապատկման գումարը ոչ զրո թիվ է:

Այսպիսով, եթե մեր ազդանշանը բազմապատկվի f1- ով, բազմապատկման գումարը կլինի զրո (իսկական կիրառման դեպքում `զրոյին մոտ): Նմանատիպ դեպք է f3, f4- ի դեպքում: Այնուամենայնիվ, արժեքի համար f2 և f5 ելքերը կլինեն ոչ թե զրո, այլ զգալիորեն ավելի բարձր, քան մնացած արժեքները:

Այստեղ ազդանշանը փորձարկվում է 5 հաճախականությամբ, ուստի ազդանշանը պետք է բազմապատկվի հինգ հաճախականությամբ: Նման ինտենսիվ հաշվարկը ավելի երկար ժամանակ է պահանջում: Մաթեմատիկորեն ցույց է տրվում, որ N թվով նմուշների համար անհրաժեշտ է N*N համալիր բազմապատկում:

Քայլ 2: Արագ Ֆուրիեի փոխակերպում

DFT- ի հաշվարկն ավելի արագ դարձնելու համար FFT ալգորիթմը մշակվել է Jamesեյմս Քուլիի և Johnոն Թուկիի կողմից: Այս ալգորիթմը համարվում է նաև որպես 20 -րդ դարի ամենակարևոր ալգորիթմներից մեկը: Այն ազդանշանը բաժանում է կենտ և զույգ հաջորդական մասի, ինչը նվազեցնում է մի շարք պահանջվող հաշվարկները: Օգտագործելով դրա ընդհանուր պահանջվող բարդ բազմապատկումը կարող է կրճատվել մինչև NlogN: ինչը զգալի բարելավում է:

Ստորև կարող եք հղումներ անել, որոնց ես անդրադարձել եմ ծածկագիրը գրելիս ՝ FFT- ի հիմքում ընկած մաթեմատիկան մանրամասն հասկանալու համար.

1.

2.

3.

4.

Քայլ 3. Կոդի բացատրություն

1. Արագ սինուս և կոսինոս.

Հաշվարկը FFT- ն մի քանի անգամ վերցնում է տարբեր սինուսների և կոսինուսների արժեքը: Arduino- ի ներկառուցված գործառույթը բավականաչափ արագ չէ և բավական ժամանակ է պահանջում պահանջվող արժեքը ապահովելու համար: Ինչը զգալիորեն դանդաղեցնում է ծածկագիրը (կրկնապատկում է ժամանակը 64 նմուշների համար): Այս խնդրին հակազդելու համար 0 -ից 90 աստիճանի համար սինուսի արժեքը պահվում է 255 -ի բազմապատիկ: Դա անելով կվերացնենք թվերը որպես բոց օգտագործելու անհրաժեշտությունը, և մենք կարող ենք այն պահել որպես բայթ, որը զբաղեցնում է Arduino- ի 1/4 -րդ տարածքը: Sine_data - ն պետք է տեղադրվի ծածկագրի վերևում `այն որպես գլոբալ փոփոխական հայտարարելու համար:

Բացի sine_data- ից, f_peaks կոչվող զանգվածը հայտարարված է որպես գլոբալ փոփոխական: FFT գործառույթի յուրաքանչյուր գործարկումից հետո այս զանգվածը թարմացվում է: Որտեղ f_peaks [0] - ը նվազագույն կարգով առավել գերակշռող հաճախականությունն է և հետագա արժեքները:

բայթ 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, 239, 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];

Քանի որ մենք պահպանել ենք սինուսի արժեքը 0 -ից 90 աստիճանի համար, կարող է հաշվարկվել սինուսի կամ կոսինուսի ցանկացած արժեք: Ստորև գործում է թվի առաջին փուլը մինչև զրո տասնորդական կետ և վերադարձված արժեքը պահված տվյալներից: այս մեթոդին անհրաժեշտ է միայն մեկ լողացող բաժանում: Սա կարող է հետագայում կրճատվել ՝ սինուսային արժեքներն ուղղակիորեն պահելով (ոչ թե 255 բազմակի): բայց դա ուտում է բարձր հիշողություն Արդուինոյի վրա:

Վերոնշյալ ընթացակարգի օգտագործումը նվազեցնում է ճշգրտությունը, բայց բարելավում է արագությունը: 64 միավորի դեպքում այն տալիս է 8ms առավելություն և 128 միավորի դեպքում `20ms:

Քայլ 4. Կոդի բացատրություն. FFT գործառույթ

FFT- ն կարող է իրականացվել միայն 2, 4, 8, 16, 32, 64 և այլն ընտրանքի չափի համար: եթե արժեքը 2^n չէ, ապա այն կստանա արժեքի ստորին կողմը: Օրինակ, եթե ընտրենք նմուշի 70 -ի չափը, ապա այն կդիտարկի միայն առաջին 64 նմուշները և բաց կթողնի հանգիստը:

Միշտ խորհուրդ է տրվում ունենալ 2^n նմուշի չափ: որը կարող է լինել.

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

Երկու floats out_r և out_im կպահանջեն մեծ քանակությամբ հիշողություն: Arduino- ի համար nano- ն չի աշխատի 128 -ից բարձր (և որոշ դեպքերում `128 -ից) նմուշների վրա` մատչելի հիշողության բացակայության պատճառով:

անստորագիր int տվյալներ [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 ++) // մակարդակների հաշվարկ {{if (data <= a) {o = i;}} int in_ps [data [o] = {}; // մուտքագրում հաջորդականության համար float out_r [data [o] = {}; // փոխակերպման իրական մասը float out_im [data [o] = {}; // փոխակերպման երևակայական մասը

Հետագա հոսքը հետևյալն է.

1. Կոդը մի փոքր հակադարձում է տվյալ ընտրանքի չափի կարգին (հղումների վրա բիթերի հետադարձման վերաբերյալ մանրամասներ. Քայլ 2)

2. Մուտքագրված տվյալները պատվիրված են ըստ գեներացված պատվերի, 3. FFT կատարված

4. Հաշվարկված բարդ թվի ամպլիտուդը, 5. Գագաթները հայտնաբերվում և պատվիրվում են նվազման կարգով

6. արդյունքները կարող են հասանելի լինել f_peaks- ից :

[այլ տվյալներ մուտք գործելու համար (բացի գագաթնակետային հաճախականությունից) ծածկագիրը պետք է փոփոխվի, որպեսզի տեղային փոփոխականը կարողանա պատճենվել որոշ կանխորոշված գլոբալ փոփոխականի վրա]

Քայլ 5: Կոդի փորձարկում

Կոդի փորձարկում
Կոդի փորձարկում
Կոդի փորձարկում
Կոդի փորձարկում

Եռանկյունի ալիքի օրինակ տրվում է որպես մուտքագրում: այս ալիքի նմուշառման հաճախականությունը 10 Հց է, իսկ ալիքի հաճախականությունը `1.25 Հց:

Ինչպես կարելի է ցույց տալ հում արդյունքից, արժեքը համընկնում է Scilab- ի կողմից հաշվարկված FFT- ի հետ: սակայն, այս արժեքները ճիշտ նույնը չեն, ինչ մենք ցածր ճշգրտությամբ, բայց ավելի արագ սինուս ալիքը:

Ելքային հաճախականությունների զանգվածի հաճախականությունը 1.25 և 3.75 է: անհրաժեշտ չէ ամեն անգամ ստանալ ճշգրիտ արժեքը: սովորաբար այդ թվերը կոչվում են հաճախականության աղբարկղեր: այնպես որ ելքային արժեքը կարող է լինել որևէ տեղ ՝ նշված աղբարկղերի ներսում:

Արագություն:

Arduino nano- ի համար անհրաժեշտ է.

16 միավոր ՝ 4 ms32 միավոր ՝ 10 ms 64 միավոր ՝ 26 ms 128 միավոր ՝ 53 ms

Քայլ 6: Եզրակացություն

Այս FFT ծածկագիրը կարող է օգտագործվել իրական ժամանակի ծրագրերում: Քանի որ հաշվարկը լրացնելու համար տևում է մոտ 30 ms: Այնուամենայնիվ, դրա լուծաչափը սահմանափակված է մի շարք նմուշներով: Նմուշի քանակը սահմանափակված է Arduino հիշողությամբ: Arduino Mega- ի կամ այլ ավելի բարձր արդյունավետության տախտակի օգտագործմամբ կարելի է բարելավել:

եթե ունեք որևէ հարց, առաջարկ կամ ուղղում, ազատ զգացեք մեկնաբանելու համար:

Թարմացում (2/5/21)

Թարմացումներ ՝ // ----------------------------- FFT գործառույթ --------------- ---------------------------------- // float FFT (int in , int N, float Frequency)

N- ի տվյալների տեսակը փոխվել է Integer (գոյություն ունեցող բայթ) `> 255 նմուշի չափս ապահովելու համար: Եթե նմուշի չափը <= 128 է, ապա պետք է օգտագործել բայթ տվյալների տեսակը:

Խորհուրդ ենք տալիս: