Mittelwert berechnen (Windspeed)

Hallo,

ich versuche gerade mir einen Sinnvollen Anzeigewert für die Windgeschwindigkeit zu berechnen.
Ich betreibe eine SCN-WS3HW.01, das ist im Prinzip ein Windrad mit Dämmerungssensoren und Tempereatursensor.

Eigentlich gedacht zur Fassadenstererung, aber: wenn man da sowieso eine „kleine Wetterstation“ hat würde ich mir gerne die aktuelle Windgeschwindigkeit anzeigen lassen, einfach aus Interesse.

Das Teil sendet den aktuellen Windspeed bei einer Änderung von 10%. Ich würde mir jetzt gerne einen Mittelwert über z.B. 10 Minuten errechnen. Mein bisheriges Script schreibt jeden neuen Wert in eine angelegte IPS-Variable, löscht alte Variablen die älter als die definierte Zeit sind und berechnet danach einen Mittelwert über die verbleibenden Variablen. Das funktioniert, sieht aber irgendwie so aus wie als ob man das noch besser lösen kann, ohne Variablenverbrauch. Mir fällt aber als Hobby Programmierer nichts ein. Gibts einen Weg den ich nicht sehe, oder ist das wirklich nur so zu lösen wie ich es mache ?

anbei mein Script:

<?

$time = time();
$EventIdCyclic = 21744 /*[Scripte\KNX\Wind auf Bus\Täglich alle 5 Minuten]*/;
$VarIdInbetrieb = 28919 /*[KNX\Stör - Statusobjekte\Statussachen / Timestamp\Inbetrieb Wetter\Wert]*/;
$VarIdWindmeter = GetValueFloat(37550 /*[KNX\7 Wetter\Dach\Wind\Wert]*/);
$VarValWindknoten = ($VarIdWindmeter * 900 / 463);
$Inbetrieb = 1;
$Var = 21759 /*[Scripte\KNX\Wind auf Bus\Var]*/;
$Anzahl = 0;
$VarSchnittValue = 0;
$Interval = 300; //Zeit über welche Durchschnitt gebildet wird

$VarId = IPS_CreateVariable(2);
IPS_SetParent ($VarId, $Var);
SetValueFloat ($VarId, $VarValWindknoten);

foreach(IPS_GetChildrenIDs($Var) as $item)
{
	$VarInfo = IPS_GetVariable($item);
	$Differenz = $time - $VarInfo['VariableUpdated'];
	if ($Differenz <= $Interval)
	{
		$Anzahl++;
		$VarSchnittValue = $VarSchnittValue + GetValueFloat($item);
	}
	else
	{
		IPS_DeleteVariable ($item);
	}
}

if ($VarSchnittValue)
	$VarSchnittValue = $VarSchnittValue / $Anzahl;

$VarGetInbetrieb = IPS_GetVariable($VarIdInbetrieb);
$Differenz = $time - $VarGetInbetrieb['VariableUpdated'];
if ($Differenz > 720)
	$Inbetrieb = 0;

if($Inbetrieb)
		{
		SetValueFloat (28889 /*[Scripte\KNX\Wind auf Bus\Wind]*/, $VarValWindknoten);
		SetValueFloat (10076 /*[Scripte\KNX\Wind auf Bus\Wind10]*/, $VarSchnittValue);
		EIB_Value(20190 /*[KNX\7 Wetter\IPS\Wind knots]*/, $VarSchnittValue);
		}
else
		{
		SetValueFloat (28889 /*[Scripte\KNX\Wind auf Bus\Wind]*/, -1);
		SetValueFloat (28889 /*[Scripte\KNX\Wind auf Bus\Wind]*/, -1);
		EIB_Value(20190 /*[KNX\7 Wetter\IPS\Wind knots]*/, -1);
		}


?>

Gruß Julian

Ich würde schauen das eher ein rollierendn Mittelwert errechnet …

Gesendet von meinem SM-G930F mit Tapatalk

Um einen Mittelwert zu bilden must Du nicht extra Variablen anlegen und dann wieder löschen. Du must lediglich die Variable, die die Windgeschwindigkeit enthält, aufzeichen.

Dann kannst Du die aufgezeichneten Werte mit AC_GetLoggedValues auslesen und dann aus den Werten den Mittelwert berechnen.

Wenn du das Logging für deine Windgeschwindigkeit aktivierst, dann kannst du dir den Durchschnitt direkt über AC_GetAggregatedValues holen.[emoji1]

Gruß Burkhard

Vielen Dank für eure Antworten !

