Fourier-transformasjon på en mikrokontroller. Spektralanalyse av signaler. Rask Fourier-transformasjon

Det er mange spesialiserte prosessorer for digital signalbehandling (DSP), slik som DSP fra Texas Instruments TMS320-serien, som inkluderer både enkle heltallskjerner og slike monstre som C6000-familiens underfamilie som behandler flyttallsdata. Det finnes en hel serie med ADSP fra Analog Devices (som inkluderer den mer eller mindre universelle BlackFin), det finnes også enklere løsninger fra MicroChip - dsPIC.

En spesialisert DSP er imidlertid bra, men er det alltid så nødvendig? Ja, med en enorm informasjonsflyt er den rett og slett uerstattelig, men det finnes også enklere behandlingsoppgaver. Spesielt var jeg interessert i oppgaven med dobbel konvertering - lydsignalet er konvolvert, og oppnår dermed et spektrum, deretter kan alle operasjoner utføres på spekteret og den inverse konverteringen kan utføres, og dermed oppnå et behandlet signal. Alt dette må gjøres i sanntid og få kvalitet som ikke er lavere enn telefonkvalitet.

Dette er ikke år 2000, det er enkeltbrikkeløsninger basert på høyytelses ARM7/Cortex-M3-kjerner som har falt betydelig i pris; de er 32-biters, har en maskinvareimplementering av en 32-bits multiplikasjonsoperasjon (i tillegg , nesten en DSP-multiog 64-biters resultat), og Cortex-M3 inkluderer også maskinvaredivisjon.

Jeg vil med en gang advare deg om at signalbehandling ikke er min spesialitet, nesten all kunnskapen (eller rettere sagt, forståelsen av prinsippene) ble bevart fra instituttet, men nå ville jeg bare teste og implementere det. Det jeg mener er at det kan være unøyaktigheter i beskrivelsen, substitusjon av begreper osv. Faktisk bekymret ikke akademisk nøyaktighet meg særlig.

For nesten alle DSP er oppgaven skissert ovenfor enkel og grei. Men hvordan vil en generell RISC-kjerne oppføre seg på den? Hvis vi vurderer AVR eller PIC, vil de neppe være nok. 8-bit og lav klokkefrekvens har en effekt. Selv om Elm-Chan har design der han utfører en FFT på AVR og tegner spekteret til signalet. Men i dette tilfellet, i sanntid, gjøres ganske enkelt visualisering (med minimal prosesseringsnøyaktighet), og ikke fullstendig signalbehandling med akseptabel lydkvalitet.

LPC2146 ble valgt som en eksperimentell brikke, basert på ARM7TDMI-S-kjernen og med en maksimal klokkefrekvens på 60 MHz (i praksis fungerer den ikke på 72 eller til og med 84 MHz). Hvorfor? For det første har jeg et debug-kort for det, og for det andre er det en ADC og DAC ombord, dvs. minimal ekstern trim nødvendig.

Litt teori

Først av alt var det interessant å evaluere ytelsen til FFT (Fast Fourier Transform) på ARM-mikrokontrollere. Basert på denne vurderingen kan vi konkludere om den har nok hastighet til å behandle en strøm av lyddata, og et signal med hvilken samplingsfrekvens og hvor mange kanaler som kan behandles på en slik mikrokontroller.

Basert på Fourier-transformasjonen kan du bygge smarte filtre (med svært attraktive egenskaper). Jeg var først og fremst interessert i problemene med å endre tonen i signalet (øke og senke spekteret) og "reflektere" spekteret. Sistnevnte kreves i SDR-radioer for å lytte til LSB-radiosendinger med lavere sidebånd.

Jeg vil ikke laste deg med teori og forklare hva Fourier-transformasjonen er; det er ganske mye materiale om dette emnet, fra det jeg brukte: en wiki og et kapittel fra en veldig god og informativ bok.

Programvareimplementering

Det er mange programvareimplementeringer av FFT, men jeg skrev min egen. Hovedmålet jeg forfulgte var å optimalisere koden for en spesifikk arkitektur. For det første fokuserte jeg umiddelbart på 32-bit, for det andre var det bare heltallsberegninger som var nødvendig og det var ønskelig å unngå divisjonsoperasjonen. Å finne noe ferdig for å oppfylle disse kravene er allerede problematisk.

Alle konstanter som kunne beregnes på forhånd ble beregnet og plassert i tabeller (for det meste verdiene til trigonometriske funksjoner). Dette er hovedoptimaliseringen av algoritmen, ellers gjentar den nesten fullstendig den beskrevne algoritmen.

Det viktigste er kravet til heltallsberegninger. Under implementeringsprosessen var det til og med en feil som forårsaket overløp i en av 32-bits sløyfevariablene. Dessuten dukket det ikke opp på alle testdata, så det forårsaket ganske hodepine før det ble funnet.

Jeg samlet alle kildetekstene i ett arkiv. Implementeringen er ikke endelig, det er dupliserte beregninger (spekter og fasesymmetri er ikke tatt i betraktning), og optimalisering av bruken av buffere er nødvendig, siden det for tiden brukes for mye RAM til beregninger (nesten 12k for en konvertering på 1024 poeng) ).

Første tester

Trommelrull: Jeg tester konverteringshastigheten for en prøve på 1024 poeng, prosessorens kjernefrekvens er 60 MHz. Testing ble utført i en emulator, så den hevder ikke å være 100% nøyaktig, men dette resultatet kan brukes som en indikator (i min tidligere erfaring, selv om emulatoren løy, var det ikke mye). Test av den første versjonen av koden, RealView MDK-kompilator, O3-optimeringsalternativ, ARM-kodegenereringsmodus.

Så det vi ser:

6ms for hver konvertering, totalt i overkant av 12ms for rundturskonverteringen. Det viser seg at med en samplingsfrekvens på 44100Hz (standard for lyd) og sampler med en oppløsning på opptil 16 bits, vil rene beregninger ta ~44*12ms = 528ms. Og dette er på en mellomversjon av fastvaren, når noen kodeoptimaliseringer ennå ikke er fullført (ifølge estimater kan algoritmen akselereres med nesten 2 ganger)! Etter min mening er det bare en utmerket indikator.

Totalt forventes kjernebelastningen å være rundt 50 %, ytterligere 50 % gjenstår for konverteringer over spekteret og overheadkostnader ved arbeid med ADC-er, DAC-er og andre dataoverføringer. Hvis du senker samplingsfrekvensen til "telefon"-nivået (ca. 4800-9600Hz), vil kjernebelastningen være enda lavere (ca. 15-30%).

Så den matematiske delen er mer eller mindre klar. Du kan gå videre til konkret implementering.

Jern

For testplattformen brukte vi et Keil MCB2140 utviklingskort med høyttaler. En Mini-Jack-ledning er loddet for å koble til den lineære utgangen på enheten og en enkel inngangskjede er satt sammen. Som allerede nevnt har brettet allerede en høyttaler koblet til den analoge utgangen på mikrokontrolleren og det er kontroller (knapp og potensiometer).

Her er en skisse av inngangskretsen:


Feilsøking av programvaren skjedde i trinn:

  1. Feilsøking av alt nødvendig periferiutstyr: ADC, DAC, timere, LED-indikasjon.
  2. Test med signaldigitalisering: Jeg digitaliserer dataene med ønsket hastighet og legger dem i en buffer, så trekker jeg ut dataene fra bufferen og spiller av signalet. De. enkel signalforskyvning i tid, uten noen transformasjoner. På dette stadiet testes mekanismen for å jobbe med 2 buffere, nødvendig for videre arbeid.
  3. Forover- og inverse Fourier-transformasjoner legges til den forrige versjonen. Denne testen verifiserer til slutt riktig funksjon av FFT-koden, samt kontrollerer at koden passer innenfor den tilgjengelige ytelsen.
  4. Etter dette er hovedskjelettet til applikasjonen ferdig, du kan gå videre til praktiske applikasjoner.

Problemet oppsto etter å ha lagt til FFT i koden: fremmed støy og fløyter dukket opp i signalet. Generelt virket denne oppførselen ganske merkelig for meg, fordi... Uten konvertering forble signalet som går gjennom den digitale banen ganske rent. Den første grunnen til dette: etter den analoge kretsen var signalamplituden på ADC ikke full (0-3,3V), men bare innenfor 0,5-2V ved maksimalt volum til spilleren, den andre: ganske sterk støy på grunn av heltall beregninger (+-1 enhet, som viste seg å være tilstrekkelig til å forårsake hørbar interferens).

For å bekjempe det første problemet, ble det besluttet å begynne å justere den analoge delen. Og for å løse problemet med støy, prøv å bruke et lavpassfilter.

Applikasjon 1: endre tonen på signalet

Brettet har potensiometer (variabel motstand), som kan brukes til styring. I dette tilfellet setter den signalspekteret til å skifte opp og ned, ganske nok til å "transformere" favorittkomposisjonene dine.

Her er hva som skjer i frekvensdomenet:


I dette tilfellet er konverteringsresultatet inneholdt i 2 buffere. En buffer er den virkelige delen, og den andre er den imaginære delen. Den fysiske betydningen av tallene oppnådd i dem: den virkelige delen inneholder verdiene til harmonikkene, den imaginære delen inneholder faseforskyvningen for disse harmoniske. Dessuten, som du kan se, er startsignalet beskrevet av N-verdier, og etter konvertering oppnås 2N-verdier. Informasjonsmengden endres ikke, og 2-doblingen i informasjonsmengden oppstår på grunn av at bufferdataene har redundans i form av duplisering av verdier.

En LCD-indikator med to linjer brukes som en visningsenhet. Hovedpoenget i implementeringen av dette prosjektet er ikke maskinvaren, men programvaren, mer presist implementeringen av den diskrete Fourier-transformasjonen (DFT) på en 8-bits mikrokontroller. Det skal bemerkes med en gang at forfatteren ikke er en ekspert på dette feltet og startet derfor med det grunnleggende - med en enkel diskret Fourier-transformasjon. Den raske Fourier-transformasjonsalgoritmen er ikke bare rask, men også ganske kompleks.

Discrete Fourier Transform (i engelsk litteratur DFT, Discrete Fourier Transform) er en av Fourier-transformasjonene som er mye brukt i digitale signalbehandlingsalgoritmer (modifikasjonene brukes i lydkomprimering i MP3, bildekomprimering i JPEG, etc.), så vel som i andre områder relatert til analyse av frekvenser i et diskret (for eksempel digitalisert analog) signal. Den diskrete Fourier-transformasjonen krever en diskret funksjon som input. Slike funksjoner lages ofte ved sampling (samplingverdier fra kontinuerlige funksjoner).

Kretsskjemaet til en lydsignalspektrumanalysator er veldig enkelt og kan deles inn i en digital og analog del.

Den digitale delen er dannet av en mikrokontroller og en LCD-indikator koblet til den. Mikrokontrolleren klokkes fra en 16 MHz kvartsresonator; +5 V-forsyningsspenningen brukes som referansespenning for mikrokontrollerens ADC.
Databussen til LCD-indikatoren er koblet til port C på mikrokontrolleren (inngangs-/utgangslinjer PC0-PC3), kontrollbussen er koblet til port D (PD5, PD6) på mikrokontrolleren. Indikatoren fungerer i 4-bits modus. En variabel motstand med en nominell verdi på 4,7 kOhm brukes til å justere kontrasten. For å jobbe med indikatoren ble det laget egendefinerte symboler for å vise 8 horisontale kolonner i analysatoren; disse egendefinerte symbolene opptar alle 64 byte med RAM på LCD-indikatoren.

Mikrokontrolleren opererer fra en ekstern 16 MHz kvartsresonator.

Den analoge delen av enheten er den viktigste delen og er en forforsterker av elektretmikrofonsignalet, hvis utgang er koblet til ADC0-kanalen til ADC innebygd i mikrokontrolleren. Vi må sette nullnivået på ADC-inngangen til nøyaktig halvparten av referansespenningen, dvs. 2,5 V. I dette tilfellet kan vi bruke den positive og negative halvbølgen til signalet, men amplituden bør ikke overstige den etablerte grensen, dvs. Forsterkningen må finjusteres for å forhindre overbelastning. Alle de ovennevnte betingelsene oppfylles av en felles laveffekts operasjonsforsterkermikrokrets.

DFT-algoritmen er litt tregere sammenlignet med Fast Fourier Transform. Men vår spektrumanalysator krever ikke høy hastighet, og hvis den kan gi en oppdateringshastighet på rundt 30 bilder per sekund, vil dette være mer enn nok til å visualisere spekteret til et lydsignal. I alle fall, i vår versjon er det mulig å oppnå en hastighet på 100 bilder per sekund, men dette er allerede en for høy parameterverdi for en LCD-indikator med to linjer og anbefales ikke. Samplingsfrekvensen er 20 kHz for en 32-punkts diskret Fourier-transformasjon og siden resultatet av transformasjonen er symmetrisk trenger vi kun å bruke den første halvdelen, dvs. første 16 resultater. Derfor kan vi vise frekvensspekteret opp til 10 kHz og analysatoroppløsningen er 10 kHz/16 = 625 Hz.

Forfatteren av designet gjorde forsøk på å øke hastigheten på DFT-beregninger. Hvis denne transformasjonen har N poeng, må vi finne N2/2-verdier av sinus og cosinus. For vår 32-punktstransformasjon må vi finne 512 sinus- og cosinusverdier. Men før vi finner dem, må vi beregne vinkelen (grader), noe som vil ta litt CPU-tid, så det ble bestemt å bruke verditabeller for disse beregningene. Ved beregning i mikrokontrollerprogrammet brukes ikke flyttall og doble presisjonstall, da dette vil ta lengre tid å behandle på en 8-bits mikrokontroller. I stedet bruker verdiene i oppslagstabellene 16-bits heltallsdata multiplisert med 10000. Deretter, etter at konverteringen er utført, deles resultatene på 10000. Med denne tilnærmingen er det mulig å utføre 120 32-punkts konverteringer pr. andre, noe som er mer enn nok for enhetene våre.

Demonstrasjon av driften av en spektrumanalysator på en ATmega32 mikrokontroller

Nedlastinger

Kildekode (mikrokontrollerprogram, sinus-, cosinus- og vinkeldatatabeller) -

  • Det er tydelig at det er vanskelig å gå lenger enn lys og musikk på en AVR, parameterne stemmer ikke. Men 120 32-punkts konverteringer per sekund kan være tilstrekkelig for de fleste oppgaver. Og du kan selvfølgelig ta en ny prøve på 625Hz, eller rettere sagt miste oppdateringsfrekvensen. Det er verdt å merke seg at MK vil føle seg dårlig; når det gjelder ytelse, er det lite annet du kan feste på den. Men her kan du organisere resultatet av resultatet ved hjelp av maskinvaredataoverføringsmetoder. Da vil det være en ekstra mikrokontroller, og den viktigste vil bare motta data fra den og behandle den kompatibel med andre prosesser. I det store og hele avhenger det fortsatt av frekvensen til prosessoren. Det var en gang mulig å overklokke megaen over 20 MHz, men til disse oppgavene vil vi nok bare få feil ved høye frekvenser. Ideen er god, hvis bare flere av de matematiske delene ville blitt skrevet ... det er implementeringen på MK
  • Jeg har også laget mer interessante analysatorer: You Tube eller en versjon på en farge-LCD: You Tube er basert på det berømte Chen-biblioteket :)
  • "vi må beregne vinkelen (grader)" Kan noen fortelle oss mer detaljert hvordan verdiene for disse tabellene beregnes?
  • Alt er klart med tabellen over sinus og cosinus. Det er ikke klart hvordan verdiene i grade_lookup-tabellen beregnes?

Introduksjon

Bøker og publikasjoner om digital signalbehandling er skrevet av forfattere som ofte ikke har noen anelse om eller forståelse for utfordringene utviklere står overfor. Dette gjelder spesielt for systemer som opererer i sanntid. Disse forfatterne tildeler seg selv den beskjedne rollen som en gud som eksisterer utenfor tid og rom, noe som forårsaker en viss forvirring blant lesere av slik litteratur. Denne publikasjonen har som mål å fjerne forvirringen som oppstår blant de fleste utviklere og hjelpe dem med å overvinne "terskelen for inngang"; for disse formålene bruker teksten bevisst analogier og terminologi fra programmeringsfeltet.

Dette opuset later ikke til å være komplett og sammenhengende.

Lagt til etter å ha lest kommentarer.
Det finnes utallige publikasjoner om hvordan man lager en FFT, men det er tydeligvis ikke nok publikasjoner om hvordan man lager en FFT, konverterer et spektrum og setter sammen et signal på nytt, og til og med i sanntid. Forfatteren prøver å fylle dette gapet.

Del én, oversikt

Det er to hovedmåter å konstruere diskrete lineære dynamiske systemer. I litteraturen kalles slike systemer vanligvis digitale filtre, som er delt inn i to hovedtyper: Finite Impulse Response (FIR) filtre og Infinite Impulse Response (IIR) filtre.

Den algoritmiske essensen av FIR-filteret er den diskrete beregningen av konvolusjonsintegralet:

Hvor x(t) er inngangssignalet
y(t) – utgangssignal
h(t) – impulsrespons fra filteret eller respons til filteret på deltafunksjonen. Impulsresponsen er den inverse Fourier-transformasjonen av den komplekse frekvensresponsen til filteret K(f).

For å danne et klart bilde for leseren, vil vi gi et eksempel på diskret beregning av konvolusjonsintegralet i C-språk i sanntid.

#define L (4) //filterlengde int FIR(int a) (statisk int i=0; //nåværende posisjon statisk int reg[L]; //array of input-verdier static const int h[L]= (1, 1,1,1);//impulsrespons int b=0;//utgangsverdi reg[i]=a; //kopier inngangsverdien til matrisen av inngangsverdier for(int j=0 ;j

Ved å kalle denne funksjonen til bestemte tidsintervaller T og gi den et inngangssignal som et argument, vil vi ved utgangen motta et utgangssignal som tilsvarer responsen til et filter med en impulsrespons av formen:

H(t)=1 ved 0 h(t)=0 i andre tilfeller.

For alle tilstedeværende er et filter med en slik impulsrespons bedre kjent som et "bevegende gjennomsnittsfilter", og følgelig er det mye enklere å implementere. I dette tilfellet brukes en slik impulsrespons som eksempel.

Mye litteratur er viet til syntese av impulsresponser til FIR-filtre; det finnes også ferdige programvareprodukter for å skaffe filtre med spesifiserte egenskaper. Forfatteren foretrekker buggy Filter Design-verktøyet fra Matlab-pakken, men dette er en smakssak.

Ved å bruke et filter med endelig impulsrespons er det mulig å sveve litt over den vanlige virkeligheten, siden det i naturen ikke er noen dynamiske systemer som har en endelig impulsrespons. Et FIR-filter er et forsøk på å gå inn i tids-frekvensdomenet fra den andre enden, ikke som naturen går, så frekvenskarakteristikkene til disse filtrene har ofte uventede egenskaper.

Filtre med uendelig impulsrespons er mye nærmere naturen. Den algoritmiske essensen av filtre med en uendelig impulsrespons kommer ned til en tilbakevendende (ikke å forveksle med rekursiv!) løsning av differensialligningen som beskriver filteret. Det vil si at hver etterfølgende verdi av filterutgangssignalet beregnes basert på den forrige verdien. Det er akkurat slik prosesser fungerer i den virkelige verden. En stein som faller fra en skyskraper hvert sekund, øker hastigheten med 9,8 m/s Speed=Speed+9,8, og den tilbakelagte distansen øker hvert sekund Distance=Distance+Speed. Den som sier at dette ikke er en tilbakevendende algoritme, la ham være den første til å kaste en stein på meg. Bare i vår Matrise tidsintervallet for å kalle funksjonen som returnerer posisjonen til steinen er mye mindre enn delingsprisen på måleinstrumentene som er tilgjengelige for oss.

Separat vil jeg definere konseptet "filterrekkefølge". Dette er antallet variabler som er gjenstand for tilbakevendende operasjoner. I eksemplet ovenfor er funksjonen som returnerer hastigheten til steinen av første orden, funksjonen som returnerer tilbakelagt distanse er av andre orden.

For til slutt å opplyse leseren, vil vi gi et eksempel på C-språket på det enkleste lavpassfilteret, kjent som "eksponentielt utjevningsfilter".

#define alfa (2) //utjevningsparameter int filter(int a) ( statisk int out_alfa=0; out_alfa=out_alfa - (out_alfa >>alfa) + a; return (out_alfa >> alfa); )

Ved å kalle denne funksjonen med frekvens F og gi den et inngangssignal som et argument, vil vi få et utgangssignal som tilsvarer responsen til et førsteordens lavpassfilter med en grensefrekvens:

Det gitte eksemplet på kildekode er helt uforståelig fra synspunktet om å forstå essensen av algoritmen. Fra synspunktet til den tilbakevendende essensen (se "fall av en stein") av algoritmen, er det mer korrekt y=y+((x-y)>>alfa);, men i dette tilfellet er det et tap av alfa signifikant sifre. Det tilbakevendende filteruttrykket fra eksempelkoden er konstruert på en slik måte at man unngår tap av betydelige biter. Det er den begrensede nøyaktigheten til beregninger som kan ødelegge skjønnheten til et digitalt filter med en uendelig impulsrespons. Dette er spesielt merkbart på høyordnede filtre med høy kvalitetsfaktor. I virkelige dynamiske systemer oppstår ikke dette problemet; vårt Matrise gjør beregninger med utrolig nøyaktighet for oss.

Mye litteratur er viet til syntese av slike filtre, og det finnes også ferdige programvareprodukter (se ovenfor).

Andre del. Fourier filter

Fra universitetskurs (for dere virkelig var det OTEC-kurset) husker mange av de tilstedeværende to hovedtilnærminger til analyse av lineære dynamiske systemer: analyse i tidsdomenet og analyse i frekvensdomenet. Tidsdomeneanalyse er løsningen av differensialligninger, konvolusjon og Duhamel-integraler. Disse analysemetodene er diskret nedfelt i digitale IIR- og FIR-filtre.

Men det er en frekvenstilnærming til analyse av lineære dynamiske systemer. Noen ganger kalles det operatør. Fourier-transformen, Laplace-transformen osv. brukes som operatorer. I det følgende skal vi bare snakke om Fourier-transformasjonen.

Denne analysemetoden er ikke mye brukt i konstruksjonen av digitale filtre. Forfatteren var ikke i stand til å finne fornuftige praktiske anbefalinger for å konstruere slike filtre på russisk. Den eneste korte omtalen av et slikt filter i praktisk litteratur er [Rabiner L., Gould B., Theory and Application of Digital Signal Processing 1978], men i denne boken er vurderingen av et slikt filter veldig overfladisk. I denne boken kalles dette filterkonstruksjonsskjemaet: "sanntidskonvolusjon ved bruk av FFT-metoden," som etter min ydmyke mening ikke gjenspeiler essensen i det hele tatt, navnet bør være kort, ellers vil det ikke være tid igjen for hvile.

Responsen til et lineært dynamisk system er den inverse Fourier-transformasjonen av produktet av Fourier-bildet til inngangssignalet x(t) og den komplekse overføringskoeffisienten K(f):

Rent praktisk antar dette analytiske uttrykket følgende prosedyre: vi tar Fourier-transformasjonen av inngangssignalet, multipliserer resultatet med den komplekse overføringskoeffisienten, utfører den inverse Fourier-transformasjonen, hvis resultat er utgangssignalet. I virkelig diskret tid kan ikke denne prosedyren utføres. Hvordan ta integralet over tid fra minus til pluss uendelig?! Det kan bare tas utenom tid...

I den diskrete verden er det et verktøy for å utføre Fourier-transformasjonen - Fast Fourier Transform (FFT)-algoritmen. Dette er hva vi skal bruke når vi implementerer Fourier-filteret vårt. Argumentet til FFT-funksjonen er en rekke tidsprøver av 2^n elementer, resultatet er to matriser med lengde 2^n elementer som tilsvarer de reelle og imaginære delene av Fourier-transformasjonen. Et diskret trekk ved FFT-algoritmen er at inngangssignalet betraktes som periodisk med et intervall på 2^n. Dette legger noen begrensninger på Fourier-filteralgoritmen. Hvis du tar en sekvens av prøver av inngangssignalet, utfører en FFT på dem, multipliserer FFT-resultatet med den komplekse forsterkningen til filteret og utfører den inverse transformasjonen ... ingenting vil ordne seg! Utgangssignalet vil ha enorme ikke-lineære forvrengninger i nærheten av prøvekryssene.

For å løse dette problemet må du bruke to teknikker:

  • 1. Prøver må behandles av Fourier-transformasjonen med overlapping. Det vil si at hver påfølgende prøve må inneholde en del av den forrige. Ideelt sett bør prøvene overlappe med (2^n-1) prøver, men dette krever enorm beregningsinnsats. I praksis er mer enn trekvart (2^n-2^(n-2)), halv (2^(n-1)) og jevn kvart overlapping (2^(n-2)) tilstrekkelig.
  • 2. Resultatene av den inverse Fourier-transformasjonen, for å oppnå utgangssignalet, må multipliseres med en vektingsfunksjon (en rekke vektkoeffisienter) før de overlapper hverandre. Vektingsfunksjonen må tilfredsstille følgende betingelser:
  • 2.1 Lik null overalt bortsett fra intervallet 2^n.
  • 2.2 På kantene av intervallet tenderer det til null.
  • 2.3 Og viktigst av alt, summen av vektfunksjonene Fv(t) forskjøvet av overlappingsintervallet k må være konstant:

Slike funksjoner er mye brukt i digital signalbehandlingsteknologi, og de kalles vanligvis vinduer. Etter forfatterens ydmyke mening er det beste, fra et praktisk synspunkt, vinduet oppkalt etter Khan:

Figuren viser grafer som illustrerer egenskapene til Hahn-vinduet med en lengde på 2^n=256. Vinduforekomster bygges med halv overlapping k=128. Som du kan se, er alle egenskapene nevnt ovenfor tilgjengelige.

På forespørsel fra arbeidere viser følgende figur et diagram over beregningene av Fourier-filteret, med en prøvelengde på 2^n=8, antall prøver er 3. I slike figurer er det svært vanskelig å vise beregningsprosessen , er det spesielt vanskelig å vise dens syklisitet, så vi begrenset antall prøver til tre .

Inngangssignalet er delt inn i blokker med lengde 2^n=8 med en overlapping på 50%, en FFT tas fra hver blokk, FFT-resultatene gjennomgår den nødvendige transformasjonen, invers FFT tas, resultatet av invers FFT er skalært multiplisert med vinduet, etter multiplikasjonen legges blokkene til med overlapping.

Når du utfører spektrumtransformasjoner, ikke glem hovedegenskapen til FFT-arrayen av reelle signaler, den første halvdelen av FFT-arrayen er komplekst konjugert med den andre halvdelen, dvs. Re[i]=Re[(1<

Nå vet vi alt vi trenger for å skrive en Fourier-filteralgoritme. La oss beskrive algoritmen i C-språk.

#inkludere #define FSempl (8000) //samplingsfrekvens Hz #define BufL (64) //prosesseringsbufferlengde #define Perk (2) //rammeoverlapping 2-1/2, 4-3/4 //spektrumbegrensning, båndpassfilter #define FsrLow (300)//lav filterfrekvens Hz #define FsrHi (3100)//høy filterfrekvens Hz #define FsrLowN ((BufL*FsrLow+(FSempl/2))/FSempl)//lav frekvens i harmoniske #define FsrHiN ((BufL*FsrHi +(FSempl/2))/FSempl)//høy frekvens i harmoniske //Spektrumforskyvning #define SdvigSp (0)//spektrumforskyvning i harmoniske +(ned) -(opp) 0 (ingen skift) //Tidsspektrumfilter, ekko #define FilterSpekrtaT_EN (1)//bruk spektrumfilter 1/0 #define FiltSpektrFsr (0.100025f) //spektrumfilter cutoff frequency volatile unsigned short ShBuf;//input buffer counter signed short BufIn;/ / input buffer signed short BufOut;//output buffer signed short BufInOut;//buffer for rewriting float FurRe;//Fourier real part float FurIm;//Fourier imaginær del #if (FilterSpekrtaT_EN!=0) float FStektr;//filter amplitude spektrum #endif //Sinus cosinustabell #if BufL==64 const float SinCosF= ( 0,000000000 , 0,098017140 , 0,195090322 , 0,290284677 , 0,38268 , 500000000 , 0,098017140 , 0,195090322 , 0,290284677 , 0,38268 , 50,500 17140 70233, 0,634393284, 0,707106781, 0,773010453, 0,831469612, 0,881921264, 0,923879533, 0,9567940380, 8,5290 0,995184727; 106781 , 0,634393284 , 0,555570233 , 0,471396737 , 0,382683432 , 0,290284677 , 0,195090322 , 0,10009 , 0,000, 0,000, 0,0009 98017140, -0,195090322, -0,290284677, -0,382683432, - 0,471396737 , -0,555570233, -0,634393284, -0,707106781, -0,773010453, -0,831469612, -0,881921264, -0,592, -0,592, -0,596, -0,592, -0,592, -0,592, -0,592, 785280, -0,99 5184727, -1,000000000, -0,995184727, -0,980785280, -0,956940336, -0,923879533, -0,884192126 , - 0,831469612, -0,773010453, -0,707106781, -0,634393284, -0,555570233, -0,471396737, -0,3826834792, -0,90,52, -0,555570233, -0,471396737, -0,3826834792, -0. 980 17140, 0,000000000, 0,098017140, 0,195090322, 0,290284677, 0,382683432, 0,471396737, 0,53437, 7,0. 81 , 0,773010453, 0,831469612, 0,881921264, 0,923879533, 0,956940336, 0,980785280, 0,995184727); #endif //FFT sorteringstabell #if BufL==64 const unsigned short sortFFT= ( 0x0000,0x0020,0x0010,0x0030,0x0008,0x0028,0x0018,0x0038, 0x00024,0x0x0x0,4,0x0,0x0x0x0x0x0x0x0x0x 002C,0x001C, 0x003C , 0x0002,0x0022,0x0012,0x0032,0x000A,0x002A,0x001A,0x003A, 0x0006,0x0026,0x0016,0x00002,Ex0002,E0x001,E0x0002,E0x01 0x0001, 0x0021,0x0011,0x0031,0x0009,0x0029,0x0019,0x0039, 0x0005. x0027,0 x0017,0x0037,0x000F,0x002F,0x001F,0x003F ); #endif //Han vindustabell #if BufL==64 const float WinHanF= ( 0. 0, 0,002407637, 0,00960736, 0,021529832, 0,038060234, 0,059039368, 0,084265194, 0,113494773, 0,113494776, 0,82046, 0,31043, 0,31043, 0,3104, 0,6104, 0,6104, 0,6104, 0. 22214883; 0,264301632; 1716, 0,735698368, 0,777785117, 0,817196642, 0,853553391; 9903 9264, 0,978470168. 68, 0,691341716, 0,645142339, 0,597545161, 0,54900857, 0,5; 0,45099143; 084265194 , 0,059039368 , 0,038060234 , 0,021529832 , 0,00960736 , 0,002407637 ); #slutt om //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //Beregning av direkte Fast Fourier Transform //argumenter //peker til array for ekte ReFT og imaginær del ImFT //Etter utførelse inneholder arrayene koeffisienten. reelle og imaginære deler void FFTnoInv(float* ReFT,float* ImFT) ( //kopiering og omorganisering for(int i=0;i >1; lang arg=0; //kjerneargument, fase for(int j=0;j >1; long arg=0;////kjerneargument, fase for(int j=0;j 0 //skift spekteret ned, Karabas-Barabas for(int i=1;i<(BufL/2);i++) { if(i>=(BufL/2-SdvigSp)) ( FurRe[i]=FurIm[i]=0; FurRe=FurIm=0; fortsett; ) FurRe[i]=FurRe; FurIm[i]=FurIm; FurRe=FurRe[i]; FurIm=-FurIm[i]; ) #endif #if SdvigSp<0 //сдвиг спектра вверх, Буратино for(int i=(BufL/2-1);i>0;i--) ( if(i<=(-SdvigSp)) { FurRe[i]=FurIm[i]=0; FurRe=FurIm=0; continue; } FurRe[i]=FurRe; FurIm[i]=FurIm; FurRe=FurRe[i]; FurIm=-FurIm[i]; } #endif //обрезание спектра, полосовой фильтр FurRe=0.0F;FurIm=0.0F; //постоянная составляющая FurRe[(BufL/2)]=0.0F;FurIm[(BufL/2)]=0.0F;//последняя гармоника float ZnStektr;//амплитудный спектр кадра for(int i=1;i<(BufL/2);i++) { if((i < FsrLowN)//нижняя частота || (i >FsrHiN)//høy frekvens) (//spekteravskjæring, harmoniske utenfor båndet er nullstilt FurRe[i]=0.0F;FurIm[i]=0.0F;//direkte harmoniske FurRe=0.0F;FurIm=0.0F ;//conjugate harmonics ) else //beregn amplitudespekteret til den ukuttede delen ( ZnStektr[i]=sqrtf(FurRe[i]*FurRe[i])+(FurIm[i]*FurIm[i]);// amplitudespektrum ) ) // amplitudespektrumfilter i tid, ekko for(int i= FsrLowN;//lavere frekvens i<=FsrHiN ;//верхняя частота i++) { #if FilterSpekrtaT_EN!=0 //фильтр спектра во времени, эхо FStektr[i]=FStektr[i]+ FiltSpektrFsr*(ZnStektr[i]-FStektr[i]); #endif //переходим от модуля к комплексному числу FurRe[i]=FurRe=(FStektr[i]*FurRe[i])/ZnStektr[i]; FurIm[i]=(FStektr[i]*FurIm[i])/ZnStektr[i]; FurIm=-FurIm[i]; } //выполняем обратное БПФ FFTInv(FurRe,FurIm); //копирование буферов for(int i=0;i<(BufL);i++) { BufInOut[i]=((signed short)(FurRe[i]+0.5f)); } } //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ //Фурье фильтр signed short FureFilter(signed short t1) { //записываем во входной буфер BufIn=t1; //выходное значение signed short out=BufOut; //инкремент указателя буфера ShBuf=(ShBuf+1)&((BufL*2)-1); //если в буфере часть кадра обработки if((ShBuf&((BufL/Perk)-1))==0) { //переписываем буфер обработки в выходной буфер int ShTmpOut=ShBuf; int ShTmpIn=(ShBuf-BufL)&((BufL*2)-1); for(int i=0;i<(BufL);i++) { if(i<(BufL-(BufL/Perk))) { //переписываем первую часть буфера обработки в выходной буфер BufOut=BufOut+BufInOut[i]; } else { //переписываем вторую часть буфера обработки в выходной буфер BufOut=BufInOut[i]; } //инкремент указателя выходного буфера ShTmpOut=(ShTmpOut+1)&((BufL*2)-1); //переписываем входной буфер в буфер обработки BufInOut[i]=BufIn; //инкремент указателя входного буфера ShTmpIn=(ShTmpIn+1)&((BufL*2)-1); } }//конец if((ShBuf&((BufL/Perk)-1))==0) //вызов функции обработки //в на реальном процессоре распараллелить! if((ShBuf&((BufL/Perk)-1))==0)ObrBuf(); return out; }

Ved å kalle FureFilter()-funksjonen med frekvensen FSempl og gi den et inngangssignal som et argument, vil resultatet være et utgangssignal. I dette eksemplet behandles inngangssignalet som følger: signalet sendes gjennom et båndpassfilter med grensefrekvenser FsrLow, FsrHi, alle spektralkomponenter over og under de angitte frekvensene undertrykkes, signalspekteret forskyves (for lydsignaler er dette oppfattet som Buratino-Karabas-effekten), jevnes amplitudespekteret til signalet ut av et lavpassfilter (for lyd er dette effekten av et blomstrende rom). Disse handlingene med signalet utføres som et eksempel for å vise tekniske teknikker for å behandle et signal i frekvensdomenet, for eksempel: opprettholde kompleks konjugering av koeffisienter, gjenopprette et komplekst spektrum fra amplituden, uten å bruke trigonometriske funksjoner, etc.

Konklusjon

Det er verdt å merke seg at denne Fourier-filterfunksjonen mest sannsynlig ikke vil fungere i praksis. Når du ringer denne funksjonen, selv med en lav frekvens på 8000 Hz, vil den ikke ha tid til å utføres ved neste samtale, ytelsen vil ikke være nok. Denne Fourier-filterkoden er gitt som en beskrivelse av algoritmen, uten referanse til spesifikke maskinvareressurser, og har rene pedagogiske formål (se introduksjon).

I praktisk implementering er det nødvendig å parallellisere utførelsen av bufferfyllingstømmingsfunksjonen BufInOut (fortrinnsvis DMA, etc.) og bufferbehandlingsfunksjonen ObrBuf(), men det er en helt annen historie.

Fouriers teorem sier at ethvert signal kan utvides til en serie i et ortonormalt sett med periodiske funksjoner (for eksempel sinus og cosinus) med frekvenser som er multipler av frekvensen til det periodiske signalet. Dermed er spektralanalysen av et signal basert på søket etter vektingskoeffisienter (i det generelle tilfellet komplekse), hvis modul tilsvarer brøkdelen av oscillasjonskraften til den tilsvarende harmoniske introdusert i den generelle superposisjonen av alle harmoniske .

Rask Fourier-transformasjon

Fast Fourier Transform er en beregningsalgoritme som vellykket utnytter periodisitetsegenskapene til trigonometriske funksjoner for å unngå unødvendige beregninger i den diskrete Fourier-transformasjonen (DFT), og dermed gjør det raskere å finne koeffisienter i Fourier-utvidelsen. Hovedforskjellen fra diskret konvertering er bare i metoden for å beregne numeriske verdier (algoritme), og ikke i selve signalbehandlingen. Både når det gjelder FFT og når det gjelder DFT er resultatet av beregningene det samme. Det eneste kravet for FFT-algoritmen er en prøvestørrelse som er et multiplum av N = 2L, der L er et hvilket som helst positivt heltall. De vanligste base-2 FFT-algoritmene er: tidsdesimert og frekvensdesimert.

I dette arbeidet er en radix-2 FFT-algoritme med tidstynning (Cooley-Tukey-algoritme) implementert. Det er enkelt å få tak i ved å studere noen DFT-lover. La oss introdusere den såkalte rotasjonskoeffisienten:

I dette tilfellet, i DFT, er Fourier-koeffisientene for et antall signalverdier (f0,f1,...,fN-1) uttrykt av relasjonen:

Tenk på en signalserie med 4 verdier: (f0,f1,f2,f3). La oss presentere Fourier-transformasjonen i matriseform (normaliseringskoeffisienten 1/N er inkludert i kolonnevektoren Cij på høyre side av uttrykket):

Etter å ha skrevet rotasjonskoeffisientene ved hjelp av Eulers formel og bestemt verdiene deres for k = 0, 1, 2, .. 9, kan du konstruere et diagram (fig. 2), hvorfra mønsteret av gjentatte koeffisienter kan sees.

Figur 2. Effektserie w for N=4

Ved å erstatte numeriske verdier i (4) får vi:

Det vil si at verdiene til w, fra w4, er lik den tilsvarende verdien fra w0 til w3. Deretter omskriver vi matriseligningen (4) i en ikke-standard form (lignende notasjoner er introdusert for klarhet i videre operasjoner):

La oss bytte kolonnene i matrisen, dele den inn i to grupper: etter partall f0, f2 og oddetall f1, f3 indekser:

La oss ta i betraktning at wk+1 = wkw1, så vil uttrykk (6) bli omskrevet som:

Bruke forholdstallene:

Vi får de nødvendige ekspansjonskoeffisientene i form av en kolonnevektor med celleverdier:

Den grafiske representasjonen av algoritmen (fig. 3) ser ut som en sommerfugl med åpne vinger, og derfor kalles denne beregningsmetoden "sommerfugl".

Figur 3. Sommerfuglgraf for en serie på 4 ledd

Så i det første trinnet av algoritmen er medlemmene av en rekke signalverdier delt inn i partall og oddetallsindeks. Deretter utføres "sommerfugl"-grafen; den består av to trinn, antallet er lik kraften til to av prøvestørrelsen (N = 4 = 22). På hvert trinn utføres to "sommerfugler", og deres totale antall forblir uendret. Hver sommerfugloperasjon tilsvarer én multiplikasjonsoperasjon. Til sammenligning: i DFT med sampling (f0,f1,f2,f3), må multiplikasjonsoperasjonen utføres 4×4 = 16 ganger, og i tilfelle FFT bare 4 ganger.

Teori

Først en liten teori. Som alle vet bruker slike analysatorer den raske Fourier-transformasjonen og det sies ofte at DFT ikke kan brukes i slike design, bare FFT og selv da i assembler. Jeg brukte den diskrete Fourier-transformasjonen (DFT) og Walsh-transformasjonen i stedet. Og i denne artikkelen vil jeg bevise at du til og med kan bruke ikke bare FFT, men DFT skrevet i C. Men først, i rekkefølge, hvordan få en enkel DFT-funksjon fra DFT og ifølge Walsh. DFT ser klassisk slik ut:

Siden μ har få ressurser, erstatter de cos og sin med arrays med dimensjon N. I tillegg er μ 8-bit og det er mer hensiktsmessig å lagre arrays i form av 8-bits verdier. Siden cos og sin varierer fra -1 til 1, er det best å øke dette området med 127 ganger, siden en 8-bits fortegnsvariabel kan lagre verdier fra -127 til 127. Derfor, med tanke på transformasjonene av formelen , vil det være:

hvor m endres fra 0 til N-1 med et trinn lik k, når m blir større enn N, reduseres m med N-1. Det brukes totalt 12 kanaler, så kraften til DFT er begrenset til et så lite antall kanaler.

For eksempel har vi 512 ADC-sampler; vi må beregne de imaginære og reelle delene for 150 Hz ved en samplingsfrekvens på 19200 Hz:

Dermed oppnås de virkelige og imaginære delene mye raskere enn på tradisjonell måte, men 127 ganger større. For å få deres virkelige verdier, må du dele med 127, men MK har ingen divisjon, det ville være mye mer rasjonelt å ikke dele diktet, men å skifte det! Ett skift tilsvarer å dele på 2. Det vil si at hvis du skifter et tall 7 ganger, deler du det i hovedsak på 128! Siden tap i nøyaktighet allerede var uunngåelig, vil ikke dele på 128 endre bildet.

Den diskrete Fourier-transformasjonen for 150 Hz ved en samplingshastighet på 19200 Hz ser da slik ut:

For Walsh erstatter vi sinus- og cosinusbølgene med middelverdiene for de tilsvarende periodene. Det vil si at for synd fra 0 til 180 grader vil det være 1 og fra >180 til 360 vil det være -1. Følgelig, for en sinus fra 0 til 90 er det 1, fra 90 til 270 er det -1 og fra 270 til 360 er det 1. Dermed vil alle beregninger av de imaginære og reelle delene være en enkel akkumulering av summer og forskjeller av ADC-verdien. Det vil si at når for eksempel sinus er lik 1, så legges ADC-verdien til, og når -1 trekkes fra. Ulempen med denne løsningen er igjen feilen, som uunngåelig øker og når 20%. Men siden designet mitt bare har 8 verdier, er det igjen få som vil merke en betydelig forskjell.

Et eksempel på implementering av beregning av imaginære og reelle deler for 150 Hz ved en samplingsfrekvens på 19200 og 512 prøver:

På denne måten får vi de imaginære og reelle delene ganske raskt uten multiplikasjonsprosedyrer.

Og så, etter å ha fått de imaginære og virkelige delene, er det nødvendig å finne amplituden til spekteret. For å gjøre dette, må du finne roten til summen av kvadrater av de imaginære og reelle delene. Men hvis du bruker en funksjon fra matematikkbiblioteket, vil utvinningen ta lang tid og funksjonen vil også spise opp et ganske stort stykke ROM. Etter litt graving på Internett fant jeg en elegant funksjon, som jeg så forenklet litt mer på grunn av at den opererer på små verdier. Dette er funksjonen:

Etter å ha sammenlignet denne funksjonen og funksjonen fra matematikkbiblioteket, kom jeg til den konklusjonen at nøyaktigheten er nok til at resultatet blir det samme. Selve funksjonen veier 2% mot 12% av MK ROM. I tillegg regner den mye raskere.

Men hvordan gikk det til at MK klarer å beregne 12 kanaler, og til og med i DFT. Foruten alle triksene med shift i stedet for divisjon og den raske firkantfunksjonen, er det ett triks til. Som jeg skal fortelle deg om nå. Faktum er at jo høyere valgfrekvens, desto smalere er filterets passbånd, siden overgangen av cos og sin akselererer og antall perioder øker. Og jo mer slike passerer cos og sin, jo smalere blir båndbredden. For eksempel, for en frekvens på 150 Hz, gjentas cos og sin 4 ganger, og for 1,2 kHz gjentas cos og sin 32 ganger. Av dette kan man se at for at passbåndet skal være enhetlig på alle områder og dekke alle frekvensområder, må antallet samples reduseres med økende filtreringsfrekvens. For 150 Hz er for eksempel alle 512 prøver boret, for 600 Hz 256 prøver, og for 2,4 kHz 32 prøver, og så videre. Det er ikke vanskelig å erstatte at ved å redusere antall prøver med økende frekvens, øker hastigheten på DFT kraftig, siden mye færre multiplikasjoner og summer må gjøres.

Praktisk gjennomføring

Og så den teoretiske delen er forberedt, kan vi begynne å beskrive designet. Hele designet består av én mikrokontroller, 4 transistorer, flere kondensatorer og mange motstander. Det er bedre å installere mange motstander, selv om du kan begrense deg til bare motstander horisontalt, dvs. en for hver portpinne. Opplegget er klassisk, bortsett fra det eneste som jeg brukte 3 porter per 1 pass med dynamisk skanning i stedet for 1, som de gjør alle andre steder. Dette gjorde det mulig å redusere skannefrekvensen og redusere antall transistorer til 4. Resultatet ble faktisk en 24x4 skala.

Spektrumanalysatoren opererer med en samplingshastighet på 19,2 kHz fra en 16 MHz krystall.

Spektrumanalysatoren beregner spektralamplitudene til følgende frekvenser:

9,6 kHz, 4,8 kHz, 2,4 kHz, 1,6 kHz, 1,2 kHz, 800 Hz, 600 Hz, 500 Hz, 400 Hz, 300 Hz, 150 Hz, 75 Hz. Programmet ble testet for 33 Hz og DFT lyktes til tross for at dimensjonene til cos og sin ble lik 512, men bestemte seg for å begrense det til 75 Hz.

Det er frekvenser her som ikke er et multiplum av 2 til n-te potens, men som likevel beregnes. For eksempel, 400 Hz når dividert med 19200 får vi 48 som ikke er et multiplum av 2 i potensen n. Jeg valgte en vei ut av situasjonen ved å ta et tall nær tallet 2 i potensen av n. Den nærmeste er 240, den er nær 256. Det vil si at av 512 tok vi bare 240 prøver. I tillegg kan du ikke bare ta noe nært. For eksempel kunne vi tatt 480 som er nær 512, men likevel tok vi nærmere 256. Forklaringen på dette er at ved ulike frekvenser påvirker antall sampler båndbredden. Jo større antall prøver, jo smalere båndbredde. Dette skyldes det faktum at ved en høy frekvens går cosinus gjennom en periode mye raskere enn ved en lav og amplituden beregnes så nøyaktig at nabofrekvenser rett og slett blir kastet ut og blinde frekvenssoner dannes mellom frekvenser som ikke oppfattes. av analysatoren. For at analysatoren skal oppfatte alle frekvenser og dekke hele spekteret, er det nødvendig å utvide båndet ved høye frekvenser ved å ta færre prøver, og ved lave frekvenser å begrense det mest mulig ved å ta tilsvarende flere prøver. Ved praktisk valg av antall avlesninger valgte jeg derfor følgende:

9,6 kHz 16 tellinger, 4,8 kHz 32 tellinger, 2,4 kHz 32 tellinger, 1,6 kHz 60 tellinger, 1,2 kHz 64 tellinger, 800 Hz 240 tellinger, 600 Hz 256 0 0 tellinger, 256 0 0 Hz 4 s, 300 Hz 512 teller, 150 Hz 512 tellinger, 75 Hz 512 tellinger.

Dette valget av antall prøver tillot båndet å være ensartet over hele frekvensområdet.

En annen fallgruve oppsto ved en frekvens på 9,6 kHz. Siden det ikke er noen imaginær del (dette kan enkelt kontrolleres ved å erstatte 256-spekteretall i formelen ovenfor med 512 sampler og sinusen alltid vil være lik 0), kan den reelle delen endre seg ganske kraftig på grunn av at cosinusverdien vil bli beregnet annenhver gang i motfase til hovedsignalet. Det vil si at det beregnes én gang. For å unngå dette er det nødvendig å beregne minst 2 verdier av den reelle delen forskjøvet med 90 grader og velge maksimum av de to verdiene.

Programalgoritmen akkumulerer 512 prøver i intervallet, overfører mikrokontrolleren til hvilemodus og våkner når neste prøve er klar. I tillegg skannes lysdiodene ved 150 Hz – dette er 128 ganger samplingsfrekvensen på 19200. Det vil si at før ADC tar alle prøvene, vil den rekke å fullføre ett helt sveip. Så snart alle prøvene er klare, beregnes alle amplitudene til spekteret i hovedprogramsyklusen. På dette tidspunktet fortsetter sveipet, men MK sovner ikke, men teller amplitudene. Så snart amplitudene er beregnet, går mikrokontrolleren i dvale og programmet gjentas igjen. Amplituder beregnes basert på et 20 dB-område, det vil si at de er logaritmiske.

Basert på tiden for å motta alle avlesninger og tiden for å beregne alle amplituder, er oppdateringsfrekvensen i området 10-15 Hz.


En verden av gratis programmer og nyttige tips
2024 whatsappss.ru