Thursday 10 August 2017

Cirkulär Buffert Glidande Medelvärde


Scientist och Engineers Guide till Digital Signal Processing av Steven W. Smith, Ph. D. Kapitel 28: Digitala signalprocessorer Digitala signalprocessorer är konstruerade för att snabbt utföra FIR-filter och liknande tekniker. För att förstå hårdvaran. vi måste först förstå algoritmerna. I det här avsnittet kommer vi att göra en detaljerad lista över de steg som behövs för att implementera ett FIR-filter. I nästa avsnitt ser vi hur DSPs är utformade för att utföra dessa steg så effektivt som möjligt. För att börja, måste vi skilja mellan offlinebehandling och realtidsbehandling. Vid off-line-bearbetning ligger hela insignalen i datorn samtidigt. Till exempel kan en geofysiker använda en seismometer för att registrera markrörelsen under en jordbävning. Efter skakningen är slut kan informationen läsas in i en dator och analyseras på något sätt. Ett annat exempel på off-line-behandling är medicinsk bildbehandling, såsom datortomografi och MR. Datauppsättningen förvärvas när patienten är inne i maskinen, men bildrekonstruktionen kan fördröjas till en senare tidpunkt. Det viktigaste är att all information är tillgänglig för bearbetningsprogrammet samtidigt. Detta är vanligt inom vetenskaplig forskning och teknik, men inte i konsumentprodukter. Off-line bearbetning är riken för persondatorer och mainframes. Vid realtidsbehandling produceras utsignalen samtidigt som insignalen förvärvas. Det behövs till exempel i telefonkommunikation, hörselhjälpmedel och radar. Dessa applikationer måste ha informationen omedelbart tillgänglig, även om den kan försenas med en kort mängd. Till exempel kan en 10-sekunders fördröjning av ett telefonsamtal inte detekteras av talaren eller lyssnaren. På samma sätt spelar ingen roll om en radarsignal fördröjs med några sekunder innan den visas till operatören. Realtidsprogram anger ett prov, utför algoritmen och matar ut ett prov, över och över. Alternativt kan de mata in en grupp av prover, utföra algoritmen och mata ut en grupp av prover. Det här är en värld av digitala signalprocessorer. Se nu tillbaka på Fig. 28-2 och föreställ dig att detta är ett FIR-filter som implementeras i realtid. För att kunna beräkna utgångsprovet måste vi ha tillgång till ett visst antal av de senaste proverna från inmatningen. Antag att vi använder åtta koefficienter i detta filter, en 0. en 1. hellip a 7. Det betyder att vi måste veta värdet av de åtta senaste proverna från ingångssignalen xn, x n -1, hellip x n -7. Dessa åtta prover måste lagras i minnet och uppdateras kontinuerligt när nya prover förvärvas. Vad är det bästa sättet att hantera dessa lagrade prover Svaret är cirkulär buffring. Figur 28-3 illustrerar en åtta prov cirkulär buffert. Vi har placerat den här cirkulära bufferten i åtta på varandra följande minnesplatser, 20041 till 20048. Figur (a) visar hur de åtta proverna från ingången kan lagras vid ett visst ögonblick, medan (b) visar ändringarna efter nästa prov är förvärvas. Tanken med cirkulär buffring är att slutet av den här linjära gruppen är kopplad till sin startminnesplats 20041 ses som närmast 20048, precis som 20044 bredvid 20045. Du håller reda på matrisen med en pekare (en variabel vars värdet är en adress) som anger var det senaste provet ligger. Till exempel i (a) pekaren innehåller adressen 20044, medan den i (b) innehåller 20045. När ett nytt prov förvärvas ersätter det det äldsta provet i matrisen och pekaren flyttas en adress framåt. Cirkulära buffertar är effektiva eftersom endast ett värde behöver ändras när ett nytt prov förvärvas. Fyra parametrar behövs för att hantera en cirkulär buffert. Först måste det finnas en pekare som indikerar starten på den cirkulära bufferten i minnet (i det här exemplet, 20041). För det andra måste det finnas en pekare som indikerar slutet av matrisen (t ex 20048) eller en variabel som håller dess längd (t ex 8). För det tredje måste steget för minnesadressering anges. I Fig. 28-3 är stegstorleken en. till exempel: adress 20043 innehåller ett exempel, adress 20044 innehåller nästa prov, och så vidare. Detta är ofta inte fallet. Till exempel kan adresseringen referera till bitgrupper, och varje prov kan kräva två eller fyra byte för att hålla sitt värde. I dessa fall måste stegstorleken vara två respektive fyra. Dessa tre värden definierar storleken och konfigurationen för den cirkulära bufferten och kommer inte att ändras under programoperationen. Det fjärde värdet, pekaren till det senaste provet, måste ändras när varje nytt prov förvärvas. Med andra ord måste det finnas programlogik som styr hur detta fjärde värde uppdateras baserat på värdet av de tre första värdena. Medan denna logik är ganska enkel, måste den vara väldigt snabb. Detta är hela punkten i denna diskussion. DSP bör optimeras vid hantering av cirkulära buffertar för att uppnå högsta möjliga körhastighet. Som en sido är cirkulär buffring också användbar vid offlinebehandling. Tänk på ett program där både ingångs - och utgångssignalerna är helt i minnet. Cirkulär buffring är inte nödvändig för en konvolutionsberäkning, eftersom varje prov kan omedelbart nås. Men många algoritmer implementeras i steg. med en mellanliggande signal skapad mellan varje steg. Exempelvis fungerar ett rekursivt filter som utförs som en serie biquader på detta sätt. Brute Force-metoden är att lagra hela längden på varje mellansignal i minnet. Cirkulär buffring ger ett annat alternativ: lagra endast de mellanprover som behövs för beräkningen vid handen. Detta minskar den önskade mängden minne, på bekostnad av en mer komplicerad algoritm. Den viktiga tanken är att cirkulära buffertar är användbara för offlinebehandling, men är kritiska för realtidsapplikationer. Nu kan vi titta på de steg som behövs för att implementera ett FIR-filter med cirkulära buffertar för både ingångssignalen och koefficienterna. Denna lista kan tyckas trivial och överexaminerad - den är inte Den effektiva hanteringen av dessa enskilda uppgifter är vad som skiljer en DSP från en traditionell mikroprocessor. För varje nytt prov måste alla följande steg vidtas: Målet är att få dessa steg att utföras snabbt. Eftersom steg 6-12 upprepas många gånger (en gång för varje koefficient i filtret), måste särskild uppmärksamhet ägnas åt dessa operationer. Traditionella mikroprocessorer måste i allmänhet utföra dessa 14 steg i seriell (en efter en), medan DSPs är utformade för att utföra dem parallellt. I vissa fall kan alla operationer inom slingan (steg 6-12) slutföras i en enda klockcykel. Låt oss titta på den interna arkitekturen som tillåter denna magnifika prestanda. Jag har ingen aning om cirkulära buffertar i termer av C-språk i samband med ditt uppdrag: en kvotcirkulär bufferquot är en grupp. Du börjar lägga saker i element noll och öka indexet för nästa åtkomst. När indexet blir större än det största tillåtna värdet (det vill säga nästa åtkomst skulle gå utöver slutet av arrayen), sätt bara indexet tillbaka till noll. Detta betyder att efter att bufferten är full (programmet har skrivit något i varje element i arrayen) kommer ytterligare accessor att skriva över det föregående värdet vid varje adress. Detta medför att det äldsta värdet ersätts med det nyaste värdet varje gång, och medlet av alla element i arrayen använder alltid de senaste samplingsvärdena. Till exempel för en cirkulär buffert av ints: Naturligtvis behöver du inte egentligen en separat variabel som heter MAXINDEX, men jag stavade det för betoning. (Det är: enkelt jämföra currentindex med BUFFERSIZE-1.) Ursprungligen postat av tellthatmatt snabb fråga, finns det någon dedikerad funktion för att låta mig ta medeltalet av en array eller skulle jag behöva koda det genom att lägga till alla elementen tillsammans förstärkare sedan dela . Det kallas en loop. (Inte en funktion, men det finns flera inbyggda kontrollkonstruktioner för att skapa loopar.) Om du vet att du kommer att göra någonting exakt n gånger så kan slingan se ut så här: Antag att du har en matris, x, av tio dubbla precisionsnummer och du vill hitta summan av deras värden (dvs: du vill ha summan x0 x1 x2. x9). Då kan du göra det så här: Ursprungligen postat av tellthatmatt Vad är det bästa sättet att läsa heltal från filen i det här fallet har vi inte täckt det här i klassförstärkaren min lärobok förklarar det inte alls bra alls. Jag tycker att det är något att göra med funktionen fgetsc () men jag är inte säker. Resten av mitt program fungerar bra, jag vet bara inte hur man läser heltal från TEXT-filen. Om textfilen innehåller heltal är fscanf () förmodligen det enklaste sättet och det är enligt min mening det mest lämpliga. (Men det finns andra sätt.) När du använder fscanf (), anger du adressen (er) av vilken variabel (er) du läser in. Returvärdet för fscanf är antalet poster som konverterades med framgång. Du bör alltid (alltid) testa returvärdet. Till exempel om du vill läsa värdet i ett värde: Detta är bara ett test för att visa vad som försökt att förklara. fscanf () kommer att misslyckas (det vill säga dess värde kommer att vara noll) om det inte kan konvertera grejer till en int --- det är det möter ett tecken som inte är blankutrymme och inte en decimalsiffra från 0 till 9. Det misslyckas också om det försöker läsa förbi slutet av filen. Om du vill läsa ett värde i ett matriselement, ge bara skanning till adressen till elementet. Om du vill läsa hela filens innehåll i ett heltal som används som en cirkulär buffert: cirkulär buffertsignal flowgraphs kranar tappade fördröjningslinje Automatisk regressiv rörelse De tre minnesorden läggs i ett område som är organiserat som en cirkulär buffert. Inmatningen skrivs till ordet pekat av indexet och de tre föregående värdena för ingången läses med de tre föregående värdena på indexet. Vid varje provtid ökar de fyra indexerna med en, med tricket från början från plats 0 när vi överstiger buffertens längd M (detta säkerställer buffertens cirkuläritet). Den vänstra pilen indikerar den riktning som indexen tar, medan pilen medurs klarar av den rörelse som ska göras av data om indexen skulle ligga i ett fast läge. I fig. 13 Vi använder små trianglar för att indikera multiplikationerna av filterkoefficienterna. Detta är en notation som vanligtvis används för multiplikationer inom signalflödesgraferna som representerar digitala filter. FIR-filter innehåller faktiskt en fördröjningslinje eftersom den lagrar N följaktiga prover av ingångssekvensen och använder var och en av dem med en fördröjning av N-prover högst. Punkterna där den cirkulära bufferten läses kallas kranar och hela strukturen kallas en tappad fördröjningslinje. I allmänhet representeras ett kausal IIR-filter med en skillnadsekvation där utsignalen vid ett givet tillfälle erhålles som en linjär kombination av prover av ingångs - och utsignaler vid tidigare tidpunkter. Dessutom är ett momentant beroende av utmatningen på ingången vanligtvis också inkluderad i IIR-filtret. Skillnadsekvationen som representerar ett IIR-filter är ekv. (24) kallas även Auto-Regressive Moving Average (ARMA) representation. Medan impulsresponsen hos FIR-filter har en begränsad tidsförlängning har impulsresponsen hos IIR-filter i allmänhet en oändlig förlängning. Överföringsfunktionen erhålles genom applicering av Z-transformen till sekvensen (24). I kraft av skiftteorem är Z-transformen enbart operativ substitution av varje översättning med m-prover med en multiplikation med z. Resultatet är den rationella funktionen H (z) som hänför Z-transformen till utgången till Z-transformen av Inmatning: Filtreringsordningen definieras som graden av polynomet i z Det enklaste IIR-filtret I det här avsnittet analyserar vi egenskaperna hos det enklaste, icke-rationella IIR-filtret som kan uppfattas: ettpoligt filter med koefficienter som genomför en 80-72 -64-48 multi-pass glidande medelfilter för ett inbäddat system i C och i fast punkt. Implementeringen är en cirkulär buffert där jag håller en löpande summa och beräknar yn-1 xn - xn-M där M är längden på ett filter. Detta görs för varje subfilter med utgången från en tjänst som ingång för en annan. Jag skalar mina koefficienter med 2 som ger mig koefficienter med längd 2 eller 2 beroende på filterlängden. Då avkalas resultatet med 2 igen för att få rätt utgång. Nu ser allt bra ut på korta vågar men under långa tider får jag en drift. Orsaken till det rekursiva genomförandet är att spara beräkningar på en inbäddad processor. Jag har tagit med bilder av några av mina interners mittfilter, det här är när ett stegsvar tillämpas och vi kan se överföringsfunktionerna hos filtren som tar form, kvadrat, triangel och approximerar sedan en gauss, så filtret fungerar som förväntat. Finns det något sätt att fixa detta, och var är den mest troliga källan till detta. Är den här driften på grund av att en bit går vilse i skiftet eller något annat. Driften är inte närvarande för DC-ingångar, men för AC-signaler går det långsamt. Lösning: Problemet var i ackumulatorn som Robert föreslog i kommentarerna. Frågan var att ett element i beräkningen hade gått igenom ett extra upp och ner skift jämfört med resten, vilket skapade en runda offset som ackumulerades. frågade 27 apr 15 kl 21:12 är din ackumulator yn avrundad eller kvantiserad på något sätt måste du se till att xn-M som subtraheras är exakt samma värde som xn som tillsattes M-prov sedan. så du vill verkligen göra en rörlig summa. Snarare än ett glidande medelvärde och skala utmatningen av din rörliga summa (med 1M) för att få dig genomsnittet. Detta är ganska genomförbart och ännu bättre gjort i fast punkt snarare än flytande punkt. Ndash robert bristow-johnson Apr 27 15 at 22:52 quotScaling coefficientsquot Jag antar att du delar upp med M efter varje steg och det är den koefficient som du skala Det är förmodligen orsaken till offset. Bättre än att dela upp med prod Mi i slutet av alla filter. Du måste hålla reda på de interna amplituderna men eftersom du så småningom kommer att strömma över ackumulatorerna. Detta löses emellertid lätt genom modulo aritmetik (varav komplementet är ett speciellt fall). Ndash Oscar 28 apr 15 kl 7:00 Oscar, det här är ett fast punktfilter. Jag menar att jag bara gör heltal aritmetiska. För ett glidande medelvärde av längden gt 1 med förstärkning 1 kommer filterkonstanterna att vara en fraktion som inte kan representeras i heltal. Så skalas koefficienterna för att göra dem heltal genom att vänster skifta dem x många bitar. På grund av detta måste slutprodukten också flyttas till höger av så många bitar. Jag kan inte hålla en löpande summa genom alla 4 filter utan att återställa utmatningen däremellan, ingångssignalen är 16 bitar och med koefficientskalan och längderna ett enda filter använder hela mitt ackumulatorutrymme på 32 bitars ndash user70614 28 april kl 15:20

No comments:

Post a Comment