Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 9 von 9

Thema: Median-Filter für CoDeSys

  1. #1
    Registriert seit
    06.10.2011
    Beiträge
    4
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo,

    für eine Messwertaufbereitung benötige ich einen Median-Filter, damit Ausreißer nicht so ins Gewicht gehen.
    Die Messwerte werden über eine For-Schleife eingelesen und dass Array dann sortiert. Bei den Messwerten handelt es sich um Real-Werte (wären vielleicht skalierte INt-Werte besser --> weniger Speicher?). Der Median wird dann an den Ausgang übergeben.
    Es scheint mit 21 Werten ganz gut zu funktionieren, aber das Fenster müsste vergrößert werden. Wenn z.B. mit 201 Werten gearbeitet werden soll, macht die WAGO 750-872 PLC nichts mehr. Gibt es vielleicht irgendwo einen Median-Filter in einer freiverfügbaren Bibliothek, der getestet wurde?
    Hier mal der Code:

    PROGRAM Filter


    VAR
    MessSignal:REAL; (*Eingang*)
    Count: INT;
    ValueArray: ARRAY [0..20] OF REAL;
    myCount: INT;
    k: INT;
    l: INT;
    Value: REAL;
    FilterSignal:REAL; (*Ausgang*)
    END_VAR

    IF Count>20 THEN Count:=1; END_IF

    FOR Count:=1 TO 21 DO
    ValueArray[Count-1]:=MessSignal;
    myCount:=myCount+1;
    END_FOR;

    FOR k:=1 TO 20 DO
    FOR l:=1 TO 21 DO
    IF ValueArray[k-1]>ValueArray[l-1]
    THEN
    Value:=ValueArray[k-1];
    ValueArray[k-1]:=ValueArray[l-1];
    ValueArray[l-1]:=Value;
    END_IF
    END_FOR
    END_FOR
    IF k>20 THEN

    (*YValue:=;*)
    FilterSignal:=ValueArray[10];
    k:=1;
    l:=1;
    END_IF


    Vielleicht hat jemand ja schon mal so einen Filter benutzt und kann mir helfen? Vielen Dank,

    Ossi
    Zitieren Zitieren Median-Filter für CoDeSys  

  2. #2
    Registriert seit
    24.02.2009
    Beiträge
    1.244
    Danke
    23
    Erhielt 276 Danke für 235 Beiträge

    Standard

    Bis du sicher das dein Filter so funktioniert?

    Du füllst dein ValueArray
    Code:
    FOR Count:=1 TO 21 DO
      ValueArray[Count-1]:=MessSignal;
      myCount:=myCount+1;
    END_FOR;
    komplett mit dem gleichen Messwert. D.h. alle Elemente haben den selben Wert, was willst du da noch Filtern ?


    Das die Wago bei einer Fenstergröße von 200 in die Knie geht sollte dich nicht wundern. Immerhin muss deine verschachtelte Schleifenanordnung dann 40000 mal je Zyklus abgearbeitet werden.

    Brauchst du überhaupt so ein großes Fenster?

    Um Messwerte zu filtern verwende ich i.d.R einen gleitenen Mittelwert. Der haut schon bei einer Breite von 50 Werten die groben Ausreißer zuverlässig platt und ist auch wesentlich resourcenschonender.


    Noch ein paar kleine Anmerkungen zur Syntax:
    Zählervariablen für FOR-Schleifen brauchst du nicht zurücksetzen. Das macht die Schleife selber ( FOR i:=1 TO).
    Wenn dein Array von 0..20 geht, dann kannst du die FOR-Schleife auch bei 0 beginnen lassen ( FOR i:=0 TO), das spart dir dieses ständige -1 im Index.
    Alternativ kannst du das Array aber auch von 1..21 deklarieren.

    Der letzte Abschnitt
    Code:
    IF k> 20 THEN
    zeigt, dass du die zyklische Abarbeitung eines SPS Programms noch nicht so ganz verinnerlicht hast. Die beiden Schleifen werden im Zyklus immer komplett durchlaufen (wenn sie nicht durch den EXIT Befehl unterbrochen werden). D.H. k ist auch immer >20 wenn das Programm an der IF Abfrage ankommt. Also kannst du dir das IF sparen.

  3. #3
    Registriert seit
    29.03.2004
    Beiträge
    5.792
    Danke
    144
    Erhielt 1.706 Danke für 1.238 Beiträge

    Standard

    Das zeitraubendste ist der Sortieralgorithmus Bubblesort den du dort verwendest.
    Das meiste bringt es wenn du auf ein effizientes Sortierverfahren wechselst.
    Zum Vergleich in Zeiteinheiten:
    Bubblesort n². bei 200 Elementen = 40000
    Quicksort: im Mittel n log n, bei 200 Elementen = 460 (wobei es schlimmstenfalls vorkommen kann dass es auch 40000 benötigt)

    Und da gibt es noch effizientere Verfahren (Radixsort à la 00 alex)

  4. #4
    Ossi ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    06.10.2011
    Beiträge
    4
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo,
    Deine Hinweise waren sehr hilfreich! Vielen Dank!
    Ich habe mich jetzt für einen gleitenden Mittelwert entschieden...

    IF Count<20 AND Init=FALSE THEN
    ValueArray[Count]:=MessSignal;
    Count:=Count+1;
    IF count=20 THEN Init:=TRUE; END_IF
    END_IF

    IF PufferFil=TRUE THEN
    PufferArray[20]:=MessSignal;
    ValueArray:=PufferArray;
    PufferFil:=FALSE;
    END_IF

    FOR i:=1 TO 20 DO
    Value:=Value+ValueArray[i];
    IF i<20 THEN
    PufferArray[i]:=ValueArray[i+1];
    PufferFil:=TRUE;
    END_IF
    END_FOR

    (*YValue:=;*)
    FilterSignal:=Value/20;
    Value:=0;

    Gruß,

    Ossi
    Geändert von Ossi (15.08.2013 um 12:23 Uhr)

  5. #5
    Registriert seit
    21.02.2011
    Ort
    Deutschland, Baden-Würtemberg
    Beiträge
    992
    Danke
    115
    Erhielt 125 Danke für 100 Beiträge

    Standard

    (Radixsort à la 00 alex)
    ich sehe es kommen, in 20 Jahren bekommt er den Nobel-Preis

  6. #6
    Registriert seit
    24.02.2009
    Beiträge
    1.244
    Danke
    23
    Erhielt 276 Danke für 235 Beiträge

    Standard

    Welchen Filter aus der OSCAT Lib hast du denn genommen? Ich habe auf die schnelle nur den Filter_MAV_W bzw Filter_MAV_DW gefunden. Beide können keine REAL-Werte verarbeiten und auch nur über 32 Werte Filtern.

    Im Grunde ist ein Gleitender Mittelwert ganz einfach zu programmieren.

    Code:
    VAR_INPUT
      Messwert_neu :REAL;
    END_VAR
    VAR_OUTPUT
      FilterWert :REAL;
    END_VAR
    VAR
      Puffer :ARRAY[1..100] OF REAL; 
      Summe :REAL;
      i,pos :INT;
    END_VAR
    
    IF pos > 100 THEN
      pos := 1;
    END_IF
    
    Puffer[pos] := Messwert_neu;
    Summe := 0;
    
    FOR i := 1 TO 100 DO
      Summe := Summe + Puffer[i];
    END_FOR
    
    FilterWert := Summe / 100.0;
    pos := pos +1;
    wie immer ohne Gewähr

    Der aktuelle Messwert wird fortlaufend in den Puffer geschrieben, sodass der Puffer immer den neuen Wert und die 99 letzten Werte enthält.
    Diese 100 Werte werden dann aufsummiert und durch 100 dividiert. => Mittelwert
    Im nächsten Zyklus kommt wieder eine neuer Messwert hinzu und es gibt einen neuen Mittelwert.
    Bei den ersten 99 Messwerten kommt hier natürlich nur Murks raus, weil der Puffer ja noch mit 0 gefüllt ist. Das musst du berücksichtigen!
    Da gibt es aber Lösungen für, z.B. im ersten Aufruf den Puffer mit dem ersten Messwert vollschreiben.

    Über wieviele Werte du filterst, solltest du je nach benötigter Reaktionszeit und Rauschunterdrückung abwägen.

    Wenn du starke Spitzen im Signal hast, wirst du die mit einem MAV Filter nie ganz weg bekommen. Starke Ausreißer werden nur "breit gezogen" aber nicht entfernt. Für sowas ist dann z.B. ein Median wieder besser geeignet.
    Geändert von MasterOhh (15.08.2013 um 12:21 Uhr) Grund: Typo

  7. Folgender Benutzer sagt Danke zu MasterOhh für den nützlichen Beitrag:

    PLC_HD (10.02.2016)

  8. #7
    Registriert seit
    29.03.2004
    Beiträge
    5.792
    Danke
    144
    Erhielt 1.706 Danke für 1.238 Beiträge

    Standard

    Median gibt es in der Oscat Bibliothek, nennt sich _ARRAY_MEDIAN.
    Beim Aufruf muss man aber die Größe des Arrays mit übergeben.

    Beispiel:
    Code:
    VAR
    	werte : ARRAY[1..10] OF REAL;
    	median : REAL;
    END_VAR
    Wenn du den Median über das gesamte Array (also alle 10 Elemente) bilden willst, muss der Aufruf so lauten:
    Code:
    median := _ARRAY_MEDIAN(pt := ADR(werte), size := SIZEOF(werte));
    Soll der Median über z.B. die ersten 5 Elemente des Arrays gebildet werden, dann so:
    Code:
    median := _ARRAY_MEDIAN(pt := ADR(werte), size := 5 * SIZEOF(werte[1]));
    da der Parameter "size" die Größe des Arrays im Speicher, und nicht die Anzahl der Elemente angibt.

  9. #8
    Registriert seit
    24.02.2009
    Beiträge
    1.244
    Danke
    23
    Erhielt 276 Danke für 235 Beiträge

    Standard

    Müsste man mal reinschauen wie dort die Werte Sortiert werden.

  10. #9
    Registriert seit
    29.03.2004
    Beiträge
    5.792
    Danke
    144
    Erhielt 1.706 Danke für 1.238 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Das sieht bei Oscat nach Quicksort aus. Ist bei einer sehr größen Anzahl an Elementen vielleicht nicht die beste Lösung, da es im ungünstigen Fall dann doch sehr lange dauern kann.
    Wobei es im hier gezeigten Beispielcode wohl daran liegt, dass es hier mit 20 Elementen nicht funktioniert weil überhaupt kein korrekter Median gebildet wurde. Vielleicht erstmal mit einem korrekten Median über 20 Werte probieren.

    Des weiteren ist zu beachten dass das Array in der Oscat-Sortier-Funktion verändert wird. Wenn man z.B. ein Median fortlaufend über die letzten n Werte erstellen will, muss man sich die alten Werte vorher wegsichern, bzw. die Oscat Median Funktion auf einer Kopie des Arrays arbeiten lassen.

Ähnliche Themen

  1. Median S7-1200
    Von Michael J. im Forum Simatic
    Antworten: 6
    Letzter Beitrag: 12.12.2012, 22:39
  2. Sensoren Filter
    Von Blackdriver im Forum CODESYS und IEC61131
    Antworten: 2
    Letzter Beitrag: 04.11.2011, 16:05
  3. Filter für analoge Ausreißer
    Von mitchih im Forum Simatic
    Antworten: 10
    Letzter Beitrag: 21.01.2011, 14:36
  4. Ein Spül-FC (FB) für 10 Filter
    Von DerTheo im Forum Simatic
    Antworten: 1
    Letzter Beitrag: 01.10.2009, 17:19
  5. Filter
    Von Gerd1994 im Forum Simatic
    Antworten: 4
    Letzter Beitrag: 09.07.2009, 16:47

Stichworte

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •