Wie Maximalwert aus Messreihe ermitteln?

Nehmen wir an, dass ich kontinuierlich Analogmessungen vornehme. Ziel ist es, jeweils den aktuellen Maximalwert der letzten 20 Messungen auszugeben.

Meine Idee dazu: Ein Array nehmen und den aktuellen Messwert reinschreiben, Index inkrementieren und von vorn. Wenn Index == 19, Index wieder auf 0 setzen.

Auswertung: Inhalt von Index 0 und Index 1 vergleichen, den größeren Wert speichern, gespeicherten Wert mit Index 2 vergleichen usw.

Erscheint mir recht umständlich. Geht das auch einfacher / besser?

Gruß,

Helmuth

hi,

am beginn würde ich max auf 0 setzen dann den jeweils "neuen" wert mit max vergleichen und gegebenfalls max ersetzen. nebenbei bis 20 zählen. wenn 20, dann ausgabe max, zähler auf 0 und max auf 0.

so sparst Du Dir das array.

gruß stefan

so sparst Du Dir das array.

Dann bekomme ich - wenn ich Dich richtig verstehe - aber auch nur jede 20. Messung einen Maxwert.

Ich brauch nach jeder Messung den Maxwert der letzten 20 Messungen.

Beste Grüße,

Helmuth

Dann passt die Array Lösung. Oder in anderen Worten: ein Ringpuffer

Danke.

Hallo,

nö. Mach es wie Eisbär geschrieben hat. Lies das nochmal durch. Nach jeder Messung mit alten Maxwert vergleichen. Damit hast du immer den aktuellen Maxwert. Nach der 20. Messung nullen. Alles ohne zusätzlichen Buffer. Dafür kannste die max Funktion verwendet.

Nach der 20. Messung nullen

Dann hat er ja den Maximalwert der letzten 20 Messungen verloren…

hi,

ja, das hab' ich falsch verstanden. war schon verwundert über die triviale frage von helmut. ein ringpuffer wär schon was nettes, aber frißt halt speicher...

gruß stefan

Speicher für die 147 Byte (7 Audiobänder * (20 Werte + Maxwert)) ist kein Problem, ich habe noch 50k frei.

Es ging mir darum, ob es vielleicht noch einen geschickteren (schnelleren) Sortieralgo gibt, als jedesmal alle 20 Werte zu vergleichen.

Das Ergebnis sieht übrigens schon sehr gut aus. Ich bin jetzt mit meiner Audiovisualisierung bei 700 fps - da sieht man jedes kleinste Detail im Sound - und damit leider auch das ziemlich hohe Grundrauschen vom MSGEQ7. Da ist ein hochfrequentes flattern / zittern der Werte erkennbar. Habe ich vorher nie so deutlich gesehen.

Dieser Maximalwertspeicher hilft da, die Ausreisser nach unten auszusortieren. Die Anstiegszeit bleibt kurz (1/700s), die Abfallzeit vergrößert sich auf 20/700s. Klingt viel, ist aber scheißegal, das Ergebnis ist jetzt viel ruhiger und kontinuierlicher, als vorher - aber immer noch sehr reaktiv und “snappy”.
Schließlich interessiert die steigende Flanke viel mehr, als die fallende.

Gruß,

Helmuth

ob es vielleicht noch einen geschickteren (schnelleren) Sortieralgo gibt, als jedesmal alle 20 Werte zu vergleichen.

Wenn du dir den Max-Wert als Zeiger merkst, bist du meist etwas schneller. Nur wenn der alte Max Wert grade durch eine neue kleinere Messung überschrieben wird, bist du wieder genauso langsam.

Manchmal stört aber unregelmässige Geschwindigkeit auch ...

Beispiel:

const byte SIZE = 20;
byte valarray[SIZE];
byte* aktpos;
byte* maxpos;

byte * findMax(byte* arr, byte sz);

void setup() {
   aktpos = valarray;
   maxpos = valarray;
}

void loop() {
   *aktpos = getValue();
   if (*aktpos > *maxpos) maxpos = aktpos;
   else if (aktpos == maxpos) maxpos = findMax(valarray, SIZE);

   log(*aktpos, aktpos - valarray, maxpos - valarray);

   aktpos++;
   if (aktpos == valarray + SIZE) aktpos = valarray;
}

byte * findMax(byte* arr, byte sz) {
   byte* m = arr;
   for (byte* p = arr; p != arr + sz; p++)
      if (*p > *m) m = p;
   return m;
}

Danke, schöne Idee! Werde es testen und schauen, ob man die Unregelmäßigkeit wahrnimmt, oder nicht.

Gruß, H.

combie: Dann hat er ja den Maximalwert der letzten 20 Messungen verloren.....

Bsp.haft Quote von dir.

Eingangsfrage war, den Maximalwert der letzten 20 Messungen zubekommen. Ich lese daraus, jeden Wert mit dem letzten Max vergleichen, sofort ohne Buffer o.ä., ggf. Maxwert nachziehen, nach der 20. Messung alles verwerfen und von vorn. Wenn der Maximalwert nach der 20. Messung nicht verloren gehen soll, dann einfach nicht nullen. Nur dann wird er nie wieder kleiner. Ergibt auch keinen Sinn.

Das ist das was ich rausgelesen habe. Wenn das nicht so ist, dann weis ich aktuell nicht wo die Frage liegt.

Meine Problembeschreibung lautete:

Nehmen wir an, dass ich kontinuierlich Analogmessungen vornehme. Ziel ist es, jeweils den aktuellen Maximalwert der letzten 20 Messungen auszugeben.

Ich selbst sehe wenig Interpretationsspielraum in dieses 2 Sätzen, aber offensichtlich ist er dennoch gegeben.

Ich präzisiere also:

Ich will nach jeder einzelnen Messung den Maximalwert aus den vergangenen 19 und der aktuellen Messung wissen.

Ich werde mich zukünftig um klarere Formulierungen bemühen.

Grüße in die Runde,

Helmuth

Nur dann wird er nie wieder kleiner. Ergibt auch keinen Sinn.

Ich verstehe dein Problem evtl. auch nicht.

Wenn der bisherige Maximalwert älter als 20 Messungen wird, fällt er raus und der Maximalwert der letzen 20 muss neu bestimmt werden. Ergebnis wird dadurch etwas kleiner, ist aber sofort da, als größter der letzten 20.

Ziel ist es, jeweils den aktuellen Maximalwert der letzten 20 Messungen auszugeben.

Irgendwelche Ausreisser-Störungen wirken also genau 20 Zyklen lang, bis sie dann schlagartig und komplett wieder weg sind. Das lassen wir ausnahmsweise mal als sinnvolle Anforderung so stehen ... ;)

Irgendwelche Ausreisser-Störungen wirken also genau 20 Zyklen lang, bis sie dann schlagartig und komplett wieder weg sind. Das lassen wir ausnahmsweise mal als sinnvolle Anforderung so stehen ... ;)

Dieser Maximalwertspeicher hilft da, die Ausreisser nach unten auszusortieren. Die Anstiegszeit bleibt kurz (1/700s), die Abfallzeit vergrößert sich auf 20/700s.

Ein gleitender Durchschnitt würde Anstieg und Abfall verzögern. Sofortiger Anstieg ist aber wichtig. Deshalb meine Entscheidung, den Maxwert aus einem "gleitenden Zeitfenster" zu nehmen. Annahme dahinter ist, dass sich die Rauschdifferenzen über 20 Messungen zu ca. 0 addieren.

Wenn man sich mal analoge VU-Meter oder auch digitale oder Spectrumanalyzer Displays anschaut, haben die alle eine schnellere Anstiegs- als Abfallzeit. Der Betrachter ist daran gewöhnt.

