# Werte beruhigen



## Draco Malfoy (3 November 2014)

Moin zusammen.

Ich möchte sehr gerne einen halb-analogen Wert beruhigen, der mir noch zu sehr schwankt bzw. teilweise auch richtig heftige Ausschläge zeigt, die nicht ins Messergebnis passen.
Ich habe dabei entweden an einen gleitenden Mittelwertfilter gedacht, oder an einen Tiefpass (1.er Ordnung, 2.er Ordnung ?? N-ter Ordnung ?) Grundlage sind jeweils OSCAT-Bausteine.

Die Werte werden je 150mS abgefragt also etwa 6 mal pro Sekunde eingelesen. Wie müsste ich jetzt sinnvollerweise die Glättungszeit und die Glättungskonstanten (K1, K2..) wählen ?
Wie kommt man am schnellsten zu den optimalen Einstellungen ?


Thanx im Voraus!


----------



## vollmi (3 November 2014)

Heftige Ausschläge sprechen IMHO gegen einen gleitenden Mittelwert. Wie wäre es mit einem FIFO und darauf aufgesetzen Median?


mfG René


----------



## Draco Malfoy (3 November 2014)

> Wie wäre es mit einem FIFO und darauf aufgesetzen Median?


Habe ich auch schon überlegt. Würde denn aber ein Tiefpass tendenziell nicht genau solche einzelstehende Spitzen ausfiltern können ?
...P.S.  Die Implementierung von FIFO im Verbund mit Median ist mir jetzt auch noch nicht so ganz geläufig


----------



## RobiHerb (3 November 2014)

Mal eine Strategie kurz angedeutet:

Nimm jeweils die letzten n  Werte, bilde den Mittelwert M1, werfe die Extrema (die x Werte, die am  meisten vom Mittel M1 abweichen) fort, bilde über die verbleibenden  Werte das Mittel M2. Das kannst Du auch rekursiv machen.

M2 ist Dein beruhigter Wert. Die Anzahl der weggelassenen x Extremwerte kannst Du nur durch Ausprobieren optimieren. Das Ganze ist dann ein modifizierter Tiefpass, der durch die Anzahl n bestimmt wird.

Natürlich ist diese Sache eine Beschönigung, man müsste zuerst einmal versuchen, zu ergründen, woher die Ausreisser stammen!

Wenn die Quelle schon nichts taugt, dann wird die Auswertung nicht unbedingt besser.


----------



## Draco Malfoy (3 November 2014)

> Wenn die Quelle schon nichts taugt, dann wird die Auswertung nicht unbedingt besser.


Die Quelle taugt nichts, aber seitens des AG kam die Aufforderung diese zu implementieren. Von daher...
 Außerdem - naja was heißt heftige Ausreißer. Wir haben z.B. einen exacten Wert (nach der Linearisierung) der bei 380 liegt. Jetzt geht er teilweise runter auf 370 und hoch bis 390, aber nicht in einem Peak, sondern er "krabbelt" sich da so lustig hoch und runter und schwankt dabei immer um 2-3 Einheiten. Wenn man dieses feine Zittern wegnehmen würde, wäre ja möglicherweise schon etwas gewonnen.


----------



## MasterOhh (3 November 2014)

Gegen so einen Drift wird es schwer mit einem Filter anzugehen ohne die gewollte Signaländerungen zu sehr zu verzerren. Hochfrequente Schwankungen mit geringer Amplitude bekommst du aber idR schon über wenig Messwerte gut herausgemittelt. Manche Steuerungshersteller haben auch schon in den Analogeingangskarten Filter integriert, die man nach Bedarf aktivieren kann, vlt. gibt es das bei dir auch?


----------



## Draco Malfoy (3 November 2014)

MasterOhh schrieb:


> Hochfrequente Schwankungen mit geringer Amplitude bekommst du aber idR schon über wenig Messwerte gut herausgemittelt. Manche Steuerungshersteller haben auch schon in den Analogeingangskarten Filter integriert, die man nach Bedarf aktivieren kann, vlt. gibt es das bei dir auch?


Die Werte werden aber nicht über eine analoge Karte eingelesen sondern per RS-232 Interface. Die Sachlage ist da leider etwas komplexer. Steuerung is ne normale S7-416 mit abgesetzten I/O s sprich ET200S.
Welche Werte des Filtes (und welchen Filters ? FILTER_I, FT_PT1, Gleitender Mittelwert ?) würdest Du zu Beginn veranschlagen um das hochfrequente Zittern zu unterdrücken ?


----------



## SanjaDO (3 November 2014)

Hier ist ein schöner EA-Filter:


```
FUNCTION_BLOCK "Filter_AA"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      IN : Real;
      V_IN : Real;
   END_VAR

   VAR_OUTPUT 
      OUT : Real;
   END_VAR

   VAR 
      V : Real;
   END_VAR


BEGIN
    
    
    
    #V:=#V_IN;
      IF #IN = #OUT THEN
        #V:=0.0;
      ELSIF #IN<#OUT THEN
        #OUT:= LIMIT(MN:=0.0,IN:=#OUT-MIN(IN1:=#V,IN2:=#OUT-#IN),MX:=100.0);
      ELSIF #IN>#OUT THEN
        #OUT:= LIMIT(MN:=0.0,IN:=#OUT+MIN(IN1:=#V,IN2:=#IN-#OUT),MX:=100.0);
      END_IF;
      
    
    
END_FUNCTION_BLOCK
```


----------



## Draco Malfoy (3 November 2014)

> Hier ist ein schöner EA-Filter:


Danke für den Code. Funktioniert auch anständig ? Hast Du selber geschrieben ? Mit welchen Arten von Signalen hast Du das schon getestet ? 
Was für Parameter sollen da rein ? Warum wird der max. Wert auf 100 begrenzt ?


----------



## vollmi (3 November 2014)

Draco Malfoy schrieb:


> Habe ich auch schon überlegt. Würde denn aber ein Tiefpass tendenziell nicht genau solche einzelstehende Spitzen ausfiltern können ?
> ...P.S.  Die Implementierung von FIFO im Verbund mit Median ist mir jetzt auch noch nicht so ganz geläufig



Mir ist dafür der Tiefpass hier nicht so geläufig 

Ich habe so eine ähnliche Problemstellung so gelöst.

```
FUNCTION_Block WM_gleit_MedianTITLE = '_MEDIAN'
(* Diese Funktion gibt den Median aus bis zu 200 aufgezeichneten Gleitpunktwerten aus 
   V1.0 Abgegebene Version
 *)


VERSION : '1.0'
AUTHOR  : VoR
NAME    : Med_R
FAMILY  : FunkB


VAR_INPUT
 MW : REAL; // Windmesswert.
 Takt : BOOL; // Trigger um Messwert einzlesen. Reagiert auf steigende Flanke
 Anz : INT; // Anzahl Messwerte aus denen der Median gebildet wird.


END_VAR
VAR
 rwert : ARRAY[1..200] OF REAL; // Array für FIFO
 rwert_sort : ARRAY[1..200] OF REAL; // Array für Sortierung
 rMedian : REAL; 
 getauscht : BOOL;
 zw: REAL;
 i: INT;
 anzahl_save : INT;
 TAKT_ZM : BOOL;
    Onimp : BOOL;
    Onimpmem : BOOL;
END_VAR
VAR_OUTPUT
  median: REAL;
END_VAR




BEGIN
IF Anz < 3 THEN // Sicherstellen das index für FOR Schleife mindestens eine drei enthält.
    anzahl_save := 3;
ELSE
    anzahl_save := Anz;
END_IF;


Onimp :=  Takt AND NOT Onimpmem;
    Onimpmem := Takt;




IF onimp THEN // nur beim Takt ausführen
    FOR i := anzahl_save TO 2 BY -1 DO
        rwert[i] := rwert[i - 1];
    END_FOR;
        rwert[1] := MW;
END_IF;


    rwert_sort := rwert; // kopieren zum sortieren


(* Bubblesort Algoritmus sortiert aufsteigend das Array rwert (geschwindigkeit)
   und kopiert die irtg (windrichtung) die dazugehören gleich mit *) 
REPEAT
  getauscht := false; // tauschmerker
      FOR i := anzahl_save TO 2 BY -1 DO
          IF rwert_sort[i-1] > rwert_sort[i] THEN // tauschen
            zw := rwert_sort[i];
            rwert_sort[i] := rwert_sort[i-1];
            rwert_sort[i-1] := zw;
            getauscht := true;
          END_IF;
      END_FOR;
  UNTIL NOT getauscht
END_REPEAT;




   
// median auswählen    
median := rwert_sort[anzahl_save/2]; // den wert aus der Mitte der Anzahl werte nehmen. Wurden sortiert


END_FUNCTION_BLOCK
```

Das ist der Ursprungsbaustein. Das sortierte Array muss also nicht im Stat bereich stehen. ausserdem werden noch nicht gefüllte Zellen nicht ausgefiltert. Aber die Grundsätzliche Funktion ist gegeben. Vielleicht hilft dir das schon weiter.

mfG René


----------



## SanjaDO (3 November 2014)

In diesem Fall ist mein Messwerbeich von 0 bis 100 %, du kannst dein Messbereich natürlich anpassen. 
Ich hab's mit analogen Eingangssignalen getestet, funktioniert wunderbar. Der Nachteil hierbei ist, dass der Filter in einem Weckalarm ob wie z. B. 100ms OB aufgerufen werden sollte.
V_IN ist das die "Geschwindigkeit deines Filters. In dem Fall wenn für du für V_IN eine 2 einstellst, hast du 20 digits in einer Sekunde. Bei einem Sprung von 0 auf 100 wäre der Ausgangswert in 5 Sekunden ausgeglichen.
Den Paramter V_IN kannst du dann wärend einer Inbetriebnahme schnell anpassen.


