Mündəricat:

EasyFFT: Arduino üçün Sürətli Fourier Dönüşümü (FFT): 6 addım
EasyFFT: Arduino üçün Sürətli Fourier Dönüşümü (FFT): 6 addım

Video: EasyFFT: Arduino üçün Sürətli Fourier Dönüşümü (FFT): 6 addım

Video: EasyFFT: Arduino üçün Sürətli Fourier Dönüşümü (FFT): 6 addım
Video: QuickFFT: High Speed FFT for Arduino 2024, Noyabr
Anonim
Image
Image

Tutulan siqnaldan tezliyin ölçülməsi, xüsusilə də daha aşağı hesablama gücünə malik olduğu üçün Arduinoda çətin bir iş ola bilər. Siqnalın müəyyən müddət ərzində sıfır xətləri neçə dəfə keçdiyini yoxlamaqla tezliyin tutulduğu sıfır keçidini tutmaq üçün mövcud üsullar var. Siqnal müxtəlif tezliklərin birləşməsi olduqda belə bir üsul işləməyə bilər.

Belə bir fondan deyilsinizsə, kodlaşdırmaq bir qədər çətindir. Ancaq bu kod bir işçi olaraq musiqi, siqnal təhlili ilə əlaqədar müxtəlif layihələr üçün çox faydalı ola bilər. Bu layihənin məqsədi Arduinonun arxa planına girmədən tətbiq etmək asan olan bir kod hazırlamaq idi.

Bu layihə FFT -nin işini izah etmir, lakin FFT funksiyasının tətbiqini izah edir. Eyni proses əlavə olunmuş videoda da izah edilmişdir.

Yalnız kodun tətbiqi ilə maraqlanırsınızsa və bunun izahı ilə maraqlanmırsınızsa. 3 nömrəli addıma keçə bilərsiniz.

Addım 1: Tezlik Dönüşümünə Giriş

Tezlik Dönüşümünə Giriş
Tezlik Dönüşümünə Giriş
Tezlik Dönüşümünə Giriş
Tezlik Dönüşümünə Giriş

İstənilən siqnal müxtəlif sinusoidal dalğaların birləşməsindən ibarət ola bilər. Beləliklə, hər hansı bir zaman əsaslı siqnal fərqli amplitüdlərin müxtəlif sinüslərinin birləşməsi kimi də göstərilə bilər.

Əvvəlki təlimatlardan birində DFT (diskret Fourier çevrilməsi) işini izah etməyə çalışdım (https://www.instructables.com/id/Arduino-Frequency…). Bu üsullar hər hansı bir real vaxt tətbiqi üçün son dərəcə yavaşdır. demək olar ki, yararsız hala gətirir.

Şəkildə f2 və f5 tezliklərinin birləşməsindən ibarət bir siqnal göstərilir. Bu siqnal f1 -dən f5 -ə qədər olan test sinus dalğaları ilə vurulur.

Riyazi olaraq göstərilə bilər ki, fərqli frekansa malik iki harmonik məlumat toplusunun vurulmasının yekunu sıfıra bərabərdir (daha çox məlumat sayı meyilli nəticəyə səbəb ola bilər). Bizim vəziyyətimizdə, əgər bu iki vurma tezliyi eyni (və ya çox yaxın) tezliyə malikdirsə, vurma cəminin sıfır olmayan sayıdır.

Beləliklə, siqnalımız f1 ilə vurulursa, vurma cəmlənməsi sıfır olacaq (real tətbiq üçün sıfıra yaxın). f3, f4 üçün də oxşardır. Ancaq dəyər üçün, f2 və f5 çıxışı sıfır olmayacaq, lakin digər dəyərlərdən əhəmiyyətli dərəcədə yüksəkdir.

Burada bir siqnal 5 tezliklə sınaqdan keçirilir, ona görə də siqnalın beş tezliklə vurulması lazımdır. Belə sıx hesablama daha yüksək vaxt tələb edir. Riyazi olaraq göstərilir ki, N ədəd nümunə üçün N*N kompleks vurma tələb olunur.

Addım 2: Sürətli Fourier Dönüşümü

DFT hesablamasını daha sürətli etmək üçün James Cooley və John Tukey tərəfindən FFT alqoritmi hazırlanmışdır. Bu alqoritm həm də 20 -ci əsrin ən əhəmiyyətli alqoritmlərindən biri hesab olunur. Siqnalı bir sıra tələb olunan hesablamaları aşağı edən tək və hətta ardıcıl bir hissəyə bölür. İstifadə edərək ümumi tələb olunan kompleks vurma NlogN -ə endirilə bilər. əhəmiyyətli bir inkişafdır.

FFT -nin arxasındakı riyaziyyat haqqında ətraflı məlumat əldə etmək üçün kodu yazarkən istinad etdiyim istinadlara aşağıdakılara istinad edə bilərsiniz:

1.

2.

3.

4.

Addım 3: Kodun izahı

1. Tez sinus və Kosinus:

Hesablama FFT müxtəlif sinus və kosinus dəyərlərini dəfələrlə alır. Arduinonun daxili funksiyası kifayət qədər sürətli deyil və lazımi dəyəri təmin etmək üçün çox vaxt lazımdır. Hansı ki, kodu xeyli ləngidir (64 nümunə üçün vaxtı iki dəfə artırır). Bu problemi həll etmək üçün 0 -dan 90 dərəcəyə qədər olan sinus dəyəri 255 -in birdən çoxu kimi saxlanılır. Bunu etməklə ədədlərin float olaraq istifadə edilməsinə ehtiyac qalmayacaq və Arduino -da 1/4 yer tutan bayt olaraq saxlaya bilərik. Sine_data kodunu qlobal bir dəyişən olaraq elan etmək üçün onu yapışdırmaq lazımdır.

Sine_data -dan başqa, f_peaks adlı bir sıra qlobal dəyişən olaraq elan edildi. Hər FFT funksiyasından sonra bu sıra yenilənir. Harada f_peaks [0] ən azalan sıra ilə daha çox üstünlük təşkil edən tezlik və digər dəyərlərdir.

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

Sinüs dəyərini 0 ilə 90 dərəcə arasında saxladığımız üçün hər hansı bir sinus və ya kosinus dəyəri hesablana bilər. Aşağıda rəqəmin ilk turu sıfır ondalık nöqtəsinə və saxlanan məlumatlardan dəyər qaytarmağa xidmət edir. Bu üsul yalnız bir üzən bölməyə ehtiyac duyur. Bu sinus dəyərlərini birbaşa saxlayaraq daha da azalda bilər (255 çox deyil). lakin bu, Arduinoda yüksək yaddaş yeyir.

Yuxarıdakı prosedurdan istifadə dəqiqliyi azaldır, lakin sürəti artırır. 64 bal üçün 8ms, 128 bal üçün 20ms üstünlük verir.

Addım 4: Kodun izahı: FFT funksiyası

FFT yalnız 2, 4, 8, 16, 32, 64 və s. Nümunə ölçüləri üçün edilə bilər. dəyər 2^n deyilsə, dəyərin aşağı tərəfini alacaq. Məsələn, 70 nümunə ölçüsünü seçsək, yalnız ilk 64 nümunəni nəzərdən keçirəcək və istirahət etməyəcək.

Nümunə ölçüsünün 2^n olması həmişə tövsiyə olunur. hansı ola bilər:

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

Out_r və out_im iki üzgüçülük çoxlu yaddaş tutacaq. Arduino nano, mövcud yaddaşın olmaması səbəbindən 128 (və bəzi hallarda 128) -dən yuxarı olan nümunələrdə işləməyəcək.

imzasız int data [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 ++) // səviyyələrin hesablanması {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // sıralama üçün giriş float out_r [data [o] = {}; // çevrilmənin həqiqi hissəsi float out_im [data [o] = {}; // çevrilmənin xəyali hissəsi

Əlavə axın aşağıdakı kimidir:

1. Kod, verilən nümunə ölçüsü üçün bir az tərsinə sifariş yaradır (istinadlarda bitlərin geri çevrilməsi ilə bağlı detallar: addım 2)

2. Giriş məlumatları yaradılan sifarişə görə sifariş verilir, 3. FFT yerinə yetirildi

4. Kompleks ədədin amplitudası hesablanır, 5. Zirvələr azalan qaydada aşkarlanır və sıralanır

6. nəticələrə f_peaks saytından daxil olmaq olar.

[digər məlumatlara daxil olmaq üçün (pik tezlikdən başqa) kod dəyişdirilməlidir ki, yerli dəyişən əvvəlcədən müəyyən edilmiş bir qlobal dəyişənə kopyalana bilsin)

Addım 5: Kodun sınanması

Kodun sınanması
Kodun sınanması
Kodun sınanması
Kodun sınanması

Nümunə üçbucaq dalğası giriş olaraq verilir. bu dalğa üçün nümunə götürmə tezliyi 10 Hz və dalğanın özü 1.25 Hz -dir.

Xam çıxışdan da göründüyü kimi, dəyər Scilab tərəfindən hesablanan FFT ilə uyğun gəlir. lakin, bu dəyərlər dəqiqliyimizlə eyni deyil, daha sürətli sinus dalğasıdır.

Çıxış tezliyində serialın tezliyi 1.25 və 3.75 -dir. hər dəfə dəqiq dəyəri əldə etmək lazım deyil. adətən bu ədədlərə tezlik qutuları deyilir. belə ki, çıxış dəyəri müəyyən qutular daxilində ola bilər.

Sürət:

Arduino nano üçün:

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

Addım 6: Nəticə

Bu FFT kodu real vaxt tətbiqlərində istifadə edilə bilər. Hesablamanı başa çatdırmaq üçün təxminən 30 ms lazımdır. Bununla birlikdə, onun həlli bir sıra nümunələrlə məhdudlaşır. Nümunənin sayı Arduino yaddaşı ilə məhdudlaşır. Arduino Mega və ya digər daha yüksək performans lövhələrinin dəqiqliyi artırıla bilər.

hər hansı bir sualınız, təklifiniz və ya düzəlişiniz varsa şərh etməkdən çekinmeyin.

Yeniləmə (5.05.221)

Yeniləmələr: // ---------------------------- FFT Function --------------- ------------------------------- // float FFT (int

N məlumat növü> 255 nümunə ölçüsünü dəstəkləmək üçün Integer (mövcud Bayt) olaraq dəyişdirildi. Nümunə ölçüsü <= 128 olarsa, bayt məlumat növü istifadə edilməlidir.

Tövsiyə: