Përmbajtje:

1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284: 9 Hapa
1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284: 9 Hapa

Video: 1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284: 9 Hapa

Video: 1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284: 9 Hapa
Video: Smart Meter Interference to 902-928 MHz 2024, Korrik
Anonim
1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284
1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284
1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284
1024 Mostra FFT Spectrum Analyzer Duke përdorur një Atmega1284

Ky mësim relativisht i lehtë (duke marrë parasysh kompleksitetin e kësaj lënde) do t'ju tregojë se si mund të bëni një analizues spektri shumë të thjeshtë 1024 mostrash duke përdorur një tabelë të tipit Arduino (1284 Ngusht) dhe komplotuesin serik. Çdo lloj bordi i pajtueshëm me Arduino do të bëjë, por sa më shumë RAM të ketë, rezolucioni më i mirë i frekuencës që do të merrni. Do të duhen më shumë se 8 KB RAM për të llogaritur FFT me 1024 mostra.

Analiza e spektrit përdoret për të përcaktuar përbërësit kryesorë të frekuencës së një sinjali. Shumë tinguj (si ata të prodhuar nga një instrument muzikor) përbëhen nga një frekuencë themelore dhe disa harmonikë që kanë një frekuencë që është një shumëfish i plotë i frekuencës themelore. Analizuesi i spektrit do t'ju tregojë të gjithë këta përbërës spektralë.

Ju mund të dëshironi ta përdorni këtë konfigurim si një numërues frekuence ose për të kontrolluar çdo lloj sinjali që dyshoni se po sjell pak zhurmë në qarkun tuaj elektronik.

Ne do të përqëndrohemi këtu në pjesën e softuerit. Nëse dëshironi të bëni një qark të përhershëm për një aplikim specifik, do t'ju duhet të amplifikoni dhe filtroni sinjalin. Ky para-kondicionim varet tërësisht nga sinjali që dëshironi të studioni, në varësi të amplitudës së tij, rezistencës, frekuencës maksimale etj … Mund të kontrolloni

Hapi 1: Instalimi i Bibliotekës

Ne do të përdorim bibliotekën ArduinoFFT të shkruar nga Enrique Condes. Meqenëse ne duam të kursejmë RAM -in sa më shumë që të jetë e mundur, ne do të përdorim degën e zhvillimit të këtij depoja që ju lejon të përdorni llojin e të dhënave float (në vend të dyfishtë) për të ruajtur të dhënat e mostruara dhe të llogaritura. Pra, ne duhet ta instalojmë manualisht. Mos u shqetësoni, thjesht shkarkoni arkivin dhe hiqeni atë në dosjen tuaj të bibliotekës Arduino (për shembull në konfigurimin e paracaktuar të Windows 10: C: / Users / _your_user_name_ / Documents / Arduino / bibliotekat)

Ju mund të kontrolloni që biblioteka është instaluar saktë duke përpiluar një nga shembujt e dhënë, si "FFT_01.ino."

Hapi 2: Transformimi i Furierit dhe Konceptet FFT

Paralajmërim: nëse nuk duroni të shihni ndonjë shënim matematikor, mund të kaloni në Hapin 3. Gjithsesi, nëse nuk i merrni të gjitha, thjesht merrni parasysh përfundimin në fund të seksionit.

Spektri i frekuencës merret përmes një algoritmi të Shndërrimit të Furierit të Shpejtë. FFT është një zbatim dixhital që përafron konceptin matematikor të Transformimit Furier. Nën këtë koncept sapo të merrni evolucionin e një sinjali duke ndjekur një aks kohor, mund të njihni përfaqësimin e tij në një fushë frekuence, të përbërë nga vlera komplekse (reale + imagjinare). Koncepti është reciprok, kështu që kur të njihni përfaqësimin e fushës së frekuencës, mund ta transformoni atë në fushën e kohës dhe ta ktheni sinjalin saktësisht si para transformimit.

Por çfarë do të bëjmë me këtë grup vlerash komplekse të llogaritura në fushën e kohës? Epo, pjesa më e madhe do t'i lihet inxhinierëve. Për ne do të thërrasim një algoritëm tjetër që do t'i transformojë këto vlera komplekse në të dhëna të densitetit spektral: kjo është një vlerë e madhësisë (= intensitetit) e lidhur me secilën brez frekuence. Numri i brezit të frekuencës do të jetë i njëjtë me numrin e mostrave.

Ju me siguri jeni njohur me konceptin e barazimit, si ky i kthyer në vitet 1980 Me EQ Grafik. Epo, ne do të marrim të njëjtin lloj rezultati, por me 1024 banda në vend të 16 dhe rezolucion shumë më intensiv. Kur barazuesi jep një pamje globale të muzikës, analiza spektrale e mirë ju lejon të llogaritni me saktësi intensitetin e secilës prej 1024 grupeve.

Një koncept perfekt, por:

  1. Meqenëse FFT është një version i dixhitalizuar i transformimit të Furierit, ai përafron sinjalin dixhital dhe humb disa informacione. Pra, në mënyrë rigoroze, rezultati i FFT nëse shndërrohet përsëri me një algoritëm të përmbysur FFT nuk do të japë saktësisht sinjalin origjinal.
  2. Gjithashtu teoria konsideron një sinjal që nuk është i kufizuar, por që është një sinjal konstant i qëndrueshëm. Meqenëse ne do ta digjitalizojmë atë vetëm për një periudhë të caktuar kohe (d.m.th. mostra), do të futen edhe disa gabime të tjera.
  3. Së fundi, zgjidhja e konvertimit analog në dixhital do të ndikojë në cilësinë e vlerave të llogaritura.

Në praktikë

1) Frekuenca e kampionimit (shënuar fs)

Ne marrim një sinjal, domethënë matim amplitudën e tij, çdo 1/fs sekonda. fs është frekuenca e kampionimit. Për shembull, nëse marrim mostër në 8 KHz, ADC (konvertuesi analog në dixhital) që është në bordin e çipit do të sigurojë një matje çdo 1/8000 sekonda.

2) Numri i mostrave (shënuar N ose mostra në kod)

Meqenëse ne duhet të marrim të gjitha vlerat para se të ekzekutojmë FFT, do të na duhet t'i ruajmë ato dhe kështu do të kufizojmë numrin e mostrave. Algoritmi FFT ka nevojë për një numër mostrash që është një fuqi prej 2. Sa më shumë mostra të kemi aq më mirë por kërkon shumë memorie, aq më tepër që do të na duhet gjithashtu për të ruajtur të dhënat e transformuara, që janë vlera komplekse. Biblioteka Arduino FFT kursen pak hapësirë duke përdorur

  • Një grup i quajtur "vReal" për të ruajtur të dhënat e marra dhe pastaj pjesën reale të të dhënave të transformuara
  • Një grup i quajtur "vImag" për të ruajtur pjesën imagjinare të të dhënave të transformuara

Sasia e nevojshme e RAM -it është e barabartë me 2 (vargje) * 32 (bit) * N (mostra).

Pra, në Atmega1284 -in tonë që ka 16 KB RAM të bukur do të ruajmë një maksimum prej vlerave N = 16000*8 /64 = 2000. Meqenëse numri i vlerave duhet të jetë një fuqi prej 2, ne do të ruajmë një maksimum prej 1024 vlerash.

3) Rezolucioni i frekuencës

FFT do të llogarisë vlerat për aq breza frekuencash sa numri i mostrave. Këto breza do të shtrihen nga 0 HZ në frekuencën e marrjes së mostrave (fs). Prandaj, zgjidhja e frekuencës është:

Rezolucioni = fs / N

Rezolucioni është më i mirë kur është më i ulët. Pra, për një rezolucion më të mirë (më të ulët) ne duam:

  • më shumë mostra, dhe/ose
  • një fs më të ulët

Por…

4) Fs minimale

Meqenëse ne duam të shohim shumë frekuenca, disa prej tyre janë shumë më të larta se "frekuenca themelore", ne nuk mund t'i vendosim fs shumë të ulëta. Në fakt ekziston teorema e marrjes së mostrave Nyquist -Shannon që na detyron të kemi një frekuencë marrjeje shumë më të madhe se dyfishi i frekuencës maksimale që do të donim të testonim.

Për shembull, nëse do të donim të analizonim të gjithë spektrin nga 0 Hz deri në 15 KHz, që është afërsisht frekuenca maksimale që shumica e njerëzve mund të dëgjojnë në mënyrë të qartë, ne duhet të vendosim frekuencën e marrjes së mostrës në 30 KHz. Në fakt elektronikët shpesh e vendosin atë në 2.5 (ose edhe 2.52) * frekuencën maksimale. Në këtë shembull do të ishte 2.5 * 15 KHz = 37.5 KHz. Frekuencat e zakonshme të marrjes së mostrave në audion profesionale janë 44.1 KHz (regjistrimi i audios CD), 48 KHz dhe më shumë.

Përfundim:

Pikat 1 deri në 4 çojnë në: ne duam të përdorim sa më shumë mostra të jetë e mundur. Në rastin tonë me një pajisje RAM 16 KB ne do të marrim parasysh 1024 mostra. Ne duam të marrim mostra në frekuencën më të ulët të marrjes së mostrave, për aq kohë sa është mjaft e lartë për të analizuar frekuencën më të lartë që presim në sinjalin tonë (2.5 * kjo frekuencë, të paktën).

Hapi 3: Simulimi i një sinjali

Simulimi i një sinjali
Simulimi i një sinjali

Për përpjekjen tonë të parë, ne do të modifikojmë pak shembullin TFT_01.ino të dhënë në bibliotekë, për të analizuar një sinjal të përbërë nga

  • Frekuenca themelore, e vendosur në 440 Hz (A muzikore)
  • Harmonika e tretë në gjysmën e fuqisë themelore ("-3 dB")
  • Harmonika e 5-të në 1/4 e fuqisë së bazës ("-6 dB)

Ju mund të shihni në figurën sipër sinjalin që rezulton. Duket vërtet shumë si një sinjal i vërtetë që ndonjëherë mund të shihni në një oshiloskop (unë do ta quaja "Batman") në një situatë kur ka një prerje të një sinjali sinusoidal.

Hapi 4: Analiza e një Sinjali të Simuluar - Kodimi

0) Përfshini bibliotekën

#përfshi "arduinoFFT.h"

1) Përkufizimet

Në seksionet e deklaratave, ne kemi

const byte adcPin = 0; // A0

const uint16_t mostra = 1024; // Kjo vlerë DUHET GJITHMON të jetë një fuqi prej 2 const uint16_t samplingFrequency = 8000; // Do të ndikojë në vlerën maksimale të kohëmatësit në timer_setup () SYSCLOCK/8/samplingFrekuenca duhet të jetë një numër i plotë

Meqenëse sinjali ka një harmonikë të 5 -të (frekuenca e këtij harmoniku = 5 * 440 = 2200 Hz) ne duhet të vendosim frekuencën e marrjes së mostrës mbi 2.5 * 2200 = 5500 Hz. Këtu zgjodha 8000 Hz.

Ne gjithashtu deklarojmë vargjet ku do të ruajmë të dhënat e papërpunuara dhe të llogaritura

noton vReal [mostra];

float vImag [mostra];

2) Instalimi

Ne krijojmë një objekt ArduinoFFT. Versioni dev i ArduinoFFT përdor një shabllon kështu që ne mund të përdorim ose llojin e të dhënave float ose të dyfishtë. Float (32 bit) është e mjaftueshme në lidhje me saktësinë e përgjithshme të programit tonë.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, mostra, mostraFrequency);

3) Simulimi i sinjalit duke plotësuar grupin vReal, në vend që ta populloni atë me vlera ADC.

Në fillim të lakut, ne e mbushim grupin vReal me:

ciklet e notimit = ((((mostrat) * sinjal Frekuenca) / marrja e mostraveFrekuenca); // Numri i cikleve të sinjalit që do të lexojë kampioni

për (uint16_t i = 0; i <mostra; i ++) {vReal = noton ((amplituda * (sin ((i * (TWO_PI * ciklet))) / mostra)))); / * Ndërtoni të dhëna me pozitive dhe vlerat negative */ vReal += noton ((amplituda * (sin ((3 * i * (TWO_PI * cikle))/ mostra)))/ 2.0);/ * Ndërtoni të dhëna me vlera pozitive dhe negative */ vReal += noton ((amplituda * (sin ((5 * i * (TWO_PI * cikle))) / mostra))) / 4.0); / * Ndërtoni të dhëna me vlera pozitive dhe negative * / vImag = 0.0; // Pjesa imagjinare duhet të zerohet në rast të lakimit për të shmangur llogaritjet dhe daljet e gabuara}

Ne shtojmë një dixhitalizim të valës themelore dhe dy harmonikave me më pak amplituda. Atëherë ne inicializojmë grupin imagjinar me zero. Meqenëse kjo grup është e populluar nga algoritmi FFT, ne duhet ta pastrojmë atë përsëri para çdo llogaritjeje të re.

4) Llogaritja FFT

Pastaj ne llogarisim FFT dhe densitetin spektral

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

FFT.compute (FFTDirection:: Forward); / * Llogarit FFT */ FFT.complexToMagnitude (); / * Llogaritni madhësitë */

Operacioni FFT.windowing (…) modifikon të dhënat e papërpunuara sepse ne e drejtojmë FFT -në në një numër të kufizuar mostrash. Mostrat e para dhe të fundit paraqesin një ndërprerje (nuk ka "asgjë" në njërën anë të tyre). Ky është një burim gabimi. Operacioni "dritare" tenton të zvogëlojë këtë gabim.

FFT.compute (…) me drejtimin "Përpara" llogarit shndërrimin nga fusha e kohës në fushën e frekuencës.

Pastaj ne llogarisim vlerat e madhësisë (dmth. Intensitetit) për secilën nga brezat e frekuencave. Grupi vReal tani është i mbushur me vlera të madhësive.

5) Vizatim serial plotter

Le të shtypim vlerat në komplotuesin serik duke thirrur funksionin printVector (…)

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

Ky është një funksion i përgjithshëm që lejon printimin e të dhënave me bosht kohor ose bosht frekuence.

Ne gjithashtu shtypim frekuencën e brezit që ka vlerën më të madhe të madhësisë

noton x = FFT.majorPeak ();

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

Hapi 5: Analiza e një Sinjali të Simuluar - Rezultatet

Analiza e një Sinjali të Simuluar - Rezultatet
Analiza e një Sinjali të Simuluar - Rezultatet

Ne shohim 3 thumba që korrespondojnë me frekuencën themelore (f0), harmonikën e 3 -të dhe të 5 -të, me gjysmën dhe 1/4 të madhësisë f0, siç pritej. Ne mund të lexojmë në krye të dritares f0 = 440.430114 Hz. Kjo vlerë nuk është saktësisht 440 Hz, për të gjitha arsyet e shpjeguara më lart, por është shumë afër vlerës reale. Nuk ishte me të vërtetë e nevojshme të tregoheshin kaq shumë decimale të parëndësishme.

Hapi 6: Analiza e një Sinjali Real - Instalimi i ADC

Analiza e një Sinjali Real - Instalimi i ADC
Analiza e një Sinjali Real - Instalimi i ADC

Meqenëse ne dimë si të veprojmë në teori, ne do të donim të analizonim një sinjal të vërtetë.

Instalimet elektrike janë shumë të thjeshta. Lidhni bazat së bashku dhe vijën e sinjalit në pinin A0 të tabelës tuaj përmes një rezistence seri me një vlerë prej 1 Koh në 10 Koh.

Ky rezistencë seri do të mbrojë hyrjen analoge dhe do të shmangë zhurmën. Duhet të jetë sa më i lartë që të shmanget zilja dhe sa më i ulët të jetë e mundur për të siguruar rrymë të mjaftueshme për të ngarkuar ADC me shpejtësi. Referojuni fletës së të dhënave MCU për të ditur rezistencën e pritshme të sinjalit të lidhur në hyrjen ADC.

Për këtë demonstrim kam përdorur një gjenerator funksioni për të ushqyer një sinjal sinusoidal me frekuencë 440 Hz dhe amplituda rreth 5 volt (është më mirë nëse amplituda është midis 3 dhe 5 volt, kështu që ADC përdoret në shkallë të plotë), përmes një rezistori 1.2 KOhm Me

Hapi 7: Analiza e një Sinjali Real - Kodimi

0) Përfshini bibliotekën

#përfshi "arduinoFFT.h"

1) Deklaratat dhe instancimi

Në pjesën e deklaratës ne përcaktojmë hyrjen ADC (A0), numrin e mostrave dhe frekuencën e marrjes së mostrave, si në shembullin e mëparshëm.

const byte adcPin = 0; // A0

const uint16_t mostra = 1024; // Kjo vlerë DUHET GJITHMON të jetë një fuqi prej 2 const uint16_t samplingFrequency = 8000; // Do të ndikojë në vlerën maksimale të kohëmatësit në timer_setup () SYSCLOCK/8/samplingFrekuenca duhet të jetë një numër i plotë

Ne krijojmë objektin ArduinoFFT

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, mostra, mostraFrequency);

2) Vendosja e kohëmatësit dhe ADC

Ne vendosëm kohëmatësin 1 kështu që ai ciklohet në frekuencën e marrjes së mostrave (8 KHz) dhe ngre një ndërprerje në krahasimin e daljes.

void timer_setup () {

// rivendos Kohëmatësi 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bit (CS11) | bit (WGM12); // CTC, parakalues i 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000 /8) / samplingFrequency) -1; }

Dhe vendosni ADC ashtu

  • Përdor A0 si hyrje
  • Shkakton automatikisht në çdo dalje të kohëmatësit 1 krahasoni ndeshjen B
  • Krijon një ndërprerje kur konvertimi është i plotë

Ora ADC është vendosur në 1 MHz, duke parakaluar orën e sistemit (16 MHz) me 16. Meqenëse çdo konvertim merr afërsisht 13 orë në shkallë të plotë, shndërrimet mund të arrihen në një frekuencë 1/13 = 0.076 MHz = 76 KHz. Frekuenca e marrjes së mostrave duhet të jetë dukshëm më e ulët se 76 KHz për t'i dhënë ADC -së të ketë kohë për të marrë të dhënat. (kemi zgjedhur fs = 8 KHz).

void adc_setup () {

ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF); // ndizni ADC, dëshironi ndërprerje në përfundim ADCSRA | = bit (ADPS2); // Parashkruesi i 16 ADMUX = bit (REFS0) | (adcPin & 7); // vendosja e hyrjes ADC ADCSRB = bit (ADTS0) | bit (ADTS2); // Kohëmatësi/Counter1 Krahaso Match B burimin e shkaktimit ADCSRA | = bit (ADATE); // ndiz aktivizimin automatik}

Ne deklarojmë mbajtësin e ndërprerjes që do të thirret pas çdo konvertimi ADC për të ruajtur të dhënat e konvertuara në grupin vReal dhe pastrimin e ndërprerjes

// ISC e plotë ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; nëse (rezultatiNumri == mostra) {ADCSRA = 0; // çaktivizo ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Ju mund të keni një shpjegim shterues mbi konvertimin ADC në Arduino (analogRead).

3) Konfigurimi

Në funksionin e konfigurimit pastrojmë tabelën e të dhënave imagjinare dhe thërrasim funksionet e kohëmatësit dhe ADC

zeroI (); // një funksion që vendos në 0 të gjitha të dhënat imagjinare - shpjeguar në pjesën e mëparshme

timer_setup (); adc_setup ();

3) Lak

FFT.dcRemoval (); // Hiq komponentin DC të këtij sinjali pasi ADC i referohet tokëzimit

FFT.dritare (FFTWindow:: Hamming, FFTDirection:: Forward); // Peshoni të dhënat FFT.compute (FFTDirection:: Forward); // Llogarit FFT FFT.complexToMagnitude (); // Llogarit madhësitë // shtypja e spektrit dhe frekuenca themelore f0 PrintVector (vReal, (mostrat >> 1), SCL_FREQUENCY); noton x = FFT.majorPeak (); Serial.print ("f0 ="); Serial.print (x, 6); Serial.println ("Hz");

Ne heqim komponentin DC sepse ADC i referohet tokës dhe sinjali përqendrohet rreth 2.5 volt përafërsisht.

Pastaj ne llogarisim të dhënat siç shpjegohet në shembullin e mëparshëm.

Hapi 8: Analiza e një Sinjali Real - Rezultatet

Analiza e një Sinjali Real - Rezultatet
Analiza e një Sinjali Real - Rezultatet

Në të vërtetë ne shohim vetëm një frekuencë në këtë sinjal të thjeshtë. Frekuenca themelore e llogaritur është 440.118194 Hz. Këtu përsëri vlera është një përafrim shumë i ngushtë i frekuencës reale.

Hapi 9: Po në lidhje me një sinjal sinusoidal të prerë?

Po në lidhje me një sinjal sinusoidal të prerë?
Po në lidhje me një sinjal sinusoidal të prerë?

Tani le të mbingarkojmë pak ADC duke rritur amplituda e sinjalit mbi 5 volt, kështu që është e prerë. Mos nxitoni shumë për të mos shkatërruar hyrjen ADC!

Ne mund të shohim shfaqjen e disa harmonikëve. Prerja e sinjalit krijon komponentë me frekuencë të lartë.

Ju keni parë bazat e analizës FFT në një bord Arduino. Tani mund të provoni të ndryshoni frekuencën e marrjes së mostrave, numrin e mostrave dhe parametrin e dritares. Biblioteka gjithashtu shton disa parametra për të llogaritur FFT më shpejt me më pak saktësi. Ju do të vini re se nëse e vendosni frekuencën e marrjes së mostrave shumë të ulët, madhësitë e llogaritura do të duken krejtësisht të gabuara për shkak të palosjes spektrale.

Recommended: