INHOUDSOPGAWE:
- Stap 1: Installeer die biblioteek
- Stap 2: Fourier Transform en FFT -konsepte
- Stap 3: Simuleer 'n sein
- Stap 4: Ontleding van 'n gesimuleerde sein - kodering
- Stap 5: Ontleding van 'n gesimuleerde sein - Resultate
- Stap 6: Ontleding van 'n werklike sein - Bedrading van die ADC
- Stap 7: Ontleding van 'n werklike sein - kodering
- Stap 8: Ontleding van 'n werklike sein - Resultate
- Stap 9: Wat van 'n geknipte sinusvormige sein?
Video: 1024 monsters FFT -spektrumanaliseerder met behulp van 'n Atmega1284: 9 stappe
2024 Outeur: John Day | [email protected]. Laas verander: 2024-01-30 07:24
Hierdie relatief maklike handleiding (met inagneming van die kompleksiteit van hierdie onderwerp) sal u wys hoe u 'n baie eenvoudige 1024 monsters spektrumanaliseerder kan maak met 'n Arduino -tipe bord (1284 smal) en die seriële plotter. Enige soort Arduino -versoenbare bord sal dit doen, maar hoe meer RAM dit het, hoe beter is die frekwensie -resolusie. Dit sal meer as 8 KB RAM benodig om die FFT met 1024 monsters te bereken.
Spektrumanalise word gebruik om die hooffrekwensie -komponente van 'n sein te bepaal. Baie klanke (soos die wat deur 'n musiekinstrument geproduseer word) bestaan uit 'n fundamentele frekwensie en 'n paar harmonieke wat 'n heelgetal veelvoud van die fundamentele frekwensie het. Die spektrumanaliseerder wys al hierdie spektrale komponente.
Miskien wil u hierdie opstelling as 'n frekwensieteller gebruik of om te kyk of daar enige seine is wat u vermoed dat dit 'n bietjie geraas in u elektroniese stroombaan veroorsaak.
Ons fokus hier op die sagtewaregedeelte. As u 'n permanente kring vir 'n spesifieke toepassing wil maak, moet u die sein versterk en filter. Hierdie vooraf kondisionering is heeltemal afhanklik van die sein wat u wil bestudeer, afhangende van die amplitude, impedansie, maksimum frekwensie, ens … U kan
Stap 1: Installeer die biblioteek
Ons sal die ArduinoFFT -biblioteek gebruik wat deur Enrique Condes geskryf is. Aangesien ons soveel as moontlik RAM wil bespaar, sal ons die ontwikkel -tak van hierdie bewaarplek gebruik wat die float -datatipe (in plaas van dubbel) kan gebruik om die bemonsterde en berekende data te stoor. Ons moet dit dus handmatig installeer. Moenie bekommerd wees nie, laai net die argief af en pak dit uit in u Arduino -biblioteekmap (byvoorbeeld in Windows 10 se standaardkonfigurasie: C: / Users / _your_user_name_ / Documents / Arduino / libraries)
U kan seker maak dat die biblioteek korrek geïnstalleer is deur een van die voorbeelde saam te stel, soos "FFT_01.ino."
Stap 2: Fourier Transform en FFT -konsepte
Waarskuwing: as u nie 'n wiskundige notasie kan sien nie, wil u moontlik na stap 3. As u dit nie alles regkry nie, moet u die gevolgtrekking aan die einde van die afdeling oorweeg.
Die frekwensiespektrum word verkry deur 'n Fast Fourier Transform -algoritme. FFT is 'n digitale implementering wat die wiskundige konsep van die Fourier Transform benader. Onder hierdie konsep, sodra u die evolusie van 'n sein na 'n tydas kry, kan u die voorstelling daarvan ken in 'n frekwensiedomein, saamgestel uit komplekse (werklike + denkbeeldige) waardes. Die konsep is wederkerig, dus as u die frekwensiedomeinvoorstelling ken, kan u dit na die tyddomein terugskakel en die sein presies terug kry soos voor die transformasie.
Maar wat gaan ons met hierdie stel berekende komplekse waardes in die tydsgebied doen? Die grootste deel daarvan word aan die ingenieurs oorgelaat. Vir ons sal ons 'n ander algoritme noem wat hierdie komplekse waardes in spektrale digtheidsdata sal omskep: dit is 'n grootte (= intensiteit) waarde wat met elke frekwensieband geassosieer word. Die aantal frekwensieband sal dieselfde wees as die aantal monsters.
U is beslis bekend met die gelykmaker -konsep, soos hierdie Terug na die 1980's met die grafiese EQ. Wel, ons sal dieselfde soort resultate behaal, maar met 1024 bands in plaas van 16 en veel meer intensiteitsresolusie. As die gelykmaker 'n globale beeld van die musiek gee, kan die fyn spektrale analise die intensiteit van elk van die 1024 bande presies bereken.
'N Perfekte konsep, maar:
- Aangesien die FFT 'n gedigitaliseerde weergawe van die Fourier -transform is, benader dit die digitale sein en verloor dit inligting. Dus, streng gesproke, sou die resultaat van die FFT as dit met 'n omgekeerde FFT -algoritme teruggeskakel word, nie presies die oorspronklike sein gee nie.
- Die teorie beskou ook 'n sein wat nie eindig is nie, maar dit is 'n ewigdurende konstante sein. Aangesien ons dit slegs vir 'n sekere tydsduur (byvoorbeeld monsters) sal digitaliseer, sal nog 'n paar foute ingestel word.
-
Uiteindelik sal die resolusie van die analoog na digitale omskakeling die kwaliteit van die berekende waardes beïnvloed.
In die praktyk
1) Die steekproeffrekwensie (opgemerk fs)
Ons neem elke 1/fs sekonde 'n sein, dit wil sê die amplitude daarvan. fs is die bemonsteringsfrekwensie. As ons byvoorbeeld met 'n monster van 8 KHz meet, sal die ADC (analoog na digitaal omskakelaar) wat aan boord is, elke 1/8000 sekondes 'n meting lewer.
2) Die aantal monsters (aangeteken N of monsters in die kode)
Aangesien ons al die waardes moet kry voordat ons die FFT gebruik, moet ons dit stoor, en daarom beperk ons die aantal monsters. Die FFT -algoritme benodig 'n aantal monsters met 'n krag van 2. Hoe meer monsters ons het, hoe beter, maar dit verg baie geheue, des te meer sal ons ook die getransformeerde data moet stoor, wat komplekse waardes is. Die Arduino FFT -biblioteek bespaar ruimte deur te gebruik
- Een skikking met die naam "vReal" om die gegewe monsters te stoor en dan die werklike deel van die getransformeerde data
- Een skikking met die naam "vImag" om die denkbeeldige deel van die getransformeerde data op te slaan
Die benodigde hoeveelheid RAM is gelyk aan 2 (skikkings) * 32 (bisse) * N (monsters).
In ons Atmega1284 met 'n goeie 16 KB RAM, sal ons 'n maksimum van N = 16000*8/64 = 2000 waardes stoor. Aangesien die aantal waardes 'n krag van 2 moet wees, sal ons 'n maksimum van 1024 waardes stoor.
3) Die frekwensie -resolusie
Die FFT sal waardes bereken vir soveel frekwensiebande as die aantal monsters. Hierdie bande sal strek van 0 HZ tot die bemonsteringsfrekwensie (fs). Daarom is die frekwensie -resolusie:
Oplossing = fs / N
Die resolusie is beter as dit laer is. Vir 'n beter resolusie (laer) wil ons:
- meer monsters, en/of
- 'n laer fs
Maar…
4) Minimale fs
Aangesien ons baie frekwensies wil sien, waarvan sommige baie hoër is as die 'fundamentele frekwensie', kan ons nie fs te laag stel nie. In werklikheid is daar die Nyquist -Shannon -bemonsteringsstelling wat ons dwing om 'n bemonsteringsfrekwensie te hê wat baie hoër is as twee keer die maksimum frekwensie wat ons wil toets.
As ons byvoorbeeld die hele spektrum van 0 Hz wil analiseer om 15 KHz te sê, wat ongeveer die maksimum frekwensie is wat die meeste mense duidelik kan hoor, moet ons die bemonsteringsfrekwensie op 30 KHz stel. Trouens, elektronici stel dit dikwels op 2,5 (of selfs 2,52) * die maksimum frekwensie. In hierdie voorbeeld sou dit 2,5 * 15 KHz = 37,5 KHz wees. Gewone bemonsteringsfrekwensies in professionele klank is 44,1 KHz (klank -CD -opname), 48 KHz en meer.
Afsluiting:
Punte 1 tot 4 lei tot: ons wil soveel monsters as moontlik gebruik. In ons geval met 'n 16 KB RAM -toestel, sal ons 1024 monsters oorweeg. Ons wil op die laagste bemonsteringsfrekwensie moontlik meet, solank dit hoog genoeg is om die hoogste frekwensie wat ons in ons sein verwag, te ontleed (ten minste 2,5 * hierdie frekwensie).
Stap 3: Simuleer 'n sein
Vir ons eerste poging, sal ons die TFT_01.ino -voorbeeld wat in die biblioteek gegee word, effens verander om 'n sein wat uit
- Die fundamentele frekwensie, ingestel op 440 Hz (musikale A)
- 3de harmoniese met die helfte van die krag van die fundamentele ("-3 dB")
- 5de harmoniese by 1/4 van die krag van die fundamentele ("-6 dB)
U kan die sein bo -op die prentjie sien. Dit lyk inderdaad baie na 'n werklike sein wat 'n mens soms op 'n ossilloskoop kan sien (ek sou dit 'Batman' noem) in 'n situasie as daar 'n sinusvormige sein uitknip.
Stap 4: Ontleding van 'n gesimuleerde sein - kodering
0) Sluit die biblioteek in
#sluit "arduinoFFT.h" in
1) Definisies
In die verklaringsafdelings het ons
const byte adcPin = 0; // A0
const uint16_t monsters = 1024; // Hierdie waarde MOET ALTYD 'n krag van 2 konst uint16_t samplingFrequency = 8000 wees; // Sal die maksimum waarde van die timer in timer_setup () SYSCLOCK/8/sampling beïnvloed Die frekwensie moet 'n heelgetal wees
Aangesien die sein 'n 5de harmonika het (frekwensie van hierdie harmoniese = 5 * 440 = 2200 Hz), moet ons die bemonsteringsfrekwensie bo 2,5 * 2200 = 5500 Hz stel. Hier het ek 8000 Hz gekies.
Ons verklaar ook die skikkings waar ons die rou en berekende data sal stoor
float vReal [monsters];
float vImag [monsters];
2) Instantiëring
Ons skep 'n ArduinoFFT -voorwerp. Die dev -weergawe van ArduinoFFT gebruik 'n sjabloon sodat ons óf die float óf die dubbele datatipe kan gebruik. Float (32 bis) is genoeg met betrekking tot die algehele presisie van ons program.
ArduinoFFT FFT = ArduinoFFT (vReal, vImag, monsters, samplingFrequency);
3) Simuleer die sein deur die vReal -skikking te vul, in plaas daarvan dat dit gevul word met ADC -waardes.
Aan die begin van die lus vul ons die vReal -skikking in met:
vlot siklusse = (((monsters) * seinfrekwensie) / steekproeffrekwensie); // Aantal seinsiklusse wat die steekproefneming sal lees
for (uint16_t i = 0; i <samples; i ++) {vReal = float ((amplitude * (sin ((i * (TWO_PI * siklusse)) / monsters))))) / / Bou data met positiewe en negatiewe waardes */ vReal += float ((amplitude * (sin ((3 * i * (TWO_PI * siklusse))/ monsters)))/ 2.0);/ * Bou data met positiewe en negatiewe waardes */ vReal += float ((amplitude * (sin ((5 * i * (TWO_PI * siklusse)) / monsters))) / 4.0); / * Bou data met positiewe en negatiewe waardes * / vImag = 0.0; // Die denkbeeldige deel moet nul word in die geval van 'n lus om verkeerde berekeninge en oorstromings te vermy}
Ons voeg 'n digitalisering van die fundamentele golf en die twee harmonieke by met minder amplitude. Dan begin ons die denkbeeldige skikking met nulle. Aangesien hierdie skikking deur die FFT -algoritme ingevul word, moet ons dit weer voor elke nuwe berekening uitvee.
4) FFT -rekenaars
Dan bereken ons die FFT en die spektrale digtheid
FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward);
FFT.compute (FFTDirection:: Forward); / * Bereken FFT */ FFT.complexToMagnitude (); / * Bereken groottes */
FFT.windowing (…) werking verander die rou data omdat ons die FFT op 'n beperkte aantal monsters gebruik. Die eerste en laaste monsters toon 'n diskontinuïteit (daar is "niks" aan die een kant). Dit is 'n bron van foute. Die "venster" -bewerking is geneig om hierdie fout te verminder.
FFT.compute (…) met die rigting "Vorentoe" bereken die transformasie van die tyddomein na die frekwensiedomein.
Dan bereken ons die grootte (d.w.s. intensiteit) waardes vir elk van die frekwensiebande. Die vReal -skikking is nou gevul met grootteswaardes.
5) Seriële plottertekening
Laat ons die waardes op die reeksplotter druk deur die funksie printVector (…) te noem
PrintVector (vReal, (monsters >> 1), SCL_FREQUENCY);
Dit is 'n generiese funksie waarmee data met 'n tydas of 'n frekwensie -as gedruk kan word.
Ons druk ook die frekwensie van die band met die hoogste groottewaarde af
float x = FFT.majorPeak ();
Serial.print ("f0 ="); Reeks.afdruk (x, 6); Serial.println ("Hz");
Stap 5: Ontleding van 'n gesimuleerde sein - Resultate
Ons sien 3 spykers wat ooreenstem met die fundamentele frekwensie (f0), die 3de en 5de harmonieke, met die helfte en 1/4 van die f0 -grootte, soos verwag. Ons kan bo in die venster lees f0 = 440.430114 Hz. Hierdie waarde is nie presies 440 Hz nie, as gevolg van al die redes hierbo verduidelik, maar dit is baie naby aan die werklike waarde. Dit was nie regtig nodig om soveel onbeduidende desimale aan te toon nie.
Stap 6: Ontleding van 'n werklike sein - Bedrading van die ADC
Aangesien ons weet hoe om teoreties te werk te gaan, wil ons 'n werklike sein ontleed.
Die bedrading is baie eenvoudig. Koppel die gronde en die seinlyn aan die A0 -pen van u bord deur 'n reeksweerstand met 'n waarde van 1 KOhm tot 10 KOhm.
Hierdie reeksweerstand beskerm die analoog insette en voorkom dat dit lui. Dit moet so hoog as moontlik wees om te voorkom dat dit lui, en so laag as moontlik om genoeg stroom te gee om die ADC vinnig te laai. Raadpleeg die MCU -datablad om die verwagte impedansie van die sein wat by die ADC -ingang gekoppel is, te ken.
Vir hierdie demo het ek 'n funksiegenerator gebruik om 'n sinusvormige sein van frekwensie 440 Hz en amplitude rondom 5 volt te voer (dit is die beste as die amplitude tussen 3 en 5 volt is, sodat die ADC naby volle skaal gebruik word), deur 'n weerstand van 1,2 KOhm.
Stap 7: Ontleding van 'n werklike sein - kodering
0) Sluit die biblioteek in
#sluit "arduinoFFT.h" in
1) Verklarings en instansie
In die deklarasie -afdeling definieer ons die ADC -invoer (A0), die aantal monsters en die bemonsteringsfrekwensie, soos in die vorige voorbeeld.
const byte adcPin = 0; // A0
const uint16_t monsters = 1024; // Hierdie waarde MOET ALTYD 'n krag van 2 konst uint16_t samplingFrequency = 8000 wees; // Sal die maksimum waarde van die timer in timer_setup () SYSCLOCK/8/sampling beïnvloed Die frekwensie moet 'n heelgetal wees
Ons skep die ArduinoFFT -voorwerp
ArduinoFFT FFT = ArduinoFFT (vReal, vImag, monsters, samplingFrequency);
2) Timer en ADC opstelling
Ons stel timer 1 in sodat dit met die bemonsteringsfrekwensie (8 KHz) siklusse kry en 'n onderbreking van die uitset vergelyk.
nietig timer_setup () {
// reset timer 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bietjie (CS11) | bietjie (WGM12); // CTC, prescaler van 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000 /8) / steekproef frekwensie) -1; }
En stel die ADC so in
- Gebruik A0 as invoer
- Triggers outomaties op elke timer 1 uitset vergelyk wedstryd B
- Genereer 'n onderbreking wanneer die omskakeling voltooi is
Die ADC -klok word op 1 MHz gestel, deur die stelselklok (16 MHz) vooraf te skaal met 16. Omdat elke omskakeling ongeveer 13 horlosies op volle skaal neem, kan omskakelings bereik word met 'n frekwensie van 1/13 = 0,076 MHz = 76 KHz. Die bemonsteringsfrekwensie moet aansienlik laer as 76 KHz wees, sodat die ADC tyd het om die data te neem. (ons het fs = 8 KHz gekies).
ongeldig adc_setup () {
ADCSRA = bietjie (ADEN) | bietjie (ADIE) | bietjie (ADIF); // skakel ADC aan, wil onderbreking by voltooiing ADCSRA | = bit (ADPS2); // Voorverkoeler van 16 ADMUX = bit (REFS0) | (adcPin & 7); // die ADC -invoer instel ADCSRB = bit (ADTS0) | bietjie (ADTS2); // Timer/Counter1 Vergelyk Match B -snellerbron ADCSRA | = bit (ADATE); // skakel outomatiese sneller aan}
Ons verklaar die onderbrekingshanteerder wat na elke ADC -omskakeling gebel sal word, om die omskepte data in die vReal -skikking te stoor en die onderbreking te verwyder
// ADC volledige ISR
ISR (ADC_vect) {vReal [resultNumber ++] = ADC; as (resultNumber == monsters) {ADCSRA = 0; // skakel ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect) af;
U kan 'n volledige uiteensetting hê van die ADC -omskakeling op die Arduino (analogRead).
3) Opstel
In die opstelfunksie maak ons die denkbeeldige datatabel skoon en skakel die timer en ADC -opstelfunksies
zeroI (); // 'n funksie wat al die denkbeeldige data op 0 stel - verduidelik in die vorige afdeling
timer_setup (); adc_setup ();
3) Lus
FFT.dcRemoval (); // Verwyder die GS -komponent van hierdie sein, aangesien die ADC na die aarde verwys word
FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward); // Weeg data FFT.compute (FFTDirection:: Forward); // Bereken FFT FFT.complexToMagnitude (); // Bereken groottes // druk die spektrum en die fundamentele frekwensie uit f0 PrintVector (vReal, (monsters >> 1), SCL_FREQUENCY); float x = FFT.majorPeak (); Serial.print ("f0 ="); Reeks.afdruk (x, 6); Serial.println ("Hz");
Ons verwyder die GS -komponent omdat die ADC na die aarde verwys en die sein ongeveer 2,5 volt gesentreer is.
Dan bereken ons die data soos uiteengesit in die vorige voorbeeld.
Stap 8: Ontleding van 'n werklike sein - Resultate
Ons sien inderdaad slegs een frekwensie in hierdie eenvoudige sein. Die berekende fundamentele frekwensie is 440.118194 Hz. Ook hier is die waarde 'n baie noue benadering van die werklike frekwensie.
Stap 9: Wat van 'n geknipte sinusvormige sein?
Laat ons nou die ADC 'n bietjie oordryf deur die amplitude van die sein bo 5 volt te verhoog, sodat dit geknip word. Moenie te veel druk om nie die ADC -invoer te vernietig nie!
Ons kan 'n paar harmonieke sien verskyn. Deur die sein te knip, word hoëfrekwensie -komponente gevorm.
U het die grondbeginsels van FFT -analise op 'n Arduino -bord gesien. Nou kan u die bemonsteringsfrekwensie, die aantal monsters en die venstervenster probeer verander. Die biblioteek voeg ook 'n parameter by om die FFT vinniger te bereken met minder presisie. U sal opmerk dat as u die bemonsteringsfrekwensie te laag stel, die berekende groottes totaal verkeerd sal lyk as gevolg van spektrale vou.
Aanbeveel:
Arduino Nano -klok met aanpasbare helderheid met behulp van prototipe PCB van NextPCB.com: 11 stappe
Arduino Nano -klok met aanpasbare helderheid met behulp van prototipe PCB van NextPCB.com: Almal wou 'n horlosie hê wat tyd en datum saam wys. In hierdie projek sal ek u wys hoe u 'n arduino -nano -klok met aanpasbare helderheid kan bou met behulp van RTC en 'n ontwerp PCB van NextPCB
Tel van 0 tot 9999 met 8051 met behulp van 7 segmentweergawe: 5 stappe
Tel van 0 tot 9999 Met 8051 met 7 segment -skerms: Hallo almal, in hierdie tutoriaal gaan ons u vertel hoe om van 0 tot 9999 te tel met behulp van vier 7 -segment -skerms deur slegs enkele poort en 4 digitale penne te gebruik
Beheer oor die hele wêreld met behulp van internet met behulp van Arduino: 4 stappe
Beheer oor die hele wêreld met behulp van internet met behulp van Arduino: Hallo, ek is Rithik. Ons gaan 'n internetbeheerde LED maak met u telefoon. Ons gaan sagteware soos Arduino IDE en Blynk gebruik. Dit is eenvoudig, en as u daarin geslaag het, kan u soveel elektroniese komponente beheer as wat u wil
Monitor versnelling met behulp van Raspberry Pi en AIS328DQTR met behulp van Python: 6 stappe
Monitering van versnelling met behulp van Raspberry Pi en AIS328DQTR Gebruik van Python: Versnelling is eindig, volgens ek volgens sommige wette van die fisika.- Terry Riley 'n Jagluiperd gebruik ongelooflike versnelling en vinnige spoedveranderinge wanneer hy jaag. Die vinnigste wesens aan wal gebruik af en toe sy hoogste tempo om prooi te vang. Die
Hoe om van 0 tot 99 te tel met behulp van 8051 mikrobeheerder met 7 segmentweergawe: 5 stappe (met foto's)
Hoe om van 0 tot 99 te tel Met behulp van 8051 mikrobeheerder met 7 -segmentweergawe: Hallo almal, in hierdie tutoriaal gaan ons u vertel hoe om van 0 tot 99 te tel met twee 7 -segment -skerms