2903 lines
117 KiB
C++
Executable File
2903 lines
117 KiB
C++
Executable File
/*
|
||
File: Controller.h
|
||
Description: This is a C++ source file containing implementation code for a program or library component.
|
||
Rev: 0.1
|
||
Created: nn.03.2026
|
||
Author: [Your Name]
|
||
Copyright: Binder GmbH TUT 2026
|
||
Purpose: [Briefly describe the file's functionality, e.g., "Implements a class for managing user data."]
|
||
Notes: [Any relevant details, such as dependencies, usage examples, or known issues.]
|
||
*/
|
||
|
||
/*
|
||
* todo - 111 Remove magic numbers ( as far as possible ) or make a comment
|
||
*/
|
||
|
||
|
||
|
||
#pragma once
|
||
|
||
#ifdef BUILD_TARGET_SOM
|
||
|
||
#if defined(_WIN32)
|
||
#define BINDER_SIMULINK_API_EXPORT __declspec(dllexport)
|
||
#else
|
||
#define BINDER_SIMULINK_API_EXPORT __attribute__((visibility("default")))
|
||
#endif
|
||
#include "algorithm/ControllerBase.hpp"
|
||
#include "asio/SignalConnection.hpp"
|
||
|
||
#endif
|
||
|
||
#include <algorithm>
|
||
#include <array>
|
||
#include <cmath>
|
||
#include <cstdint>
|
||
|
||
//UJ: not yet needed, future use
|
||
// #include <limits>
|
||
// #include <memory>
|
||
// #include <vector>
|
||
|
||
#include <QList>
|
||
|
||
#include "datamodel.h"
|
||
#include "util.h"
|
||
|
||
const double PI_CONST = 3.14159265358979323846;
|
||
|
||
|
||
// -------------------------
|
||
// Regelkern (ST -> C++)
|
||
// -------------------------
|
||
|
||
class PWM {
|
||
public:
|
||
PWM(double zyklus_min, double zyklus_max, double initial_zykluszeit = -1.0) {
|
||
Zykluszeit = 0.0;
|
||
Ausgabe = 0.0;
|
||
Zyklus_MAX = zyklus_max;
|
||
Zyklus_MIN = zyklus_min;
|
||
}
|
||
/*(* Puls Pause Generierung Kühlung *)
|
||
Zyklus_Kuehlventil := Zyklus_Kuehlventil + sampling_time;
|
||
|
||
IF Ausgabe_Kuehlventil > 0.0 THEN
|
||
Kuehlventil := NOT Status_Untertemperatur;
|
||
Ausgabe_Kuehlventil := Ausgabe_Kuehlventil - sampling_time;
|
||
IF Ausgabe_Kuehlventil < 0.0 THEN
|
||
Zykluszeit_Kuehlventil := Zykluszeit_Kuehlventil -
|
||
Ausgabe_Kuehlventil * 100.0 / MAX(Stellgrad_Kuehlventil, sampling_time /
|
||
Zykluszeit_Kuehlventil_MAX * 100.0); Ausgabe_Kuehlventil := 0.0; END_IF; ELSE
|
||
Kuehlventil := FALSE;
|
||
END_IF;
|
||
|
||
IF Stellgrad_Kuehlventil > sampling_time / Zykluszeit_Kuehlventil_MAX * 100.0
|
||
THEN IF Zyklus_Kuehlventil >= Zykluszeit_Kuehlventil OR Zyklus_Kuehlventil >=
|
||
MAX(2.0 * Zykluszeit_Kuehlventil_MIN, sampling_time * 100.0 /
|
||
Stellgrad_Kuehlventil) THEN Ausgabe_Kuehlventil := MIN(Ausgabe_Kuehlventil +
|
||
Stellgrad_Kuehlventil / 100.0 * Zykluszeit_Kuehlventil_MIN,
|
||
Zykluszeit_Kuehlventil); Zykluszeit_Kuehlventil := Zykluszeit_Kuehlventil_MIN;
|
||
Zyklus_Kuehlventil := 0.0;
|
||
END_IF;
|
||
END_IF;*/
|
||
|
||
bool step(double Stellgrad, double samplingTime) {
|
||
Zyklus += samplingTime;
|
||
bool output_bool;
|
||
if (Ausgabe > 0.0) {
|
||
output_bool = true;
|
||
Ausgabe -= samplingTime;
|
||
if (Ausgabe < 0.0) {
|
||
Zykluszeit -=
|
||
Ausgabe * 100 / MAX(Stellgrad, samplingTime / Zyklus_MAX * 100.0);
|
||
Ausgabe = 0.0;
|
||
}
|
||
|
||
} else {
|
||
output_bool = false;
|
||
}
|
||
if (Stellgrad > samplingTime / Zyklus_MAX * 100.0) {
|
||
if (Zyklus >= Zykluszeit ||
|
||
Zyklus >= MAX(2.0 * Zyklus_MIN, samplingTime * 100.0 / Stellgrad)) {
|
||
Ausgabe = MIN(Ausgabe + Stellgrad / 100.0 * Zyklus_MIN, Zyklus);
|
||
Zykluszeit = Zyklus_MIN;
|
||
Zyklus = 0.0;
|
||
}
|
||
}
|
||
return output_bool;
|
||
}
|
||
|
||
private:
|
||
double Zyklus = 0.0;
|
||
double Ausgabe = 0.0;
|
||
double Zykluszeit = 0.0;
|
||
double Zyklus_MAX = 0.0;
|
||
double Zyklus_MIN = 0.0;
|
||
};
|
||
|
||
|
||
|
||
class ClimateAlgorithm {
|
||
public:
|
||
struct BinInputs {
|
||
// Eingangswerte aus bool_inXX / real_inXX / reset_flag
|
||
bool reset_flag{};
|
||
bool Sammelalarm_quittiert{};
|
||
bool Tuer_offen{};
|
||
bool Sollwert_Feuchte_aktiv{};
|
||
bool Steuerkontakt_Standby{};
|
||
bool Steuerkontakt_Befeuchtung_aus{};
|
||
bool Steuerkontakt_Entfeuchtung_aus{};
|
||
bool Entleerbehaelter_Oben{};
|
||
bool Wasserkanister_leer{};
|
||
bool Entleerbehaelter_Unten{};
|
||
bool Sammelalarm{};
|
||
} binInput;
|
||
|
||
struct AnalogInputs {
|
||
double Istwert_Temperatur{};
|
||
double Sollwert_Temperatur{};
|
||
double Temperaturband{};
|
||
double Istwert_Ueberwachungsregler{};
|
||
double Klasse_Ueberwachungsregler{};
|
||
double Grenzwert_Untertemperatur{};
|
||
double Istwert_Feuchte{};
|
||
double Sollwert_Feuchte{};
|
||
double Feuchteband{};
|
||
double Sollwert_Luefter{};
|
||
double Istwert_Temperatur_Tuer{};
|
||
double Istwert_Temperatur_Verdampferausgang{};
|
||
double Temperatur_Feuchtemodul{};
|
||
double Bandalarm_nach{};
|
||
double Betauungsschutz{};
|
||
double real_in11{}; // du nutzt real_in11 später direkt in alarm_15
|
||
} analogInput;
|
||
|
||
struct BinOutputs {
|
||
// bool_outXX
|
||
bool bool_out01{};
|
||
bool bool_out02{};
|
||
bool bool_out03{};
|
||
bool bool_out07{};
|
||
bool bool_out09{};
|
||
bool bool_out11{};
|
||
bool bool_out12{};
|
||
bool bool_out13{};
|
||
bool bool_out14{};
|
||
bool bool_out16{};
|
||
bool bool_out17{};
|
||
bool bool_out18{};
|
||
bool bool_out19{};
|
||
bool bool_out20{};
|
||
bool bool_out21{};
|
||
bool bool_out23{};
|
||
} binOut;
|
||
|
||
struct AnalogOutputs {
|
||
// real_outXX (nur die, die du im ST setzt)
|
||
double real_out01{};
|
||
double real_out02{};
|
||
double real_out04{};
|
||
double real_out05{};
|
||
double real_out06{};
|
||
double real_out07{};
|
||
double real_out08{};
|
||
double real_out09{};
|
||
double real_out10{};
|
||
double real_out11{};
|
||
double real_out12{};
|
||
double real_out13{};
|
||
double real_out14{};
|
||
double real_out16{};
|
||
double Stellgrad_Feuchtemodul{}; // ...out17
|
||
double real_out18{};
|
||
double real_out19{};
|
||
double real_out20{};
|
||
double real_out21{};
|
||
double real_out25{};
|
||
double real_out26{};
|
||
double Stellgrad_Heizung{};
|
||
double Stellgrad_Kuehlung{};
|
||
double Stellgrad_Befeuchtung{};
|
||
double Stellgrad_Entfeuchtung{};
|
||
double Counter_Tuer{};
|
||
} analogOut;
|
||
|
||
struct Alarm {
|
||
// alarm_01..alarm_15
|
||
bool Startup{};
|
||
bool alarm_01{};
|
||
bool alarm_02{};
|
||
bool alarm_03{};
|
||
bool alarm_04{};
|
||
bool alarm_05{};
|
||
bool alarm_06{};
|
||
bool alarm_07{};
|
||
bool alarm_08{};
|
||
bool alarm_09{};
|
||
bool alarm_10{};
|
||
bool alarm_11{};
|
||
bool alarm_12{};
|
||
bool alarm_13{};
|
||
bool alarm_14{};
|
||
bool alarm_15{};
|
||
} alarmOut;
|
||
|
||
ClimateAlgorithm() = default;
|
||
|
||
|
||
void Step(void)
|
||
{
|
||
using UTILITY_FUNCTIONS::is_valid;
|
||
using UTILITY_FUNCTIONS::limit;
|
||
|
||
bool Wasserkanister_leer = false;
|
||
double Istwert_Temperatur_Verdampferausgang = analogInput.Istwert_Temperatur_Verdampferausgang;
|
||
double Betauungsschutz = 50.0; // 111
|
||
double Feuchteband = 10; // 111
|
||
double Temperaturband = 5; // 111
|
||
bool reset_flag = binInput.reset_flag;
|
||
|
||
// ---------------------------
|
||
// Eingangswerte (ST Zuweisungen)
|
||
// ---------------------------
|
||
Sammelalarm_quittiert = binInput.Sammelalarm_quittiert;
|
||
Tuer_offen = binInput.Tuer_offen;
|
||
Sollwert_Feuchte_aktiv = true;
|
||
Steuerkontakt_Standby = false;
|
||
Steuerkontakt_Befeuchtung_aus = false;
|
||
Steuerkontakt_Entfeuchtung_aus = false;
|
||
Entleerbehaelter_Oben = binInput.Entleerbehaelter_Oben;
|
||
Entleerbehaelter_Unten = binInput.Entleerbehaelter_Unten;
|
||
Sammelalarm = false;
|
||
Istwert_Temperatur = analogInput.Istwert_Temperatur;
|
||
Istwert_Ueberwachungsregler = Istwert_Temperatur;
|
||
Sollwert_Temperatur = analogInput.Sollwert_Temperatur;
|
||
Istwert_Feuchte = analogInput.Istwert_Feuchte;
|
||
Sollwert_Feuchte = analogInput.Sollwert_Feuchte;
|
||
// uj - not yet needed - silence compiler
|
||
// double Sollwert_Luefter = analogInput.Sollwert_Luefter;
|
||
Temperatur_Feuchtemodul = analogInput.Temperatur_Feuchtemodul;
|
||
Istwert_Temperatur_Tuer = analogInput.Istwert_Temperatur_Tuer;
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Ende Zuweisungen aus ST-Code Zeilen 1 ... 355
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
// Zähler reset_flag
|
||
// -----------------
|
||
if (reset_flag) {
|
||
Counter_reset_flag = 0;
|
||
}
|
||
else {
|
||
Counter_reset_flag += 1;
|
||
}
|
||
Startup_finished = (Counter_reset_flag > static_cast<std::uint32_t>(10 * 4));
|
||
|
||
/* -------------------------------------------------------------------------------
|
||
* Selbsttest
|
||
* Entfällt hier, da anderer Kontext und Maschine: Findet an anderer Stelle statt!
|
||
* Gilt evtl. auch für die Zeilen oben : 'Zähler reset_flag'
|
||
*/
|
||
|
||
/* Quittierung Sammelalarm */
|
||
// F_TRIG01(Sammelalarm_quittiert); UJ: todo - kären !
|
||
|
||
// ------------------------------------------
|
||
// Verzögerte Abschaltung Regelung bei Türöffnung
|
||
// ------------------------------------------
|
||
#if 1
|
||
// f_PostDoorOpeningCutOffDelaed(...)
|
||
if (Tuer_offen || Steuerkontakt_Standby)
|
||
{
|
||
Counter_Regelung_AUS += sampling_time;
|
||
}
|
||
else
|
||
{
|
||
Counter_Regelung_AUS = 0.0;
|
||
}
|
||
Regelung_AUS = (Counter_Regelung_AUS > 60.0);
|
||
#else
|
||
// Original ST Code
|
||
// UJ: todo Ist das wirklich äquivalent ?
|
||
(* Verzögerte Abschaltung Regelung bei Türöffnung *)
|
||
TON01(Tuer_offen OR Steuerkontakt_Standby, 60, 2);
|
||
Regelung_AUS := TON01.Q;
|
||
#endif
|
||
|
||
#if 1
|
||
// todo: insert C++ code here
|
||
#else
|
||
// UJ: Enfällt dieser ST Code ?
|
||
(* ------------------------------- *)
|
||
(* Erkennung Typ Befeuchtungsmodul *)
|
||
(* ------------------------------- *)
|
||
|
||
IF NOT is_valid(Counter_Typ_Feuchtemodul) THEN
|
||
Counter_Typ_Feuchtemodul := 0.0;
|
||
ELSIF Entleerbehaelter_Unten OR Entleerbehaelter_Oben THEN
|
||
Counter_Typ_Feuchtemodul := MIN(Counter_Typ_Feuchtemodul + sampling_time, 10.0);
|
||
ELSE
|
||
Counter_Typ_Feuchtemodul := MAX(Counter_Typ_Feuchtemodul - sampling_time, -10.0);
|
||
END_IF;
|
||
BDR_Feuchtemodul := Counter_Typ_Feuchtemodul > 5.0;
|
||
BDR_300W_Feuchtemodul := Counter_Typ_Feuchtemodul < -5.0;
|
||
#endif
|
||
|
||
|
||
// -------------------
|
||
// Nachlauf Türöffnung
|
||
// -------------------
|
||
// f_PostDoorOpening(..)
|
||
if (!Startup_finished)
|
||
{
|
||
Counter_Tuer_offen = 0.0;
|
||
Counter_Tuer_geschlossen = 600.0;
|
||
}
|
||
else if (Tuer_offen)
|
||
{
|
||
Counter_Tuer_offen += sampling_time;
|
||
Counter_Tuer_geschlossen = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Counter_Tuer_offen = 0.0;
|
||
Counter_Tuer_geschlossen += sampling_time;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/// UJ: Warum fehlt folgender ST-Code ?
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
|
||
(* -------------------- *)
|
||
(* LQC Lichtintegration *)
|
||
(* -------------------- *)
|
||
|
||
R_TRIG08(get_second(rtc.cdt) > 0);
|
||
IF (R_TRIG08.Q AND Lichtintegral_AN) THEN
|
||
IF (Istwert_UVA > 0.0 AND Istwert_UVA < 100.0) THEN
|
||
Integral_UVA := LIMIT(Integral_UVA + Istwert_UVA / 60.0, 0.0, 99999.0) ;
|
||
END_IF;
|
||
IF (Istwert_VIS > 0.0 AND Istwert_VIS < 100.0) THEN
|
||
Integral_VIS := LIMIT(Integral_VIS + Istwert_VIS / (1000.0 * 60.0), 0.0, 99999.0);
|
||
END_IF;
|
||
END_IF;
|
||
|
||
TON07(Lichtintegral_RESET_UVA, 5, 2);
|
||
TOF06(NOT Lichtintegral_RESET_UVA, 6, 2);
|
||
TOF05(reset_flag, 8, 2);
|
||
IF TON07.Q AND TOF06.Q AND NOT TOF05.Q THEN
|
||
Integral_UVA := 0.0;
|
||
END_IF;
|
||
|
||
TON08(Lichtintegral_RESET_VIS, 5, 2);
|
||
TOF08(NOT Lichtintegral_RESET_VIS, 6, 2);
|
||
TOF07(reset_flag, 8, 2);
|
||
IF TON08.Q AND TOF08.Q AND NOT TOF07.Q THEN
|
||
Integral_VIS := 0.0;
|
||
END_IF;
|
||
|
||
UVA_Dosis_erreicht := Integral_UVA >= Grenzwert_UVA AND Lichtintegral_AN;
|
||
VIS_Dosis_erreicht := Integral_VIS >= Grenzwert_VIS AND Lichtintegral_AN;
|
||
|
||
(* Steuerung Lichtkassetten *)
|
||
IF (Steuerkontakt_Standby) THEN
|
||
Beleuchtung_UVA := FALSE;
|
||
Beleuchtung_VIS := FALSE;
|
||
ELSE
|
||
Beleuchtung_UVA := (Integral_UVA < Grenzwert_UVA AND Lichtintegral_AN) OR Steuerkontakt_Beleuchtung_UVA;
|
||
Beleuchtung_VIS := (Integral_VIS < Grenzwert_VIS AND Lichtintegral_AN) OR Steuerkontakt_Beleuchtung_VIS;
|
||
END_IF;
|
||
|
||
(* Fehler UVA-Sensor *)
|
||
IF NOT Startup_finished OR NOT is_valid (Counter_Alarm_Lichtsensor_UVA) OR (is_valid(Istwert_UVA) AND Lichtsensor_UVA) OR NOT Lichtintegral_AN THEN
|
||
Counter_Alarm_Lichtsensor_UVA := 0.0;
|
||
ELSE
|
||
Counter_Alarm_Lichtsensor_UVA := Counter_Alarm_Lichtsensor_UVA + sampling_time;
|
||
END_IF;
|
||
|
||
(* Fehler VIS-Sensor *)
|
||
IF NOT Startup_finished OR NOT is_valid (Counter_Alarm_Lichtsensor_VIS) OR (is_valid(Istwert_VIS) AND Lichtsensor_VIS) OR NOT Lichtintegral_AN THEN
|
||
Counter_Alarm_Lichtsensor_VIS := 0.0;
|
||
ELSE
|
||
Counter_Alarm_Lichtsensor_VIS := Counter_Alarm_Lichtsensor_VIS + sampling_time;
|
||
END_IF;
|
||
|
||
(* Sollwertbegrenzung Temperatur *)
|
||
IF Lichtbox OR Lichtsensor_UVA OR is_valid(Istwert_UVA) OR Lichtsensor_VIS OR is_valid(Istwert_VIS) OR Steuerkontakt_Beleuchtung_UVA OR Steuerkontakt_Beleuchtung_VIS THEN
|
||
Sollwert_Temperatur_MIN := 5.0;
|
||
Sollwert_Temperatur_MAX := 60.0;
|
||
ELSE
|
||
|
||
*/
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
/*
|
||
(* Sollwertbegrenzung Temperatur *)
|
||
*/
|
||
Sollwert_Temperatur_MIN = -5.0;
|
||
Sollwert_Temperatur_MAX = 100.0;
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/// UJ: Warum fehlt folgender ST-Code ?
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
|
||
(* ---------- *)
|
||
(* CO2-Regler *)
|
||
(* ---------- *)
|
||
|
||
(* Überprüfung ob Sensor gesteckt oder defekt *)
|
||
IF Istwert_CO2 < -3.75 OR NOT is_valid(Istwert_CO2) THEN (* < 1mA *)
|
||
CO2_Sensor_gesteckt := FALSE;
|
||
CO2_Sensor_defekt := FALSE;
|
||
Istwert_CO2 := 3.0e37;
|
||
ELSIF Istwert_CO2 >= -3.75 AND Istwert_CO2 < -1.25 THEN (* >=1mA && < 3mA *)
|
||
CO2_Sensor_gesteckt := TRUE;
|
||
CO2_Sensor_defekt := TRUE;
|
||
Istwert_CO2 := 3.0e37;
|
||
ELSE
|
||
CO2_Sensor_gesteckt := TRUE;
|
||
CO2_Sensor_defekt := FALSE;
|
||
END_IF;
|
||
|
||
(* Korrektur CO2-Istwert *)
|
||
(* Als quadratische Funktion gefittete Internationale Höhenformel
|
||
p = 1013.25*(1-(0.0065*h)/288.15).^5.255;
|
||
maximaler Fehler: +/- 0.053 im Bereich von 0..2000m*)
|
||
Luftdruck_NHN := LIMIT(5.3532e-06 * Hoehe_NHN * Hoehe_NHN - 0.11979 * Hoehe_NHN + 1013.2, 702.0088, 1013.2); (* mbar *)
|
||
|
||
(* Korrekturformel *)
|
||
(* Korrektur auf Referenzwert bei 0m (1013.25mbar) und 37°C *)
|
||
(* Formel laut Vaisala PDF: W:\FuE_Projekte\2016\16-031_PDP_Entwicklung C170-E7\A12 Elektrokonstruktion, MSR\Wie misst man CO2.pdf *)
|
||
IF is_valid(Istwert_CO2) THEN
|
||
Istwert_CO2 := LIMIT(Istwert_CO2 * 1013.25 / Luftdruck_NHN * (273.15 + Istwert_Temperatur) / (273.15 + 37.0), 0.0, 20.0); (* Vol.% *)
|
||
END_IF;
|
||
|
||
Regler_CO2_Xp := F_Xp_CO2;
|
||
|
||
IF Steuerkontakt_Messbereich_0bis1 THEN
|
||
Istwert_CO2 := Istwert_CO2 * 1.0 / 20.0;
|
||
Sollwert_CO2 := MIN(Sollwert_CO2, 1.0);
|
||
Regler_CO2_Xp := F_Xp_CO2 * 1.0 / 20.0;
|
||
END_IF;
|
||
|
||
(*Regelabweichung*)
|
||
IF NOT Tuer_offen OR ABS(Regelabweichung_CO2) > ABS(Sollwert_CO2 - Istwert_CO2) OR NOT is_valid(Regelabweichung_CO2) THEN
|
||
Regelabweichung_CO2 := Sollwert_CO2 - Istwert_CO2;
|
||
END_IF;
|
||
(* P-Anteil *)
|
||
IF NOT is_valid(Regelabweichung_CO2) THEN
|
||
P_Anteil_CO2 := 0.0;
|
||
ELSE
|
||
P_Anteil_CO2 := 100.0 / Regler_CO2_Xp * Regelabweichung_CO2;
|
||
END_IF;
|
||
(* I-Anteil *)
|
||
(* Anti-wind-up über dynamisches Integrator Clamping *)
|
||
IF NOT Startup_finished OR NOT is_valid(I_Anteil_CO2) THEN
|
||
I_Anteil_CO2 := 0.0;
|
||
ELSIF is_valid(Regelabweichung_CO2) THEN
|
||
I_Anteil_CO2 := LIMIT(I_Anteil_CO2 + 100.0 / Regler_CO2_Xp / Regler_CO2_Tn * sampling_time * Regelabweichung_CO2, Regler_CO2_I_Anteil_MIN, MAX(Regler_CO2_I_Anteil_MAX - P_Anteil_CO2, Regler_CO2_I_Anteil_MIN));
|
||
END_IF;
|
||
(* D-Anteil *)
|
||
IF NOT Startup_finished OR NOT is_valid(D_Anteil_CO2) THEN
|
||
D_Anteil_CO2 := 0.0;
|
||
ELSIF is_valid(Regelabweichung_CO2) AND is_valid(Regelabweichung_CO2_alt) THEN
|
||
D_Anteil_CO2 := D_Anteil_CO2 + (100.0 / Regler_CO2_Xp * Regler_CO2_Tv * (Regelabweichung_CO2 - Regelabweichung_CO2_alt) / sampling_time - D_Anteil_CO2) / (Tau_CO2_Tv / sampling_time);
|
||
END_IF;
|
||
(* Berechnung Stellgrad *)
|
||
IF Tuer_offen OR Regelung_AUS OR NOT Startup_finished OR NOT Sollwert_CO2_aktiv OR NOT is_valid(Regelabweichung_CO2) THEN
|
||
Stellgrad_CO2 := 0.0;
|
||
ELSE
|
||
Stellgrad_CO2 := LIMIT(P_Anteil_CO2 + I_Anteil_CO2 + D_Anteil_CO2, Regler_CO2_MIN, Regler_CO2_MAX);
|
||
END_IF;
|
||
|
||
IF Steuerkontakt_Messbereich_0bis1 THEN
|
||
Stellgrad_CO2 := Stellgrad_CO2 / 20.0;
|
||
END_IF;
|
||
|
||
(* Fehler CO2-Sensor *)
|
||
IF NOT Startup_finished OR NOT is_valid (Counter_Fehler_Sensor_CO2) OR NOT Sollwert_CO2_aktiv OR NOT CO2_Sensor_defekt THEN
|
||
Counter_Fehler_Sensor_CO2 := 0.0;
|
||
ELSE
|
||
Counter_Fehler_Sensor_CO2 := Counter_Fehler_Sensor_CO2 + sampling_time;
|
||
END_IF;
|
||
|
||
|
||
(* -------------------- *)
|
||
(* Heißluftdesinfektion *)
|
||
(* -------------------- *)
|
||
|
||
IF Automatikbetrieb AND Programmnummer < 1.5 AND Programmabschnitt < 1.5 THEN
|
||
Desinfektion_aktiv := TRUE;
|
||
Sollwert_Temperatur_Offset := Sollwert_Temperatur_MAX;
|
||
Signal_Programm_Stopp := Istwert_Temperatur < Sollwert_Temperatur_Geber - 1.0;
|
||
ELSIF Automatikbetrieb AND Programmnummer < 1.5 AND Programmabschnitt > 1.5 THEN
|
||
Desinfektion_aktiv := TRUE;
|
||
Sollwert_Temperatur_Offset := GET_VALUE_REAL(82,0,0,0);
|
||
Signal_Programm_Stopp := Istwert_Temperatur > Sollwert_Temperatur_Offset + 1.0;;
|
||
ELSIF Programmendesignal AND Programmnummer < 1.5 THEN
|
||
Desinfektion_aktiv := FALSE;
|
||
Sollwert_Temperatur_Offset := GET_VALUE_REAL(82,0,0,0);
|
||
Signal_Programm_Stopp := FALSE;
|
||
ELSE
|
||
Desinfektion_aktiv := FALSE;
|
||
Sollwert_Temperatur_Offset := 0.0;
|
||
Signal_Programm_Stopp := FALSE;
|
||
END_IF;
|
||
|
||
|
||
(* -------------- *)
|
||
(* Kaskadenregler *)
|
||
(* -------------- *)
|
||
|
||
(* Begrenzung der Sensitivität *)
|
||
Sensitivitaet_Kaskade := MAX(Sensitivitaet_Kaskade, 1.0);
|
||
|
||
(* Regelabweichung *)
|
||
Regelabweichung_Kaskade := Sollwert_Temperatur_Geber - Istwert_Objekttemperatur;
|
||
|
||
(* Gradient Regelabweichung Temperatur *)
|
||
IF NOT Startup_finished OR NOT IS_VALID(Regelabweichung_Kaskade_Gradient) THEN
|
||
Regelabweichung_Kaskade_Gradient := 0.0;
|
||
ELSIF IS_VALID(Regelabweichung_Kaskade) AND IS_VALID(Regelabweichung_Kaskade_alt) THEN
|
||
Regelabweichung_Kaskade_Gradient := LIMIT(Regelabweichung_Kaskade_Gradient + ((Regelabweichung_Kaskade - Regelabweichung_Kaskade_alt) * 60.0 / sampling_time - Regelabweichung_Kaskade_Gradient) / (60.0 * 100.0 / Sensitivitaet_Kaskade) * sampling_time, -1.0 * Sensitivitaet_Kaskade / 100.0, 1.0 * Sensitivitaet_Kaskade / 100.0);
|
||
END_IF;
|
||
|
||
(* Xp, Tn und Tv Berechnung *)
|
||
Regler_Kaskade_Xp := F_Xp_Kaskade;
|
||
IF Regelabweichung_Kaskade > 0.0 THEN
|
||
Regler_Kaskade_Tn := 300.0 * 100.0 / Sensitivitaet_Kaskade * LIMIT(Regelabweichung_Kaskade_Gradient / (-0.05 * Sensitivitaet_Kaskade / 100.0), 1.0, 100.0);
|
||
ELSE
|
||
Regler_Kaskade_Tn := 300.0 * 100.0 / Sensitivitaet_Kaskade * LIMIT(Regelabweichung_Kaskade_Gradient / (0.05 * Sensitivitaet_Kaskade / 100.0), 1.0, 100.0);
|
||
END_IF;
|
||
Regler_Kaskade_Tv := 60.0 * 100.0 / Sensitivitaet_Kaskade;
|
||
|
||
(* Anti-wind-up über dynamisches Clamping *)
|
||
Regler_Kaskade_MIN := -Korrektur_Temperatur_MAX;
|
||
Regler_Kaskade_MAX := Korrektur_Temperatur_MAX;
|
||
Regler_Kaskade_I_Anteil_MIN := LIMIT(Regler_Kaskade_MIN - Regler_Kaskade_MIN * Regelabweichung_Kaskade_Gradient / (1.0 * Sensitivitaet_Kaskade / 100.0) - P_Anteil_Kaskade, Regler_Kaskade_MIN, 0.0);
|
||
Regler_Kaskade_I_Anteil_MAX := LIMIT(Regler_Kaskade_MAX - Regler_Kaskade_MAX * Regelabweichung_Kaskade_Gradient / (-1.0 * Sensitivitaet_Kaskade / 100.0) - P_Anteil_Kaskade, 0.0, Regler_Kaskade_MAX);
|
||
|
||
(* P-Anteil *)
|
||
IF NOT is_valid(Regelabweichung_Kaskade) THEN
|
||
P_Anteil_Kaskade := 0.0;
|
||
ELSE
|
||
P_Anteil_Kaskade := LIMIT(Korrektur_Temperatur_MAX / Regler_Kaskade_Xp * Regelabweichung_Kaskade, -100.0, 100.0);
|
||
END_IF;
|
||
(* I-Anteil *)
|
||
IF NOT Startup_finished OR NOT is_valid(I_Anteil_Kaskade) THEN
|
||
I_Anteil_Kaskade := 0.0;
|
||
ELSIF is_valid(Regelabweichung_Kaskade) AND Counter_Tuer_geschlossen > 300.0 AND NOT Temperatursprung THEN
|
||
I_Anteil_Kaskade := LIMIT(I_Anteil_Kaskade + (D_Anteil_Kaskade + Korrektur_Temperatur_MAX / Regler_Kaskade_Xp * Regelabweichung_Kaskade) / Regler_Kaskade_Tn * sampling_time, Regler_Kaskade_I_Anteil_MIN, Regler_Kaskade_I_Anteil_MAX);
|
||
END_IF;
|
||
(* D-Anteil *)
|
||
IF NOT Startup_finished OR NOT is_valid(D_Anteil_Kaskade) THEN
|
||
D_Anteil_Kaskade := 0.0;
|
||
ELSIF is_valid(Regelabweichung_Kaskade) AND is_valid(Regelabweichung_Kaskade_alt) AND Counter_Tuer_geschlossen > 60.0 THEN
|
||
D_Anteil_Kaskade := D_Anteil_Kaskade + (Korrektur_Temperatur_MAX / Regler_Kaskade_Xp * Regler_Kaskade_Tv * (Regelabweichung_Kaskade - Regelabweichung_Kaskade_alt) / sampling_time - D_Anteil_Kaskade) / (Tau_Kaskade_Tv / sampling_time);
|
||
END_IF;
|
||
(* Berechnung Stellgrad *)
|
||
IF Regelung_AUS OR NOT Startup_finished OR NOT Steuerkontakt_Kaskade OR NOT is_valid(Regelabweichung_Kaskade) THEN
|
||
Stellgrad_Kaskade := 0.0;
|
||
ELSE
|
||
Stellgrad_Kaskade := LIMIT(P_Anteil_Kaskade + I_Anteil_Kaskade + D_Anteil_Kaskade, Regler_Kaskade_MIN, Regler_Kaskade_MAX);
|
||
END_IF;
|
||
|
||
(* Objektfeuchte *)
|
||
p_H2O_MAX_Objekttemperatur := 6.112 * EXP(17.62 * Istwert_Objekttemperatur / (243.12 + Istwert_Objekttemperatur));
|
||
p_H2O_MAX_Temperatur := 6.112 * EXP(17.62 * Istwert_Temperatur / (243.12 + Istwert_Temperatur));
|
||
|
||
IF NOT Startup_finished OR NOT is_valid(Stellgrad_Kaskade_Feuchte) OR NOT Steuerkontakt_Kaskade THEN
|
||
Istwert_Objektfeuchte := Istwert_Feuchte;
|
||
Stellgrad_Kaskade_Feuchte := 0.0;
|
||
ELSIF IS_VALID(p_H2O_MAX_Objekttemperatur) AND IS_VALID(p_H2O_MAX_Temperatur) THEN
|
||
Istwert_Objektfeuchte := Istwert_Feuchte * p_H2O_MAX_Temperatur / p_H2O_MAX_Objekttemperatur;
|
||
Stellgrad_Kaskade_Feuchte := LIMIT(Stellgrad_Kaskade_Feuchte + ((Istwert_Feuchte - Istwert_Objektfeuchte) - Stellgrad_Kaskade_Feuchte) / (600.0 / sampling_time), -Korrektur_Feuchte_MAX, Korrektur_Feuchte_MAX);
|
||
END_IF;
|
||
|
||
(* Sollwerte für Temperatur und Feuchteregelung im Seitenteil *)
|
||
Sollwert_Temperatur := LIMIT(Sollwert_Temperatur_Geber + Stellgrad_Kaskade, Sollwert_Temperatur_MIN, Sollwert_Temperatur_MAX);
|
||
Sollwert_Feuchte := Sollwert_Feuchte_Geber + Stellgrad_Kaskade_Feuchte ;
|
||
|
||
|
||
*/
|
||
|
||
// ------------------------------------------
|
||
// (* Sollwert Feuchteregelung (absolut/relativ) *)
|
||
// Sollwert Feuchte (Limit-Kennfeld)
|
||
// ------------------------------------------
|
||
// (* Begrenzung Feuchtesollwert*)
|
||
Index_Sollwert_Feuchte_Limit = 1;
|
||
while ((Kennfeld_Sollwert_Feuchte_Limit[0][Index_Sollwert_Feuchte_Limit] < Sollwert_Temperatur) &&
|
||
(Index_Sollwert_Feuchte_Limit < 10))
|
||
{
|
||
Index_Sollwert_Feuchte_Limit++;
|
||
}
|
||
|
||
Interpolation_Sollwert_Feuchte_Limit =
|
||
limit((Kennfeld_Sollwert_Feuchte_Limit[0][Index_Sollwert_Feuchte_Limit - 1] - Sollwert_Temperatur) /
|
||
(Kennfeld_Sollwert_Feuchte_Limit[0][Index_Sollwert_Feuchte_Limit - 1] - Kennfeld_Sollwert_Feuchte_Limit[0][Index_Sollwert_Feuchte_Limit]),
|
||
0.0,
|
||
1.0);
|
||
|
||
Sollwert_Feuchte_Max =
|
||
Kennfeld_Sollwert_Feuchte_Limit[1][Index_Sollwert_Feuchte_Limit] * Interpolation_Sollwert_Feuchte_Limit +
|
||
Kennfeld_Sollwert_Feuchte_Limit[1][Index_Sollwert_Feuchte_Limit - 1] * (1.0 - Interpolation_Sollwert_Feuchte_Limit);
|
||
|
||
Sollwert_Feuchte_Min =
|
||
Kennfeld_Sollwert_Feuchte_Limit[2][Index_Sollwert_Feuchte_Limit] * Interpolation_Sollwert_Feuchte_Limit +
|
||
Kennfeld_Sollwert_Feuchte_Limit[2][Index_Sollwert_Feuchte_Limit - 1] * (1.0 - Interpolation_Sollwert_Feuchte_Limit);
|
||
|
||
Sollwert_Feuchte = limit(Sollwert_Feuchte, Sollwert_Feuchte_Min, Sollwert_Feuchte_Max);
|
||
|
||
|
||
|
||
// Abschaltung Feuchteregelung
|
||
// f_CutOffHumidityControl(...)
|
||
Befeuchtung_aus = !Sollwert_Feuchte_aktiv || Steuerkontakt_Befeuchtung_aus ||
|
||
(Sollwert_Temperatur > 95.0) || (Sollwert_Temperatur < 5.0);
|
||
Entfeuchtung_aus = !Sollwert_Feuchte_aktiv || Steuerkontakt_Entfeuchtung_aus ||
|
||
(Sollwert_Temperatur > 95.0) || (Sollwert_Temperatur < 5.0);
|
||
|
||
// (p_H2Omax, Taupunkt etc.)
|
||
p_H2Omax_Sollwert = 6.112 * std::exp(17.62 * Sollwert_Temperatur / (243.12 + Sollwert_Temperatur));
|
||
p_H2Omax_Istwert = 6.112 * std::exp(17.62 * Istwert_Temperatur / (243.12 + Istwert_Temperatur));
|
||
|
||
Taupunkt_Istwert = (241.2 * std::log(std::max(Istwert_Feuchte, 0.001) / 100.0) +
|
||
(4222.03716 * Istwert_Temperatur) / (241.2 + Istwert_Temperatur)) / (17.5043 - std::log(std::max(Istwert_Feuchte, 0.001) / 100.0) -
|
||
(17.5043 * Istwert_Temperatur) / (241.2 + Istwert_Temperatur));
|
||
|
||
if (Temperatursprung)
|
||
{
|
||
Sollwert_Feuchte_Absolut = limit(Sollwert_Feuchte * p_H2Omax_Sollwert / p_H2Omax_Istwert,
|
||
0.0,
|
||
Sollwert_Feuchte);
|
||
}
|
||
else
|
||
{
|
||
Sollwert_Feuchte_Absolut = Sollwert_Feuchte;
|
||
}
|
||
|
||
if (!is_valid(Sollwert_Feuchte_Absolut))
|
||
{
|
||
Sollwert_Feuchte_Absolut = Sollwert_Feuchte;
|
||
}
|
||
|
||
// ------------------
|
||
// Überwachungsregler
|
||
// ------------------
|
||
Modus_Ueberwachungsregler = UTILITY_FUNCTIONS::GET_VALUE_DINT(71,0,3,0);
|
||
Grenzwert_Uebertemperatur = UTILITY_FUNCTIONS::GET_VALUE_REAL(71,0,4,0);
|
||
Offset_Ueberwachungsregler = UTILITY_FUNCTIONS::GET_VALUE_REAL(71,0,5,0);
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/// UJ: Warum fehlt folgender ST-Code ?
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/*
|
||
IF Desinfektion_aktiv THEN
|
||
Schaltwert_Uebertemperatur := 110.0;
|
||
Schaltwert_Untertemperatur := -30.0;
|
||
~~ ELSIF Modus_Ueberwachungsregler > 0 THEN
|
||
*/
|
||
|
||
if (Modus_Ueberwachungsregler > 0)
|
||
{
|
||
Schaltwert_Uebertemperatur = limit(Sollwert_Temperatur + Offset_Ueberwachungsregler, -30.0, 110.0);
|
||
Schaltwert_Untertemperatur = limit(Sollwert_Temperatur - Offset_Ueberwachungsregler, -30.0, 110.0);
|
||
}
|
||
else
|
||
{
|
||
Schaltwert_Uebertemperatur = Grenzwert_Uebertemperatur;
|
||
Schaltwert_Untertemperatur = Grenzwert_Untertemperatur;
|
||
}
|
||
|
||
const double maxUeberw = std::max(Istwert_Ueberwachungsregler, Istwert_Temperatur);
|
||
const double minUeberw = std::min(Istwert_Ueberwachungsregler, Istwert_Temperatur);
|
||
|
||
if ( (maxUeberw > Schaltwert_Uebertemperatur) || (Status_Uebertemperatur && (maxUeberw > Schaltwert_Uebertemperatur - 1.0)) ||
|
||
(StatusQuittierung_Uebertemperatur && (Klasse_Ueberwachungsregler < 3.0)) )
|
||
{
|
||
Counter_Status_Uebertemperatur += 1;
|
||
}
|
||
else
|
||
{
|
||
Counter_Status_Uebertemperatur = 0;
|
||
}
|
||
|
||
Status_Uebertemperatur = (Counter_Status_Uebertemperatur >= static_cast<std::uint32_t>(10 * 4));
|
||
StatusQuittierung_Uebertemperatur = (Status_Uebertemperatur && Counter_Status_Uebertemperatur < static_cast<std::uint32_t>(11 * 4)) ||
|
||
(StatusQuittierung_Uebertemperatur && Sammelalarm_quittiert);
|
||
|
||
if ( ((minUeberw < Schaltwert_Untertemperatur) || (Status_Untertemperatur && (minUeberw < Schaltwert_Untertemperatur + 1.0))) &&
|
||
(Klasse_Ueberwachungsregler >= 3.0) )
|
||
{
|
||
Counter_Status_Untertemperatur += 1;
|
||
}
|
||
else
|
||
{
|
||
Counter_Status_Untertemperatur = 0;
|
||
}
|
||
|
||
Status_Untertemperatur = (Counter_Status_Untertemperatur >= static_cast<std::uint32_t>(10 * 4));
|
||
StatusQuittierung_Untertemperatur = Status_Untertemperatur && ( Counter_Status_Untertemperatur < static_cast<std::uint32_t>(11 * 4)) ||
|
||
(StatusQuittierung_Untertemperatur && Sammelalarm_quittiert);
|
||
|
||
if (Status_Untertemperatur || StatusQuittierung_Untertemperatur)
|
||
{
|
||
Sollwert_Temperatur = std::max(Sollwert_Temperatur, Schaltwert_Untertemperatur);
|
||
}
|
||
|
||
if (Status_Uebertemperatur || StatusQuittierung_Uebertemperatur)
|
||
{
|
||
Sollwert_Temperatur = std::min(Sollwert_Temperatur,
|
||
Schaltwert_Uebertemperatur);
|
||
}
|
||
|
||
// ------------------------
|
||
// Parametersatzumschaltung
|
||
// ------------------------
|
||
// (* Parametersatzumschaltung über Kennfeld *)
|
||
Index_Feuchte = static_cast<std::uint16_t>( 8 - UTILITY_FUNCTIONS::real_to_int(limit((Sollwert_Feuchte - 10.0) /
|
||
(90.0 - 10.0) * 8.0, 0.0, 8.0) + 0.5)); // 111
|
||
Index_Temperatur = static_cast<std::uint16_t>( UTILITY_FUNCTIONS::real_to_int(limit((Sollwert_Temperatur - 10.0) /
|
||
(90.0 - 10.0) * 8.0, 0.0, 8.0) + 0.5)); // 111
|
||
Index_Temperatur_ohne_Feuchte = static_cast<std::uint16_t>(UTILITY_FUNCTIONS::real_to_int( limit((Sollwert_Temperatur - (-20.0)) /
|
||
(100.0 - (-20.0)) * 12.0, 0.0, 12.0) + 0.5)); // 111
|
||
|
||
// (* Zuweisung der Regelparameter *)
|
||
Regler_Heizung_Xp = F_Xp_Heizung * Kennfeld_Regler_Heizung_Xp[Index_Temperatur_ohne_Feuchte];
|
||
Regler_Kuehlung_Xp = F_Xp_Kuehlung * Kennfeld_Regler_Kuehlung_Xp[Index_Temperatur_ohne_Feuchte];
|
||
/*
|
||
* UJ : Warum fehlt das?
|
||
IF BDR_Feuchtemodul THEN
|
||
Regler_Befeuchtung_Xp := F_Xp_Befeuchtung_BDR * Kennfeld_Regler_Befeuchtung_Xp[Index_Feuchte, Index_Temperatur];
|
||
ELSIF BDR_300W_Feuchtemodul THEN
|
||
Regler_Befeuchtung_Xp := F_Xp_Befeuchtung_BDR_300W * Kennfeld_Regler_Befeuchtung_Xp[Index_Feuchte, Index_Temperatur];
|
||
END_IF;
|
||
*/
|
||
Regler_Befeuchtung_Xp = F_Xp_Befeuchtung_BINDER * Kennfeld_Regler_Befeuchtung_Xp[Index_Feuchte][Index_Temperatur];
|
||
Regler_Entfeuchtung_Xp = F_Xp_Entfeuchtung * Kennfeld_Regler_Entfeuchtung_Xp[Index_Feuchte][Index_Temperatur];
|
||
Regler_Tuer_Xp = F_Xp_Tuer; // * Kennfeld_Regler_Tuer_Xp[Index_Temperatur_ohne_Feuchte]; UJ : Warum fehlt das?
|
||
|
||
// ---------------------
|
||
// PID Regler Temperatur
|
||
// ---------------------
|
||
// (* Regelabweichung *)
|
||
Regelabweichung_Temperatur = Sollwert_Temperatur - Istwert_Temperatur;
|
||
|
||
// Zykluszeit Regelabweichung Temperatur
|
||
// (* Berechnung Regelabweichung Temperatur Mittelwert *)
|
||
if (!Startup_finished || !is_valid(Standardregelabweichung_Temperatur) ||
|
||
!is_valid(Standardgradient_Regelabweichung_Temperatur) ||
|
||
Standardgradient_Regelabweichung_Temperatur <= 0.0)
|
||
{
|
||
Zykluszeit_Regelabweichung_Temperatur = 600.0; // 111
|
||
}
|
||
else
|
||
{
|
||
Zykluszeit_Regelabweichung_Temperatur = limit( 2.0 * 3.1415 * Standardregelabweichung_Temperatur / Standardgradient_Regelabweichung_Temperatur * 60.0,
|
||
120.0,
|
||
1200.0); // 111
|
||
}
|
||
Zykluszeit_Regelabweichung_Heizung = std::min(Zykluszeit_Regelabweichung_Temperatur, 300.0); // 111
|
||
Zykluszeit_Regelabweichung_Kuehlung = std::max(Zykluszeit_Regelabweichung_Temperatur, 600.0); // 111
|
||
Amplitude_Regelabweichung_Temperatur = 1.4142 * Standardregelabweichung_Temperatur; // 111
|
||
|
||
// Mittelwert Regelabweichung Temperatur
|
||
if (!Startup_finished || !is_valid(Regelabweichung_Temperatur_Mittelwert) || Temperatursprung)
|
||
{
|
||
Regelabweichung_Temperatur_Mittelwert = 0.0;
|
||
}
|
||
else if (is_valid(Regelabweichung_Temperatur))
|
||
{
|
||
const double alpha = (Zykluszeit_Regelabweichung_Temperatur / sampling_time);
|
||
Regelabweichung_Temperatur_Mittelwert = limit( Regelabweichung_Temperatur_Mittelwert + (Regelabweichung_Temperatur - Regelabweichung_Temperatur_Mittelwert) / alpha,
|
||
Regelabweichung_Temperatur - 1.0,
|
||
Regelabweichung_Temperatur + 1.0);
|
||
}
|
||
|
||
// Standardregelabweichung Temperatur
|
||
if (!Startup_finished || !is_valid(Standardregelabweichung_Temperatur) || Temperatursprung)
|
||
{
|
||
Standardregelabweichung_Temperatur = 0.0;
|
||
}
|
||
else if (is_valid(Regelabweichung_Temperatur))
|
||
{
|
||
const double n = (Zykluszeit_Regelabweichung_Temperatur / sampling_time);
|
||
Standardregelabweichung_Temperatur = std::min( std::sqrt(((Regelabweichung_Temperatur - Regelabweichung_Temperatur_Mittelwert) *
|
||
(Regelabweichung_Temperatur - Regelabweichung_Temperatur_Mittelwert) +
|
||
Standardregelabweichung_Temperatur * Standardregelabweichung_Temperatur * (n - 1.0)) / n),
|
||
1.0);
|
||
}
|
||
|
||
// Gradient Regelabweichung Temperatur
|
||
// f_PID_Temperaure.GradientDifference(...)
|
||
if (!Startup_finished || !is_valid(Regelabweichung_Temperatur_Gradient))
|
||
{
|
||
Regelabweichung_Temperatur_Gradient = 0.0;
|
||
}
|
||
else if (is_valid(Regelabweichung_Temperatur) && is_valid(Regelabweichung_Temperatur_alt))
|
||
{
|
||
Regelabweichung_Temperatur_Gradient = limit(Regelabweichung_Temperatur_Gradient + ((Regelabweichung_Temperatur - Regelabweichung_Temperatur_alt) *
|
||
(60.0 / sampling_time) - Regelabweichung_Temperatur_Gradient) / (10.0 / sampling_time),
|
||
-4.0,
|
||
2.0);
|
||
}
|
||
|
||
// Standardgradient Temperatur
|
||
// f_PID_Temperaure.StandardGradient(...)
|
||
if (!Startup_finished || !is_valid(Standardgradient_Regelabweichung_Temperatur) || Temperatursprung)
|
||
{
|
||
Standardgradient_Regelabweichung_Temperatur = 0.0;
|
||
}
|
||
else if (is_valid(Regelabweichung_Temperatur))
|
||
{
|
||
const double n = (Zykluszeit_Regelabweichung_Temperatur / sampling_time);
|
||
Standardgradient_Regelabweichung_Temperatur = limit(std::sqrt((Regelabweichung_Temperatur_Gradient * Regelabweichung_Temperatur_Gradient +
|
||
Standardgradient_Regelabweichung_Temperatur *
|
||
Standardgradient_Regelabweichung_Temperatur * (n - 1.0)) / n),
|
||
0.01,
|
||
1.0);
|
||
}
|
||
|
||
// UJ: Todo ST Code neu konvertieren !!
|
||
// Temperatursprung
|
||
// f_TemperatureJumpHandler(...)
|
||
if (!Startup_finished)
|
||
{
|
||
Counter_Temperatursprung = 0.0;
|
||
}
|
||
else if (((Sollwert_Temperatur != Sollwert_Temperatur_alt) &&
|
||
(std::abs(Regelabweichung_Temperatur) > 1.0)) ||
|
||
Tuer_offen)
|
||
{
|
||
Counter_Temperatursprung = std::max(Counter_Temperatursprung + sampling_time, 0.0);
|
||
}
|
||
else if (Regelabweichung_Temperatur < std::max(0.2, Amplitude_Regelabweichung_Temperatur) &&
|
||
Regelabweichung_Temperatur > -std::max(0.2, Amplitude_Regelabweichung_Temperatur))
|
||
{
|
||
Counter_Temperatursprung = std::min(Counter_Temperatursprung - sampling_time, 0.0);
|
||
}
|
||
else if (Regelabweichung_Temperatur > std::max(0.5, 2.0 * Amplitude_Regelabweichung_Temperatur) ||
|
||
Regelabweichung_Temperatur < -std::max(0.5, 2.0 * Amplitude_Regelabweichung_Temperatur))
|
||
{
|
||
Counter_Temperatursprung = std::max(Counter_Temperatursprung + sampling_time, -120.0); // 111
|
||
}
|
||
Temperatursprung = (Counter_Temperatursprung > 0.0) || (Temperatursprung && Counter_Temperatursprung > -60.0); // 111
|
||
|
||
// Anti-wind-up Heizung (dynamisches Clamping)
|
||
// ------ F_PID_Temperatuer.AntiWindUpHeater(...)
|
||
if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0)) // 111
|
||
{
|
||
Regler_Heizung_MIN = 0.0;
|
||
Regler_Heizung_I_Anteil_MIN = 0.0;
|
||
Regler_Heizung_MAX = 100.0; // 111
|
||
Regler_Heizung_I_Anteil_MAX = limit(100.0 - P_Anteil_Heizung,
|
||
Regler_Heizung_I_Anteil_MIN,
|
||
Stellgrad_Heizung_Mittelwert);
|
||
}
|
||
else
|
||
{
|
||
Regler_Heizung_MIN = 0.0;
|
||
Regler_Heizung_I_Anteil_MIN = 0.0;
|
||
Regler_Heizung_MAX = 100.0; // 111
|
||
Regler_Heizung_I_Anteil_MAX = limit(100.0 - P_Anteil_Heizung,
|
||
Regler_Heizung_I_Anteil_MIN,
|
||
Regler_Heizung_MAX); // 111
|
||
}
|
||
|
||
/* Anpassung P-Anteil Heizung bei Temperatursprung */
|
||
if (Temperatursprung)
|
||
{
|
||
}
|
||
else
|
||
{
|
||
Regler_Heizung_I_Anteil_MAX = 100.0; // 111
|
||
}
|
||
//----------------------
|
||
|
||
// Anpassung Xp Heizung
|
||
// // ------------F_PID_Temperatuer.AdaptXp(...)
|
||
if (Regelabweichung_Temperatur > Amplitude_Regelabweichung_Temperatur &&
|
||
Regelabweichung_Temperatur_Mittelwert > 0.05 &&
|
||
!Temperatursprung)
|
||
{
|
||
Regler_Heizung_Xp /= 2.0; // 111
|
||
}
|
||
// Achtung: du referenzierst hier Zykluszeit_Regelabweichung_Feuchte später
|
||
// – steht unten. Wir setzen default, falls noch uninitialisiert:
|
||
if (!is_valid(Zykluszeit_Regelabweichung_Feuchte) || Zykluszeit_Regelabweichung_Feuchte <= 0.0)
|
||
{
|
||
Zykluszeit_Regelabweichung_Feuchte = 600.0; // 111
|
||
}
|
||
|
||
Regler_Heizung_Xp = Regler_Heizung_Xp * limit(Zykluszeit_Regelabweichung_Feuchte / 300.0, 1.0, 2.0) *
|
||
limit(1.0 + Amplitude_Regelabweichung_Temperatur / 0.5 + Stellgrad_Kuehlung_Mittelwert / -100.0,
|
||
1.0,
|
||
2.0);
|
||
|
||
// P/I/D Heizung
|
||
//----------------- F_PID_Temperature.step(...)
|
||
if (!Startup_finished || !is_valid(Regelabweichung_Temperatur)) {
|
||
P_Anteil_Heizung = 0.0;
|
||
} else {
|
||
P_Anteil_Heizung = 100.0 / Regler_Heizung_Xp * Regelabweichung_Temperatur; // 111
|
||
}
|
||
|
||
if (!Startup_finished || !is_valid(I_Anteil_Heizung)) {
|
||
I_Anteil_Heizung = 0.0;
|
||
} else if (!Regelung_AUS && is_valid(Regelabweichung_Temperatur) &&
|
||
Counter_Tuer_geschlossen > 60.0) {
|
||
I_Anteil_Heizung = limit(
|
||
I_Anteil_Heizung + 100.0 / Regler_Heizung_Xp /
|
||
(1.0 * Zykluszeit_Regelabweichung_Heizung) *
|
||
sampling_time * Regelabweichung_Temperatur,
|
||
Regler_Heizung_I_Anteil_MIN, Regler_Heizung_I_Anteil_MAX);
|
||
}
|
||
|
||
if (!Startup_finished || !is_valid(D_Anteil_Heizung))
|
||
{
|
||
D_Anteil_Heizung = 0.0;
|
||
}
|
||
else if (is_valid(Regelabweichung_Temperatur) &&
|
||
is_valid(Regelabweichung_Temperatur_alt) &&
|
||
Counter_Tuer_geschlossen > 0.0)
|
||
{
|
||
D_Anteil_Heizung = D_Anteil_Heizung + (100.0 / Regler_Heizung_Xp * (0.1 * Zykluszeit_Regelabweichung_Heizung) *
|
||
(Regelabweichung_Temperatur - Regelabweichung_Temperatur_alt) / sampling_time -
|
||
D_Anteil_Heizung) / (Tau_Heizung_Tv / sampling_time);
|
||
}
|
||
|
||
/* Berechnung Stellgrad Heizung */
|
||
if (Counter_Tuer_offen > 60.0 || Regelung_AUS || !Startup_finished)
|
||
{
|
||
Stellgrad_Heizung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Heizung = limit(P_Anteil_Heizung + I_Anteil_Heizung + D_Anteil_Heizung,
|
||
Regler_Heizung_MIN,
|
||
Regler_Heizung_MAX);
|
||
}
|
||
|
||
/* Berechnung Stellgrad Heizung Mittelwert *
|
||
if (!Startup_finished || !is_valid(Stellgrad_Heizung_Mittelwert))
|
||
{
|
||
Stellgrad_Heizung_Mittelwert = 0.0;
|
||
}
|
||
else if (Temperatursprung)
|
||
{
|
||
Stellgrad_Heizung_Mittelwert = Stellgrad_Heizung;
|
||
}
|
||
else if (is_valid(Stellgrad_Heizung))
|
||
{
|
||
Stellgrad_Heizung_Mittelwert = Stellgrad_Heizung_Mittelwert +
|
||
(Stellgrad_Heizung - Stellgrad_Heizung_Mittelwert) / (Zykluszeit_Regelabweichung_Temperatur / sampling_time);
|
||
}
|
||
|
||
|
||
// ------------ F_PID_Temperature.step(...) !!!!! todo uj umbenennen in Heizung !!!!!!!!!!!!!!!!!!!
|
||
|
||
|
||
// ----------------------------------------------------
|
||
// Ab hier: Kühlung + Feuchte-PIDs + Tür-PID + Aktorlogik
|
||
// ----------------------------------------------------
|
||
// => in gleicher Art übersetzen (Muster ist identisch).
|
||
//
|
||
// Für dieses Snippet: wir übernehmen für die Outputs zumindest die Werte,
|
||
// die schon berechnet sind, und lassen Stellgrade der restlichen Aktoren,
|
||
// falls nicht berechnet, auf gültigen Default stehen.
|
||
|
||
// Regelabweichung Kühlung
|
||
// F_ PID PID_Cooling()
|
||
double Regelabweichung_Kuehlung = Regelabweichung_Temperatur;
|
||
|
||
// Gradient Regelabweichgun Kuehlung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Regelabweichung_Kuehlung_Gradient = 0.0;
|
||
|
||
}
|
||
else
|
||
{
|
||
Regelabweichung_Kuehlung_Gradient = limit((Regelabweichung_Kuehlung - Regelabweichung_Kuehlung_alt) * 60.0 / sampling_time - Regelabweichung_Kuehlung_Gradient,
|
||
-4.0,
|
||
2.0);
|
||
}
|
||
|
||
// Faktor Kuehlung
|
||
|
||
if (!Startup_finished || Temperatursprung)
|
||
{
|
||
Faktor_Kuehlung = 5.0;
|
||
}
|
||
else if (Regelabweichung_Kuehlung < -0.1)
|
||
{
|
||
Faktor_Kuehlung = std::min(Faktor_Kuehlung + sampling_time, 5.0);
|
||
}
|
||
else
|
||
{
|
||
Faktor_Kuehlung = std::max(Faktor_Kuehlung - sampling_time / 60.0, 0.2);
|
||
}
|
||
|
||
// --------------------------- Gegenheizen Band !!! Überwacher !!!!!
|
||
double Regelabweichung_Entfeuchtung = Regelabweichung_Feuchte;
|
||
if (!Startup_finished || Temperatursprung || (Counter_Temperatursprung > -600.0 && Faktor_Gegenheizen_Band == 10.0))
|
||
{
|
||
Faktor_Gegenheizen_Band = 10.0;
|
||
}
|
||
else if (Stellgrad_Heizung_Mittelwert - Sollwert_Gegenheizen < -1.0)
|
||
{
|
||
if (Regelabweichung_Entfeuchtung > 0.5)
|
||
{
|
||
Faktor_Gegenheizen_Band = std::max(Faktor_Gegenheizen_Band - sampling_time / 10.0, 0.0);
|
||
} else
|
||
{
|
||
Faktor_Gegenheizen_Band = std::min(Faktor_Gegenheizen_Band + sampling_time / 60.0, 10.0);
|
||
}
|
||
|
||
} else if (Stellgrad_Heizung_Mittelwert - Sollwert_Gegenheizen > 1.0 && Stellgrad_Kuehlung_Mittelwert < -5.0)
|
||
{
|
||
if (Regelabweichung_Entfeuchtung < -0.5)
|
||
{
|
||
Faktor_Gegenheizen_Band = std::max(Faktor_Gegenheizen_Band - sampling_time / 10.0, 0.0);
|
||
}
|
||
else
|
||
{
|
||
Faktor_Gegenheizen_Band = std::min(Faktor_Gegenheizen_Band + sampling_time / 600.0, 5.0);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Faktor_Gegenheizen_Band = std::max(Faktor_Gegenheizen_Band - sampling_time / 60.0, 0.1);
|
||
}
|
||
// --------------------------- Gegenheizen Band
|
||
|
||
// -----------------------Sollwert Gegenheizen für I-Anteilverschiebung
|
||
|
||
double Faktor_Entfeuchtung_Kuehlung = 0.0;
|
||
double Offset_Kuehlung = Faktor_Entfeuchtung_Kuehlung;
|
||
Offset_Kuehlung = Faktor_Entfeuchtung_Kuehlung * Stellgrad_Entfeuchtung_Mittelwert *
|
||
std::max((50.0 - Stellgrad_Heizung_Mittelwert) / (50 - 0.0), 0.0) * (8.0 - Stellgrad_Befeuchtung_Standby) / (8.0 - 2.0);
|
||
|
||
// P-Anteil Kühlung
|
||
double P_Anteil_Kuehlung = 0.0;
|
||
if (!Startup_finished)
|
||
{
|
||
P_Anteil_Kuehlung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
P_Anteil_Kuehlung = 100.0 / Regler_Kuehlung_Xp * Faktor_Kuehlung * Regelabweichung_Kuehlung;
|
||
}
|
||
|
||
// Begrenzung I-Anteil Kühlung bei Türöffnung
|
||
double Regler_Kuehlung_MAX = 0;
|
||
double Regler_Kuehlung_MIN = 0;
|
||
double Regler_Kuehlung_I_Anteil_MAX = 0;
|
||
double Regler_Kuehlung_I_Anteil_MIN = 0;
|
||
|
||
if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0))
|
||
{
|
||
Regler_Kuehlung_MAX = I_Anteil_Kuehlung;
|
||
Regler_Kuehlung_MIN = -100.0;
|
||
Regler_Kuehlung_I_Anteil_MAX = I_Anteil_Kuehlung;
|
||
Regler_Kuehlung_I_Anteil_MIN = limit( -100.0 - P_Anteil_Kuehlung, Regler_Kuehlung_MIN, Regler_Kuehlung_MAX);
|
||
}
|
||
else
|
||
{
|
||
Regler_Kuehlung_MAX = 0.0;
|
||
Regler_Kuehlung_MIN = -100.0;
|
||
Regler_Kuehlung_I_Anteil_MAX = 0.1 / Regler_Kuehlung_Xp * 100.0;
|
||
Regler_Kuehlung_I_Anteil_MIN = limit( -100.0 - P_Anteil_Kuehlung + Regelabweichung_Kuehlung_Gradient / 0.5 * 100.0,
|
||
Regler_Kuehlung_MIN,
|
||
Regler_Kuehlung_MAX);
|
||
}
|
||
|
||
// f_PID_Cooling.Step(...)
|
||
// I Anteil Kühlung
|
||
if (!Startup_finished)
|
||
{
|
||
I_Anteil_Kuehlung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 60.0)
|
||
{
|
||
I_Anteil_Kuehlung = limit(I_Anteil_Kuehlung + 100.0 / Regler_Kuehlung_Tn * sampling_time *
|
||
(Regelabweichung_Kuehlung + (Stellgrad_Heizung - Sollwert_Gegenheizen) / 100.0 *
|
||
Regler_Heizung_Xp * Theta_I_Kuehlung * Faktor_Gegenheizen_Band),
|
||
Regler_Kuehlung_I_Anteil_MIN,
|
||
Regler_Kuehlung_I_Anteil_MAX);
|
||
}
|
||
|
||
// D-Anteil Kühlung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
D_Anteil_Kuehlung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 0.0)
|
||
{
|
||
D_Anteil_Kuehlung += (100.0 / Regler_Kuehlung_Xp * Regler_Kuehlung_Tv * (Regelabweichung_Kuehlung -
|
||
Regelabweichung_Kuehlung_alt) / sampling_time -
|
||
D_Anteil_Kuehlung) / (Tau_Kuehlung_Tv / sampling_time);
|
||
}
|
||
|
||
// Berechnung Stellgrad Kühlung
|
||
// f_
|
||
if (Counter_Tuer_offen > 60.0 || !Startup_finished)
|
||
{
|
||
Stellgrad_Kuehlung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Kuehlung = limit(P_Anteil_Kuehlung + I_Anteil_Kuehlung + D_Anteil_Kuehlung + Offset_Kuehlung,
|
||
Regler_Kuehlung_MIN,
|
||
Regler_Kuehlung_MAX);
|
||
}
|
||
|
||
// Berechnung Stellgrad Mittelwert
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Kuehlung_Mittelwert = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Kuehlung_Mittelwert = limit(Stellgrad_Kuehlung_Mittelwert + (Stellgrad_Kuehlung - Stellgrad_Kuehlung_Mittelwert) / (600.0 / sampling_time),
|
||
Stellgrad_Kuehlung - 0.5 * 100.0 * Regler_Kuehlung_Xp,
|
||
Stellgrad_Kuehlung + 0.5 * 100.0 / Regler_Kuehlung_Xp);
|
||
}
|
||
// ------------------- F_ PID PID_Cooling()
|
||
|
||
|
||
// PID Regler Feuchte
|
||
// f_PID_Humidiy
|
||
Regelabweichung_Feuchte = Sollwert_Feuchte_Absolut - Istwert_Feuchte;
|
||
|
||
// Berechnung Regelabweichung Feuchte Mittelwert
|
||
if (!Startup_finished)
|
||
{
|
||
Regelabweichung_Feuchte_Mittelwert = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Regelabweichung_Feuchte_Mittelwert = limit(Regelabweichung_Feuchte_Mittelwert + (Regelabweichung_Feuchte - Regelabweichung_Feuchte_Mittelwert) / (60.0 / sampling_time),
|
||
Regelabweichung_Feuchte - 10.0,
|
||
Regelabweichung_Feuchte + 10.0);
|
||
}
|
||
|
||
// Feuchtesprung
|
||
// f_PID_Hunidity.HandleJump(...)
|
||
if (!Startup_finished)
|
||
{
|
||
Counter_Feuchtesprung = 0.0;
|
||
}
|
||
else if (Sollwert_Feuchte != Sollwert_Feuchte_alt && std::abs(Regelabweichung_Feuchte) > 2.0)
|
||
{
|
||
Counter_Feuchtesprung = std::max(Counter_Feuchtesprung + sampling_time, 0.0);
|
||
}
|
||
else if (std::abs(Regelabweichung_Feuchte) < 2.0 || std::abs(Regelabweichung_Feuchte_Mittelwert) < 2.0)
|
||
{
|
||
Counter_Feuchtesprung = std::min(Counter_Feuchtesprung - sampling_time, 0.0);
|
||
} else if (std::abs(Regelabweichung_Feuchte_Mittelwert) > 5.0)
|
||
{
|
||
Counter_Feuchtesprung = std::max(Counter_Feuchtesprung + sampling_time, -120.0);
|
||
}
|
||
|
||
Feuchtesprung = (Counter_Feuchtesprung > 0.0 || (Feuchtesprung && Counter_Feuchtesprung > -120.0));
|
||
|
||
// Regelabweichung Befeuchtung
|
||
|
||
double Regelabweichung_Befeuchtung = Regelabweichung_Feuchte;
|
||
|
||
// Gradient regelabweichung Feuchte
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Regelabweichung_Befeuchtung_Gradient = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Regelabweichung_Befeuchtung_Gradient = limit(Regelabweichung_Befeuchtung_Gradient +
|
||
((Regelabweichung_Befeuchtung - Regelabweichung_Befeuchtung_alt) * 60.0 / sampling_time -
|
||
Regelabweichung_Befeuchtung_Gradient) / 60.0 * sampling_time,
|
||
-20.0,
|
||
5.0);
|
||
}
|
||
|
||
// Begrenzung I-Anteil bei Türöffnung
|
||
double Regler_Befeuchtung_MIN = 0.0;
|
||
double Regler_Befeuchtung_MAX = 0.0;
|
||
double Regler_Befeuchtung_I_Anteil_MIN = 0.0;
|
||
double Regler_Befeuchtung_I_Anteil_MAX = 0.0;
|
||
|
||
if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0))
|
||
{
|
||
Regler_Befeuchtung_MIN = std::max(Stellgrad_Befeuchtung_Standby - 2.0, Standby_Feuchtemodul);
|
||
Regler_Befeuchtung_MAX = std::min(100.0, Stellgrad_Feuchtemodul_MAX);
|
||
Regler_Befeuchtung_I_Anteil_MIN = 0.0;
|
||
Regler_Befeuchtung_I_Anteil_MAX = limit(100.0 - P_Anteil_Befeuchtung,
|
||
Regler_Befeuchtung_I_Anteil_MIN,
|
||
Stellgrad_Befeuchtung_Mittelwert);
|
||
} else
|
||
{
|
||
if (Feuchtesprung)
|
||
{
|
||
Regler_Befeuchtung_MIN = std::max(Stellgrad_Befeuchtung_Standby - 2.0, Standby_Feuchtemodul);
|
||
}
|
||
else
|
||
{
|
||
Regler_Befeuchtung_MIN = std::max(std::min(Stellgrad_Befeuchtung_Standby + 0.25 * P_Anteil_Befeuchtung + D_Anteil_Befeuchtung + Z_Anteil_Befeuchtung,
|
||
Stellgrad_Befeuchtung_Standby + 2.0),
|
||
std::max(Stellgrad_Befeuchtung_Standby - 1.0,
|
||
Standby_Feuchtemodul));
|
||
}
|
||
Regler_Befeuchtung_MAX = std::min(100.0, Stellgrad_Feuchtemodul_MAX);
|
||
Regler_Befeuchtung_I_Anteil_MIN = 0.0;
|
||
Regler_Befeuchtung_I_Anteil_MAX = limit(100.0, Regler_Befeuchtung_I_Anteil_MIN, Stellgrad_Befeuchtung_Mittelwert);
|
||
}
|
||
|
||
// Anteil P-Anteil Befeuchtung bei Feuchtesprung und Türöffnung
|
||
|
||
if (Counter_Tuer_geschlossen < 180.0 && Feuchtesprung)
|
||
{
|
||
Regler_Befeuchtung_Xp = Regler_Befeuchtung_Xp * 2.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 300.0 && Feuchtesprung)
|
||
{
|
||
Regler_Befeuchtung_Xp = Regler_Befeuchtung_Xp / 2.0;
|
||
}
|
||
else
|
||
{
|
||
Regler_Befeuchtung_Xp = Regler_Befeuchtung_Xp * (1.0 + Stellgrad_Entfeuchtung_Mittelwert / -100.0);
|
||
}
|
||
|
||
// P-Anteil Befeuchtung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
P_Anteil_Befeuchtung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
P_Anteil_Befeuchtung = 100.0 / Regler_Befeuchtung_Xp * Regelabweichung_Befeuchtung;
|
||
}
|
||
|
||
// I-Anteil Befeuchtung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
I_Anteil_Befeuchtung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 60.0)
|
||
{
|
||
I_Anteil_Befeuchtung = limit(I_Anteil_Befeuchtung + 100.0 / Regler_Befeuchtung_Xp / Regler_Befeuchtung_Tn * sampling_time * Regelabweichung_Befeuchtung,
|
||
Regler_Befeuchtung_I_Anteil_MIN,
|
||
Regler_Befeuchtung_I_Anteil_MAX);
|
||
}
|
||
|
||
// D-Anteil Befeuchtung
|
||
if (!Startup_finished)
|
||
{
|
||
D_Anteil_Befeuchtung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen)
|
||
{
|
||
D_Anteil_Befeuchtung += (100.0 / Regler_Befeuchtung_Xp * Regler_Befeuchtung_Tv * (Regelabweichung_Befeuchtung - Regelabweichung_Befeuchtung_alt) / sampling_time -
|
||
D_Anteil_Befeuchtung) / (Tau_Befeuchtung_Tv / sampling_time);
|
||
}
|
||
|
||
// Z-Anteil Befeuchtung
|
||
|
||
if (!Startup_finished || Feuchtesprung)
|
||
{
|
||
Z_Anteil_Befeuchtung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 0.0)
|
||
{
|
||
Z_Anteil_Befeuchtung += (100.0 / Regler_Befeuchtung_Xp * Regler_Befeuchtung_Tz * ((Regelabweichung_Befeuchtung -Regelabweichung_Befeuchtung_alt) -
|
||
(Regelabweichung_Befeuchtung_alt -
|
||
Regelabweichung_Befeuchtung_alt_alt)) / sampling_time -
|
||
Z_Anteil_Befeuchtung) / (Tau_Befeuchtung_Tz / sampling_time);
|
||
}
|
||
// Regler_Befeuchtung_MAX = 10.0;
|
||
// Berechnung Stellgrad Befeuchtung
|
||
if (Counter_Tuer_offen > 60.0 || !Startup_finished)
|
||
{
|
||
Stellgrad_Befeuchtung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Befeuchtung = limit(P_Anteil_Befeuchtung + I_Anteil_Befeuchtung + D_Anteil_Befeuchtung + Z_Anteil_Befeuchtung,
|
||
Regler_Befeuchtung_MIN,
|
||
Regler_Befeuchtung_MAX);
|
||
}
|
||
|
||
// Berechnung Stellgrad befeuchtung Mittelwert
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Befeuchtung_Mittelwert = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Befeuchtung_Mittelwert = limit(Stellgrad_Befeuchtung_Mittelwert + (Stellgrad_Befeuchtung - Stellgrad_Befeuchtung_Mittelwert) / (600.0 / sampling_time),
|
||
Stellgrad_Befeuchtung - 5.0 * 100.0 / Regler_Befeuchtung_Xp,
|
||
Stellgrad_Befeuchtung + 5.0 * 100.0 / Regler_Befeuchtung_Xp);
|
||
}
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Befeuchtung_Standby = 4.0;
|
||
}
|
||
else if (!(Feuchtesprung && Counter_Feuchtesprung < 300.0))
|
||
{
|
||
Stellgrad_Befeuchtung_Standby = limit(Stellgrad_Befeuchtung_Standby + (Stellgrad_Befeuchtung - Stellgrad_Befeuchtung_Standby) / (600.0 / sampling_time),
|
||
2.0,
|
||
8.0);
|
||
}
|
||
|
||
// Regelabweichung Entfeuchtung
|
||
|
||
Regelabweichung_Entfeuchtung = Regelabweichung_Feuchte;
|
||
|
||
// Gradient Regelabweichung Entfeuchtung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Regelabweichung_Entfeuchtung_Gradient = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Regelabweichung_Entfeuchtung_Gradient = limit(Regelabweichung_Entfeuchtung_Gradient +
|
||
((Regelabweichung_Entfeuchtung - Regelabweichung_Entfeuchtung_alt) * 60.0 / sampling_time -
|
||
Regelabweichung_Entfeuchtung_Gradient) / 60.0 * sampling_time,
|
||
-20.0,
|
||
5.0);
|
||
}
|
||
|
||
// Faktor Entfeuchtung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Faktor_Entfeuchtung = 5.0;
|
||
}
|
||
else if (Regelabweichung_Entfeuchtung < -0.5)
|
||
{
|
||
Faktor_Entfeuchtung = std::min(Faktor_Entfeuchtung + sampling_time / 60.0, 5.0);
|
||
}
|
||
else
|
||
{
|
||
Faktor_Entfeuchtung = std::max(Faktor_Entfeuchtung - sampling_time, 0.2);
|
||
}
|
||
|
||
// Gegenbefeuchten Band
|
||
|
||
if (!Startup_finished || Feuchtesprung || (Counter_Feuchtesprung > -600.0 &&
|
||
Faktor_Gegenbefeuchten_Band == 5.0))
|
||
{
|
||
Faktor_Gegenbefeuchten_Band = 5.0;
|
||
}
|
||
else if (Stellgrad_Befeuchtung_Mittelwert - Sollwert_Gegenbefeuchten < -1.0)
|
||
{
|
||
if (Regelabweichung_Kuehlung > 0.05)
|
||
{
|
||
Faktor_Gegenbefeuchten_Band = std::max(Faktor_Gegenbefeuchten_Band - sampling_time / 10.0, 0.0);
|
||
}
|
||
else
|
||
{
|
||
Faktor_Gegenbefeuchten_Band = std::min(Faktor_Gegenbefeuchten_Band + sampling_time / 60.0, 5.0);
|
||
}
|
||
|
||
}
|
||
else if (Stellgrad_Befeuchtung_Mittelwert - Sollwert_Gegenbefeuchten > 1.0 && Stellgrad_Entfeuchtung_Mittelwert < -10.0)
|
||
{
|
||
if (Regelabweichung_Kuehlung < -0.05)
|
||
{
|
||
Faktor_Gegenbefeuchten_Band = std::max(Faktor_Gegenbefeuchten_Band - sampling_time / 10.0, 0.0);
|
||
}
|
||
else
|
||
{
|
||
Faktor_Gegenbefeuchten_Band = std::min(Faktor_Gegenbefeuchten_Band + sampling_time / 600.0, 2.0);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Faktor_Gegenbefeuchten_Band = std::max(Faktor_Gegenbefeuchten_Band - sampling_time / 60.0, 0.2);
|
||
}
|
||
|
||
// Sollwert Gegenbefeuchten für I-Anteilverschiebung
|
||
|
||
Sollwert_Gegenbefeuchten = 6.0 - 4.0 * (-Stellgrad_Entfeuchtung_Mittelwert / 100.0);
|
||
double Offset_Entfeuchtung = 0.0 * Stellgrad_Kuehlung_Mittelwert;
|
||
|
||
//(* P-Anteil Entfeuchtung *)
|
||
|
||
double P_Anteil_Entfeuchtung = 0.0;
|
||
if (!Startup_finished)
|
||
{
|
||
P_Anteil_Entfeuchtung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
P_Anteil_Entfeuchtung = 100.0 / Regler_Entfeuchtung_Xp * Faktor_Entfeuchtung * Regelabweichung_Entfeuchtung;
|
||
}
|
||
// I-Anteil Entfeuchtung
|
||
if (!Startup_finished)
|
||
{
|
||
I_Anteil_Entfeuchtung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 60.0)
|
||
{
|
||
I_Anteil_Entfeuchtung = limit(I_Anteil_Entfeuchtung + 100.0 / Regler_Entfeuchtung_Xp / Regler_Entfeuchtung_Tn * sampling_time * (Regelabweichung_Entfeuchtung +
|
||
(Stellgrad_Befeuchtung - Sollwert_Gegenbefeuchten) / 100.0 * Regler_Befeuchtung_Xp * Theta_I_Entfeuchtung * Faktor_Gegenbefeuchten_Band),
|
||
Regler_Entfeuchtung_I_Anteil_MIN,
|
||
Regler_Entfeuchtung_I_Anteil_MAX);
|
||
}
|
||
// D-Anteil Entfeuchtung
|
||
if (!Startup_finished)
|
||
{
|
||
D_Anteil_Entfeuchtung = 0.0;
|
||
}
|
||
else if (Counter_Tuer_geschlossen > 0.0)
|
||
{
|
||
D_Anteil_Entfeuchtung = D_Anteil_Entfeuchtung + (100.0 / Regler_Entfeuchtung_Xp * Regler_Entfeuchtung_Tv *
|
||
(Regelabweichung_Entfeuchtung - Regelabweichung_Entfeuchtung_alt) / sampling_time -
|
||
D_Anteil_Entfeuchtung) / (Tau_Entfeuchtung_Tv / sampling_time);
|
||
}
|
||
|
||
// Begrenzung Stellgrad und I-Anteil
|
||
|
||
if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0))
|
||
{
|
||
Regler_Entfeuchtung_MAX = I_Anteil_Entfeuchtung;
|
||
Regler_Entfeuchtung_MIN = -100.0;
|
||
Regler_Entfeuchtung_I_Anteil_MAX = I_Anteil_Entfeuchtung;
|
||
Regler_Entfeuchtung_I_Anteil_MIN = limit(-100.0 - P_Anteil_Entfeuchtung,
|
||
Regler_Entfeuchtung_MIN,
|
||
Regler_Entfeuchtung_I_Anteil_MAX);
|
||
}
|
||
else
|
||
{
|
||
Regler_Entfeuchtung_MAX = 0.0;
|
||
Regler_Entfeuchtung_MIN = -100.0;
|
||
Regler_Entfeuchtung_I_Anteil_MAX = 1.5 / Regler_Entfeuchtung_Xp * 100.0;
|
||
Regler_Entfeuchtung_I_Anteil_MIN = limit(-100.0 - P_Anteil_Entfeuchtung + Regelabweichung_Entfeuchtung_Gradient / 20.0 * 100.0,
|
||
Regler_Entfeuchtung_MIN,
|
||
Regler_Entfeuchtung_I_Anteil_MAX);
|
||
}
|
||
|
||
// Berechnung Stellgrad Entfeuchtung
|
||
|
||
if (Counter_Tuer_offen > 60.0 || !Startup_finished)
|
||
{
|
||
Stellgrad_Entfeuchtung = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Entfeuchtung = limit(P_Anteil_Entfeuchtung + I_Anteil_Entfeuchtung + Offset_Entfeuchtung + D_Anteil_Entfeuchtung,
|
||
Regler_Entfeuchtung_MIN,
|
||
Regler_Entfeuchtung_MAX);
|
||
}
|
||
|
||
// Berechnung Stellgrad entfeuchtung Mittelwert
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Entfeuchtung_Mittelwert = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Entfeuchtung_Mittelwert = limit((Stellgrad_Entfeuchtung - Stellgrad_Entfeuchtung_Mittelwert) / (600.0 / sampling_time),
|
||
Stellgrad_Entfeuchtung - 5.0 * 100.0 / Regler_Entfeuchtung_Xp,
|
||
Stellgrad_Entfeuchtung + 5.0 * 100.0 / Regler_Entfeuchtung_Xp);
|
||
}
|
||
|
||
// PID Regler Tür
|
||
// f_PID_Door(...)
|
||
double Offset_Temperatur_Tuer;
|
||
if (Feuchtesprung)
|
||
{
|
||
Offset_Temperatur_Tuer = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Offset_Temperatur_Tuer = 2.0 * Betauungsschutz / 100.0 * limit((90.0 + Stellgrad_Kuehlung_Mittelwert) / (90.0 - 80.0),
|
||
0.0,
|
||
1.0);
|
||
}
|
||
|
||
// Regelabweichung
|
||
if (!Tuer_offen || std::abs(Regelabweichung_Tuer) > std::abs(Sollwert_Temperatur + Offset_Temperatur_Tuer - Istwert_Temperatur_Tuer))
|
||
{
|
||
Regelabweichung_Tuer = Sollwert_Temperatur + Offset_Temperatur_Tuer - Istwert_Temperatur_Tuer;
|
||
}
|
||
|
||
// P-Anteil
|
||
|
||
// Anti-Windup über dynamisches Integrator Clamping
|
||
|
||
double Regler_Tuer_MAX = limit( (100.0 + Stellgrad_Kuehlung) / (100.0 - 80.0) * 100.0, 0.0, 100.0);
|
||
double Regler_Tuer_MIN = 0.0;
|
||
double Regler_Tuer_I_Anteil_MAX = limit(100.0 - P_Anteil_Tuer, 0.0, Regler_Tuer_MAX);
|
||
double Regler_Tuer_I_Anteil_MIN = 0.0;
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
P_Anteil_Tuer = 0.0;
|
||
}
|
||
else
|
||
{
|
||
P_Anteil_Tuer = 100.0 / Regler_Tuer_Xp * Regelabweichung_Tuer;
|
||
}
|
||
|
||
// I-Anteil
|
||
if (!Startup_finished)
|
||
{
|
||
I_Anteil_Tuer = 0.0;
|
||
} else if (Temperatursprung && Regelabweichung_Tuer > 0.0)
|
||
{
|
||
I_Anteil_Tuer = limit(I_Anteil_Tuer,
|
||
Regler_Tuer_I_Anteil_MIN,
|
||
Regler_Tuer_I_Anteil_MAX);
|
||
}
|
||
else if (!Tuer_offen)
|
||
{
|
||
I_Anteil_Tuer = limit(I_Anteil_Tuer + 100.0 / Regler_Tuer_Xp / Regler_Tuer_Tn * sampling_time * Regelabweichung_Tuer,
|
||
Regler_Tuer_I_Anteil_MIN,
|
||
Regler_Tuer_I_Anteil_MAX);
|
||
}
|
||
// D-Anteil
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
D_Anteil_Tuer = 0.0;
|
||
}
|
||
else
|
||
{
|
||
D_Anteil_Tuer = D_Anteil_Tuer + (100.0 / Regler_Tuer_Xp * Regler_Tuer_Tv * (Regelabweichung_Tuer - Regelabweichung_Tuer_alt) / sampling_time -
|
||
D_Anteil_Tuer) / (Tau_Tuer_Tv / sampling_time);
|
||
}
|
||
|
||
double Stellgrad_Tuer;
|
||
// Berechnung Stellgrad Tür
|
||
if (Tuer_offen || !Startup_finished)
|
||
{
|
||
Stellgrad_Tuer = limit(P_Anteil_Tuer + I_Anteil_Tuer + D_Anteil_Tuer,
|
||
Regler_Tuer_MIN,
|
||
Regler_Tuer_MAX);
|
||
}
|
||
|
||
// Kennfelder Kühlung/Entfeuchtung
|
||
|
||
int Index_Ueberhitzung = 1;
|
||
while (Kennfeld_Ueberhitzung[0][Index_Ueberhitzung] < Istwert_Temperatur && Index_Ueberhitzung < 12)
|
||
{
|
||
Index_Ueberhitzung++;
|
||
}
|
||
double Interpolation_Ueberhitzung = limit((Kennfeld_Ueberhitzung[0][Index_Ueberhitzung - 1] - Istwert_Temperatur) / (Kennfeld_Ueberhitzung[0][Index_Ueberhitzung - 1] - Kennfeld_Ueberhitzung[0][Index_Ueberhitzung]),
|
||
0.0,
|
||
1.0);
|
||
double Skalierung_Ueberhitzung_Kennfeld_Min = Kennfeld_Ueberhitzung[1][Index_Ueberhitzung] *
|
||
(Interpolation_Ueberhitzung + Kennfeld_Ueberhitzung[1][Index_Ueberhitzung - 1]) *
|
||
(1.0 - Interpolation_Ueberhitzung);
|
||
double Skalierung_Ueberhitzung_Kennfeld_Max = Kennfeld_Ueberhitzung[2][Index_Ueberhitzung] *
|
||
(Interpolation_Ueberhitzung + Kennfeld_Ueberhitzung[2][Index_Ueberhitzung - 1]) *
|
||
(1.0 - Interpolation_Ueberhitzung);
|
||
double Sollwert_Ueberhitzung = Kennfeld_Ueberhitzung[3][Index_Ueberhitzung] *
|
||
(Interpolation_Ueberhitzung + Kennfeld_Ueberhitzung[3][Index_Ueberhitzung - 1]) *
|
||
(1.0 - Interpolation_Ueberhitzung);
|
||
|
||
//(* Entfeuchtung und Abtauung aus Kennfeld *)
|
||
int Index_Entfeuchtung = 1; // todo uj - warum nicht mit 0 starten?
|
||
while ((Kennfeld_Entfeuchtung[0][Index_Entfeuchtung] < Istwert_Temperatur) && (Index_Ueberhitzung < 12))
|
||
{
|
||
Index_Entfeuchtung++;
|
||
}
|
||
double Interpolation_Entfeuchtung = limit((Kennfeld_Entfeuchtung[0][Index_Entfeuchtung - 1] -
|
||
(Istwert_Temperatur) / (Kennfeld_Entfeuchtung[0][Index_Entfeuchtung - 1] ) -
|
||
Kennfeld_Entfeuchtung[0][Index_Entfeuchtung]),
|
||
0.0,
|
||
1.0);
|
||
double Skalierung_Entfeuchtungsventil = Kennfeld_Entfeuchtung[1][Index_Entfeuchtung] * Interpolation_Entfeuchtung +
|
||
Kennfeld_Entfeuchtung[1][Index_Entfeuchtung - 1] * (1.0 - Interpolation_Entfeuchtung);
|
||
|
||
double Abtauzyklus_Pause = Kennfeld_Entfeuchtung[2][Index_Entfeuchtung] * Interpolation_Entfeuchtung +
|
||
Kennfeld_Entfeuchtung[2][Index_Entfeuchtung - 1] * (1.0 - Interpolation_Entfeuchtung);
|
||
|
||
double Abtauzyklus_Dauer = Kennfeld_Entfeuchtung[3][Index_Entfeuchtung] * Interpolation_Entfeuchtung +
|
||
Kennfeld_Entfeuchtung[3][Index_Entfeuchtung - 1] * (1.0 - Interpolation_Entfeuchtung);
|
||
|
||
// Ende - f_PID_Door(...)
|
||
|
||
// Überhitzungsregelung
|
||
|
||
// Temperatur Verdampferausgang PT1
|
||
// f_PT1.Vapourize(...)
|
||
if (!Startup_finished)
|
||
{
|
||
Istwert_Temperatur_Verdampferausgang_PT1 = Istwert_Temperatur_Verdampferausgang;
|
||
}
|
||
else
|
||
{
|
||
Istwert_Temperatur_Verdampferausgang_PT1 += (Istwert_Temperatur_Verdampferausgang -
|
||
Istwert_Temperatur_Verdampferausgang_PT1) / (60.0 * 4.0);
|
||
}
|
||
|
||
// Skalierung Überhitzung
|
||
if (Istwert_Temperatur_Verdampferausgang < (Istwert_Temperatur + Sollwert_Ueberhitzung))
|
||
{
|
||
Counter_Durchzug = MIN(Counter_Durchzug + sampling_time, 10.0);
|
||
}
|
||
else
|
||
{
|
||
// uj-todo; template for MAX
|
||
// Counter_Durchzug = MAX(MAX(Counter_Durchzug-sampling_time,-10),0);
|
||
}
|
||
if (Counter_Durchzug >= 10.0)
|
||
{
|
||
Durchzug = true;
|
||
}
|
||
else if (Counter_Durchzug <= -10.0)
|
||
{
|
||
Durchzug = false;
|
||
}
|
||
|
||
double Skalierung_Ueberhitzung_PT1 = Skalierung_Ueberhitzung_Kennfeld_Max;
|
||
|
||
// Magnetventil Kühlung
|
||
|
||
// Stellgrad Kühlung
|
||
|
||
if (Counter_Verdichter_aus > 60.0 && Counter_Verdichter_aus < 600.0)
|
||
{
|
||
Stellgrad_Kuehlventil = 1.0;
|
||
}
|
||
else if (Istwert_Temperatur > 120.0 || Counter_Kuehlung_Freigabe <= 0.0)
|
||
{
|
||
Stellgrad_Kuehlventil = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Kuehlventil = MAX(-Stellgrad_Kuehlung, 0.0) * Skalierung_Ueberhitzung_PT1 * Counter_Kuehlung_Freigabe;
|
||
}
|
||
|
||
// Ende - f_PT1.Vapourize(...)
|
||
|
||
// PWM Generierung Kuehlventil
|
||
// bool step(double Stellgrad,double sampling_time){
|
||
|
||
// f_PWMCoolingValve.Step(...)
|
||
Kuehlventil = PWM_Kuehlventil.step(Stellgrad_Kuehlventil, sampling_time);
|
||
|
||
// Magnetventil Entfeuchtung
|
||
double T_Entfeuchtung;
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
T_Entfeuchtung = Istwert_Temperatur;
|
||
}
|
||
else if (Entfeuchtungsventil)
|
||
{
|
||
T_Entfeuchtung = limit(T_Entfeuchtung + ((Istwert_Temperatur - T_Entfeuchtung) * U_Entfeuchtung -
|
||
P_Entfeuchtung) / (4.0 * C_Entfeuchtung),
|
||
-30.0,
|
||
Istwert_Temperatur);
|
||
}
|
||
else
|
||
{
|
||
T_Entfeuchtung = limit(T_Entfeuchtung + ((Istwert_Temperatur - T_Entfeuchtung) * U_Entfeuchtung) / (4.0 * C_Entfeuchtung),
|
||
-30.0,
|
||
Istwert_Temperatur);
|
||
}
|
||
// Stellgrad Entfeuchtung
|
||
|
||
if (Istwert_Temperatur > 120.0 || Counter_Entfeuchtung_Freigabe <= 0.0)
|
||
{
|
||
Stellgrad_Entfeuchtungsventil = 0.0;
|
||
} else
|
||
{
|
||
Stellgrad_Entfeuchtungsventil = MAX(-Stellgrad_Entfeuchtung, 0.0) *
|
||
Skalierung_Entfeuchtungsventil *
|
||
Counter_Entfeuchtung_Freigabe;
|
||
}
|
||
|
||
// Abtauzyklus
|
||
bool Freigabe_Abtauzyklus = Istwert_Feuchte > Sollwert_Feuchte_Absolut + 2.5;
|
||
if (!Freigabe_Abtauzyklus)
|
||
{
|
||
Counter_Freigabe_Abtauzyklus = 0.0;
|
||
} else
|
||
{
|
||
Counter_Freigabe_Abtauzyklus += sampling_time;
|
||
}
|
||
double Skalierung_Abtauzyklus_Dauer = 0.0;
|
||
;
|
||
if (Abtauzyklus_Pause > 0.0 && Abtauzyklus_Dauer > 0.0)
|
||
{
|
||
Skalierung_Abtauzyklus_Dauer = limit(Counter_Freigabe_Abtauzyklus / (10.0 * (Abtauzyklus_Pause + Abtauzyklus_Dauer) * 60.0),
|
||
1.0,
|
||
5.0);
|
||
}
|
||
if (Counter_Abtauzyklus > (Abtauzyklus_Pause + Abtauzyklus_Dauer * Skalierung_Abtauzyklus_Dauer) * 60.0)
|
||
{
|
||
Counter_Abtauzyklus = 0.0;
|
||
}
|
||
else if ((T_Entfeuchtung < 0.0 && Freigabe_Abtauzyklus) || Abtauzyklus)
|
||
{
|
||
Counter_Abtauzyklus += sampling_time;
|
||
}
|
||
else
|
||
{
|
||
Counter_Abtauzyklus = MAX(Counter_Abtauzyklus - sampling_time, 0.0);
|
||
}
|
||
Abtauzyklus = Counter_Abtauzyklus > Abtauzyklus_Pause * 60.0 && Abtauzyklus_Pause > 0.0;
|
||
|
||
if (Abtauzyklus)
|
||
{
|
||
Stellgrad_Entfeuchtungsventil = 0.0;
|
||
}
|
||
// Ende -f_PWMCoolingValve.Step(...)
|
||
|
||
|
||
// PWM Entfeuchtungsventil
|
||
// f_PWMDeHumizeValve.Step(...)
|
||
Entfeuchtungsventil = PWM_Entfeuchtungsventil.step(Stellgrad_Entfeuchtungsventil, sampling_time);
|
||
|
||
// Druckausgleich vor Start Verdichter
|
||
if (!Verdichter && Counter_Entfeuchtung_Freigabe > 5.0)
|
||
{
|
||
Entfeuchtungsventil = true;
|
||
}
|
||
|
||
// Heizung Kessel
|
||
|
||
if (Freigabe_Heizung)
|
||
{
|
||
Stellgrad_HeizungKessel = MAX(Stellgrad_Heizung * Counter_Heizung_Freigabe, 0.0);
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_HeizungKessel = 0.0;
|
||
}
|
||
|
||
// PWM Heizung Kessel
|
||
HeizungKessel = PWM_Heizung_Kessel.step(Stellgrad_HeizungKessel, 0.25);
|
||
|
||
// Betauungsschutz
|
||
|
||
double Stellgrad_Betauungsschutz_MAX = limit( (90.0 + Stellgrad_Kuehlung_Mittelwert) / (90.0 - 80.0) * 100.0,
|
||
0.0,
|
||
limit((Sollwert_Temperatur - 25.0) / (-20.0 - 25.0) * Betauungsschutz,
|
||
0.0,
|
||
Betauungsschutz));
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Betauungsschutz = 0.0;
|
||
}
|
||
|
||
// Tuerheizung
|
||
Stellgrad_HeizungTuer = limit(Stellgrad_Tuer + Stellgrad_Betauungsschutz / 10.0, 0.0, 100.0);
|
||
|
||
HeizungTuer = PWM_Heizung_Tuer.step(Stellgrad_HeizungTuer, 0.25);
|
||
|
||
// Heizung Kesselrand
|
||
|
||
Stellgrad_HeizungKesselrand = limit(Stellgrad_Tuer * limit(1.0 + Betauungsschutz / 100.0 * 2.0 * (90.0 + Stellgrad_Kuehlung_Mittelwert) / (90.0 - 80.0),
|
||
1.0,
|
||
2.0) + Stellgrad_Betauungsschutz,
|
||
0.0,
|
||
100.0);
|
||
|
||
// Ende - f_PWMDeHumizeValve.Step(...)
|
||
|
||
|
||
// PWM Kesselrand
|
||
// Ende - f_PWMKesselRand.Step(...)
|
||
HeizungKesselrand = PWM_Heizung_Kesselrand.step(Stellgrad_HeizungKesselrand, 0.25);
|
||
// Ende - f_PWMKesselRand.Step(...)
|
||
|
||
{
|
||
// Binder Feuchtemodul
|
||
|
||
// Sperrsignal Feuchtemodul
|
||
|
||
bool Sperrsignal_Feuchte = false;
|
||
|
||
// Gradient Feuchtemodul
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Temperatur_Feuchtemodul_Gradient = 0;
|
||
}
|
||
else
|
||
{
|
||
Temperatur_Feuchtemodul_Gradient += ((Temperatur_Feuchtemodul - Temperatur_Feuchtemodul_alt) * 60.0 * 4.0 -
|
||
Temperatur_Feuchtemodul_Gradient) / (4.0 * 10.0);
|
||
}
|
||
|
||
Sollwert_Temperatur_Feuchtemodul = Sollwert_Temperatur_Feuchtemodul_MIN + Stellgrad_Feuchtemodul_Mittelwert / 100.0 *
|
||
(Sollwert_Temperatur_Feuchtemodul_MAX - Sollwert_Temperatur_Feuchtemodul_MIN);
|
||
|
||
// Offset Stellgrad Feuchtemodul
|
||
|
||
double Temperatur_Feuchtemodul_Standby = Sollwert_Temperatur_Feuchtemodul - (Stellgrad_Entfeuchtung_Mittelwert - 0.0) / (-100.0 - 0.0) * 60.0;
|
||
double Standby_Feuchtemodul = limit((Temperatur_Feuchtemodul_Standby - Temperatur_Feuchtemodul) / 10.0 * 5.0,
|
||
0.0,
|
||
5.0);
|
||
|
||
// Stellgrad Feuchtemodul
|
||
Stellgrad_Feuchtemodul = limit(Stellgrad_Befeuchtung + 2.0 * limit(Stellgrad_Befeuchtung - Stellgrad_Feuchtemodul_PT1,
|
||
-2.0,
|
||
2.0) + Stellgrad_Feuchtemodul_Nachfuellen,
|
||
0.0,
|
||
100.0);
|
||
|
||
// Begrenzung Temperatur Feuchtemodul über Temperatur
|
||
double Stellgrad_Feuchtemodul_MAX_Temperatur = limit((Temperatur_Feuchtemodul_MAX - Temperatur_Feuchtemodul) / 40.0 * 100.0,
|
||
0.0,
|
||
100.0);
|
||
|
||
double Temperatur_Feuchtemodul_Gradient_MAX = 10.0;
|
||
if (Temperatur_Feuchtemodul < 90.0)
|
||
{
|
||
Temperatur_Feuchtemodul_Gradient_MAX = 10.0;
|
||
}
|
||
else
|
||
{
|
||
Temperatur_Feuchtemodul_Gradient_MAX = limit(20.0 - (Temperatur_Feuchtemodul - (Temperatur_Feuchtemodul_MAX - 60.0)) / 60.0 * 20.0 - Stellgrad_Feuchtemodul_MAX / 100.0 * 10.0,
|
||
5.0,
|
||
20.0);
|
||
}
|
||
|
||
double Stellgrad_Feuchtemodul_MAX_adaptiv = 10.0;
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv = 10.0;
|
||
}
|
||
else if (Temperatur_Feuchtemodul < 80.0)
|
||
{
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv = 10.0;
|
||
}
|
||
else if (Stellgrad_Feuchtemodul + 20.0 > Stellgrad_Feuchtemodul_MAX_adaptiv &&
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv < Stellgrad_Feuchtemodul_MAX_Temperatur &&
|
||
Temperatur_Feuchtemodul_Gradient < 2.0 * Temperatur_Feuchtemodul_Gradient_MAX &&
|
||
!Sperrsignal_Feuchte)
|
||
{
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv = limit(Stellgrad_Feuchtemodul_MAX_adaptiv + 20.0 * limit((Temperatur_Feuchtemodul_Gradient_MAX -
|
||
Temperatur_Feuchtemodul_Gradient) / Temperatur_Feuchtemodul_Gradient_MAX,
|
||
-2.0,
|
||
1.0) / (60.0 * 4.0),
|
||
0.0,
|
||
Stellgrad_Feuchtemodul_MAX_Temperatur);
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv = limit(Stellgrad_Feuchtemodul_MAX_adaptiv - 5.0 / (60.0 * 4.0),
|
||
10.0,
|
||
Stellgrad_Feuchtemodul_MAX_Temperatur);
|
||
}
|
||
|
||
// Begrenzung Stellgrad_Feuchtemodul
|
||
|
||
Stellgrad_Feuchtemodul_MAX = MIN(Stellgrad_Feuchtemodul_MAX_Temperatur - 5.0,
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv + Stellgrad_Feuchtemodul_Boost);
|
||
|
||
Stellgrad_Feuchtemodul = MIN(Stellgrad_Feuchtemodul, Stellgrad_Feuchtemodul_MAX);
|
||
|
||
// Stellgrad Feuchtemodul Boost
|
||
|
||
if (!Startup_finished || Temperatur_Feuchtemodul < 80.0)
|
||
{
|
||
Stellgrad_Feuchtemodul_Boost = 0.0;
|
||
}
|
||
else if (Stellgrad_Feuchtemodul < Stellgrad_Feuchtemodul_MAX_adaptiv - 10.0)
|
||
{
|
||
Stellgrad_Feuchtemodul_Boost = MIN(Stellgrad_Feuchtemodul_Boost + 10.0 / 60.0 * sampling_time,
|
||
2.0 * Stellgrad_Feuchtemodul_MAX_Temperatur);
|
||
} else {
|
||
Stellgrad_Feuchtemodul_Boost = MAX(Stellgrad_Feuchtemodul_Boost - (Stellgrad_Feuchtemodul + 10.0 -
|
||
Stellgrad_Feuchtemodul_MAX_adaptiv) / 60.0 * sampling_time,
|
||
0.0);
|
||
}
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Feuchtemodul_PT1 = Stellgrad_Feuchtemodul;
|
||
}
|
||
else if (is_valid(Stellgrad_Feuchtemodul_PT1))
|
||
{
|
||
Stellgrad_Feuchtemodul_PT1 = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Feuchtemodul_PT1 = Stellgrad_Feuchtemodul_PT1 +
|
||
(Stellgrad_Feuchtemodul - Stellgrad_Feuchtemodul_PT1) / (4.0 * 30.0);
|
||
}
|
||
|
||
// Nachfüllen Befeuchtungsmodul
|
||
|
||
double Stellgrad_Nachfuellen_Temperatur = 0.0;
|
||
double Skalierung_Nachfuellen_Temperatur_P_Anteil = 0.0;
|
||
double Skalierung_Nachfuellen_Temperatur_D_Anteil = 0.0;
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Stellgrad_Nachfuellen_Temperatur = 0.0;
|
||
Skalierung_Nachfuellen_Temperatur_D_Anteil = 0.0;
|
||
Skalierung_Nachfuellen_Temperatur_D_Anteil = 0.0;
|
||
Skalierung_Nachfuellen_Temperatur_I_Anteil = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Nachfuellen_Temperatur = limit(MAX(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) * 2.0 +
|
||
MIN(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) * 1.0,
|
||
-20.0,
|
||
50.0);
|
||
Skalierung_Nachfuellen_Temperatur_P_Anteil = limit(MAX(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) / 20.0 +
|
||
MIN(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) / 40.0,
|
||
-0.2,
|
||
5.0);
|
||
Skalierung_Nachfuellen_Temperatur_D_Anteil = limit(Temperatur_Feuchtemodul_Gradient / 10.0, -5.0, 5.0);
|
||
Skalierung_Nachfuellen_Temperatur_I_Anteil = limit(Skalierung_Nachfuellen_Temperatur_I_Anteil + limit(Skalierung_Nachfuellen_Temperatur_P_Anteil +
|
||
Skalierung_Nachfuellen_Temperatur_D_Anteil,
|
||
-0.2,
|
||
25.0) *
|
||
sampling_time / 1200.0,
|
||
0.0,
|
||
5.0);
|
||
}
|
||
double Stellgrad_Nachfuellen = 0.0;
|
||
Stellgrad_Feuchtemodul_Nachfuellen = 0.0;
|
||
|
||
if (Temperatur_Feuchtemodul > Temperatur_Feuchtemodul_MAX && Temperatur_Feuchtemodul_Gradient > 0.0)
|
||
{
|
||
Stellgrad_Nachfuellen = 20.0;
|
||
Stellgrad_Feuchtemodul_Nachfuellen = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Stellgrad_Nachfuellen = limit(((Stellgrad_Feuchtemodul_PT1 - Stellgrad_Feuchtemodul_Nachfuellen) *
|
||
(MAX(Skalierung_Nachfuellen_Temperatur_P_Anteil + Skalierung_Nachfuellen_Temperatur_D_Anteil,
|
||
0.0) + Skalierung_Nachfuellen_Temperatur_I_Anteil) + Stellgrad_Nachfuellen_Temperatur) * 2.0 * 7.9681 / Durchflussmenge_Einlassventil_Feuchtemodul,
|
||
0.0,
|
||
100.0);
|
||
Stellgrad_Feuchtemodul_Nachfuellen = 0.5 * Stellgrad_Nachfuellen * Durchflussmenge_Einlassventil_Feuchtemodul / 60.0 * 4.19 * 75.0 / 600.0;
|
||
}
|
||
|
||
//(* Entleeren des Kessels *)
|
||
bool Entleeren_Kessel = false;
|
||
if (Startup_finished && Temperatur_Feuchtemodul < 70.0) {
|
||
Entleeren_Kessel = Counter_Entleeren_Kessel < 60.0;
|
||
Counter_Entleeren_Kessel += sampling_time;
|
||
} else {
|
||
Counter_Entleeren_Kessel = 0.0;
|
||
Entleeren_Kessel = false;
|
||
}
|
||
|
||
//(* Abschlämmen des Kessels *)
|
||
Abschlaemmintegral = Abschlaemmintegral + 0.1 * Durchflussmenge_Einlassventil_Feuchtemodul / Durchflussmenge_Abschlaemmventil_Feuchtemodul *
|
||
Stellgrad_Nachfuellen / 100.0 * sampling_time;
|
||
|
||
if (Entleeren_Kessel)
|
||
{
|
||
Abschlaemmventil = true;
|
||
Stellgrad_Abschlaemmventil_zyklisch = 100.0;
|
||
}
|
||
else
|
||
{
|
||
Counter_Zyklus_Abschlaemmventil += sampling_time;
|
||
if (Abschlaemmintegral > 0.25 && Temperatur_Feuchtemodul_Gradient < 0.0)
|
||
{
|
||
Abschlaemmventil = true;
|
||
Stellgrad_Abschlaemmventil_zyklisch = 2.5;
|
||
Counter_Zyklus_Abschlaemmventil = 0.0;
|
||
Abschlaemmintegral -= 0.25;
|
||
}
|
||
else
|
||
{
|
||
Abschlaemmventil = false;
|
||
if (Counter_Zyklus_Abschlaemmventil >= 10.0)
|
||
{
|
||
Stellgrad_Abschlaemmventil_zyklisch = 0.0;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Stellgrad_Feuchtemodul = 2.0;
|
||
|
||
// PWM Befeuchtungsmodul
|
||
HeizungFeuchtemodul = PWM_Heizung_Feuchtemodul.step(Stellgrad_Feuchtemodul, 0.25);
|
||
// PWM Nachfüllen
|
||
Nachfuellen = PWM_Nachfuellen.step(Stellgrad_Nachfuellen, 0.25);
|
||
|
||
// Abwassermanagement
|
||
if (!Entleerbehaelter_Unten || !Entleerbehaelter_Oben || Entleeren_Kessel)
|
||
{
|
||
Counter_Nachlauf_Entleeren = 10.0;
|
||
Counter_Pause_Entleeren += sampling_time;
|
||
if (Counter_Pause_Entleeren > 30.0)
|
||
{
|
||
Counter_Pause_Entleeren = 0.0;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
Counter_Nachlauf_Entleeren = MAX(Counter_Nachlauf_Entleeren - sampling_time, 0.0);
|
||
Counter_Pause_Entleeren = 0.0;
|
||
}
|
||
|
||
bool Entleeren_Pause = false;
|
||
Entleeren = Counter_Nachlauf_Entleeren > 0.0;
|
||
Entleeren_Pause = Counter_Pause_Entleeren > 27.0;
|
||
Entleerpumpe = Entleeren && !Entleeren_Pause;
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Zyklus_Entleeren_Mittelwert = 600.0;
|
||
}
|
||
else if (Entleeren && !Entleeren_alt)
|
||
{
|
||
Zyklus_Entleeren_Mittelwert = limit(Zyklus_Entleeren_Mittelwert + (Counter_Zyklus_Entleeren - Zyklus_Entleeren_Mittelwert) / 10.0,
|
||
10.0,
|
||
3600.0);
|
||
Counter_Zyklus_Entleeren = 0.0;
|
||
}
|
||
else
|
||
{
|
||
Counter_Zyklus_Entleeren += sampling_time;
|
||
}
|
||
|
||
if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0)
|
||
{
|
||
Counter_Kuehlung_Freigabe = 0.0;
|
||
} else
|
||
{
|
||
if (Stellgrad_Kuehlung < 0.0 || Stellgrad_Heizung < 2.0 || Counter_Tuer_geschlossen < 300.0)
|
||
{
|
||
Counter_Kuehlung_Freigabe = MIN(Counter_Kuehlung_Freigabe + sampling_time / 10.0, 1.0);
|
||
}
|
||
else
|
||
{
|
||
Counter_Kuehlung_Freigabe = MAX(Counter_Kuehlung_Freigabe - sampling_time / 300.0, 0.0);
|
||
}
|
||
}
|
||
Freigabe_Kuehlung = Counter_Kuehlung_Freigabe >= 1.0 || (Freigabe_Kuehlung && Counter_Kuehlung_Freigabe > 0.0);
|
||
// * Freigabe Kühlung *)
|
||
|
||
// (* Freigabe Entfeuchtung *)
|
||
if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0)
|
||
{
|
||
Counter_Entfeuchtung_Freigabe = 0.0;
|
||
}
|
||
else
|
||
{
|
||
if (Stellgrad_Entfeuchtung < 0.0 || Stellgrad_Befeuchtung < 2.0 || Counter_Tuer_geschlossen < 300.0) {
|
||
Counter_Entfeuchtung_Freigabe = MIN(Counter_Entfeuchtung_Freigabe + sampling_time / 10.0, 10.0);
|
||
}
|
||
else
|
||
{
|
||
Counter_Entfeuchtung_Freigabe = MAX(Counter_Entfeuchtung_Freigabe - sampling_time / 300.0, 0.0);
|
||
}
|
||
}
|
||
Freigabe_Entfeuchtung = Counter_Entfeuchtung_Freigabe >= 1.0 || (Freigabe_Entfeuchtung && Counter_Entfeuchtung_Freigabe > 0.0);
|
||
|
||
// (* Freigabe Heizung *)
|
||
if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0)
|
||
{
|
||
Counter_Heizung_Freigabe = 0.0;
|
||
}
|
||
else
|
||
{
|
||
if (Stellgrad_Heizung < 0.0 || Stellgrad_Kuehlung > -2.0 || Counter_Tuer_geschlossen < 300.0)
|
||
{
|
||
Counter_Heizung_Freigabe = MIN(Counter_Heizung_Freigabe + sampling_time / 10.0, 10.0);
|
||
}
|
||
else
|
||
{
|
||
Counter_Heizung_Freigabe = MAX(Counter_Heizung_Freigabe - sampling_time / 300.0, 0.0);
|
||
}
|
||
}
|
||
Freigabe_Heizung = Counter_Heizung_Freigabe >= 1.0 || (Freigabe_Heizung && Counter_Heizung_Freigabe > 0.0);
|
||
// (* Freigabe Befeuchtung *)
|
||
if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0)
|
||
{
|
||
Counter_Befeuchtung_Freigabe = 0.0;
|
||
}
|
||
else
|
||
{
|
||
if (Stellgrad_Befeuchtung < 0.0 || Stellgrad_Entfeuchtung > -2.0 || Counter_Tuer_geschlossen < 300.0)
|
||
{
|
||
Counter_Befeuchtung_Freigabe = MIN(Counter_Befeuchtung_Freigabe + sampling_time / 10.0, 10.0);
|
||
}
|
||
else
|
||
{
|
||
Counter_Befeuchtung_Freigabe = MAX(Counter_Befeuchtung_Freigabe - sampling_time / 300.0, 0.0);
|
||
}
|
||
}
|
||
Freigabe_Befeuchtung = Counter_Befeuchtung_Freigabe >= 1.0 || (Freigabe_Befeuchtung && Counter_Befeuchtung_Freigabe > 0.0);
|
||
|
||
// Verdichterabscaltung
|
||
|
||
if (!Startup_finished)
|
||
{
|
||
Drehzahl_Verdichter_adaptiv = Drehzahl_Verdichter_MAX;
|
||
}
|
||
else if (Temperatursprung)
|
||
{
|
||
Drehzahl_Verdichter_adaptiv = MAX(Drehzahl_Verdichter_Kuehlung, Drehzahl_Verdichter_Entfeuchtung);
|
||
}
|
||
else if (is_valid(Stellgrad_Kuehlung))
|
||
{
|
||
Drehzahl_Verdichter_adaptiv = limit(Drehzahl_Verdichter_adaptiv + (-Stellgrad_Kuehlung - 25.0) / 100.0 * (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN) / (4.0 * 600.0),
|
||
Drehzahl_Verdichter_MIN,
|
||
Drehzahl_Verdichter_MAX);
|
||
}
|
||
|
||
Drehzahl_Verdichter_Kuehlung = Drehzahl_Verdichter_MIN + (MAX(-Stellgrad_Kuehlung_Mittelwert, -Stellgrad_Kuehlung) - 30.0) / (90.0 - 30.0) * (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN);
|
||
Drehzahl_Verdichter_Entfeuchtung = Drehzahl_Verdichter_MIN + 0.5 * (MAX(-Stellgrad_Entfeuchtung_Mittelwert, -Stellgrad_Entfeuchtung) -
|
||
50.0) / (90.0 - 50.0) * (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN);
|
||
|
||
if (Verdichter)
|
||
{
|
||
Drehzahl_Verdichter = limit(MAX(Drehzahl_Verdichter_Kuehlung, MAX(Drehzahl_Verdichter_Entfeuchtung, Drehzahl_Verdichter_adaptiv)),
|
||
Drehzahl_Verdichter_MIN,
|
||
Drehzahl_Verdichter_MAX);
|
||
}
|
||
else
|
||
{
|
||
Drehzahl_Verdichter = 1000.0;
|
||
}
|
||
|
||
Stellgrad_Verdichter = Drehzahl_Verdichter / Drehzahl_Verdichter_MAX * 100.0 * (160.0 / 200.0);
|
||
/*
|
||
(* -------------------- *)
|
||
(* Verflüssigerregelung *)
|
||
(* -------------------- *) */
|
||
|
||
Verfluessiger = Verfluessiger && ((Drehzahl_Verdichter_adaptiv - Drehzahl_Verdichter_MIN) / ((Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN) < 0.30) &&
|
||
(-Stellgrad_Kuehlung_Mittelwert < 30.0) &&
|
||
(-Stellgrad_Entfeuchtung_Mittelwert < 60.0) || ((Drehzahl_Verdichter_adaptiv - Drehzahl_Verdichter_MIN) / (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN) < 0.20) &&
|
||
(-Stellgrad_Kuehlung_Mittelwert < 20.0) &&
|
||
-Stellgrad_Entfeuchtung_Mittelwert < 50.0);
|
||
|
||
}// Ende Feuchtemodul
|
||
|
||
// ----------------------------------------
|
||
// Werte die auf Veränderung geprüft werden
|
||
// ----------------------------------------
|
||
Sammelalarm_quittiert_alt = Sammelalarm_quittiert;
|
||
Istwert_Temperatur_alt = Istwert_Temperatur;
|
||
Regelabweichung_Temperatur_alt = Regelabweichung_Temperatur;
|
||
Sollwert_Temperatur_alt = Sollwert_Temperatur;
|
||
Istwert_Feuchte_alt = Istwert_Feuchte;
|
||
Regelabweichung_Feuchte_alt_alt = Regelabweichung_Feuchte_alt;
|
||
Regelabweichung_Feuchte_alt = Regelabweichung_Feuchte;
|
||
Sollwert_Feuchte_alt = Sollwert_Feuchte;
|
||
Durchzug_alt = Durchzug;
|
||
Regelabweichung_Tuer_alt = Regelabweichung_Tuer;
|
||
HeizungFeuchtemodul_alt = HeizungFeuchtemodul;
|
||
Regelabweichung_Befeuchtung_alt_alt = Regelabweichung_Befeuchtung_alt;
|
||
Regelabweichung_Entfeuchtung_alt = Regelabweichung_Entfeuchtung;
|
||
|
||
|
||
|
||
// ----------------
|
||
// Rückgabewerte
|
||
// ----------------
|
||
// F_Outputs out{};
|
||
|
||
binOut.bool_out01 = (std::abs((Sollwert_Temperatur - Istwert_Temperatur)) > Temperaturband); // du nutzt Temperaturband-Alarm
|
||
// separat; hier nur Beispiel
|
||
binOut.bool_out02 = (std::abs((Sollwert_Feuchte - Istwert_Feuchte)) > Feuchteband) &&
|
||
(!Befeuchtung_aus) && (!Entfeuchtung_aus);
|
||
binOut.bool_out03 = Befeuchtung_aus || Entfeuchtung_aus;
|
||
binOut.bool_out07 = (!Status_Uebertemperatur) &&
|
||
(!(std::abs(Istwert_Ueberwachungsregler - Istwert_Temperatur) > 20.0));
|
||
alarmOut.Startup = Startup_finished;
|
||
|
||
binOut.bool_out09 = HeizungKessel;
|
||
binOut.bool_out11 = HeizungTuer;
|
||
binOut.bool_out12 = HeizungKesselrand;
|
||
binOut.bool_out13 = Verfluessiger;
|
||
binOut.bool_out14 = Nachfuellen;
|
||
binOut.bool_out16 = Entleerpumpe;
|
||
binOut.bool_out17 = HeizungFeuchtemodul;
|
||
binOut.bool_out20 = Abschlaemmventil;
|
||
binOut.bool_out18 = Kuehlventil;
|
||
binOut.bool_out19 = Entfeuchtungsventil;
|
||
binOut.bool_out21 = Verdichter;
|
||
binOut.bool_out23 = !Sammelalarm_quittiert;
|
||
|
||
analogOut.real_out01 = Istwert_Temperatur;
|
||
analogOut.real_out02 = Istwert_Temperatur;
|
||
analogOut.real_out04 = Istwert_Temperatur;
|
||
analogOut.real_out05 = limit(Istwert_Feuchte, 0.0, 100.0);
|
||
analogOut.real_out06 = limit(Istwert_Feuchte, 0.0, 100.0);
|
||
analogOut.real_out07 = Sollwert_Feuchte;
|
||
analogOut.real_out08 = limit(Istwert_Feuchte, 0.0, 100.0);
|
||
analogOut.real_out09 = Stellgrad_HeizungKessel;
|
||
analogOut.real_out10 = Stellgrad_Pumpe;
|
||
analogOut.real_out11 = Stellgrad_HeizungTuer;
|
||
analogOut.real_out12 = Stellgrad_HeizungKesselrand;
|
||
analogOut.real_out13 = Stellgrad_Feuchtemodul;
|
||
analogOut.real_out14 = Stellgrad_Abschlaemmventil_zyklisch;
|
||
analogOut.real_out16 = Temperatur_Feuchtemodul;
|
||
analogOut.Stellgrad_Feuchtemodul = Stellgrad_Feuchtemodul;
|
||
analogOut.real_out18 = Stellgrad_Kuehlventil;
|
||
analogOut.real_out19 = Stellgrad_Entfeuchtungsventil;
|
||
analogOut.real_out20 = Stellgrad_Luefter;
|
||
analogOut.real_out21 = Stellgrad_Verdichter;
|
||
analogOut.real_out25 = Schaltwert_Uebertemperatur;
|
||
analogOut.real_out26 = Schaltwert_Untertemperatur;
|
||
analogOut.Stellgrad_Heizung = Stellgrad_Heizung;
|
||
analogOut.Stellgrad_Kuehlung = Stellgrad_Kuehlung;
|
||
analogOut.Stellgrad_Befeuchtung = Stellgrad_Befeuchtung;
|
||
analogOut.Stellgrad_Entfeuchtung = Stellgrad_Entfeuchtung;
|
||
analogOut.Counter_Tuer = Counter_Tuer_offen;
|
||
|
||
// alarms (wie ST)
|
||
alarmOut.alarm_01 = Bandalarm_Temperatur;
|
||
alarmOut.alarm_02 = Bandalarm_Feuchte;
|
||
alarmOut.alarm_03 = Tueralarm;
|
||
alarmOut.alarm_04 = false;
|
||
alarmOut.alarm_05 = false;
|
||
alarmOut.alarm_06 = Alarm_Wasser_Befeuchtungsmodul && !Befeuchtung_aus;
|
||
alarmOut.alarm_07 = Alarm_Abwasser_Befeuchtungsmodul;
|
||
alarmOut.alarm_08 = (Alarm_Heizung_Befeuchtungsmodul || Alarm_PT100_Befeuchtungsmodul) && !Befeuchtung_aus;
|
||
|
||
// alarm_09..alarm_15 sind im ST mit Selbsthaltung/Quittierung etc.:
|
||
alarmOut.alarm_09 = (((Istwert_Temperatur_Tuer < -50.0) || (Istwert_Temperatur_Tuer > 120.0)) &&
|
||
Startup_finished) ||(alarm_09 && Sammelalarm_quittiert);
|
||
|
||
alarmOut.alarm_10 = (std::abs(Istwert_Ueberwachungsregler - Istwert_Temperatur) > 20.0) ||
|
||
((((Istwert_Ueberwachungsregler < -50.0) ||
|
||
(Istwert_Ueberwachungsregler > 120.0) && Startup_finished))) ||
|
||
(alarm_10 && Sammelalarm_quittiert);
|
||
|
||
alarmOut.alarm_11 = Status_Uebertemperatur || StatusQuittierung_Uebertemperatur;
|
||
alarmOut.alarm_12 = Status_Untertemperatur || StatusQuittierung_Untertemperatur;
|
||
|
||
alarmOut.alarm_13 = (((Istwert_Temperatur_Verdampferausgang < -50.0) || (Istwert_Temperatur_Verdampferausgang > 120.0)) && Startup_finished) ||
|
||
(alarm_13 && Sammelalarm_quittiert);
|
||
|
||
alarmOut.alarm_14 = (Counter_Wasserkanister_leer > 10.0 && Startup_finished) || (alarm_14 && Sammelalarm_quittiert);
|
||
|
||
alarmOut.alarm_15 = ((analogInput.real_in11 > Sollwert_Feuchte_Max && !Befeuchtung_aus) ||
|
||
(analogInput.real_in11 < Sollwert_Feuchte_Min && !Entfeuchtung_aus)) ||
|
||
(alarm_15 && Sammelalarm_quittiert);
|
||
|
||
// Selbsthaltung der Alarm-Bits (wie ST-OR alarm_x ...)
|
||
alarm_09 = alarmOut.alarm_09;
|
||
alarm_10 = alarmOut.alarm_10;
|
||
alarm_13 = alarmOut.alarm_13;
|
||
alarm_14 = alarmOut.alarm_14;
|
||
alarm_15 = alarmOut.alarm_15;
|
||
|
||
// return out;
|
||
}
|
||
|
||
private:
|
||
// ===== ST: VAR CONSTANT =====
|
||
static constexpr double sampling_time = 0.25;
|
||
// Zeitkonstanten etc.
|
||
static constexpr double Tau_Heizung_Tv = 10.0;
|
||
static constexpr double Regler_Kuehlung_Tv = 5.0;
|
||
static constexpr double Tau_Kuehlung_Tv = 30.0;
|
||
double Theta_I_Kuehlung = 1.0;
|
||
|
||
// Reglerparameter
|
||
double Regler_Befeuchtung_Tv = 30.0;
|
||
double Regler_Befeuchtung_Tn = 100.0;
|
||
double Regler_Befeuchtung_Tz = 1200.0;
|
||
double Tau_Befeuchtung_Tv = 10.0;
|
||
double Tau_Befeuchtung_Tz = 5.0;
|
||
double Regler_Entfeuchtung_Tv = 5.0;
|
||
double Regler_Entfeuchtung_Tn = 200.0;
|
||
double Tau_Entfeuchtung_Tv = 60.0;
|
||
double Theta_I_Entfeuchtung = 0.1;
|
||
double C_Entfeuchtung = 200.0;
|
||
double U_Entfeuchtung = 0.4;
|
||
double P_Entfeuchtung = 500.0;
|
||
|
||
double Regler_Tuer_Tn = 700.0;
|
||
double Regler_Tuer_Tv = 60.0;
|
||
double Tau_Tuer_Tv = 60.0;
|
||
|
||
double Drehzahl_Verdichter_MIN = 1800.0;
|
||
double Drehzahl_Verdichter_MAX = 4500.0;
|
||
double Drehzahl_Verdichter_adaptiv = 0.0;
|
||
|
||
const double Temperatur_Feuchtemodul_MAX = 200.0;
|
||
double Sollwert_Temperatur_Feuchtemodul_MIN = 110.0;
|
||
double Sollwert_Temperatur_Feuchtemodul_MAX = 130.0;
|
||
|
||
double Durchflussmenge_Einlassventil_Feuchtemodul = 400.0;
|
||
double Durchflussmenge_Abschlaemmventil_Feuchtemodul = 1500.0;
|
||
|
||
// Faktoren
|
||
static constexpr double F_Xp_Heizung = 3.8;
|
||
static constexpr double F_Xp_Kuehlung = 33.6;
|
||
|
||
static constexpr double F_Xp_Befeuchtung_BINDER = 131.0;
|
||
static constexpr double F_Xp_Entfeuchtung = 100.0;
|
||
static constexpr double F_Xp_Tuer = 10.0;
|
||
|
||
|
||
/////////////////////////////////////////
|
||
/// VAR, VAR RETAIN
|
||
double Abschlaemmintegral = 0.0;
|
||
|
||
|
||
|
||
|
||
//######################################
|
||
double Regelabweichung_Tuer_alt{};
|
||
|
||
double Regler_Heizung_Xp{};
|
||
double Regler_Kuehlung_Xp{};
|
||
double Regler_Befeuchtung_Xp{};
|
||
double Regler_Entfeuchtung_Xp{};
|
||
double Regler_Tuer_Xp{};
|
||
|
||
|
||
|
||
|
||
static constexpr std::array<std::array<double, 13>, 4> Kennfeld_Ueberhitzung{
|
||
{// 0: Temperatur
|
||
std::array<double, 13>{-20.0, -10.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0,
|
||
60.0, 70.0, 80.0, 90.0, 100.0},
|
||
// 1: Skalierung Min
|
||
std::array<double, 13>{0.01, 0.02, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7,
|
||
0.8, 0.9, 1.0, 1.0},
|
||
// 2: Skalierung Max
|
||
std::array<double, 13>{0.01, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
|
||
1.0, 1.0, 1.0},
|
||
// 3: Sollwert Überhitzung
|
||
std::array<double, 13>{-6.0, -8.0, -10.0, -8.0, -6.0, -8.0, -10.0, -12.0,
|
||
-16.0, -20.0, -24.0, -28.0, -32.0}}};
|
||
static constexpr std::array<std::array<double, 13>, 4> Kennfeld_Entfeuchtung{
|
||
{// 0: Temperatur
|
||
std::array<double, 13>{-20.0, -10.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0,
|
||
60.0, 70.0, 80.0, 90.0, 100.0},
|
||
// 1: Skalierung Entfeuchtung
|
||
std::array<double, 13>{0.08, 0.08, 0.08, 0.10, 0.12, 0.14, 0.16, 0.18,
|
||
0.20, 0.22, 0.24, 0.26, 0.28},
|
||
// 2: Abtauzyklus Pause
|
||
std::array<double, 13>{120.0, 120.0, 120.0, 120.0, 120.0, 90.0, 60.0,
|
||
60.0, 60.0, 0.0, 0.0, 0.0, 0.0},
|
||
// 3: Abtauzyklus Dauer
|
||
std::array<double, 13>{60.0, 60.0, 60.0, 30.0, 20.0, 10.0, 8.0, 4.0, 2.0,
|
||
0.0, 0.0, 0.0, 0.0}}};
|
||
|
||
// Kennfelder (nur die, die oben genutzt werden; den Rest kannst du genauso
|
||
// hinzufügen)
|
||
static constexpr std::array<double, 13> Kennfeld_Regler_Heizung_Xp{
|
||
0.2, 0.5, 0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
|
||
static constexpr std::array<double, 13> Kennfeld_Regler_Kuehlung_Xp{
|
||
0.1, 0.1, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.0};
|
||
static constexpr std::array<std::array<double, 9>, 9>
|
||
Kennfeld_Regler_Befeuchtung_Xp{
|
||
{std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02},
|
||
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
|
||
0.02}}};
|
||
static constexpr std::array<std::array<double, 9>, 9>
|
||
Kennfeld_Regler_Entfeuchtung_Xp{
|
||
{std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20},
|
||
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}}};
|
||
|
||
static constexpr std::array<std::array<double, 11>, 3>
|
||
Kennfeld_Sollwert_Feuchte_Limit{
|
||
{std::array<double, 11>{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
|
||
std::array<double, 11>{80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80},
|
||
std::array<double, 11>{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
|
||
|
||
QList<QList<double>> Kennfeld_Sollwert_Feuchte_Limit_List{
|
||
{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
|
||
{80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80},
|
||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||
|
||
|
||
|
||
// ===== ST: VAR (Zustände / Merker) =====
|
||
// (ich halte hier nur die, die im übersetzten Teil genutzt werden; den Rest
|
||
// kannst du 1:1 ergänzen)
|
||
double Istwert_Temperatur{};
|
||
double Istwert_Temperatur_alt{};
|
||
double Sollwert_Temperatur{};
|
||
double Sollwert_Temperatur_alt{};
|
||
double Sollwert_Gegenbefeuchten = 0.0;
|
||
double Regelabweichung_Befeuchtung_alt = 0.0;
|
||
double P_Anteil_Befeuchtung = 0.0;
|
||
double Counter_Entfeuchtung_Freigabe = 0.0;
|
||
double Counter_Heizung_Freigabe = 0.0;
|
||
double Counter_Befeuchtung_Freigabe = 0.0;
|
||
double Counter_Zyklus_Entleeren = 0.0;
|
||
double Drehzahl_Verdichter_Kuehlung = 0.0;
|
||
double Drehzahl_Verdichter_Entfeuchtung = 0.0;
|
||
double Drehzahl_Verdichter = 0.0;
|
||
|
||
bool Freigabe_Entfeuchtung = false;
|
||
bool Freigabe_Heizung = false;
|
||
bool Freigabe_Befeuchtung = false;
|
||
bool Abtauzyklus = false;
|
||
|
||
/*PWM(double zyklus_min, double zyklus_max, double initial_zykluszeit = -1.0)
|
||
noexcept : Zyklus(0.0), Ausgabe(0.0), Zykluszeit((initial_zykluszeit > 0.0) ?
|
||
initial_zykluszeit : zyklus_max), Zyklus_MIN(zyklus_min),
|
||
Zyklus_MAX(zyklus_max)
|
||
{}
|
||
|
||
bool step(double Stellgrad,double sampling_time,double Zyklus_MIN,double
|
||
Zyklus_MAX){*/
|
||
PWM PWM_Heizung_Kessel = {10.0, 600.0, 0.0};
|
||
PWM PWM_Heizung_Tuer = {10.0, 600.0, 0.0};
|
||
PWM PWM_Nachfuellen = {10.0, 600.0, 0.0};
|
||
PWM PWM_Heizung_Kesselrand = {10.0, 600.0, 0.0};
|
||
PWM PWM_Heizung_Feuchtemodul = {10.0, 600.0, 0.0};
|
||
PWM PWM_Kuehlventil = {10.0, 600.0, 0.0};
|
||
PWM PWM_Entfeuchtungsventil = {10.0, 600.0, 0.0};
|
||
|
||
double Istwert_Ueberwachungsregler{};
|
||
int32_t Modus_Ueberwachungsregler{};
|
||
double Offset_Ueberwachungsregler{};
|
||
double Klasse_Ueberwachungsregler{};
|
||
bool Wasserkanister_leer{};
|
||
|
||
double Regler_Entfeuchtung_MAX = 0.0;
|
||
double Regler_Entfeuchtung_MIN = 0.0;
|
||
double Regler_Entfeuchtung_I_Anteil_MAX = 0.0;
|
||
double Regler_Entfeuchtung_I_Anteil_MIN = 0.0;
|
||
bool Freigabe_Kuehlung = false;
|
||
|
||
double Zyklus_Entleeren_Mittelwert = 600.0;
|
||
|
||
double Grenzwert_Uebertemperatur{};
|
||
double Schaltwert_Uebertemperatur{};
|
||
bool Status_Uebertemperatur{};
|
||
std::uint32_t Counter_Status_Uebertemperatur{};
|
||
bool StatusQuittierung_Uebertemperatur{};
|
||
|
||
double Grenzwert_Untertemperatur{};
|
||
double Schaltwert_Untertemperatur{};
|
||
bool Status_Untertemperatur{};
|
||
std::uint32_t Counter_Status_Untertemperatur{};
|
||
bool StatusQuittierung_Untertemperatur{};
|
||
|
||
double Istwert_Feuchte{};
|
||
double Istwert_Feuchte_alt{};
|
||
double Sollwert_Feuchte{};
|
||
double Sollwert_Feuchte_alt{};
|
||
double Counter_Entleeren_Kessel{};
|
||
|
||
bool Regelung_AUS{};
|
||
double Counter_Regelung_AUS{};
|
||
bool Steuerkontakt_Standby{};
|
||
bool Sammelalarm{};
|
||
bool Sammelalarm_quittiert{};
|
||
bool Sammelalarm_quittiert_alt{};
|
||
|
||
|
||
|
||
|
||
// Feuchte absolut
|
||
double p_H2Omax_Sollwert{};
|
||
double p_H2Omax_Istwert{};
|
||
double Taupunkt_Istwert{};
|
||
double Sollwert_Feuchte_Absolut{};
|
||
double Sollwert_Temperatur_Feuchtemodul{};
|
||
double Counter_Kuehlung_Freigabe = 0.0;
|
||
|
||
// Tür
|
||
bool Tuer_offen{};
|
||
double Counter_Tuer_offen{};
|
||
double Counter_Tuer_geschlossen{};
|
||
double Istwert_Temperatur_Tuer{};
|
||
double Regelabweichung_Tuer{};
|
||
|
||
double Standby_Feuchtemodul = 0.0;
|
||
double Regelabweichung_Befeuchtung_alt_alt = 0.0;
|
||
double Regelabweichung_Entfeuchtung_alt = 0.0;
|
||
|
||
|
||
// Startup / reset
|
||
std::uint32_t Counter_reset_flag{};
|
||
bool Startup_finished{};
|
||
|
||
// Feuchte limit
|
||
std::uint16_t Index_Sollwert_Feuchte_Limit{};
|
||
double Interpolation_Sollwert_Feuchte_Limit{};
|
||
double Sollwert_Feuchte_Min{};
|
||
double Sollwert_Feuchte_Max{};
|
||
|
||
// Abschaltung Feuchte-Regler
|
||
bool Sollwert_Feuchte_aktiv{};
|
||
bool Steuerkontakt_Befeuchtung_aus{};
|
||
bool Steuerkontakt_Entfeuchtung_aus{};
|
||
bool Befeuchtung_aus{};
|
||
bool Entfeuchtung_aus{};
|
||
double Sollwert_Gegenheizen = 2.0;
|
||
// Parameter Indizes
|
||
std::uint16_t Index_Feuchte{};
|
||
std::uint16_t Index_Temperatur{};
|
||
std::uint16_t Index_Temperatur_ohne_Feuchte{};
|
||
|
||
|
||
|
||
// Regelkern Temperatur
|
||
double Sollwert_Temperatur_MIN{};
|
||
double Sollwert_Temperatur_MAX{};
|
||
|
||
double Regelabweichung_Temperatur{};
|
||
double Regelabweichung_Temperatur_alt{};
|
||
double Regelabweichung_Temperatur_Mittelwert{};
|
||
double Standardregelabweichung_Temperatur{};
|
||
double Regelabweichung_Temperatur_Gradient{};
|
||
double Standardgradient_Regelabweichung_Temperatur{};
|
||
double Zykluszeit_Regelabweichung_Temperatur{};
|
||
double Amplitude_Regelabweichung_Temperatur{};
|
||
double Zykluszeit_Regelabweichung_Heizung{};
|
||
double Zykluszeit_Regelabweichung_Kuehlung{};
|
||
double Regelabweichung_Kuehlung_Gradient{};
|
||
double Regelabweichung_Kuehlung_alt{};
|
||
double Faktor_Kuehlung{};
|
||
double Faktor_Gegenheizen_Band{};
|
||
double I_Anteil_Kuehlung{};
|
||
double D_Anteil_Kuehlung{};
|
||
double Regelabweichung_Befeuchtung_Gradient{};
|
||
double I_Anteil_Befeuchtung{};
|
||
double Istwert_Temperatur_Verdampferausgang_PT1 = 0.0;
|
||
double D_Anteil_Befeuchtung{};
|
||
bool Temperatursprung{};
|
||
double Counter_Temperatursprung{};
|
||
double Faktor_Entfeuchtung{};
|
||
double Faktor_Gegenbefeuchten_Band = 5.0;
|
||
double I_Anteil_Entfeuchtung = 0.0;
|
||
double D_Anteil_Entfeuchtung = 0.0;
|
||
double I_Anteil_Tuer = 0.0;
|
||
double P_Anteil_Tuer;
|
||
double Regler_Heizung_MIN{};
|
||
double Regler_Heizung_MAX{};
|
||
double Regler_Heizung_I_Anteil_MIN{};
|
||
double Regler_Heizung_I_Anteil_MAX{};
|
||
double P_Anteil_Heizung{};
|
||
double I_Anteil_Heizung{};
|
||
double D_Anteil_Heizung{};
|
||
double Stellgrad_Heizung{};
|
||
double Stellgrad_Heizung_Mittelwert{};
|
||
double Regelabweichung_Entfeuchtung_Gradient = 0.0;
|
||
double D_Anteil_Tuer = 0.0;
|
||
double Counter_Verdichter_aus = 0.0;
|
||
double Counter_Freigabe_Abtauzyklus = 0.0;
|
||
double Counter_Abtauzyklus;
|
||
double Stellgrad_Feuchtemodul_MAX{};
|
||
double Skalierung_Nachfuellen_Temperatur_I_Anteil{};
|
||
double Counter_Zyklus_Abschlaemmventil = 0.0;
|
||
const double Regler_Kuehlung_Tn = 200.0;
|
||
|
||
double Stellgrad_Feuchtemodul_Boost{};
|
||
|
||
// Feuchte - nur Platzhalter (weil spätere Ausdrücke referenzieren)
|
||
double Regelabweichung_Feuchte{};
|
||
double Regelabweichung_Feuchte_alt{};
|
||
double Regelabweichung_Feuchte_alt_alt{};
|
||
double Regelabweichung_Feuchte_Mittelwert{};
|
||
double Standardregelabweichung_Feuchte{};
|
||
double Regelabweichung_Feuchte_Gradient{};
|
||
double Standardgradient_Regelabweichung_Feuchte{};
|
||
double Zykluszeit_Regelabweichung_Feuchte{};
|
||
double Amplitude_Regelabweichung_Feuchte{};
|
||
bool Feuchtesprung{};
|
||
double Counter_Feuchtesprung = 0.0;
|
||
double Offset_Regelabweichung_Befeuchtung{};
|
||
double Offset_Regelabweichung_Entfeuchtung{};
|
||
double Stellgrad_Kuehlung{};
|
||
double Stellgrad_Kuehlung_Mittelwert{};
|
||
double Stellgrad_Befeuchtung{};
|
||
double Stellgrad_Befeuchtung_Mittelwert{};
|
||
double Stellgrad_Befeuchtung_Standby{};
|
||
double Stellgrad_Entfeuchtung{};
|
||
double Stellgrad_Entfeuchtung_Mittelwert{};
|
||
double Z_Anteil_Befeuchtung{};
|
||
|
||
// Aktoren/Signale (Defaults, bis restliche Logik ergänzt ist)
|
||
bool HeizungKessel{};
|
||
double Stellgrad_HeizungKessel{};
|
||
bool HeizungTuer{};
|
||
double Stellgrad_HeizungTuer{};
|
||
bool HeizungKesselrand{};
|
||
double Stellgrad_HeizungKesselrand{};
|
||
bool Verfluessiger{};
|
||
bool Nachfuellen{};
|
||
bool Entleerpumpe{};
|
||
bool HeizungFeuchtemodul{};
|
||
bool HeizungFeuchtemodul_alt{};
|
||
bool Abschlaemmventil{};
|
||
double Stellgrad_Abschlaemmventil_zyklisch{};
|
||
bool Kuehlventil{};
|
||
double Stellgrad_Kuehlventil{};
|
||
bool Entfeuchtungsventil{};
|
||
double Stellgrad_Entfeuchtungsventil{};
|
||
bool Verdichter{};
|
||
double Stellgrad_Verdichter{};
|
||
double Stellgrad_Pumpe{};
|
||
double Stellgrad_Luefter{};
|
||
double Stellgrad_Betauungsschutz{};
|
||
double Temperatur_Feuchtemodul_Gradient = 0.0;
|
||
double Stellgrad_Feuchtemodul_MAX_adaptiv = 0.0;
|
||
double Counter_Nachlauf_Entleeren = 0.0;
|
||
double Counter_Pause_Entleeren = 0.0;
|
||
|
||
// “Durchzug” (wird später in Überhitzungslogik gesetzt)
|
||
bool Durchzug{};
|
||
bool Durchzug_alt{};
|
||
double Counter_Durchzug{};
|
||
|
||
// Befeuchtungsmodul Zustände (Platzhalter, damit “Werte die auf Veränderung
|
||
// geprüft werden” passt)
|
||
double Temperatur_Feuchtemodul{};
|
||
double Temperatur_Feuchtemodul_alt{};
|
||
double Stellgrad_Feuchtemodul{};
|
||
double Stellgrad_Feuchtemodul_Mittelwert{};
|
||
double Stellgrad_Feuchtemodul_PT1{};
|
||
double Stellgrad_Feuchtemodul_Nachfuellen{};
|
||
bool Entleeren{};
|
||
bool Entleeren_alt{};
|
||
bool Entleerbehaelter_Oben{};
|
||
bool Entleerbehaelter_Unten{};
|
||
double Counter_Wasserkanister_leer{};
|
||
|
||
|
||
double Regler_Entfeuchten_I_Anteil_MIN = 0.0;
|
||
|
||
|
||
// Alarmbits mit Selbsthaltung
|
||
bool alarm_09{};
|
||
bool alarm_10{};
|
||
bool alarm_13{};
|
||
bool alarm_14{};
|
||
bool alarm_15{};
|
||
bool Alarm_Wasser_Befeuchtungsmodul{};
|
||
bool Alarm_Abwasser_Befeuchtungsmodul{};
|
||
bool Alarm_PT100_Befeuchtungsmodul{};
|
||
bool Alarm_Heizung_Befeuchtungsmodul{};
|
||
bool Bandalarm_Temperatur{};
|
||
bool Bandalarm_Feuchte{};
|
||
bool Tueralarm{};
|
||
};
|
||
|
||
// namespace UTILITY_FUNCTIONS
|
||
|
||
// double PT100_ResistanceToTemperature_Linear(double R)
|
||
// {
|
||
// constexpr double R0 = 100.0;
|
||
// constexpr double alpha = 0.00385; // IEC-Näherung
|
||
|
||
// return (R - R0) / (R0 * alpha);
|
||
// }
|
||
|
||
class PT1 {
|
||
public:
|
||
PT1() = default;
|
||
void initialize(double fs, double t_cutoff) {
|
||
fs_ = fs;
|
||
ts_ = 1 / fs_;
|
||
double f_cutoff = 1. / t_cutoff;
|
||
tau_ = 1 / (2 * PI_CONST * f_cutoff);
|
||
lambda_ = 2 * tau_ / ts_;
|
||
b0_ = k_ / (1. + lambda_);
|
||
b1_ = k_ / (1. + lambda_);
|
||
a0_ = (1. - lambda_) / (1. + lambda_);
|
||
};
|
||
|
||
double step(double x) {
|
||
|
||
double y = b0_ * x + s1_;
|
||
// s1 = b1*x - a1*y
|
||
s1_ = b1_ * x - a0_ * y;
|
||
return y;
|
||
};
|
||
|
||
private:
|
||
double s1_ = 0.;
|
||
double fs_ = 1.;
|
||
double ts_ = 1.;
|
||
double tau_ = 1.;
|
||
double a0_ = 0.;
|
||
double b0_ = 0.;
|
||
double b1_ = 0.;
|
||
double k_ = 1.;
|
||
double lambda_ = 1.;
|
||
};
|
||
|
||
#ifdef BUILD_TARGET_SOM
|
||
namespace appengine::state {
|
||
class IStateVariable;
|
||
}
|
||
#endif
|
||
|
||
#ifdef BUILD_TARGET_SOM
|
||
class Controller : public ControllerBase {
|
||
public:
|
||
bool initialize(const char *configFilePath,
|
||
appengine::IAppLogic *appLogic) override;
|
||
void step() override;
|
||
void terminate() override;
|
||
|
||
private:
|
||
appengine::IAppLogic *appLogic_{nullptr};
|
||
|
||
// Beispiel: du wirst für diese ST-Logik sehr viele StateVars mappen;
|
||
// hier nur exemplarisch:
|
||
std::shared_ptr<appengine::state::IStateVariable> tempVariable_;
|
||
std::shared_ptr<appengine::state::IStateVariable> tempSetPointVariable_;
|
||
|
||
// TODO: bool_inXX / real_inXX / bool_outXX / real_outXX / alarm_XX als
|
||
// StateVariables holen (oder je nach AppEngine: arrays/IO mapping)
|
||
|
||
ClimateAlgorithm algo_{};
|
||
PT1 FILTERED_TEMP{};
|
||
PT1 FILTER_TUER{};
|
||
// Eingänge
|
||
std::shared_ptr<appengine::state::IStateVariable> const_duty_cycle_;
|
||
std::shared_ptr<appengine::state::IStateVariable> const_freq_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Oben_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Unten_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Fuellstand_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Tuer_Variable_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Verdampferausgang_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Befeuchtungsmodul_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Verdichter_on_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Startup_;
|
||
std::shared_ptr<appengine::state::IStateVariable> CounterTuer_;
|
||
|
||
// ausgänge
|
||
std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Bef_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> MV_Kuehlung_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Abschlaemmen_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Entleerpumpe_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Kesselrand_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable>
|
||
Freigabe_Verfluessigerluefter_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Innenraum_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Tuer_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Uebertemperatur_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> MV_Entfeuchtung_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> MV_Druckluft_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable>
|
||
Ansteuerung_Wassereinlass_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable>
|
||
Ansteuerung_Verdichter_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Verdichter_Duty_Config;
|
||
std::shared_ptr<appengine::state::IStateVariable> Luefter_Innenraum_Config_;
|
||
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Heizung;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Kuehlung;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Befeuchtung;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Entfeuchtung;
|
||
// Regelgrößen
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Temperatur_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Temperatur_Variable_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Feuchte_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Feuchte_Variable_;
|
||
|
||
// std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
|
||
};
|
||
|
||
extern "C" BINDER_SIMULINK_API_EXPORT ControllerBase *create();
|
||
|
||
#else
|
||
class Controller {
|
||
public:
|
||
Controller(){
|
||
inputs=nullptr;
|
||
};
|
||
~Controller(){};
|
||
bool initialize(const char *configFilePath);
|
||
bool initialize( QList<Input_t>* inputs);
|
||
bool initialize( DataModel* instance);
|
||
void step(void);
|
||
void terminate();
|
||
void PID_Temperature(void);
|
||
|
||
private:
|
||
|
||
DataModel* model;
|
||
QList<Input_t>* inputs;
|
||
|
||
void stepSOM(void);
|
||
void stepDesk(void);
|
||
|
||
|
||
#if 0
|
||
appengine::IAppLogic *appLogic_{nullptr};
|
||
|
||
// Beispiel: du wirst für diese ST-Logik sehr viele StateVars mappen;
|
||
// hier nur exemplarisch:
|
||
std::shared_ptr<appengine::state::IStateVariable> tempVariable_;
|
||
std::shared_ptr<appengine::state::IStateVariable> tempSetPointVariable_;
|
||
|
||
// TODO: bool_inXX / real_inXX / bool_outXX / real_outXX / alarm_XX als StateVariables holen
|
||
// (oder je nach AppEngine: arrays/IO mapping)
|
||
|
||
ClimateAlgorithm algo_{};
|
||
PT1 FILTERED_TEMP{} ;
|
||
PT1 FILTER_TUER{};
|
||
// Eingänge
|
||
std::shared_ptr<appengine::state::IStateVariable> const_duty_cycle_;
|
||
std::shared_ptr<appengine::state::IStateVariable> const_freq_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Oben_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Unten_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Fuellstand_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Tuer_Variable_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Verdampferausgang_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Befeuchtungsmodul_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Verdichter_on_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Startup_;
|
||
std::shared_ptr<appengine::state::IStateVariable> CounterTuer_;
|
||
|
||
// ausgänge
|
||
std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Bef_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> MV_Kuehlung_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Abschlaemmen_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Entleerpumpe_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Kesselrand_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Freigabe_Verfluessigerluefter_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Innenraum_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Heizung_Tuer_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Uebertemperatur_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> MV_Entfeuchtung_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> MV_Druckluft_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Ansteuerung_Wassereinlass_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Ansteuerung_Verdichter_Config_;
|
||
std::shared_ptr<appengine::state::IStateVariable> Verdichter_Duty_Config;
|
||
std::shared_ptr<appengine::state::IStateVariable> Luefter_Innenraum_Config_;
|
||
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Heizung;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Kuehlung;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Befeuchtung;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Entfeuchtung;
|
||
// Regelgrößen
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Temperatur_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Temperatur_Variable_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Feuchte_;
|
||
std::shared_ptr<appengine::state::IStateVariable> SV_Feuchte_Variable_;
|
||
|
||
//std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
|
||
#endif
|
||
};
|
||
|
||
#endif
|
||
|