Die Ausreisser-Störungen haben eine klare Ober- u. Untergrenze (konstante Maximalamplitude) im Vergleich zum eigentlichen Signal. Über 20 Messungen habe ich garantiert Ausreisser nach oben und unten dabei.

Sie sind also nach den 20 Messungen nicht schlagartig weg, sondern addieren sich nach wie vor zum eigentlichen Signal.

Diese Weichzeichnung legt im Prinzip eine ADSR Hüllkurve auf den zu messenden Wert, wobei A konstant bleibt, D und S null ist, und die Releasezeit R sich um 20 Zyklen erhöht.

Ergebnis: Sofortiges ansprechen auf Änderungen nach oben, verzögertes Abfallen bei Änderungen nach unten.

Gruß,

H.

Hallo,

naja, und was ist dann angeblich falsch an #1 und #5 ?

hi,

helmut, bis zu Deinem letzten post dacht ich, ich hätte es verstanden.

jetzt isses vorbei...

wenn Du die ausreißer nach unten UND nach oben hast, filtest Du die nach oben mit Deiner methode ja nicht raus, sondern Du verlängerst die leuchtdeuer Deiner ausreißer auf das zwanzigfache.

Annahme dahinter ist, dass sich die Rauschdifferenzen über 20 Messungen zu ca. 0 addieren.

dann müßtest Du doch einen gleitenden DURCHSCHNITT nehmen, sonst addieren sich die ausreißer nicht zu 0, sondern der größte ausreißer nach oben wird verwendet...

gruß stefan

@Doc: Wenn ich es so mache, wie ich #1 und #5 verstehe, habe ich alle 20 Messungen tatsächlich einen Sprung drin, weil der alte Maxwert weggeworfen wird.

Es ist nicht dabei definiert, wie lange der Maxwert minimal gültig bleibt. Nur die Obergrenze ist fix.

Ergebnis: Ein abfallendes Signal erzeugt eine Treppe.

Bei der Variante mit Array wirkt der letzte Maxwert immer 20 Zyklen ab auftreten nach.

Ergebnis: Der Signalverlauf bleibt gleich (keine Treppe), aber wird auf der Zeitachse nach rechts verschoben.

Gruß,

H.

Jetzt macht mich nicht schwach, so kompliziert ist das doch nicht! ;)

wenn Du die ausreißer nach unten UND nach oben hast, filtest Du die nach oben mit Deiner methode ja nicht raus, sondern Du verlängerst die leuchtdeuer Deiner ausreißer auf das zwanzigfache.

Korrekt. Die der Ausreisser nach oben.

dann müßtest Du doch einen gleitenden DURCHSCHNITT nehmen

Nein, der steigt zu langsam an.

sonst addieren sich die ausreißer nicht zu 0, sondern der größte ausreißer nach oben wird verwendet

Korrekt. Vielleicht addiert es sich nicht zu null.

Aber wenn ich weiß, dass der Ausreisser maximal 5 % vom Signal beträgt und ich mir sicher bin, dass ich in 20 Messungen mindestens einen Maximalausreisser dabei habe, ist das Ergebnis mein Signal + 5% und das Geflatter nach unten enfällt dabei.

jetzt isses vorbei...

Und, fängt es jetzt wieder an?

Gruß, H.

hi,

yep, helmut, jetzt isses wieder da.

was ich an Deiner stelle noch testen würde (ich kann mir das hier ja nicht aufbauen, sind also nur vorschläge):

wenn ich mir so ein altes VU-meter vorstelle, ist es doch so, daß, egal wie schnell der anstieg ist, der abstieg IMMER mit gleicher geschwindigkeit erfolgt (außer er wird von den echtdaten verlangsamt). versuch doch mal, die "sinkgeschwindigkeit" zu begrenzen. global. also egal, wie schnell die echtdaten fallen, die LED-helligkeit fällt nie schneller als x.

und das würde ich mit beiden methoden machen, also zum steigen mit MAX-wert der letzten 20 oder zum steigen einfach den letzten wert.

wie gesagt, nur vorschläge...

gruß stefan