Sadržaj:

1024 uzorka FFT analizator spektra pomoću Atmega1284: 9 koraka
1024 uzorka FFT analizator spektra pomoću Atmega1284: 9 koraka

Video: 1024 uzorka FFT analizator spektra pomoću Atmega1284: 9 koraka

Video: 1024 uzorka FFT analizator spektra pomoću Atmega1284: 9 koraka
Video: Training Midjourney Level Style And Yourself Into The SD 1.5 Model via DreamBooth Stable Diffusion 2024, Juli
Anonim
1024 uzorka FFT analizator spektra pomoću Atmega1284
1024 uzorka FFT analizator spektra pomoću Atmega1284
1024 uzorka FFT analizator spektra pomoću Atmega1284
1024 uzorka FFT analizator spektra pomoću Atmega1284

Ovaj relativno jednostavan vodič (s obzirom na složenost ove teme) pokazat će vam kako možete napraviti vrlo jednostavan analizator spektra od 1024 uzorka koristeći ploču tipa Arduino (1284 uska) i serijski ploter. Bilo koja vrsta Arduino kompatibilne ploče će poslužiti, ali što više RAM -a ima, najbolju frekvencijsku rezoluciju ćete dobiti. Za računanje FFT -a sa 1024 uzorka trebat će mu više od 8 KB RAM -a.

Analiza spektra koristi se za određivanje glavnih frekvencijskih komponenti signala. Mnogi zvukovi (poput onih koje proizvodi muzički instrument) sastoje se od osnovne frekvencije i nekih harmonika koji imaju frekvenciju koja je cijeli broj višekratnik osnovne frekvencije. Analizator spektra će vam pokazati sve ove spektralne komponente.

Možda biste htjeli koristiti ovu postavku kao brojač frekvencija ili provjeriti bilo koju vrstu signala za koji sumnjate da unosi buku u vaše elektroničko kolo.

Ovdje ćemo se fokusirati na softverski dio. Ako želite napraviti stalni krug za određenu aplikaciju, morat ćete pojačati i filtrirati signal. Ovo predkondicioniranje u potpunosti ovisi o signalu koji želite proučavati, ovisno o njegovoj amplitudi, impedanciji, maksimalnoj frekvenciji itd … Možete provjeriti

Korak 1: Instaliranje biblioteke

Koristit ćemo ArduinoFFT biblioteku koju je napisao Enrique Condes. Budući da želimo maksimalno uštedjeti RAM, upotrijebit ćemo razvojnu granu ovog spremišta koja omogućava korištenje float tipa podataka (umjesto dvostrukog) za pohranu uzorkovanih i izračunatih podataka. Zato ga moramo instalirati ručno. Ne brinite, samo preuzmite arhivu i raspakirajte je u fasciklu Arduino biblioteke (na primjer na Windows 10 zadanoj konfiguraciji: C: / Users / _vaše_korisničko_ime_ / Dokumenti / Arduino / biblioteke)

Možete provjeriti je li knjižnica ispravno instalirana sastavljanjem jednog od ponuđenih primjera, poput "FFT_01.ino."

Korak 2: Fourierova transformacija i FFT koncepti

Upozorenje: ako ne podnosite bilo koju matematičku notaciju, možda biste htjeli preskočiti na korak 3. U svakom slučaju, ako ne razumijete sve, samo razmislite o zaključku na kraju odjeljka.

Frekvencijski spektar dobiven je algoritmom brze Fourierove transformacije. FFT je digitalna implementacija koja približava matematički koncept Fourierove transformacije. Prema ovom konceptu, nakon što dobijete evoluciju signala koja slijedi vremensku osu, možete znati njegovu reprezentaciju u frekvencijskom domenu, sastavljenom od složenih (realnih + imaginarnih) vrijednosti. Koncept je recipročan, pa kada znate prikaz frekvencijske domene, možete ga transformirati natrag u vremensku domenu i vratiti signal točno kao prije transformacije.

Ali što ćemo učiniti s ovim skupom izračunatih kompleksnih vrijednosti u vremenskoj domeni? Pa, većina će biti prepuštena inženjerima. Za nas ćemo nazvati drugi algoritam koji će pretvoriti ove složene vrijednosti u podatke o spektralnoj gustoći: to je veličina (= intenzitet) povezana sa svakim frekvencijskim pojasom. Broj frekvencijskog pojasa bit će isti kao i broj uzoraka.

Sigurno ste upoznati sa konceptom ekvilajzera, poput ovog Povratak u 1980 -te sa grafičkim ekvilajzerom. Pa, dobit ćemo istu vrstu rezultata, ali sa 1024 opsega umjesto 16 i mnogo većom rezolucijom intenziteta. Kada ekvilajzer daje globalni prikaz muzike, fina spektralna analiza omogućava precizno izračunavanje intenziteta svakog od 1024 opsega.

Savršen koncept, ali:

  1. Budući da je FFT digitalizirana verzija Fourierove transformacije, on aproksimira digitalni signal i gubi neke informacije. Dakle, strogo govoreći, rezultat FFT -a ako se transformira unatrag s obrnutim algoritmom FFT -a ne bi dao točno izvorni signal.
  2. Također teorija razmatra signal koji nije konačan, već je to konstantni konstantni signal. Budući da ćemo ga digitalizirati samo određeno vrijeme (tj. Uzorci), bit će uvedene još neke greške.
  3. Konačno, rezolucija analogno -digitalne konverzije će utjecati na kvalitetu izračunatih vrijednosti.

U praksi

1) Učestalost uzorkovanja (zabilježeno fs)

Uzorkovaćemo signal, odnosno meriti njegovu amplitudu svakih 1/fs sekundi. fs je frekvencija uzorkovanja. Na primjer, ako uzorkujemo na 8 KHz, ADC (analogno -digitalni pretvarač) koji je na čipu omogućit će mjerenje svakih 1/8000 sekundi.

2) Broj uzoraka (zabilježen N ili uzorci u kodu)

Budući da moramo dobiti sve vrijednosti prije pokretanja FFT -a, morat ćemo ih pohraniti, pa ćemo ograničiti broj uzoraka. FFT algoritmu je potreban određeni broj uzoraka snage 2. Što više uzoraka imamo, to smo bolji, ali zauzima puno memorije, utoliko će nam više trebati i za pohranu transformiranih podataka, koji su složene vrijednosti. Arduino FFT biblioteka štedi dio prostora korištenjem

  • Jedan niz pod nazivom "vReal" za spremanje uzorkovanih podataka, a zatim i stvarni dio transformiranih podataka
  • Jedan niz pod nazivom "vImag" za spremanje zamišljenog dijela transformiranih podataka

Potrebna količina RAM -a jednaka je 2 (nizovi) * 32 (bitovi) * N (uzorci).

Tako ćemo u našu Atmega1284 koja ima lijepih 16 KB RAM -a pohraniti najviše N = 16000*8 /64 = 2000 vrijednosti. Budući da broj vrijednosti mora biti 2, pohranit ćemo najviše 1024 vrijednosti.

3) Rezolucija frekvencije

FFT će izračunati vrijednosti za onoliko frekvencijskih opsega koliko je uzoraka. Ovi opsezi će se protezati od 0 HZ do frekvencije uzorkovanja (fs). Dakle, rezolucija frekvencije je:

Fresolution = fs / N

Rezolucija je bolja ako je niža. Dakle, za bolju rezoluciju (manju) želimo:

  • više uzoraka i/ili
  • niži fs

Ali…

4) Minimalni fs

Budući da želimo vidjeti mnogo frekvencija, od kojih su neke mnogo veće od "osnovne frekvencije", ne možemo postaviti fs premalo. U stvari, postoji Nyquist -Shannonova teorema uzorkovanja koja nas tjera da imamo frekvenciju uzorkovanja znatno iznad dvostruko veće od maksimalne frekvencije koju bismo željeli testirati.

Na primjer, ako želimo analizirati cijeli spektar od 0 Hz do recimo 15 KHz, što je približno maksimalna frekvencija koju većina ljudi može jasno čuti, moramo postaviti frekvenciju uzorkovanja na 30 KHz. U stvari, elektroničari ga često postavljaju na 2,5 (ili čak 2,52) * maksimalnu frekvenciju. U ovom primjeru to bi bilo 2,5 * 15 KHz = 37,5 KHz. Uobičajene frekvencije uzorkovanja u profesionalnom zvuku su 44,1 KHz (snimanje audio CD -a), 48 KHz i više.

Zaključak:

Točke 1 do 4 vode do: želimo upotrijebiti što je moguće više uzoraka. U našem slučaju sa 16 KB RAM uređaja razmotrit ćemo 1024 uzorka. Želimo uzorkovati na najmanjoj mogućoj frekvenciji uzorkovanja, sve dok je dovoljno visoka da analiziramo najveću frekvenciju koju očekujemo u našem signalu (najmanje 2,5 * ove frekvencije).

Korak 3: Simulacija signala

Simulacija signala
Simulacija signala

Za naš prvi pokušaj, malo ćemo izmijeniti primjer TFT_01.ino dat u biblioteci, kako bismo analizirali signal sastavljen od

  • Osnovna frekvencija, postavljena na 440 Hz (muzički A)
  • 3. harmonik na pola snage fundamentalnog ("-3 dB")
  • 5. harmonik na 1/4 snage fundamentalne ("-6 dB)

Rezultat signala možete vidjeti na slici iznad. Zaista jako liči na pravi signal koji se ponekad može vidjeti na osciloskopu (ja bih to nazvao "Batman") u situaciji kada dolazi do isjecanja sinusnog signala.

Korak 4: Analiza simuliranog signala - kodiranje

0) Uključite biblioteku

#include "arduinoFFT.h"

1) Definicije

U odjeljcima deklaracija imamo

const bajt adcPin = 0; // A0

const uint16_t uzorci = 1024; // Ova vrijednost MORA UVIJEK biti snaga 2 const uint16_t samplingFrequency = 8000; // Utjecat će na maksimalnu vrijednost tajmera u timer_setup () SYSCLOCK/8/samplingFrequency bi trebao biti cijeli broj

Budući da signal ima 5. harmonik (frekvencija ovog harmonika = 5 * 440 = 2200 Hz), moramo postaviti frekvenciju uzorkovanja iznad 2,5 * 2200 = 5500 Hz. Ovdje sam odabrao 8000 Hz.

Također deklariramo nizove u koje ćemo pohraniti neobrađene i izračunate podatke

float vReal [uzorci];

plutajući vImag [uzorci];

2) Instancija

Kreiramo ArduinoFFT objekt. Dev verzija ArduinoFFT -a koristi predložak pa možemo koristiti ili float ili dvostruki tip podataka. Float (32 bita) je dovoljan s obzirom na ukupnu preciznost našeg programa.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, uzorci, samplingFrequency);

3) Simulacija signala popunjavanjem vReal niza, umjesto da se popuni ADC vrijednostima.

Na početku petlje popunjavamo niz vReal sa:

float ciklusi = (((uzorci) * signalFrequency) / samplingFrequency); // Broj ciklusa signala koje će uzorkovanje očitati

za (uint16_t i = 0; i <uzorci; i ++) {vReal = float ((amplituda * (sin ((i * (TWO_PI * ciklusa))) / uzorci)))); / * Izgradite podatke s pozitivnim i negativne vrijednosti */ vReal += float ((amplituda * (sin ((3 * i * (TWO_PI * ciklusa))/ uzorci)))/ 2.0);/ * Izgradite podatke s pozitivnim i negativnim vrijednostima */ vReal += float ((amplituda * (sin ((5 * i * (TWO_PI * ciklusa))) / uzorci))) / 4,0); / * Izgradite podatke s pozitivnim i negativnim vrijednostima * / vImag = 0,0; // Zamišljeni dio mora biti nuliran u slučaju petlje kako bi se izbjegli pogrešni proračuni i prelijevanje}

Dodajemo digitalizaciju temeljnog vala i dva harmonika s manjom amplitudom. Zatim inicijaliziramo zamišljeni niz nulama. Budući da je ovaj niz popunjen algoritmom FFT, moramo ga ponovo očistiti prije svakog novog izračunavanja.

4) FFT računarstvo

Zatim izračunavamo FFT i spektralnu gustoću

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward);

FFT.compute (FFTDirection:: Forward); / * Izračunaj FFT */ FFT.complexToMagnitude (); / * Izračunajte veličine */

Operacija FFT.windowing (…) mijenja neobrađene podatke jer pokrećemo FFT na ograničenom broju uzoraka. Prvi i posljednji uzorak predstavljaju diskontinuitet (s jedne strane nema "ništa"). Ovo je izvor greške. Operacija "prozora" nastoji smanjiti ovu grešku.

FFT.compute (…) sa smjerom "Naprijed" izračunava transformaciju iz vremenske domene u frekvencijsku domenu.

Zatim izračunavamo vrijednosti veličine (tj. Intenziteta) za svaki od frekvencijskih opsega. Niz vReal sada je ispunjen veličinama.

5) Crtež serijskog plotera

Odštampajmo vrijednosti na serijskom ploteru pozivanjem funkcije printVector (…)

PrintVector (vReal, (uzorci >> 1), SCL_FREQUENCY);

Ovo je generička funkcija koja omogućava ispis podataka s vremenskom osi ili osi frekvencije.

Štampamo i frekvenciju opsega koja ima najveću vrijednost veličine

float x = FFT.majorPeak ();

Serial.print ("f0 ="); Serial.print (x, 6); Serial.println ("Hz");

Korak 5: Analiza simuliranog signala - rezultati

Analiza simuliranog signala - rezultati
Analiza simuliranog signala - rezultati

Vidimo 3 skoka koji odgovaraju osnovnoj frekvenciji (f0), 3. i 5. harmonik, sa polovinom i 1/4 veličine f0, kako se očekivalo. Možemo očitati na vrhu prozora f0 = 440.430114 Hz. Ova vrijednost nije baš 440 Hz, iz svih gore navedenih razloga, ali je vrlo blizu stvarne vrijednosti. Zaista nije bilo potrebno pokazivati toliko beznačajnih decimala.

Korak 6: Analiza stvarnog signala - Ožičenje ADC -a

Analiza stvarnog signala - ožičenje ADC -a
Analiza stvarnog signala - ožičenje ADC -a

Pošto znamo kako teoretski postupiti, htjeli bismo analizirati pravi signal.

Ožičenje je vrlo jednostavno. Spojite uzemljenje zajedno i signalnu liniju na A0 pin vaše ploče kroz serijski otpornik vrijednosti od 1 KOhm do 10 KOhm.

Ovaj serijski otpornik će zaštititi analogni ulaz i izbjeći zvonjenje. Mora biti što je moguće veće kako bi se izbjeglo zvonjenje, a što je moguće niže kako bi se osigurala dovoljna struja za brzo punjenje ADC -a. Pogledajte tehnički list MCU -a kako biste saznali očekivanu impedanciju signala spojenog na ADC ulaz.

Za ovaj demo koristio sam funkcijski generator za napajanje sinusoidnog signala frekvencije 440 Hz i amplitude oko 5 volti (najbolje je ako je amplituda između 3 i 5 volti, tako da se ADC koristi blizu pune skale), kroz otpornik od 1,2 KOhm.

Korak 7: Analiza stvarnog signala - kodiranje

0) Uključite biblioteku

#include "arduinoFFT.h"

1) Deklaracije i instalacije

U odjeljku deklaracije definiramo ADC ulaz (A0), broj uzoraka i frekvenciju uzorkovanja, kao u prethodnom primjeru.

const bajt adcPin = 0; // A0

const uint16_t uzorci = 1024; // Ova vrijednost MORA UVIJEK biti snaga 2 const uint16_t samplingFrequency = 8000; // Uticat će na maksimalnu vrijednost tajmera u timer_setup () SYSCLOCK/8/samplingFrequency bi trebao biti cijeli broj

Kreiramo ArduinoFFT objekt

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, uzorci, samplingFrequency);

2) Podešavanje tajmera i ADC -a

Tajmer 1 smo postavili tako da radi na frekvenciji uzorkovanja (8 KHz) i pokreće prekid pri usporedbi izlaza.

void timer_setup () {

// resetiranje tajmera 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bit (CS11) | bit (WGM12); // CTC, predskaler od 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000/8) / frekvencija uzorkovanja) -1; }

I postavite ADC tako

  • Koristi A0 kao ulaz
  • Aktivira se automatski na svakom izlazu tajmera 1 uporedi podudaranje B
  • Generira prekid kada je konverzija dovršena

ADC sat je postavljen na 1 MHz, predskaliranjem sistemskog takta (16 MHz) za 16. Budući da svaka konverzija traje približno 13 taktova u punom opsegu, konverzije se mogu postići na frekvenciji 1/13 = 0,076 MHz = 76 KHz. Učestalost uzorkovanja trebala bi biti znatno niža od 76 KHz kako bi ADC imao vremena za uzorkovanje podataka. (odabrali smo fs = 8 KHz).

void adc_setup () {

ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF); // uključiti ADC, želim prekid po završetku ADCSRA | = bit (ADPS2); // Predkaler od 16 ADMUX = bit (REFS0) | (adcPin & 7); // postavljanje ADC ulaza ADCSRB = bit (ADTS0) | bit (ADTS2); // Tajmer/brojač1 Usporedi izvor okidača podudaranja B ADCSRA | = bit (ADATE); // uključi automatsko aktiviranje}

Deklariramo rukovatelj prekida koji će biti pozvan nakon svake ADC konverzije za spremanje pretvorenih podataka u niz vReal i brisanje prekida

// ADC kompletan ISR

ISR (ADC_vect) {vReal [broj rezultata ++] = ADC; if (broj rezultata == uzorci) {ADCSRA = 0; // isključuje ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Možete dobiti iscrpno objašnjenje o ADC konverziji na Arduinu (analogRead).

3) Podešavanje

U funkciji postavljanja brišemo zamišljenu tablicu podataka i pozivamo funkcije za postavljanje mjerača vremena i ADC -a

zeroI (); // funkcija koja postavlja na 0 sve imaginarne podatke - objašnjeno u prethodnom odjeljku

timer_setup (); adc_setup ();

3) Petlja

FFT.dcRemoval (); // Uklonite istosmjernu komponentu ovog signala jer se ADC odnosi na masu

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward); // Vaganje podataka FFT.compute (FFTDirection:: Forward); // Računanje FFT FFT.complexToMagnitude (); // Računanje veličina // ispisivanje spektra i osnovne frekvencije f0 PrintVector (vReal, (uzorci >> 1), SCL_FREQUENCY); float x = FFT.majorPeak (); Serial.print ("f0 ="); Serial.print (x, 6); Serial.println ("Hz");

Uklanjamo istosmjernu komponentu jer se ADC odnosi na masu i signal je centriran približno na 2,5 volta.

Zatim izračunavamo podatke kako je objašnjeno u prethodnom primjeru.

Korak 8: Analiza stvarnog signala - rezultati

Analiza stvarnog signala - rezultati
Analiza stvarnog signala - rezultati

Zaista vidimo samo jednu frekvenciju u ovom jednostavnom signalu. Izračunata osnovna frekvencija je 440.118194 Hz. I ovdje je vrijednost vrlo bliska aproksimacija stvarne frekvencije.

Korak 9: Šta je sa izrezanim sinusoidnim signalom?

Šta je sa izrezanim sinusoidnim signalom?
Šta je sa izrezanim sinusoidnim signalom?

Hajde sada malo prenagliti ADC povećavajući amplitudu signala iznad 5 volti, tako da je odrezan. Ne gurajte previše da ne uništite ADC ulaz!

Možemo vidjeti neke harmonike koji se pojavljuju. Odsecanjem signala stvaraju se komponente visoke frekvencije.

Vidjeli ste osnove FFT analize na Arduino ploči. Sada možete pokušati promijeniti frekvenciju uzorkovanja, broj uzoraka i parametar prozora. Biblioteka dodaje i neke parametre za brže izračunavanje FFT -a s manje preciznosti. Primijetit ćete da će, ako postavite frekvenciju uzorkovanja prenisko, izračunate veličine izgledati potpuno pogrešne zbog spektralnog preklapanja.

Preporučuje se: