aktuellste Werte in Array und aufsummieren

Gast #4802775
Lesenswert?
• ▲
▼
Hallo zusammen,

ich habe folgendes Problem:
Ein AVR32 liefert mit Werte vom ADC. Diese werden mit 44kHz abgetastet 
(Audio-Signal). Programmiert wird in C. Ich möchte nun immer die N 
aktuellsten Werte in einem Array vorhalten und gleichzeitig mit den 
44kHz die Summe über diese Werte zur Verfügung haben.

Ich habe bisher versucht pro ISR-Durchgang des Timers alle Array-Werte 
eins nach rechts zu schieben und den neuen ADC-Wert dann auf die erste 
Position zu setzen.
Die Summe habe ich wie folgt berechnet:
1
summe=summe+ADC-wertDerAusArrayRausgeschobenWurde;

Ist das soweit okay?
Ich habe momentan noch deutliche Geschwindigkeitsprobleme (ISR wird auf 
2kHz ausgebremst)

Gruß
Dennis
#4802805
Lesenswert?
• ▲
▼
Dennis schrieb:
> Ist das soweit okay?

Nö, vieeeel zu lahm.

> Ich habe momentan noch deutliche Geschwindigkeitsprobleme (ISR wird auf
> 2kHz ausgebremst)

Kein Wunder, Du musst ja sinnlos durchs Array durch für das memmove().

Einfacher ist eine Indextransformation, d.h. Du merkst Dir den Index des 
auszutaschenden Wertes und zählst nur diesen jeweils hoch. Dann musst Du 
die restlichen Werte im Array nicht jedes Mal anfassen.
(Firma: Vescomp) #4802855
Lesenswert?
• ▲
▼
Volker S. schrieb:
> Dennis schrieb:
>> Ich habe bisher versucht pro ISR-Durchgang des Timers alle Array-Werte
>> eins nach rechts zu schieben und den neuen ADC-Wert dann auf die erste
>> Position zu setzen.
>
> Wie wäre es mit einem Ringspeicher?

 Ja, HeadPtr und TailPtr dazu und fertig ist die Laube.
 HeadPtr zeigt auf Adresse in Buffer wo reingeschrieben wird, TailPtr
 zeigt auf Adresse in Buffer wessen Wert abgezogen wird.

 Beim Start ist Arrayinhalt = 0,
 HeadPtr beliebig,
 TailPtr = HeadPtr + n(Anzahl Werte) - 1.

 Oder umgekehrt, ist egal.
 Nur bei den ersten n Samples must du aufpassen.
Moderator (Firma: Titel) Persönliche Seite #4802885
Lesenswert?
• ▲
▼
Dennis schrieb:
> Ich habe bisher versucht pro ISR-Durchgang des Timers alle Array-Werte
> eins nach rechts zu schieben und den neuen ADC-Wert dann auf die erste
> Position zu setzen.
Das ist wie wenn du beim Baden zur siebten Umkleidekabine willst, dazu 
einfach stehen bleibst und sagst: schiebt die ersten 6 Umkleidekabinen 
an mir vorbei.
Ein eher praktisch veranlagter Mensch wird an den Kabinen 1 bis 6 
vorbeigehen und in die 7. eintreten.

Sprich: du speicherst einfach den neuen Wert in die nächste Zelle, 
addierst den Wert zu der Summe und subtrahierst von der Summe den um N 
Speicherplätze zurückliegenden Wert.

Und weil du nicht unendlich viele Speicherplätze hast, musst du 
irgendwann wieder von vorn anfangen.

BTW: die Arithmetik wird simpel, wenn N eine Zweierpotenz ist. Denn dann 
gibt es kein Head und Tail-Herumgeeiere, sondern einfach nur einen 
einzigen Pointer, der auf den ältesten Wert zeigt, der subtrahiert und 
dann vom neuesten Wert überschrieben wird.
(Firma: Vescomp) #4802946
Lesenswert?
• ▲
▼
Lothar M. schrieb:
> BTW: die Arithmetik wird simpel, wenn N eine Zweierpotenz ist. Denn dann
> gibt es kein Head und Tail-Herumgeeiere, sondern einfach nur einen
> einzigen Pointer, der auf den ältesten Wert zeigt, der subtrahiert und
> dann vom neuesten Wert überschrieben wird.

 Auch so wird es nicht übermässig kompliziert:
1
        Buffer[HeadPtr] = LastSample;
2
        Summe += LastSample - Buffer[TailPtr];
3
        HeadPtr++;        TailPtr++;
4
        if(HeadPtr >= MaxSamples)  HeadPtr = 0;  // Modulo MaxSamples ist wahrscheinlich langsamer
5
        if(TailPtr >= MaxSamples)  TailPtr = 0;
#4803206
Lesenswert?
• ▲
▼
Lothar M. schrieb:
> BTW: die Arithmetik wird simpel, wenn N eine Zweierpotenz ist. Denn dann
> gibt es kein Head und Tail-Herumgeeiere, sondern einfach nur einen
> einzigen Pointer, der auf den ältesten Wert zeigt, der subtrahiert und
> dann vom neuesten Wert überschrieben wird.

Was jetzt die Anzahl der Pointer mit N zu tun hat verstehe ich zwar 
nicht,
aber ich wäre auch für nur einen Pointer.
(Die Abfrage auf einen bestimmten Wert für das Rücksetzten entfällt 
natürlich bei einer Zweierpotenz, weil man das dann einfach mit einer 
Bitmaskierung erledigen kann)
(Firma: Vescomp) #4803310
Lesenswert?
• ▲
▼
Volker S. schrieb:
> aber ich wäre auch für nur einen Pointer.
> (Die Abfrage auf einen bestimmten Wert für das Rücksetzten entfällt
> natürlich bei einer Zweierpotenz, weil man das dann einfach mit einer
> Bitmaskierung erledigen kann)

 Maskieren (mit const) braucht 1 Cy.
 Vergleichen (mit const) braucht 1Cy, das anschliessende überspringen
 oder durchfallen mit CLR braucht in beiden Fällen 2Cy mehr.
 Für 2 Pointer sind das 4Cy oder 250ns mehr bei 16MHz.
 Wird der Wert für zweiten Pointer in RAM aufbewahrt, sind es nochmal
 4Cy (LDS/STS) oder 2Cy(über Indexregister).

 Ergibt im ungünstigstem Fall insgesammt 8Cy mehr oder 500ns - WOW.

 Man kann es auch übertreiben, vor allem da das Ganze in C geschrieben
 ist...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren