Werte glätten

Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen allerseits.

Hoffe, in allen Händen ist eine Tasse heissen Kaffees.

@LL: Du meinst also, pro Schleife überprüfen, ob der gemessene Wert ein gewisses delta überschreitet, und dann überprüfen, ob dies inm Zeitraum x (bzw. in den letzten y Abtastzyklen) n-mal vorgekommen ist?

Aktuell habe ich einen Taktgeber in die Schleife integriert, der alle paar ms für einen Zyklus einen Wert auf True setzt. Dieser wird nach Abarbeiten der Schleife auf False zurückgesetzt.

@vierlagig: natürlich OR und <. Habe da zu schnell geschossen.

@Hugo: ich müsste doch beide Frequenzausreisser bereinigen also auch die unteren. Oder ist mit "oberen Frequenzbereiche" die relative Differenz zum durchschnittlichen Eingangssignal gemeint?



Wie man sieht, bin ich in dieser Thematik mehr als unerfahren.

Aber klasse, so viel positives Feedback zu bekommen. Macht den Eindruck, als machtet Ihr so was öfter. :ROFLMAO:

Gruss

McNugget
 
@hugo:

die mittelwertbildung zur quasi-glättung ist ein erprobtes und gängiges mittel. mir ist bis jetzt noch kein erfahrener programmierer untergekommen, der davon abstand nehmen würde. vorallem ist es schnell und einfach umgesetzt und darüber hinaus, richtig implentiert sehr flexibel.

Hugo hat ja in dem Sinne recht, dass man mit einer angepassten tiefpass Funktion CPU-Zyklen sparen kann und dass kann sich durchaus im Preis der SPS bemerkbar machen. Die Mittelwertbildung ist ja nichts anderes wie ein Tiefpassfilter, aber nicht sonderlich effizient.
 
@LL: Du meinst also, pro Schleife überprüfen, ob der gemessene Wert ein gewisses delta überschreitet, und dann überprüfen, ob dies inm Zeitraum x (bzw. in den letzten y Abtastzyklen) n-mal vorgekommen ist?

So hatte ich es gedacht.
Wobei es hier ja noch Alternativ-Möglichkeiten gibt :
- Abweichung zum bisher gemessenen Mittelwert (nach oben oder unten) > xyz %
- Über- oder Unterschreitung eines Absolutwertes
- Verhältnis von Wert [x] zu Wert [x+1]
usw.

@drfunfrock , hugo:
Ich finde die Glättungs / Mittelwert-Diskussion sehr müßig. Sie trägt zum eigentlichen Problem nichts bei und so nebenher realisiere ich bei Kurven-Auswertungen die Glättung (ich meine hier jetzt tatsächlich Glättung) auch auf eine ähnliche Weise (und es funktioniert).
Man kann es natürlich auch über die Hoch-Tiefpass-Formel machen - ob das aber weniger Aufwand ist ...?

Gruß
LL
 
@drfunfrock , hugo:
Ich finde die Glättungs / Mittelwert-Diskussion sehr müßig. Sie trägt zum eigentlichen Problem nichts bei und so nebenher realisiere ich bei Kurven-Auswertungen die Glättung (ich meine hier jetzt tatsächlich Glättung) auch auf eine ähnliche Weise (und es funktioniert).
Man kann es natürlich auch über die Hoch-Tiefpass-Formel machen - ob das aber weniger Aufwand ist ...?

Gruß
LL

Zum 1. Die Mittelwertbildung ist OK. Zum 2. Es geht nicht um den Aufwand beim Programmieren, sondern ob ein Tiefpassfilter effzienter ist und damit auch weniger CPU benötigt. Und das sollte der Fall sein. Ich kann hier mit Labview einen Filter bauen, der hat bei einer Abtastfrequenz von 66Hz (15ms Zykluszeit) und einer Grenzfrequenz von 5Hz gerade, eine ordnung von 2 und dürfte damit wesentlich weniger CPU benötigen.
 
Ist durch Einsatz eines Codeschnipsels aus der OSCAT.Lib erledigt.. Aber es gibt ständig neue "Herausforderungen".. ;-)

Letztendlich kann ich noch zu schlecht strukturierten Text, um so etwas (also z.B. Array mit Mittelwertbildung) selber zu schreiben.. :(



Ich fand es sehr interessant, zu sehen, wie man an diese Problematik herangehen kan..
Vielen Dank an alle Beteiligten.

Gruss

McNugget
 
anbei ein bißchen code ...

ist damals aus der "not" enstanden, da ich auch immer ausreißer ( manchmal mehr als 50% vom letzten Wert ) hatte ...

Code:
FUNCTION_block Median

VAR_INPUT
 PV: Real; // Prozessvariable
 Start: bool; // Start Mittelwert
 Reset: bool; // Reset Mittelwert
 Puls:BOOL; // Impuls Meßwert aufnehmen
 Check:REAL; // Abweichung in Prozent +/-   
END_VAR

VAR_OUTPUT
 Out: Real; // Medianwert
 Stabil:BOOL; // PV = Mittelwert ( im Bereich )
END_VAR

VAR
  Werte: ARRAY[1..10] OF REAL;
  Median:ARRAY[1..10] OF REAL;
END_VAR

VAR_TEMP
    i:INT;
    j:INT;
    Help:REAL;
END_VAR

LABEL
   Saved;
END_LABEL

BEGIN
  
Stabil:=False;  
  
IF reset THEN
   Out:=0.0;
ELSIF start AND Out = 0.0 THEN
    FOR i:=1 TO 10 DO
        Werte[i]:=PV;
    END_FOR;
    Out:=PV;
ELSIF Puls AND start THEN
    
  FOR i:=10 TO 2 BY -1 DO
     Werte[i]:=Werte[i-1];
  END_FOR; 
  
  IF start then 
    Werte[1]:=PV;
  ELSE
    Werte[1]:=0.0;
  END_IF;
  
  Median:=werte;
  
  FOR i:=1 TO 9 DO
    FOR j:=i+1 TO 10 DO
      IF median[i] > median[j] THEN
        Help:=median[i];
        median[i]:=median[j];
        median[j]:=help;
      END_IF;
    END_FOR;
  END_FOR;

  FOR i:= 4 TO 7 DO
    Out:= Out + median[i];
  END_FOR;
  
    OUT := out / 5.0;  
    
END_IF;

    Stabil:= ABS(PV-Out) * 100.0 / ABS(PV) < Check; 
    
END_FUNCTION_BLOCK

es werden einfach 10 Werte aufgenommen, mit jedem Puls ein neuer - läuft bei mir meistens mit 100ms Takt - hat sich bewährt.

Dann werden die Werte sotiert und dann nur die "inneren" 4 Werte verwendet. Die anderen verworfen.

Die anderen addiert + dem letzten und durch 5 geteilt.

Das mit dem Ausgang stabil ist nur Spielerei. Wenn der Istwert innerhalb eines Fenster ( Angabe in % ) vom gemittelten Wert liegt ist der da.

Kannst damit schnell auf ausreißer reagieren - falls gewünscht.

Nutze den mittlerweile fast bei jedem Analogwert.

1. funktioniert gut
2. der braucht kaum zykluszeit
3. du hast keine ausreißer mehr

gruß
christian
 
ich nochmal,

wieso sehe ich hier einen andren ( weniger ) text als in der email aus dem forum ...

(natürlich ist es das...)

Als Einziges fehlt noch, dass zu Beginn der Ausgangswert mit dem Eingangswert initialisiert wird, um nicht erst nach 10 * 100ms einen Wert zu erhalten.

Aber das ist ja schnell gebastelt.

Cool.

Vielen Dank!
***************

naja , egeal ... die Initialisierung ist doch drin,
Code:
IF reset THEN
   Out:=0.0;
[COLOR=Red]ELSIF start AND Out = 0.0 THEN
    FOR i:=1 TO 10 DO
        Werte[i]:=PV;
    END_FOR;
    Out:=PV;[/COLOR]
ELSIF Puls AND start THEN
    
  FOR i:=10 TO 2 BY -1 DO
     Werte[i]:=Werte[i-1];
  END_FOR;

gruß
 
Infinite Memory

Also ich würde das so machen:

Code:
durchschnitt:=(durchschnitt*10+messwert)/11;
ist etwas übersichtlicher und schneller.

Das ist nicht nur übersichtlicher, das liefert auch bessere Ergebnisse. Dieser Filtertyp wird als inifinite Memory Typ klassifiziert. Es vergisst sozusagen nie einen Wert der Vergangenheit, solange die Auflösung des Datentyps ausreichend ist.

Ein Array mit einer festen Anzahl von Elementen, kann hingegen nur diese Anzahl von Werten der Vergangenheit ausmitteln.

Die infinite Memory Filter können noch wesentlich effektiver von den Algorithmen gestaltet werden aber das muss man dann in Büchern über Mathematik nachlesen.

Ein anderer Weg ist der mit dem "Sliding Window", wie von Stricky angedeutet, dieses Verfahren hat insbesondere Vorteile im Postprozessing von Messreihen, da es im Prinzip nicht den Ärgermacht, dass Verzögerungen bei Sprüngen sich wie bei Tiefpassfiltern einstellen.
 
Zuletzt bearbeitet:
Zurück
Oben