----------



## Draco Malfoy (3 November 2014)

> In diesem Fall ist mein Messwerbeich von 0 bis 100 %, du kannst dein Messbereich natürlich anpassen.
> Ich hab's mit analogen Eingangssignalen getestet, funktioniert wunderbar. Der Nachteil hierbei ist, dass der Filter in einem Weckalarm ob wie z. B. 100ms OB aufgerufen werden sollte.
> V_IN ist das die "Geschwindigkeit deines Filters. In dem Fall wenn für du für V_IN eine 2 einstellst, hast du 20 digits in einer Sekunde. Bei einem Sprung von 0 auf 100 wäre der Ausgangswert in 5 Sekunden ausgeglichen.
> Den Paramter V_IN kannst du dann wärend einer Inbetriebnahme schnell anpassen.


Interessant. Is an sich so auch kein schlechtes Konzept. Ich werde mal morgen beide Varianten ausprobieren (und FT_P1 noch dazu) und gebe dann eine Rückmeldung ab.
... Noch so n Gedanke der mir gerade kommt: Analogwerte zur Linearisierung und Ausfilterung sollten generell in REAL oder DINT angeboten werden. Sehe immer wieder als Schnittstellenbeschreibung der Sensorik WORD, INT, STRING (!) wodrin dann CHARs stehen, die mir hexadezimale Zeichen abbilden. Wer programmiert bitte sowas ??


----------



## SanjaDO (3 November 2014)

Ich benute immer die Siemensfunktion SCALE (bei 1500er CPU's). Als Eingang habe ich dann einen INT und Ausgang natürlich einen REAL. Was anderes würde ich nicht nehmen.


----------



## SanjaDO (3 November 2014)

Beispiel:


```
#fehlercode_fuellstand:=SCALE(IN:=#LIS,HI_LIM:=100.0,LO_LIM:=0.0,BIPOLAR:=false,OUT=>#Fuellstand);
```

LIS ist eine temproräre Integer Variable die einem analogeingang gleichgesetzt wird:
LIS:=%EW256;
Fuelstand ist von Typ REAL


----------



## Draco Malfoy (3 November 2014)

Ja ich meine, wenn die Sensorik an sich schon irgendwas sehr seltsames ausgibt, muss man das 5 mal wandeln, bevor man die Werte überhaupt verarbeiten kann. Egal, ist ein anderes Thema.


----------



## Ottmar (3 November 2014)

Hi!

Was hast du denn für ein Automatisierungssystem?
Beim großen S kann man in der Hardwarekonfiguration den Filter entsprechend einstellen.

Gruß,

Ottmar


----------



## Draco Malfoy (3 November 2014)

Ottmar ich habe da schon oben was zu geschrieben.


----------



## Aventinus (3 November 2014)

Mittelwert := (Mittelwert*9+Messwert)/10;

oder zur Laufzeit änderbar:
Mittelwert := (Mittelwert*(Filter+1)+Messwert)/Filter;


----------



## riesermauf (3 November 2014)

Hallo
du verwendest ja die Oscat-Lib, ich verwende die Bausteine SH_1 und FT_AVG, das funktioniert bei meiner Wago sehr gut.


----------



## Thomas_v2.1 (3 November 2014)

Das Teil von Sanjo filtert erstmal überhaupt nicht, sondern ist nur eine Begrenzung der Anstiegsgeschwindigkeit. Sowas lässt sich benutzen um z.B. eine Sollwertänderung stetig und nicht schlagartig auf einen Regler zu geben. Um einen Wert zu filtern in der Art wie man es von einem Tiefpass erwarten würde ist es nicht brauchbar.

Der Code von Aventinus ist ein PT1-Filter, d.h. ein Tiefpass erster Ordnung. Bei den Oscat-PT1 Filtern hängt die Grenzfrequenz vom Aufrufzyklus ab, siehe hier:
http://www.sps-forum.de/simatic/70496-pt1-glied-2.html#post489053


----------



## Draco Malfoy (4 November 2014)

Moin zusammen.
Also ich habe das Zeug gestern ausprobiert, zunächst einmal den PT1 Filter aus der Library. Also der liefert brauchbare Werte erst ab einem Tau von etwa 1,5s, d.h. so erst ab 9-10 Messwerten hintereinander.
Andere Bausteine werde ich möglicherweise die Tage noch austesten. @*Thomas_v2.1*: Danke für den Hinweis. Bei mir ist Zyklus etwas zwischen 3 und 5 mS (...416er CPU) und die Aktualisierungs-f liegt bei 6Hz.


----------

