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:
- Feilsøking av alt nødvendig periferiutstyr: ADC, DAC, timere, LED-indikasjon.
- 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.
- 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.
- 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?