Spisu treści:
- Krok 1: Wprowadzenie do transformacji częstotliwości
- Krok 2: Szybka transformata Fouriera
- Krok 3: Wyjaśnienie kodu
- Krok 4: Wyjaśnienie kodu: Funkcja FFT
- Krok 5: Testowanie kodu
- Krok 6: Wniosek
Wideo: EasyFFT: Szybka transformata Fouriera (FFT) dla Arduino: 6 kroków
2024 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2024-01-30 11:27
Pomiar częstotliwości z przechwyconego sygnału może być trudnym zadaniem, zwłaszcza na Arduino, ponieważ ma mniejszą moc obliczeniową. Dostępne są metody przechwytywania przejścia przez zero, gdzie częstotliwość jest wychwytywana przez sprawdzenie, ile razy sygnał przekracza linie zerowe w określonym czasie. Taka metoda może nie działać, gdy sygnał jest kombinacją różnych częstotliwości.
Jest to jakoś trudne do zakodowania, jeśli nie jesteś z takiego środowiska. Ale będąc majsterkowiczem ten kod może być bardzo przydatny w różnych projektach związanych z muzyką, analizą sygnału. Motywem tego projektu było przygotowanie kodu, który jest łatwy do zaimplementowania na Arduino bez wchodzenia w jego tło.
Ten projekt nie wyjaśnia działania FFT, ale wyjaśnia zastosowanie funkcji FFT. Ten sam proces wyjaśniono również w załączonym filmie.
Jeśli interesuje Cię tylko zastosowanie kodu, a nie jego wyjaśnienie. Możesz przejść bezpośrednio do kroku nr 3.
Krok 1: Wprowadzenie do transformacji częstotliwości
Każdy sygnał może składać się z kombinacji różnych fal sinusoidalnych. Tak więc każdy sygnał oparty na czasie może być również pokazany jako kombinacja różnych sinusów o różnych amplitudach.
Próbowałem wyjaśnić działanie DFT (dyskretnej transformacji Fouriera) w jednym z poprzednich instrukcji (https://www.instructables.com/id/Arduino-Frequency…). Te metody są bardzo powolne dla każdej aplikacji działającej w czasie rzeczywistym. co czyni go prawie bezużytecznym.
Na obrazku pokazany jest sygnał będący kombinacją dwóch częstotliwości f2 i f5. Sygnał ten jest mnożony przez testowe sinusoidy o wartościach od f1 do f5.
Z matematycznego punktu widzenia można wykazać, że -sumowanie mnożenia dwóch zbiorów danych harmonicznych o różnej częstotliwości dąży do zera (większa liczba danych może skutkować biciem). W naszym przypadku, jeśli te dwie częstotliwości mnożenia mają taką samą (lub bardzo bliską) częstotliwość, suma mnożenia jest liczbą niezerową.
Czyli jeśli nasz sygnał jest pomnożony przez f1 suma mnożenia wyniesie zero (blisko zeru dla rzeczywistego zastosowania). podobnie jest w przypadku f3, f4. Jednak dla tej wartości wyjście f2 i f5 nie będzie zerowe, ale znacznie wyższe niż pozostałe wartości.
Tutaj sygnał jest testowany z 5 częstotliwościami, więc sygnał musi być pomnożony przez pięć częstotliwości. Taka intensywna kalkulacja zajmuje więcej czasu. Wykazano matematycznie, że dla liczby N próbek pobiera N*N mnożenia zespolonego.
Krok 2: Szybka transformata Fouriera
Aby przyspieszyć obliczenia DFT, algorytm FFT został opracowany przez Jamesa Cooleya i Johna Tukeya. Algorytm ten jest również uważany za jeden z najważniejszych algorytmów XX wieku. Dzieli sygnał na nieparzystą i parzystą część sekwencjonowaną, co zmniejsza liczbę wymaganych obliczeń. Używając go można zredukować całkowite wymagane mnożenie zespolone do NlogN. co jest znaczącą poprawą.
Możesz odwołać się do poniższych odnośników, o których wspomniałem podczas pisania kodu, aby uzyskać szczegółowe zrozumienie matematyki stojącej za FFT:
1.
2.
3.
4.
Krok 3: Wyjaśnienie kodu
1. Szybki sinus i cosinus:
Obliczenie FFT przyjmuje wielokrotnie wartości różnych sinusów i cosinusów. Wbudowana funkcja Arduino nie jest wystarczająco szybka i zajmuje dużo czasu, aby zapewnić wymaganą wartość. Co sprawia, że kod jest znacznie wolniejszy (podwaja czas dla 64 próbek). Aby temu przeciwdziałać, wartość sinusa od 0 do 90 stopni jest przechowywana jako wielokrotność 255. Wyeliminuje to potrzebę przechowywania liczb jako zmiennoprzecinkowych i możemy przechowywać go jako bajt, który zajmuje 1/4 miejsca na Arduino. Sine_data należy wkleić na górze kodu, aby zadeklarować go jako zmienną globalną.
Oprócz sine_data, tablica o nazwie f_peaks zadeklarowana jako zmienna globalna. Po każdym uruchomieniu funkcji FFT tablica ta aktualizuje się. Gdzie f_peaks[0] to najbardziej dominująca częstotliwość, a kolejne wartości w kolejności malejącej.
byte sinus_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];
Ponieważ przechowujemy wartość sinusa od 0 do 90 stopni, można obliczyć dowolną wartość sinusa lub cosinusa. Poniżej funkcja pierwsza zaokrąglenie liczby do zera przecinka i zwrócenie wartości z zapisanych danych. ta metoda wymaga tylko jednego podziału zmiennego. Można to dodatkowo zredukować poprzez bezpośrednie przechowywanie wartości sinus (nie wielokrotności 255). ale to pochłania pamięć Arduino.
Zastosowanie powyższej procedury zmniejsza dokładność, ale poprawia szybkość. Dla 64 punktów daje to 8ms przewagi, a dla 128 punktów 20ms przewagi.
Krok 4: Wyjaśnienie kodu: Funkcja FFT
FFT można wykonać tylko dla wielkości próbki 2, 4, 8, 16, 32, 64 i tak dalej. jeśli wartość nie wynosi 2^n, to przyjmie niższą stronę wartości. Na przykład, jeśli wybierzemy wielkość próby 70, to uwzględni ona tylko pierwsze 64 próbki i pominie resztę.
Zawsze zaleca się, aby wielkość próbki wynosiła 2^n. który może być:
2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …
Dwa zmiennoprzecinkowe out_r i out_im zajmują dużą ilość pamięci. dla Arduino nano nie będzie działać dla próbek wyższych niż 128 (aw niektórych przypadkach 128) z powodu braku dostępnej pamięci.
unsigned 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++) //obliczanie poziomów { if(data<=a){o=i;} } int in_ps[data[o]={}; //wejście do sekwencjonowania float out_r[data[o]={}; //rzeczywista część przekształcenia float out_im[data[o]={}; //wyimaginowana część przekształcenia
Dalszy przepływ jest następujący:
1. Kod generuje bitową odwróconą kolejność dla podanej wielkości próbki (szczegóły dotyczące odwrócenia bitów w referencjach: krok 2)
2. Dane wejściowe uporządkowane według wygenerowanego zamówienia, 3. Wykonano FFT
4. Amplituda obliczonej liczby zespolonej, 5. Piki są wykrywane i porządkowane w porządku malejącym
6. Wyniki można uzyskać z f_peaks.
[aby uzyskać dostęp do innych danych (oprócz częstotliwości szczytowej) należy zmodyfikować kod tak, aby zmienna lokalna mogła zostać skopiowana do jakiejś predefiniowanej zmiennej globalnej]
Krok 5: Testowanie kodu
Jako dane wejściowe podaje się przykładową falę trójkątną. dla tej fali częstotliwość próbkowania wynosi 10 Hz, a częstotliwość samej fali wynosi 1,25 Hz.
Jak widać na podstawie danych wyjściowych, wartość jest zgodna z FFT obliczoną przez Scilab. jednak te wartości nie są dokładnie takie same, jak nasza niska dokładność, ale szybsza fala sinusoidalna.
W tablicy częstotliwości wyjściowej częstotliwości wynoszą 1,25 i 3,75. nie jest konieczne każdorazowe uzyskiwanie dokładnej wartości. zazwyczaj te liczby są nazywane pojemnikami częstotliwości. więc wartość wyjściowa może znajdować się w dowolnym miejscu w określonych przedziałach.
Prędkość:
dla Arduino nano zajmuje:
16 punktów: 4ms32 punkty: 10ms 64 punkty: 26ms 128 punktów: 53ms
Krok 6: Wniosek
Ten kod FFT może być używany w aplikacjach czasu rzeczywistego. Ponieważ ukończenie obliczeń zajmuje około 30 ms. Jednak jego rozdzielczość jest ograniczona liczbą próbek. Liczba próbek jest ograniczona pamięcią Arduino. Dzięki zastosowaniu Arduino Mega lub innej wyższej wydajności można poprawić dokładność płyty.
jeśli masz jakieś pytania, sugestie lub poprawki, możesz je skomentować.
Aktualizacja (2/5/21)
Updates://-----------------------------Funkcja FFT--------------- -------------------------------//float FFT(int in, int N, float Częstotliwość)
Typ danych N zmienił się na Integer (istniejący Byte), aby obsłużyć rozmiar próbki >255. Jeśli wielkość próbki wynosi <=128, należy użyć typu danych bajtowych.
Zalecana:
Szybka i doskonała edycja zdjęć w programie Picasa: 10 kroków (ze zdjęciami)
Szybka i doskonała edycja zdjęć w programie Picasa: doskonały aparat cyfrowy wiąże się z wielką odpowiedzialnością za zarządzanie tysiącami zdjęć. Może to być uciążliwe, zwłaszcza jeśli chcesz ich użyć do udokumentowania procesu dla Instructables. Znam się na Photoshopie, ale najczęściej zwracam się do G
„Niespokojna maszyna”: szybka rzeźba-sztuka dla początkujących: 8 kroków (ze zdjęciami)
„Niespokojna maszyna”: szybka rzeźba-sztuka dla początkujących: (Jeśli podoba Ci się ta instrukcja, zagłosuj na nią w konkursie „Trash to Treasure”. Ale jeśli szukasz mniej niepokojącego projektu, sprawdź mój ostatni pierwszy: Jak stworzyć robota Lambada Walking! Dzięki!) Załóżmy, że masz szkołę
PCF8591 (analogowy ekspander we/wy i2c) Szybka i łatwa obsługa: 9 kroków
PCF8591 (i2c Analog I/O Expander) Szybka i łatwa obsługa: Biblioteka do użycia i2c pcf8591 IC z arduino i esp8266. Ten układ scalony może sterować (aż do 4) wejściem analogowym i/lub 1 wyjściem analogowym, takim jak pomiar napięcia, odczyt wartości termistora lub zanikanie diody LED. Może odczytywać wartość analogową i zapisywać wartość analogową za pomocą tylko 2 przewodów (ide
Szybka gra reakcji: Wersja na odległość: 5 kroków (ze zdjęciami)
Szybka gra reakcji: Odległość Wersja: Cześć. To jest instrukcja, jak stworzyć grę, która sprawdza zarówno twój czas reakcji, jak i poczucie odległości. Ten projekt jest oparty na starym projekcie, który wykonałem z udziałem dwóch graczy rywalizujących, aby zobaczyć, kto miał szybszy czas reakcji, klikając przycisk w
Szybka wideografia dla początkujących: 6 kroków (ze zdjęciami)
Szybka wideografia dla początkujących.: Wszyscy, których spotkałem i rozmawiałem, mają jedną wspólną cechę: chęć posiadania lub przynajmniej zabawy z szybką kamerą. Chociaż wątpię, czy wiele osób czytających to ma własny szybki aparat, chciałbym, aby ci nieliczni, którzy nie