Kleiner Filter für Spikes

shrimps

Level-1
Beiträge
422
Reaktionspunkte
49
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
da ich sehr oft von Einsteigern lese, das sie Störimpulse bei der Analogwertverarbeitung haben, habe ich mal meinen kleinen Filter hier abgelegt.
Ich habe auch an einigen Stellen bei der Verarbeitung von PT1000 mit einer RTD-Karte ab und zu Spikes (Peaks).
Da ich aber keinen Mittelwert oder ähnliches haben wollte, filtere ich den einfach raus.
Ist auch nur für einen Peak pro Zyklus gedacht, wenn mehrere Peaks nacheinander auftreten ist der Baustein nicht geeignet.
Alles in ST geschrieben unter Twincat2.
Sollte aber leicht in alle derivate umsetzbar sein.

Viel Spaß damit
und mal schauen was die Kommentare hergeben.

Code:
FUNCTION_BLOCK _fbFilter3
(* shrimps, 03.2017
Spikes ausfiltern:
In jedem Zyklus werden die letzten drei Messwerte sortiert und der mittlere jeweils weitergereicht.
Dadurch werden jede Menge Störimpulse weggefiltert
*)
VAR_INPUT
    x    : REAL;
END_VAR
VAR_OUTPUT
    Y    : REAL;
END_VAR
VAR
    sort     : ARRAY [0..2] OF REAL; (* Kopie des tmp zum soertieren *)
    tmp     : ARRAY [0..2] OF REAL; (* Unsere 3 Daten *)
    init     : BOOL := TRUE;            (* Aller Anfang *)
    dirty    : BOOL;                    (* Alles Sortiert ? *)
END_VAR

(* Modulstart *)
IF init THEN
    tmp[0] := x;
    tmp[1] := x;
    tmp[2] := x;
    init := FALSE;
END_IF

(* Neuwert, alles einen weiterschieben *)
tmp[0] := tmp[1];
tmp[1] := tmp[2];
tmp[2] := x;

(* Sortieren *)

sort := tmp;    (* Work-Array duplizieren *)

REPEAT    (* Solange wir mit dem Sortieren nicht fertig sind *)

    dirty := FALSE;                (* Sortieren ist Fertig !? *)

    IF sort[0] > sort[1] THEN    (* Ist der erste groesser als der zweite ? *)
        y := sort[0];            (* Dann in Y merken, wir sparen uns eine Zwischenvar *)
        sort[0] := sort[1];        (* Nun tauschen *)
        sort[1] := y;            (* Merker zurueck *)
        dirty := TRUE;            (* Wir haben sortiert ! *)
    END_IF

    IF sort[1] > sort[2] THEN    (* Ist der zweite groesser als der dritte ? *)
        y := sort[1];            (* Rest s.o. *)
        sort[1] := sort[2];
        sort[2] := y;
        dirty := TRUE;
    END_IF

UNTIL NOT dirty                (* Erst aufhoeren, wenn alles sort. ist *)
END_REPEAT

y := sort[1];                (* Unser Ergebniss ist immmer in der Mitte ! *)
 
Zuletzt bearbeitet:
Den Code rufst Du in einer speziellen Task auf? Er darf ja nicht schneller aufgerufen werden, als der Analogeingang neue Werte liefert.

Harald
 
Zurück
Oben