Forum: Mikrocontroller und Digitale Elektronik aktuellste Werte in Array und aufsummieren


von Dennis (Gast)


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

von Volker S. (vloki)


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.

Wie wäre es mit einem Ringspeicher?

von Jim M. (turboj)


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.

von Marc V. (Firma: Vescomp) (logarithmus)


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.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marc V. schrieb:
> Nur bei den ersten n Samples must du aufpassen.

 Wenn beim Start der TailPtr auf Buffer[0] und HeadPtr auf Buffer[n-1]
 zeigt, nicht mal das.

von Walter S. (avatar)


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

und warum geht das nicht auch wenn N==23 ist?

von Noch nicht Rentner (Gast)


Lesenswert?

Vergiss diesen gleitenden Mittelwert, nimm den exponentiellen 
Mittelwert, der benoetigt nur eine einzige Speicherstelle.

von Marc V. (Firma: Vescomp) (logarithmus)


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;

von Volker S. (vloki)


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)

von Marc V. (Firma: Vescomp) (logarithmus)


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...

von Volker S. (vloki)


Lesenswert?

Mir erschließt sich der Sinn von zwei Zeigern einfach nicht...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Volker S. schrieb:
> Mir erschließt sich der Sinn von zwei Zeigern einfach nicht...

 Mein Denkfehler, ich hatte an einen Buffer mit Schreib- und Lesepointer
 gedacht.
 In diesem Fall geht es selbstverständlich auch mit nur einem Pointer.

von Dennis (Gast)


Lesenswert?

Ich habe jetzt ein Ringpuffer verwendet und es funktioniert soweit ganz 
gut. Vielen Dank für die nützlichen Anregungen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.