Hi,
hat etwas gedauert. bisschen stressig grad...
Also ich hab mal ein paar (eventuell interessante) Codschnipsel rausgeholt.
Grundsätzlich ist alles in Structured Text programmiert.
Grundsätzlich werden die Messungen der Reedkontakte in eine 1ms Task abgearbeitet um auch hohe Drehzahlen richtig ermitteln zu können.
Alles andere in entsprechend langsameren Tasks....
Rotordrehzahl über einen am Geni angebrachten Reedkontakt:
Code
(* Ermitteln der Zeit zwischen 2 Impulsen des Rotors*)
(* Ermitteln des aktuellen Zeitstempels*)
TmAct := clock_ms();
IF (DI_RotorReed01 = TRUE AND DI_RotorReed01 <> _RotorReed01Old) THEN
TmDiff := TmAct - TmOld;
TmOld := TmAct;
RotorRpmAct := 1000 / TIME_TO_REAL(TmDiff) * 60 ;
ELSIF (TmAct - TmOld) >= T#5s THEN
RotorRpmAct := 0;
END_IF
_RotorReed01Old := DI_RotorReed01;
Berechnung der Windgeschwindigkeit über Reedkontakt des Anemometers:
Code
(* Ermitteln der Zeit zwischen 2 Impulsen des Anemometers*)
TmAct := clock_ms();
IF (DI_AnemoReed01 = TRUE AND DI_AnemoReed01 <> _AnemoReed01Old) THEN
TmDiff := TmAct - TmOld;
TmOld := TmAct;
WindSpdAct := 1000 / TIME_TO_REAL(TmDiff) / 1.5555555555555555555555555555556 ;
ELSIF (TmAct - TmOld) >= T#5s THEN
WindSpdAct := 0;
END_IF
_AnemoReed01Old := DI_AnemoReed01;
Achja: die "1,55555555555" ist ein empirisch ermittelter Korrekturfaktor. Hatte beim damals noch funktionierenden PowerPredictor mit dem Kompressor 30m/s erreicht und dann darauf abgestimmt.
Die Linearität des Anemometers bzw. die damals ermittelten Werte möchte ich nochmal nachmessen. Dazu werd ich die Messeinheit und meine SPS auf unser Quad montieren und über GPS-Daten bzw. Tachometer nochmal nachprüfen.
Für meine ersten Tests und die Logikerstellung reichte mir bisher dieser grobe Parameter (1,5555...)
Berechnung der Windrichtung:
Code
(*Linearisierung der Eingangsspannung auf 0- 360°*)
WindDirRaw := INT_TO_REAL(AI_WindVane01) * 360 / WINDVANCORRFAC;
(*begrenzen wenn Spannung an Windfahne zu hoch*)
IF (WindDirRaw >= 360) THEN
WindDirRaw := 360;
(*begrenzen wenn Spannung an Windfahne zu hoch*)
ELSIF (WindDirRaw <= 0) THEN
WindDirRaw := 0;
END_IF
//Korrigierte Linearisierung des gemessenen Rohwerts über MTLookUp Funktion >> Initialisierung der MTLookUp im INIT!!!!
Table.InX:= WindDirRaw; (* Rohwert *)
Table();
WindDirAct:= REAL_TO_INT(Table.Out); (* Interpolierter Wert *)
//WindDirAct := REAL_TO_INT(WindDirRaw);
"WINDVANCORRFAC" ist ein Umrechnungsfaktor für den Spannungsteiler zwischen dem Fixwiderstand und dem Windrichtungs-Potis.
In der "Table" ist eine linearisierungskennlinie enthalten um die bereits in vorherigen Posts erwähnte nicht-liniarität des Windrichtungs-Potis zu korrigieren.
Mittelung der Windgeschwindigkeit über die Letzte Minute.
(läuft in einer 1000ms-Task)
Kurzgesagt basiert das ganze auf 2 REAL-Arrays[60] in denen die x- und y-Komponente des Einheitskreises sekündlich abgelegt werden.
Aus der Mittelung der Komponenten (x und y EINZELN) wird dann dir resultierende mittlere Windrichtung errechnet.
Code
(*Aktuelle Windrichtungskomponente in Array schreiben*)
_WindDirXYMin[_i01Min, 0] := SIN(WindDirAct * CONST_PI / 180);
_WindDirXYMin[_i01Min, 1] := COS(WindDirAct * CONST_PI / 180);
_WindDirSumXMin := 0;
_WindDirSumYMin := 0;
FOR _i := 0 TO 59 BY 1 DO
_WindDirSumXMin := _WindDirSumXMin + _WindDirXYMin[_i, 0];
_WindDirSumYMin := _WindDirSumYMin + _WindDirXYMin[_i, 1];
END_FOR
_i01Min := _i01Min + 1;
IF (_i01Min >= 60 ) THEN
_i01Min := 0;
END_IF
_WindDirSumXMinInt := REAL_TO_INT((_WindDirSumXMin + 0.00444) * 100 );
_WindDirSumYMinInt := REAL_TO_INT((_WindDirSumYMin + 0.00444) * 100 );
_WindDirSumXMin := INT_TO_REAL(_WindDirSumXMinInt) / 100;
_WindDirSumYMin := INT_TO_REAL(_WindDirSumYMinInt) / 100;
_WindDirAvgXMin := _WindDirSumXMin / 60;
_WindDirAvgYMin := _WindDirSumYMin / 60;
(*In welchem Quadranten befindet sich die gemittelte Windrichtung*)
(* erster Quadrant: 360° bis 90° *)
IF (_WindDirAvgXMin >= 0 AND _WindDirAvgYMin >= 0) THEN
Quad := 1;
WindDirAvg := REAL_TO_INT( ATAN (_WindDirAvgXMin / _WindDirAvgYMin) * 180 / CONST_PI);
(* zweiter Quadrant: 90° bis 180° *)
ELSIF (_WindDirAvgXMin >= 0 AND _WindDirAvgYMin <= 0) THEN
Quad := 2;
WindDirAvg := REAL_TO_INT( 180 + ATAN (_WindDirAvgXMin / _WindDirAvgYMin) * 180 / CONST_PI);
(* dritter Quadrant: 180° bis 270° *)
ELSIF (_WindDirAvgXMin <= 0 AND _WindDirAvgYMin <= 0) THEN
Quad := 3;
WindDirAvg := REAL_TO_INT( 180 + ATAN (_WindDirAvgXMin / _WindDirAvgYMin) * 180 / CONST_PI);
//zum vorbeugen von unklaren Sprüngen auf 90 bei _WindDirAvgXMin = -1 und _WindDirAvgYMin = 0
IF WindDirAvg = 90 THEN
WindDirAvg := 270;
END_IF
(* vierter Quadrant: 270° bis 360° *)
ELSIF (_WindDirAvgXMin <= 0 AND _WindDirAvgYMin >= 0) THEN
Quad := 4;
WindDirAvg := REAL_TO_INT( 360 + ATAN (_WindDirAvgXMin / _WindDirAvgYMin) * 180 / CONST_PI);
ELSE
WindDirAvg := 0;
END_IF
Ich hoffe es ist einigermaßen lesbar. Ich persönlich tu mich meist schwer fremden code zu lesen...
Bin natürlich für jegliches Feedback dankbar!