@mactoolz: Klar, es macht Sinn den gleitenden Mittelwert auszurechnen, aber das mache ich doch sowohl mit meinem alten Script aus #1 als auch mit den jetzt verwendeten Archiv-funktionen, oder ? Ich summiere die werte der letzten 10 Minuten und teile die Summe durch die Anzahl der Werte, sobald der nächste Wert „reinkommt“ wieder das gleiche. Ist inzwischen der letzte Wert der vorherigen Rechnung älter als 10 min ist, fliegt er raus. Das ist doch was du meinst ?!
Ich müsste die Werte aber eigentlich noch gewichten, wenn ich mich nicht täusche, das stimmt.

@ Fonzo und Bumaas: Klar, genau das meinte ich mit „das muss doch eleganter gehen“. Bin nur irgendwie nicht drauf gekommen, danke für den Denkanstoss. Die Ursprungsvariable wird natürlich geloggt.

Hab mein Script umgeschrieben, so dass es nun das Archiv als Datenquelle nutzt und bisschen rumprobiert:

Wenn ich AC_GetAggregatedValues wie Bumaas epfiehlt nutze, kann ich ja nur z.B. 5 oder 1 Minutütige Aggregation wählen. Gut, kann ich ja die letzten 2 x 5 Minuten noch einzeln zusammenrechnen um auf 10 Minuten zu kommen. Aber: Die funktion gibt mir wenn ich sie richtig beobachtet habe immer volle 5 min Rückgabewert. Wenn ich die Funktion beispielsweise um 13:12 aufrufe und ihr als Zeitspanne die letzten 10 min mitgebe, bekomme ich 3 Werte zurück:
13:00-13:05, 13:05-13:10 und 13:10-13:12
Dh. die Zeitspanne über die mein Mittelwert gebildet wird ist um 5 minuten variabel. Das ist ja nicht was ich will, und ich finde es für meine Anwendung auch nicht sinnvoll. Mit der 1-Minütigen Aggregation wird der Fehler natürlich kleiner, aber er ist da, kann man sich natürlich streiten ob er ins gewicht fällt bei einer Datenquelle die nur bei Änderung>10% auf den Bus schreibt.
Aus der Doku geht das so auch nicht klar hervor finde ich: bei Stündlich und längeren Interavallen steht in klammern dabei (00:00 - 59:59). Bei fünf und einer Minute steht das nicht mehr da.

Denkfehler oder soweit richtig ?

Die von Fonzo vorgeschlagene Funktion sollte aber so wie ich sie verstehe funktionieren.

$LogWert = AC_GetLoggedValues ($Archiv, $VarIdWindmeter, $time-$Interval, $time, 0);
$Count = 0;
$VarSchnittValue = 0;
foreach($LogWert as $wert) {
    $Count++;
	$VarSchnittValue = $VarSchnittValue + $wert['Value'];
}
if ($VarSchnittValue)
	$VarSchnittValue = $VarSchnittValue / $Count ;

sollte mir den gleitenden ungewichteten Mittelwert über $Interval (600 sek) liefern, so dass ich zu jeder Sekunde die Werte für die letzten 10 Minuten habe, und nicht nur die zur vollen Minute oder ?

Gruß
Julian

Sehe ich alles genauso.

Gruß Burkhard

ich meine einen rollierenden Mittelwert … durch den rollierenden Mittelwert glättest du deine Meßaufnahme.
Wenn du dir daraus einen neuen Diagrammverlauf erstellen würdest und die Daten übereinander legst wirst
kannst du sehen das der Verlauf glatter verläuft.

Ich versuche das zu verbildlichen. Du arbeitest rein theoretisch das Array ab.
Du fängst mit eine Offset an im Array die Punkte zu berechnen.

Sagen wir mal OffSet von 3, heißt im Array -3, -2 -1 [CNT] +1, +2, +3
ar = array
cnt = counter start bei Offset + 3 bis max -3

Wert[cnt] = (ar[cnt-3] + ar[cnt-2] + ar[cnt -1] + ar[cnt] + ar[cnt +1] + ar[cnt +2] + ar[cnt +3]) / 7

Wert[cnt] = neuer Mittelwert direkt an der counter Stelle neu eintragen, sprich überschreiben.
Man muss nur aufpassen du hast dann vom ganzen Array 6 Werte weniger, weil die ersten 3 fehlen und die letzten Drei.

Ich müsste mal meine Bibliotheken aus meiner anderen Entwicklungsumgebung öffnen und genau reinschauen …

Das ganze dann alle 10 Minuten …

Ich hoffe das blickt jemand …

Gruß
MacToolz

Ok, danke euch erstmal für die Hilfe, läuft so erstmal super, wie erwartet.
Was der rollierende Mittelwert ist hab ich noch nicht ganz begriffen scheinbar, guck ich mir in einer ruigen Minute nochmal an.

Hallo @Inspra,

Deinen Ansatz zum Ermitteln des Mittelwertes der Windgeschwindigkeit finde ich sehr interessant und ich würde dies gerne für meine Markise verproben.

Kannst Du vielleicht das aktuelle Script veröffentlichen?

Vielen Dank und Gruß.

Fussi24