/* 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 #include #include #include #include // std:max //UJ: not yet needed, future use // #include // #include // #include #include #include "datamodel.h" #include "util.h" using namespace std; 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(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(10 * 4)); StatusQuittierung_Uebertemperatur = (Status_Uebertemperatur && Counter_Status_Uebertemperatur < static_cast(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(10 * 4)); StatusQuittierung_Untertemperatur = Status_Untertemperatur && ( Counter_Status_Untertemperatur < static_cast(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( 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( 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(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 */ 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 */ double Regelabweichung_Entfeuchtung = Regelabweichung_Feuchte; if (!Startup_finished || Temperatursprung || (Counter_Temperatursprung > -600.0 && Faktor_Gegenheizen_Band == 10.0)) // 111 { 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 Kühlen */ constexpr double Faktor_Entfeuchtung_Kuehlung = 0.0; double 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); // UJ: Wertezuweisung in ST-Codenicht identifizierbar // Ist '0.0' zulässig ? double P_Anteil_Kuehlung = 0.0; /* 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); } // P-Anteil Kühlung if (!Startup_finished) { P_Anteil_Kuehlung = 0.0; } else { P_Anteil_Kuehlung = 100.0 / Regler_Kuehlung_Xp * Faktor_Kuehlung * Regelabweichung_Kuehlung; } /* 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 */ 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 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); } /* ------------------ *) (* PID Regler Feuchte *) (* ------------------ */ 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 */ 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 Befeuchtung 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); } /* Anpassung 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); } // UJ - nächste Zeile steht nicht im ST-Code // 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); } /* Berechnung Stellgrad Befeuchtung Mittelwert */ 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 Entfeuchten */ Sollwert_Gegenbefeuchten = 6.0 - 4.0 * (-Stellgrad_Entfeuchtung_Mittelwert / 100.0); double Offset_Entfeuchtung = 0.0 * Stellgrad_Kuehlung_Mittelwert; /* (* Begrenzung Stellgrad und I-Anteil Entfeuchtung bei Türöffnung *) IF Counter_Tuer_geschlossen < 180.0 OR Counter_Tuer_offen > 0.0 THEN 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); END_IF; */ /* 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 */ // UJ - Im ST-Code sthet das weiter oben ! 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 Tuer *) (* --------------- */ 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; } /* 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; /* P-Anteil */ 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 */ 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 */ /* --------------------------------- */ /* Grundskalierung Überhitzung über Kennfeld */ 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); /* -------------------- */ /* Überhitzungsregelung */ /* -------------------- */ /* Temperatur Verdampferausgang PT1 */ 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 { Counter_Durchzug = MAX((Counter_Durchzug - sampling_time),static_cast(-10)); } 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; } /* Puls Pause Generierung Kühlung */ /* UJ: Aus ST-Code (Original) * Todo - Konvertieren 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; */ /* ------------------------- */ /* 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, 4> Kennfeld_Ueberhitzung{ {// 0: Temperatur std::array{-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{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{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{-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, 4> Kennfeld_Entfeuchtung{ {// 0: Temperatur std::array{-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{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{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{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 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 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, 9> Kennfeld_Regler_Befeuchtung_Xp{ {std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}, std::array{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03, 0.02}}}; static constexpr std::array, 9> Kennfeld_Regler_Entfeuchtung_Xp{ {std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}, std::array{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25, 0.20}}}; static constexpr std::array, 3> Kennfeld_Sollwert_Feuchte_Limit{ {std::array{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, std::array{80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80}, std::array{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}; QList> 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 tempVariable_; std::shared_ptr 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 const_duty_cycle_; std::shared_ptr const_freq_; std::shared_ptr Wasserstand_Oben_Config_; std::shared_ptr Wasserstand_Unten_Config_; std::shared_ptr Fuellstand_Config_; std::shared_ptr SV_Tuer_Variable_; std::shared_ptr SV_Verdampferausgang_; std::shared_ptr SV_Befeuchtungsmodul_; std::shared_ptr SV_Verdichter_on_; std::shared_ptr Startup_; std::shared_ptr CounterTuer_; // ausgänge std::vector subscriptions_{}; std::shared_ptr Heizung_Bef_Config_; std::shared_ptr MV_Kuehlung_Config_; std::shared_ptr Abschlaemmen_Config_; std::shared_ptr Entleerpumpe_Config_; std::shared_ptr Heizung_Kesselrand_Config_; std::shared_ptr Freigabe_Verfluessigerluefter_Config_; std::shared_ptr Heizung_Innenraum_Config_; std::shared_ptr Heizung_Tuer_Config_; std::shared_ptr Uebertemperatur_Config_; std::shared_ptr MV_Entfeuchtung_Config_; std::shared_ptr MV_Druckluft_Config_; std::shared_ptr Ansteuerung_Wassereinlass_Config_; std::shared_ptr Ansteuerung_Verdichter_Config_; std::shared_ptr Verdichter_Duty_Config; std::shared_ptr Luefter_Innenraum_Config_; std::shared_ptr SV_Stellgrad_Heizung; std::shared_ptr SV_Stellgrad_Kuehlung; std::shared_ptr SV_Stellgrad_Befeuchtung; std::shared_ptr SV_Stellgrad_Entfeuchtung; // Regelgrößen std::shared_ptr SV_Sollwert_Temperatur_; std::shared_ptr SV_Temperatur_Variable_; std::shared_ptr SV_Sollwert_Feuchte_; std::shared_ptr SV_Feuchte_Variable_; // std::vector 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* inputs); bool initialize( DataModel* instance); void step(void); void terminate(); void PID_Temperature(void); private: DataModel* model; QList* 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 tempVariable_; std::shared_ptr 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 const_duty_cycle_; std::shared_ptr const_freq_; std::shared_ptr Wasserstand_Oben_Config_; std::shared_ptr Wasserstand_Unten_Config_; std::shared_ptr Fuellstand_Config_; std::shared_ptr SV_Tuer_Variable_; std::shared_ptr SV_Verdampferausgang_; std::shared_ptr SV_Befeuchtungsmodul_; std::shared_ptr SV_Verdichter_on_; std::shared_ptr Startup_; std::shared_ptr CounterTuer_; // ausgänge std::vector subscriptions_{}; std::shared_ptr Heizung_Bef_Config_; std::shared_ptr MV_Kuehlung_Config_; std::shared_ptr Abschlaemmen_Config_; std::shared_ptr Entleerpumpe_Config_; std::shared_ptr Heizung_Kesselrand_Config_; std::shared_ptr Freigabe_Verfluessigerluefter_Config_; std::shared_ptr Heizung_Innenraum_Config_; std::shared_ptr Heizung_Tuer_Config_; std::shared_ptr Uebertemperatur_Config_; std::shared_ptr MV_Entfeuchtung_Config_; std::shared_ptr MV_Druckluft_Config_; std::shared_ptr Ansteuerung_Wassereinlass_Config_; std::shared_ptr Ansteuerung_Verdichter_Config_; std::shared_ptr Verdichter_Duty_Config; std::shared_ptr Luefter_Innenraum_Config_; std::shared_ptr SV_Stellgrad_Heizung; std::shared_ptr SV_Stellgrad_Kuehlung; std::shared_ptr SV_Stellgrad_Befeuchtung; std::shared_ptr SV_Stellgrad_Entfeuchtung; // Regelgrößen std::shared_ptr SV_Sollwert_Temperatur_; std::shared_ptr SV_Temperatur_Variable_; std::shared_ptr SV_Sollwert_Feuchte_; std::shared_ptr SV_Feuchte_Variable_; //std::vector subscriptions_{}; #endif }; #endif