Solch eine Funktion kann genutzt werden um schwankende Messwerte zu glätten oder um z.B. festzustellen ob sich ein Trend ergibt.
Es ist so programmiert, dass es mit nur 2 Systemvariablen auskommt und sehr variabel mit der Anzahl der Werte, über die der Mittelwert gebildet wird, umgehen kann. Weiterhin lässt sich entweder ein Kanal eines Gerätes oder eine Systemvariable als Daten Quelle nutzen.
Die Konfiguration des Script ist im Script nochmals detailliert beschrieben.
Vorbereitung:
- erstellen einer Systemvariablen vom Typ Werteliste, Inhalt in der Voreinstellung belassen - Zwischenspeicher FiFo u.a.
- erstellen einer Systemvariablen vom Typ Zahl im Wertebereich von -31.000 bis 31.000 - Speicher für den berechneten gleitenden Mittelwert
- genaue Adressierung eines Gerätekanal ODER Name der Systemvariable von dem die Messwerte genommen werden sollen um den gleitenden Mittelwert zu ermitteln
- die Anzahl der Messwerte über die der gleitende Mittelwert gebildet wird, größer gleich 2
- Den Aufruf kann man z.B. so konfigurieren, dass mit jeder Aktualisierung eines Gerätes das Script aufgerufen wird. Manchmal macht aber auch eine zeitliche Aktivierung Sinn.
- das Script liest bei jedem Aufruf einen neuen Messwert ein
- aus dem neuen Messwert und den bisherigen vergangenen Messwerten aus dem Zwischenspeicher wird ein neuer Mittelwert gebildet, dabei wurde der älteste Messwert im Zwischenspeicher nicht beachtet, FiFo Prinzip
- der neu berechnete Mittelwert wird an die konfigurierte Systemvariable ausgegeben
- der Zwischenspeicher wird aktualisiert indem der neue Messwert abgelegt und der älteste Messwert entfernt wird.
* das Script fragt keine Grenzen bezüglich der Menge der Messwerte im FiFo Speicher ab, bitte also nicht übertreiben
* Eine Änderung der Anzahl der Messwerte im FiFo lässt sich im Teil der Script Konfiguration einfach auch nachträglich durchführen (Anzahl der Werte im FiFo). Beim nächsten Durchlauf des Scriptes wird die neue Konfiguration übernommen.
* Alle Messwerte im FiFo werden nicht unterschiedlich gewichtet. Der älteste Wert wird also genau so bewertet wie der jüngste Wert.
Code: Alles auswählen
!! MittelwertGleitend V0.1
!! Berechnung eines gleitenden Mittelwertes (einfacher gleitender Durchschnitt) ueber eine frei definierbare Anzahl von Werten
!! * ermoeglicht die Aufzeichnung und Berechnung eines gleitenden Mittelwertes fuer eines
!! beliebigen Kanalnummes eines Geraetes oder eine Systemvariable aus denen die Werte kommen
!! * es findet keine Wichtung der einzelnen Werte statt,
!! * das Fenster, aus denen der Mittelwert berechnet wird bleibt gleich
!!
!!(c) duralis; zur freien Verwendung
!!
!!
!! Vorbereitung:
!! * in der CCU Anlegen einer Systemvariable vom Typ "Werteliste" anlegen, - automatisch generierten Inhalt so belassen
!! * in der CCU Anlagen einer Systemvariablen vom Typ "Zahl" mit Minimum -31000 und Maximum 31000 anlegen, dies ist der berechnete gleitende Mittelwert
!! * Konfiguration dieses Scriptes (etwas weiter unten) mit dem Namen der beiden soeben angelegten Systemvariablen und den weiteren Angaben
!! * in der CCU in der grafischen Obeflaeche ein Programm fuer Aufruf dieses Scriptes zusammenklicken, dieses angepasste Script angeben, fertig
!!
!! Aufruf:
!! * dieses Script z.B. mit jeder Messwertaufnahme (bei Aktualisierung) vom Sensor starten oder zeitlich z.B. jede Stunde je nach Zweck
!!
! ******* die folgenden Zeilen muessen angepasst werden ******
string svNameWerteliste = "v_tempor_WertelisteB"; ! Name der Systemvariablen als Werteliste, der als Speicher fuer die interne Berechnung dient (FiFo, Werte, Namen usw.)
! *** Bitte nur in einer der beiden naechsten Zeilen den Inhalt zwischen die Anfuehrungszeichen "" eintragen ***
string str_NameMesswertGeraet = "BidCos-RF.OEQ7654321:1.TEMPERATURE"; !hier in "" das Geraet angeben von dem der Messwert kommen soll inkl. kompletter Schnittstelle z.B. "BidCos-RF.OEQ1234567:1.WIND_SPEED" ODER ""
string str_NameMesswertSystemvariable = ""; !hier in "" den Namen der Systemvariablen angeben von dem der Messwert kommen soll und NICHT von einem Geraet
! Name der Systemvariable in dem der jeweils berechnete gleitende Mittelwert, also das Ergebnis, abgelegt werden soll
string svMittelwertGleitend = "v_tempor_ZahlB1"; ! Datentyp "Zahl", Wertebereich -31.000 bis +31.000; Name der Variable fuer den abzuspeichernden gleitenden Mittelwert
integer int_SollAnzahlMittelwerte = 21; ! Anzahl von Messwerten aus denen der gleitende Mittelwert berechnet wird (Beispiel 3 bedeutet, aus der aktuellen und den letzten 2 Messwerten wird der Mittelwert berechnet)
! Mindestens eine 2 als Zahl angeben, sehr grosse Werte sind eigentlich unsinnig und sorgen fuer viel zu hohe CCU Last
!! ********************************************************************************************************************
! ******* ab hier sind keine Anpassungen im Code mehr notwendig ******
object svObjekt;
! interne Variablen
string TrennzeichenDerZeilen = ";"; !das Semikolon dient als Trennzeichen in der Systemvariable(Listvariable) zum trennen der einzelnen Abschnitte
string TrennzeichenWerte = "|"; ! das "|" Pipe dient als Trennzeichen zwischen den Messwerten im FiFo Speicher
string str_WertelisteKomplett; !nimmt die komplette Werteliste auf (FiFo + Konfiguration)
string str_FiFoKomplett; !nimmt nur die Werte des FiFo auf
string str_FiFoNeu; !neue Werte die in den FiFo aufgenommen werden sollen
string str_EinSpeicherwert; !eine Zahl als String aus der Werteliste
integer int_EinSpeicherwert; !eine Zahl als Zahl aus der Werteliste
real real_Messwert; !nimmt Werte als Zahl auf - pruefen ob das nicht "real" sein sollte
integer int_IstAnzahlMittelwerteFiFo; !aktuelle Anzahl der Mittelwerte im FiFo
string str_index; !Indexvariable fuer foreach
integer int_index; !Indexvariable als Zahl
real real_GleitenderMittelwert; !enthaelt die Zwischenberechnung fuer den gleitenden Mittelwert
integer int_DifAnzahlZusatzWerte; !Anzahl FiFo Plaetze Aenderung, wenn der FiFo in der Groesse veraendert werden muss
!Aufbau Werteliste Variable
! Index 0 -> FiFo Speicher der einzelnen Messwerte, Pipe trennt die einzelnen Messwerte
! Index 1 -> komplette Adresse des Geraetes von dem die Messwerte genutzt werden ODER Name der Systemvariablen dessen Inhalt als Messwerte genutzt werden
! Index 2 -> Name der Systemvariablen in dem der gleitenden Mittelwert bei jedem Durchlauf geschrieben wird
! Index 3 -> aktuelle Anzahl der Messwerte im FiFo Speicher
!++++++++++++++++ Messwert aus Geraet oder Systemvariable auslesen +++++++++++++++++++++++++
if (str_NameMesswertSystemvariable!="")
{
real_Messwert = dom.GetObject(str_NameMesswertSystemvariable).State(); !den Messwert einlesen welcher als Mittelwert genutzt werden soll
}
else
{
real_Messwert = dom.GetObject(str_NameMesswertGeraet).Value(); !den Messwert einlesen welcher als Mittelwert genutzt werden soll
}
!++++++++++++++++ die Werteliste analysieren +++++++++++++++++++++++++
object svObjekt = (dom.GetObject(ID_SYSTEM_VARIABLES).Get(svNameWerteliste)); !Einlesen Werteliste vorbereiten
str_FiFoKomplett = svObjekt.ValueList().StrValueByIndex(TrennzeichenDerZeilen, 0);
!!wenn Script schon gelaufen ist dann Vorbelegte Werte nutzen ansonsten neue Werte erstellen, Find liefert "-1" wenn Substring nicht gefunden wurde
if (str_FiFoKomplett.Find(TrennzeichenWerte)!=-1)
{
str_EinSpeicherwert = svObjekt.ValueList().StrValueByIndex(TrennzeichenDerZeilen, 3); !Index 3 in Werteliste = Anzahl Werte im FiFo
int_IstAnzahlMittelwerteFiFo = str_EinSpeicherwert.ToFloat(); !Anzahl Werte im FiFo
real_GleitenderMittelwert = real_Messwert; !den aktuellen Messwert uebernehmen, dann den FiFo abklappern
int_index = 1; !erster Messwert wurde ja schon eingelesen
str_FiFoNeu = real_Messwert.ToString(); !den neuen Messwert in den FiFo an den Anfang setzen
int_DifAnzahlZusatzWerte = int_SollAnzahlMittelwerte - int_IstAnzahlMittelwerteFiFo; !feststellen ob der FiFo groesser, kleiner oder gleich gross bleiben soll
if (int_DifAnzahlZusatzWerte>=1)
{
while (int_DifAnzahlZusatzWerte>0)
{
str_FiFoNeu = str_FiFoNeu#TrennzeichenWerte#real_Messwert.ToString();
real_GleitenderMittelwert = real_GleitenderMittelwert + real_Messwert.ToString();
int_index = int_index +1;
int_DifAnzahlZusatzWerte = int_DifAnzahlZusatzWerte -1;
}
}
foreach(str_EinSpeicherwert, str_FiFoKomplett.Split(TrennzeichenWerte))
{
if (int_index < int_SollAnzahlMittelwerte)
{
str_FiFoNeu = str_FiFoNeu#TrennzeichenWerte;
str_FiFoNeu = str_FiFoNeu#str_EinSpeicherwert;
real_GleitenderMittelwert = real_GleitenderMittelwert + str_EinSpeicherwert.ToFloat(); !den naechsten Messwert aus dem FiFo mit berechnen
int_index = int_index +1;
}
!weitere Werte werden ignoriert weil FiFo Soll Anzahl erreicht wurde
}
!Index 0 der Listvariable fertig stellen - FiFo
str_FiFoKomplett = str_FiFoNeu#TrennzeichenDerZeilen;
!Index 1 der Listvariable fertig stellen - Quell Geraet oder Quell Variable
if (str_NameMesswertGeraet!="")
{
str_FiFoKomplett = str_FiFoKomplett#str_NameMesswertGeraet#TrennzeichenDerZeilen;
}
else
{
str_FiFoKomplett = str_FiFoKomplett#str_NameMesswertSystemvariable#TrennzeichenDerZeilen;
}
!Index 2 der Listvariable fertig stellen - Name der Systemvariable fuer die Ablage gleitender Mittelwert
real_GleitenderMittelwert = real_GleitenderMittelwert / int_index; !Berechnung neuer gleitender Mittelwert
str_EinSpeicherwert = svObjekt.ValueList().StrValueByIndex(TrennzeichenDerZeilen, 2);
str_FiFoKomplett = str_FiFoKomplett#str_EinSpeicherwert#TrennzeichenDerZeilen;
dom.GetObject(str_EinSpeicherwert).State(real_GleitenderMittelwert); !aktuellen berechneten gleitenden Mittelwert in die Systemvariable schreiben
!Index 3 der Listvariable fertig stellen - Anzahl der gleitenden Mittelwerte im FiFo
str_FiFoKomplett = str_FiFoKomplett#int_index;
svObjekt.State(0);
svObjekt.ValueList(str_FiFoKomplett); !Variableninhalt schreiben
}
else
{
!Die Systemvariable enthaelt Bloedsinn weil sie gerade angelegt wurde
!Index 0 zusammenbauen
int_index=0;
str_WertelisteKomplett = "";
str_WertelisteKomplett = str_WertelisteKomplett#real_Messwert.ToString();
int_index = int_index + 1;
while (int_index<int_SollAnzahlMittelwerte)
{
str_WertelisteKomplett = str_WertelisteKomplett#TrennzeichenWerte;
str_WertelisteKomplett = str_WertelisteKomplett#real_Messwert.ToString();
int_index = int_index + 1;
}
str_WertelisteKomplett = str_WertelisteKomplett#TrennzeichenDerZeilen;
!Index 1 zusammenbauen
str_WertelisteKomplett = str_WertelisteKomplett#str_NameMesswertGeraet#TrennzeichenDerZeilen;
!Index 2 zusammenbauen
str_WertelisteKomplett = str_WertelisteKomplett#svMittelwertGleitend#TrennzeichenDerZeilen;
!Index 3 zusammenbauen
str_WertelisteKomplett = str_WertelisteKomplett#int_index;
dom.GetObject(dom.GetObject(svNameWerteliste)).ValueList(str_WertelisteKomplett); !wieder abspeichern der korrigierten Systemvariable
!in die Systemvariable den Messwert als gleitenden Mittelwert schreiben
real_GleitenderMittelwert = real_Messwert;
dom.GetObject(svMittelwertGleitend).State(real_Messwert);
}