#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 #include #include const double PI_CONST = 3.14159265358979323846; #define MAX std::max #define MIN std::min namespace UTILITY_FUNCTIONS { inline double limit(double x, double lo, double hi) { return (x < lo) ? lo : (x > hi) ? hi : x; } inline double max3(double a, double b, double c) { return std::max(a, std::max(b, c)); } inline double min3(double a, double b, double c) { return std::min(a, std::min(b, c)); } inline bool is_valid(double x) { return std::isfinite(x); } // ST: REAL_TO_INT(x) i.d.R. trunc Richtung 0. Bei Siemens oft ROUND? Du nutzt // häufig +0.5. inline int real_to_int(double x) { return static_cast(x); } // Platzhalter für GET_VALUE_* (kommt vermutlich aus Parameter-/Recipe-System) inline std::int32_t GET_VALUE_DINT(int /*a*/, int /*b*/, int /*c*/, int /*d*/) { // TODO: an dein Parameter-System anbinden return 0; } inline double GET_VALUE_REAL(int /*a*/, int /*b*/, int /*c*/, int /*d*/) { // TODO: an dein Parameter-System anbinden return 0.0; } } // namespace UTILITY_FUNCTIONS // ------------------------- // 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; // --------------------------- // 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; bool Wasserkanister_leer = false; 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 needed double Sollwert_Luefter = analogInput.Sollwert_Luefter; Istwert_Temperatur_Tuer = analogInput.Istwert_Temperatur_Tuer; double Istwert_Temperatur_Verdampferausgang = analogInput.Istwert_Temperatur_Verdampferausgang; Temperatur_Feuchtemodul = analogInput.Temperatur_Feuchtemodul; double Betauungsschutz = 50.0; double Feuchteband = 10; double Temperaturband = 5; bool reset_flag = binInput.reset_flag; // 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)); // ------------------------------------------ // Verzögerte Abschaltung Regelung bei Türöffnung // ------------------------------------------ // 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); // ------------------- // 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; } Sollwert_Temperatur_MIN = -5.0; Sollwert_Temperatur_MAX = 100.0; // ------------------------------------------ // Sollwert Feuchte (Limit-Kennfeld) // ------------------------------------------ // f_HumiditySetValueByVector(...) 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 // ------------------ // f_SuperVisor /* Modus_Ueberwachungsregler = static_cast(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); 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 // ------------------------ // f_SwitchParameterSet(...) 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)); 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)); 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)); 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]; 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; // --------------------- // PID Regler Temperatur // --------------------- // F_PID PID_Temperature(...) Regelabweichung_Temperatur = Sollwert_Temperatur - Istwert_Temperatur; // Zykluszeit Regelabweichung Temperatur if (!Startup_finished || !is_valid(Standardregelabweichung_Temperatur) || !is_valid(Standardgradient_Regelabweichung_Temperatur) || Standardgradient_Regelabweichung_Temperatur <= 0.0) { Zykluszeit_Regelabweichung_Temperatur = 600.0; } else { Zykluszeit_Regelabweichung_Temperatur = limit(2.0 * 3.1415 * Standardregelabweichung_Temperatur / Standardgradient_Regelabweichung_Temperatur * 60.0, 120.0, 1200.0); } Zykluszeit_Regelabweichung_Heizung = std::min(Zykluszeit_Regelabweichung_Temperatur, 300.0); Zykluszeit_Regelabweichung_Kuehlung = std::max(Zykluszeit_Regelabweichung_Temperatur, 600.0); Amplitude_Regelabweichung_Temperatur = 1.4142 * Standardregelabweichung_Temperatur; // 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); } // 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); } Temperatursprung = (Counter_Temperatursprung > 0.0) || (Temperatursprung && Counter_Temperatursprung > -60.0); // Anti-wind-up Heizung (dynamisches Clamping) // ------ F_PID_Temperatuer.AntiWindUpHeater(...) if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0)) { Regler_Heizung_MIN = 0.0; Regler_Heizung_I_Anteil_MIN = 0.0; Regler_Heizung_MAX = 100.0; 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; if (Temperatursprung) { Regler_Heizung_I_Anteil_MAX = limit(100.0 - P_Anteil_Heizung, Regler_Heizung_I_Anteil_MIN, Regler_Heizung_MAX); } else { Regler_Heizung_I_Anteil_MAX = 100.0; } } //---------------------- // Anpassung Xp Heizung // // ------------F_PID_Temperatuer.AdaptXp(...) if (Regelabweichung_Temperatur > Amplitude_Regelabweichung_Temperatur && Regelabweichung_Temperatur_Mittelwert > 0.05 && !Temperatursprung) { Regler_Heizung_Xp /= 2.0; } // 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; } 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); //-----------// ------------F_PID_Temperatuer.AdaptXp(...)--------------------------------------------------- // 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; } 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); } 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); } if (!Startup_finished || !is_valid(Stellgrad_Heizung_Mittelwert)) { Stellgrad_Heizung_Mittelwert = 0.0; } else if (Temperatursprung) { Stellgrad_Heizung_Mittelwert = Stellgrad_Heizung; } else if (is_valid(Stellgrad_Heizung)) { Stellgrad_Heizung_Mittelwert = Stellgrad_Heizung_Mittelwert + (Stellgrad_Heizung - Stellgrad_Heizung_Mittelwert) / (Zykluszeit_Regelabweichung_Temperatur / sampling_time); } // ------------ F_PID_Temperature.step(...) !!!!! todo uj umbenennen in Heizung !!!!!!!!!!!!!!!!!!! // ---------------------------------------------------- // Ab hier: Kühlung + Feuchte-PIDs + Tür-PID + Aktorlogik // ---------------------------------------------------- // => in gleicher Art übersetzen (Muster ist identisch). // // Für dieses Snippet: wir übernehmen für die Outputs zumindest die Werte, // die schon berechnet sind, und lassen Stellgrade der restlichen Aktoren, // falls nicht berechnet, auf gültigen Default stehen. // Regelabweichung Kühlung // F_ PID PID_Cooling() double Regelabweichung_Kuehlung = Regelabweichung_Temperatur; // Gradient Regelabweichgun Kuehlung if (!Startup_finished) { Regelabweichung_Kuehlung_Gradient = 0.0; } else { Regelabweichung_Kuehlung_Gradient = limit((Regelabweichung_Kuehlung - Regelabweichung_Kuehlung_alt) * 60.0 / sampling_time - Regelabweichung_Kuehlung_Gradient, -4.0, 2.0); } // Faktor Kuehlung if (!Startup_finished || Temperatursprung) { Faktor_Kuehlung = 5.0; } else if (Regelabweichung_Kuehlung < -0.1) { Faktor_Kuehlung = std::min(Faktor_Kuehlung + sampling_time, 5.0); } else { Faktor_Kuehlung = std::max(Faktor_Kuehlung - sampling_time / 60.0, 0.2); } // --------------------------- Gegenheizen Band !!! Überwacher !!!!! double Regelabweichung_Entfeuchtung = Regelabweichung_Feuchte; if (!Startup_finished || Temperatursprung || (Counter_Temperatursprung > -600.0 && Faktor_Gegenheizen_Band == 10.0)) { Faktor_Gegenheizen_Band = 10.0; } else if (Stellgrad_Heizung_Mittelwert - Sollwert_Gegenheizen < -1.0) { if (Regelabweichung_Entfeuchtung > 0.5) { Faktor_Gegenheizen_Band = std::max(Faktor_Gegenheizen_Band - sampling_time / 10.0, 0.0); } else { Faktor_Gegenheizen_Band = std::min(Faktor_Gegenheizen_Band + sampling_time / 60.0, 10.0); } } else if (Stellgrad_Heizung_Mittelwert - Sollwert_Gegenheizen > 1.0 && Stellgrad_Kuehlung_Mittelwert < -5.0) { if (Regelabweichung_Entfeuchtung < -0.5) { Faktor_Gegenheizen_Band = std::max(Faktor_Gegenheizen_Band - sampling_time / 10.0, 0.0); } else { Faktor_Gegenheizen_Band = std::min(Faktor_Gegenheizen_Band + sampling_time / 600.0, 5.0); } } else { Faktor_Gegenheizen_Band = std::max(Faktor_Gegenheizen_Band - sampling_time / 60.0, 0.1); } // --------------------------- Gegenheizen Band // -----------------------Sollwert Gegenheizen für I-Anteilverschiebung double Faktor_Entfeuchtung_Kuehlung = 0.0; double Offset_Kuehlung = Faktor_Entfeuchtung_Kuehlung; Offset_Kuehlung = Faktor_Entfeuchtung_Kuehlung * Stellgrad_Entfeuchtung_Mittelwert * std::max((50.0 - Stellgrad_Heizung_Mittelwert) / (50 - 0.0), 0.0) * (8.0 - Stellgrad_Befeuchtung_Standby) / (8.0 - 2.0); //------------------------------------------------------------ // P-Anteil Kühlung // f_PID_Cooling.SetP double P_Anteil_Kuehlung = 0.0; if (!Startup_finished) { P_Anteil_Kuehlung = 0.0; } else { P_Anteil_Kuehlung = 100.0 / Regler_Kuehlung_Xp * Faktor_Kuehlung * Regelabweichung_Kuehlung; } // Begrenzung I-Anteil Kühlung bei Türöffnung // f_PID_Cooling.Limit_I_PostDoorOpening(...) double Regler_Kuehlung_MAX = 0; double Regler_Kuehlung_MIN = 0; double Regler_Kuehlung_I_Anteil_MAX = 0; double Regler_Kuehlung_I_Anteil_MIN = 0; if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0)) { Regler_Kuehlung_MAX = I_Anteil_Kuehlung; Regler_Kuehlung_MIN = -100.0; Regler_Kuehlung_I_Anteil_MAX = I_Anteil_Kuehlung; Regler_Kuehlung_I_Anteil_MIN = limit( -100.0 - P_Anteil_Kuehlung, Regler_Kuehlung_MIN, Regler_Kuehlung_MAX); } else { Regler_Kuehlung_MAX = 0.0; Regler_Kuehlung_MIN = -100.0; Regler_Kuehlung_I_Anteil_MAX = 0.1 / Regler_Kuehlung_Xp * 100.0; Regler_Kuehlung_I_Anteil_MIN = limit( -100.0 - P_Anteil_Kuehlung + Regelabweichung_Kuehlung_Gradient / 0.5 * 100.0, Regler_Kuehlung_MIN, Regler_Kuehlung_MAX); } // f_PID_Cooling.Step(...) // I Anteil Kühlung if (!Startup_finished) { I_Anteil_Kuehlung = 0.0; } else if (Counter_Tuer_geschlossen > 60.0) { I_Anteil_Kuehlung = limit(I_Anteil_Kuehlung + 100.0 / Regler_Kuehlung_Tn * sampling_time * (Regelabweichung_Kuehlung + (Stellgrad_Heizung - Sollwert_Gegenheizen) / 100.0 * Regler_Heizung_Xp * Theta_I_Kuehlung * Faktor_Gegenheizen_Band), Regler_Kuehlung_I_Anteil_MIN, Regler_Kuehlung_I_Anteil_MAX); } // D-Anteil Kühlung if (!Startup_finished) { D_Anteil_Kuehlung = 0.0; } else if (Counter_Tuer_geschlossen > 0.0) { D_Anteil_Kuehlung += (100.0 / Regler_Kuehlung_Xp * Regler_Kuehlung_Tv * (Regelabweichung_Kuehlung - Regelabweichung_Kuehlung_alt) / sampling_time - D_Anteil_Kuehlung) / (Tau_Kuehlung_Tv / sampling_time); } // Berechnung Stellgrad Kühlung // f_ if (Counter_Tuer_offen > 60.0 || !Startup_finished) { Stellgrad_Kuehlung = 0.0; } else { Stellgrad_Kuehlung = limit(P_Anteil_Kuehlung + I_Anteil_Kuehlung + D_Anteil_Kuehlung + Offset_Kuehlung, Regler_Kuehlung_MIN, Regler_Kuehlung_MAX); } // Berechnung Stellgrad Mittelwert if (!Startup_finished) { Stellgrad_Kuehlung_Mittelwert = 0.0; } else { Stellgrad_Kuehlung_Mittelwert = limit(Stellgrad_Kuehlung_Mittelwert + (Stellgrad_Kuehlung - Stellgrad_Kuehlung_Mittelwert) / (600.0 / sampling_time), Stellgrad_Kuehlung - 0.5 * 100.0 * Regler_Kuehlung_Xp, Stellgrad_Kuehlung + 0.5 * 100.0 / Regler_Kuehlung_Xp); } // ------------------- F_ PID PID_Cooling() // PID Regler Feuchte // f_PID_Humidiy Regelabweichung_Feuchte = Sollwert_Feuchte_Absolut - Istwert_Feuchte; // Berechnung Regelabweichung Feuchte Mittelwert if (!Startup_finished) { Regelabweichung_Feuchte_Mittelwert = 0.0; } else { Regelabweichung_Feuchte_Mittelwert = limit( Regelabweichung_Feuchte_Mittelwert + (Regelabweichung_Feuchte - Regelabweichung_Feuchte_Mittelwert) / (60.0 / sampling_time), Regelabweichung_Feuchte - 10.0, Regelabweichung_Feuchte + 10.0); } // Feuchtesprung // f_PID_Hunidity.HandleJump(...) if (!Startup_finished) { Counter_Feuchtesprung = 0.0; } else if (Sollwert_Feuchte != Sollwert_Feuchte_alt && std::abs(Regelabweichung_Feuchte) > 2.0) { Counter_Feuchtesprung = std::max(Counter_Feuchtesprung + sampling_time, 0.0); } else if (std::abs(Regelabweichung_Feuchte) < 2.0 || std::abs(Regelabweichung_Feuchte_Mittelwert) < 2.0) { Counter_Feuchtesprung = std::min(Counter_Feuchtesprung - sampling_time, 0.0); } else if (std::abs(Regelabweichung_Feuchte_Mittelwert) > 5.0) { Counter_Feuchtesprung = std::max(Counter_Feuchtesprung + sampling_time, -120.0); } Feuchtesprung = (Counter_Feuchtesprung > 0.0 || (Feuchtesprung && Counter_Feuchtesprung > -120.0)); // Regelabweichung Befeuchtung double Regelabweichung_Befeuchtung = Regelabweichung_Feuchte; // Gradient regelabweichung Feuchte if (!Startup_finished) { Regelabweichung_Befeuchtung_Gradient = 0.0; } else { Regelabweichung_Befeuchtung_Gradient = limit( Regelabweichung_Befeuchtung_Gradient + ((Regelabweichung_Befeuchtung - Regelabweichung_Befeuchtung_alt) * 60.0 / sampling_time - Regelabweichung_Befeuchtung_Gradient) / 60.0 * sampling_time, -20.0, 5.0); } // Begrenzung I-Anteil bei Türöffnung double Regler_Befeuchtung_MIN = 0.0; double Regler_Befeuchtung_MAX = 0.0; double Regler_Befeuchtung_I_Anteil_MIN = 0.0; double Regler_Befeuchtung_I_Anteil_MAX = 0.0; if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0)) { Regler_Befeuchtung_MIN = std::max(Stellgrad_Befeuchtung_Standby - 2.0, Standby_Feuchtemodul); Regler_Befeuchtung_MAX = std::min(100.0, Stellgrad_Feuchtemodul_MAX); Regler_Befeuchtung_I_Anteil_MIN = 0.0; Regler_Befeuchtung_I_Anteil_MAX = limit(100.0 - P_Anteil_Befeuchtung, Regler_Befeuchtung_I_Anteil_MIN, Stellgrad_Befeuchtung_Mittelwert); } else { if (Feuchtesprung) { Regler_Befeuchtung_MIN = std::max(Stellgrad_Befeuchtung_Standby - 2.0, Standby_Feuchtemodul); } else { Regler_Befeuchtung_MIN = std::max(std::min(Stellgrad_Befeuchtung_Standby + 0.25 * P_Anteil_Befeuchtung + D_Anteil_Befeuchtung + Z_Anteil_Befeuchtung, Stellgrad_Befeuchtung_Standby + 2.0), std::max(Stellgrad_Befeuchtung_Standby - 1.0, Standby_Feuchtemodul)); } Regler_Befeuchtung_MAX = std::min(100.0, Stellgrad_Feuchtemodul_MAX); Regler_Befeuchtung_I_Anteil_MIN = 0.0; Regler_Befeuchtung_I_Anteil_MAX = limit(100.0, Regler_Befeuchtung_I_Anteil_MIN, Stellgrad_Befeuchtung_Mittelwert); } // Anteil P-Anteil Befeuchtung bei Feuchtesprung und Türöffnung if (Counter_Tuer_geschlossen < 180.0 && Feuchtesprung) { Regler_Befeuchtung_Xp = Regler_Befeuchtung_Xp * 2.0; } else if (Counter_Tuer_geschlossen > 300.0 && Feuchtesprung) { Regler_Befeuchtung_Xp = Regler_Befeuchtung_Xp / 2.0; } else { Regler_Befeuchtung_Xp = Regler_Befeuchtung_Xp * (1.0 + Stellgrad_Entfeuchtung_Mittelwert / -100.0); } // P-Anteil Befeuchtung if (!Startup_finished) { P_Anteil_Befeuchtung = 0.0; } else { P_Anteil_Befeuchtung = 100.0 / Regler_Befeuchtung_Xp * Regelabweichung_Befeuchtung; } // I-Anteil Befeuchtung if (!Startup_finished) { I_Anteil_Befeuchtung = 0.0; } else if (Counter_Tuer_geschlossen > 60.0) { I_Anteil_Befeuchtung = limit( I_Anteil_Befeuchtung + 100.0 / Regler_Befeuchtung_Xp / Regler_Befeuchtung_Tn * sampling_time * Regelabweichung_Befeuchtung, Regler_Befeuchtung_I_Anteil_MIN, Regler_Befeuchtung_I_Anteil_MAX); } // D-Anteil Befeuchtung if (!Startup_finished) { D_Anteil_Befeuchtung = 0.0; } else if (Counter_Tuer_geschlossen) { D_Anteil_Befeuchtung += (100.0 / Regler_Befeuchtung_Xp * Regler_Befeuchtung_Tv * (Regelabweichung_Befeuchtung - Regelabweichung_Befeuchtung_alt) / sampling_time - D_Anteil_Befeuchtung) / (Tau_Befeuchtung_Tv / sampling_time); } // Z-Anteil Befeuchtung if (!Startup_finished || Feuchtesprung) { Z_Anteil_Befeuchtung = 0.0; } else if (Counter_Tuer_geschlossen > 0.0) { Z_Anteil_Befeuchtung += (100.0 / Regler_Befeuchtung_Xp * Regler_Befeuchtung_Tz * ((Regelabweichung_Befeuchtung - Regelabweichung_Befeuchtung_alt) - (Regelabweichung_Befeuchtung_alt - Regelabweichung_Befeuchtung_alt_alt)) / sampling_time - Z_Anteil_Befeuchtung) / (Tau_Befeuchtung_Tz / sampling_time); } // Regler_Befeuchtung_MAX = 10.0; // Berechnung Stellgrad Befeuchtung if (Counter_Tuer_offen > 60.0 || !Startup_finished) { Stellgrad_Befeuchtung = 0.0; } else { Stellgrad_Befeuchtung = limit(P_Anteil_Befeuchtung + I_Anteil_Befeuchtung + D_Anteil_Befeuchtung + Z_Anteil_Befeuchtung, Regler_Befeuchtung_MIN, Regler_Befeuchtung_MAX); } // Berechnung Stellgrad befeuchtung Mittelwert if (!Startup_finished) { Stellgrad_Befeuchtung_Mittelwert = 0.0; } else { Stellgrad_Befeuchtung_Mittelwert = limit(Stellgrad_Befeuchtung_Mittelwert + (Stellgrad_Befeuchtung - Stellgrad_Befeuchtung_Mittelwert) / (600.0 / sampling_time), Stellgrad_Befeuchtung - 5.0 * 100.0 / Regler_Befeuchtung_Xp, Stellgrad_Befeuchtung + 5.0 * 100.0 / Regler_Befeuchtung_Xp); } if (!Startup_finished) { Stellgrad_Befeuchtung_Standby = 4.0; } else if (!(Feuchtesprung && Counter_Feuchtesprung < 300.0)) { Stellgrad_Befeuchtung_Standby = limit(Stellgrad_Befeuchtung_Standby + (Stellgrad_Befeuchtung - Stellgrad_Befeuchtung_Standby) / (600.0 / sampling_time), 2.0, 8.0); } // Regelabweichung Entfeuchtung Regelabweichung_Entfeuchtung = Regelabweichung_Feuchte; // Gradient Regelabweichung Entfeuchtung if (!Startup_finished) { Regelabweichung_Entfeuchtung_Gradient = 0.0; } else { Regelabweichung_Entfeuchtung_Gradient = limit(Regelabweichung_Entfeuchtung_Gradient + ((Regelabweichung_Entfeuchtung - Regelabweichung_Entfeuchtung_alt) * 60.0 / sampling_time - Regelabweichung_Entfeuchtung_Gradient) / 60.0 * sampling_time, -20.0, 5.0); } // Faktor Entfeuchtung if (!Startup_finished) { Faktor_Entfeuchtung = 5.0; } else if (Regelabweichung_Entfeuchtung < -0.5) { Faktor_Entfeuchtung = std::min(Faktor_Entfeuchtung + sampling_time / 60.0, 5.0); } else { Faktor_Entfeuchtung = std::max(Faktor_Entfeuchtung - sampling_time, 0.2); } // Gegenbefeuchten Band if (!Startup_finished || Feuchtesprung || (Counter_Feuchtesprung > -600.0 && Faktor_Gegenbefeuchten_Band == 5.0)) { Faktor_Gegenbefeuchten_Band = 5.0; } else if (Stellgrad_Befeuchtung_Mittelwert - Sollwert_Gegenbefeuchten < -1.0) { if (Regelabweichung_Kuehlung > 0.05) { Faktor_Gegenbefeuchten_Band = std::max(Faktor_Gegenbefeuchten_Band - sampling_time / 10.0, 0.0); } else { Faktor_Gegenbefeuchten_Band = std::min(Faktor_Gegenbefeuchten_Band + sampling_time / 60.0, 5.0); } } else if (Stellgrad_Befeuchtung_Mittelwert - Sollwert_Gegenbefeuchten > 1.0 && Stellgrad_Entfeuchtung_Mittelwert < -10.0) { if (Regelabweichung_Kuehlung < -0.05) { Faktor_Gegenbefeuchten_Band = std::max(Faktor_Gegenbefeuchten_Band - sampling_time / 10.0, 0.0); } else { Faktor_Gegenbefeuchten_Band = std::min(Faktor_Gegenbefeuchten_Band + sampling_time / 600.0, 2.0); } } else { Faktor_Gegenbefeuchten_Band = std::max(Faktor_Gegenbefeuchten_Band - sampling_time / 60.0, 0.2); } // Sollwert Gegenbefeuchten für I-Anteilverschiebung Sollwert_Gegenbefeuchten = 6.0 - 4.0 * (-Stellgrad_Entfeuchtung_Mittelwert / 100.0); double Offset_Entfeuchtung = 0.0 * Stellgrad_Kuehlung_Mittelwert; //(* P-Anteil Entfeuchtung *) double P_Anteil_Entfeuchtung = 0.0; if (!Startup_finished) { P_Anteil_Entfeuchtung = 0.0; } else { P_Anteil_Entfeuchtung = 100.0 / Regler_Entfeuchtung_Xp * Faktor_Entfeuchtung * Regelabweichung_Entfeuchtung; } // I-Anteil Entfeuchtung if (!Startup_finished) { I_Anteil_Entfeuchtung = 0.0; } else if (Counter_Tuer_geschlossen > 60.0) { I_Anteil_Entfeuchtung = limit( I_Anteil_Entfeuchtung + 100.0 / Regler_Entfeuchtung_Xp / Regler_Entfeuchtung_Tn * sampling_time * (Regelabweichung_Entfeuchtung + (Stellgrad_Befeuchtung - Sollwert_Gegenbefeuchten) / 100.0 * Regler_Befeuchtung_Xp * Theta_I_Entfeuchtung * Faktor_Gegenbefeuchten_Band), Regler_Entfeuchtung_I_Anteil_MIN, Regler_Entfeuchtung_I_Anteil_MAX); } // D-Anteil Entfeuchtung if (!Startup_finished) { D_Anteil_Entfeuchtung = 0.0; } else if (Counter_Tuer_geschlossen > 0.0) { D_Anteil_Entfeuchtung = D_Anteil_Entfeuchtung + (100.0 / Regler_Entfeuchtung_Xp * Regler_Entfeuchtung_Tv * (Regelabweichung_Entfeuchtung - Regelabweichung_Entfeuchtung_alt) / sampling_time - D_Anteil_Entfeuchtung) / (Tau_Entfeuchtung_Tv / sampling_time); } // Begrenzung Stellgrad und I-Anteil if ((Counter_Tuer_geschlossen < 180.0) || (Counter_Tuer_offen > 0.0)) { Regler_Entfeuchtung_MAX = I_Anteil_Entfeuchtung; Regler_Entfeuchtung_MIN = -100.0; Regler_Entfeuchtung_I_Anteil_MAX = I_Anteil_Entfeuchtung; Regler_Entfeuchtung_I_Anteil_MIN = limit(-100.0 - P_Anteil_Entfeuchtung, Regler_Entfeuchtung_MIN, Regler_Entfeuchtung_I_Anteil_MAX); } else { Regler_Entfeuchtung_MAX = 0.0; Regler_Entfeuchtung_MIN = -100.0; Regler_Entfeuchtung_I_Anteil_MAX = 1.5 / Regler_Entfeuchtung_Xp * 100.0; Regler_Entfeuchtung_I_Anteil_MIN = limit(-100.0 - P_Anteil_Entfeuchtung + Regelabweichung_Entfeuchtung_Gradient / 20.0 * 100.0, Regler_Entfeuchtung_MIN, Regler_Entfeuchtung_I_Anteil_MAX); } // Berechnung Stellgrad Entfeuchtung if (Counter_Tuer_offen > 60.0 || !Startup_finished) { Stellgrad_Entfeuchtung = 0.0; } else { Stellgrad_Entfeuchtung = limit(P_Anteil_Entfeuchtung + I_Anteil_Entfeuchtung + Offset_Entfeuchtung + D_Anteil_Entfeuchtung, Regler_Entfeuchtung_MIN, Regler_Entfeuchtung_MAX); } // Berechnung Stellgrad entfeuchtung Mittelwert if (!Startup_finished) { Stellgrad_Entfeuchtung_Mittelwert = 0.0; } else { Stellgrad_Entfeuchtung_Mittelwert = limit( Stellgrad_Entfeuchtung_Mittelwert + (Stellgrad_Entfeuchtung - Stellgrad_Entfeuchtung_Mittelwert) / (600.0 / sampling_time), Stellgrad_Entfeuchtung - 5.0 * 100.0 / Regler_Entfeuchtung_Xp, Stellgrad_Entfeuchtung + 5.0 * 100.0 / Regler_Entfeuchtung_Xp); } // PID Regler Tür // f_PID_Door(...) double Offset_Temperatur_Tuer; if (Feuchtesprung) { Offset_Temperatur_Tuer = 0.0; } else { Offset_Temperatur_Tuer = 2.0 * Betauungsschutz / 100.0 * limit((90.0 + Stellgrad_Kuehlung_Mittelwert) / (90.0 - 80.0), 0.0, 1.0); } // Regelabweichung if (!Tuer_offen || std::abs(Regelabweichung_Tuer) > std::abs(Sollwert_Temperatur + Offset_Temperatur_Tuer - Istwert_Temperatur_Tuer)) { Regelabweichung_Tuer = Sollwert_Temperatur + Offset_Temperatur_Tuer - Istwert_Temperatur_Tuer; } // P-Anteil // Anti-Windup über dynamisches Integrator Clamping double Regler_Tuer_MAX = limit( (100.0 + Stellgrad_Kuehlung) / (100.0 - 80.0) * 100.0, 0.0, 100.0); double Regler_Tuer_MIN = 0.0; double Regler_Tuer_I_Anteil_MAX = limit(100.0 - P_Anteil_Tuer, 0.0, Regler_Tuer_MAX); double Regler_Tuer_I_Anteil_MIN = 0.0; if (!Startup_finished) { P_Anteil_Tuer = 0.0; } else { P_Anteil_Tuer = 100.0 / Regler_Tuer_Xp * Regelabweichung_Tuer; } // I-Anteil if (!Startup_finished) { I_Anteil_Tuer = 0.0; } else if (Temperatursprung && Regelabweichung_Tuer > 0.0) { I_Anteil_Tuer = limit(I_Anteil_Tuer, Regler_Tuer_I_Anteil_MIN, Regler_Tuer_I_Anteil_MAX); } else if (!Tuer_offen) { I_Anteil_Tuer = limit(I_Anteil_Tuer + 100.0 / Regler_Tuer_Xp / Regler_Tuer_Tn * sampling_time * Regelabweichung_Tuer, Regler_Tuer_I_Anteil_MIN, Regler_Tuer_I_Anteil_MAX); } // D-Anteil if (!Startup_finished) { D_Anteil_Tuer = 0.0; } else { D_Anteil_Tuer = D_Anteil_Tuer + (100.0 / Regler_Tuer_Xp * Regler_Tuer_Tv * (Regelabweichung_Tuer - Regelabweichung_Tuer_alt) / sampling_time - D_Anteil_Tuer) / (Tau_Tuer_Tv / sampling_time); } double Stellgrad_Tuer; // Berechnung Stellgrad Tür if (Tuer_offen || !Startup_finished) { Stellgrad_Tuer = limit(P_Anteil_Tuer + I_Anteil_Tuer + D_Anteil_Tuer, Regler_Tuer_MIN, Regler_Tuer_MAX); } // Kennfelder Kühlung/Entfeuchtung int Index_Ueberhitzung = 1; while (Kennfeld_Ueberhitzung[0][Index_Ueberhitzung] < Istwert_Temperatur && Index_Ueberhitzung < 12) { Index_Ueberhitzung++; } double Interpolation_Ueberhitzung = limit((Kennfeld_Ueberhitzung[0][Index_Ueberhitzung - 1] - Istwert_Temperatur) / (Kennfeld_Ueberhitzung[0][Index_Ueberhitzung - 1] - Kennfeld_Ueberhitzung[0][Index_Ueberhitzung]), 0.0, 1.0); double Skalierung_Ueberhitzung_Kennfeld_Min = Kennfeld_Ueberhitzung[1][Index_Ueberhitzung] * (Interpolation_Ueberhitzung + Kennfeld_Ueberhitzung[1][Index_Ueberhitzung - 1]) * (1.0 - Interpolation_Ueberhitzung); double Skalierung_Ueberhitzung_Kennfeld_Max = Kennfeld_Ueberhitzung[2][Index_Ueberhitzung] * (Interpolation_Ueberhitzung + Kennfeld_Ueberhitzung[2][Index_Ueberhitzung - 1]) * (1.0 - Interpolation_Ueberhitzung); double Sollwert_Ueberhitzung = Kennfeld_Ueberhitzung[3][Index_Ueberhitzung] * (Interpolation_Ueberhitzung + Kennfeld_Ueberhitzung[3][Index_Ueberhitzung - 1]) * (1.0 - Interpolation_Ueberhitzung); //(* Entfeuchtung und Abtauung aus Kennfeld *) int Index_Entfeuchtung = 1; // todo uj - warum nicht mit 0 starten? while ((Kennfeld_Entfeuchtung[0][Index_Entfeuchtung] < Istwert_Temperatur) && (Index_Ueberhitzung < 12)) { Index_Entfeuchtung++; } double Interpolation_Entfeuchtung = limit((Kennfeld_Entfeuchtung[0][Index_Entfeuchtung - 1] - (Istwert_Temperatur) / (Kennfeld_Entfeuchtung[0][Index_Entfeuchtung - 1] ) - Kennfeld_Entfeuchtung[0][Index_Entfeuchtung]), 0.0, 1.0); double Skalierung_Entfeuchtungsventil = Kennfeld_Entfeuchtung[1][Index_Entfeuchtung] * Interpolation_Entfeuchtung + Kennfeld_Entfeuchtung[1][Index_Entfeuchtung - 1] * (1.0 - Interpolation_Entfeuchtung); double Abtauzyklus_Pause = Kennfeld_Entfeuchtung[2][Index_Entfeuchtung] * Interpolation_Entfeuchtung + Kennfeld_Entfeuchtung[2][Index_Entfeuchtung - 1] * (1.0 - Interpolation_Entfeuchtung); double Abtauzyklus_Dauer = Kennfeld_Entfeuchtung[3][Index_Entfeuchtung] * Interpolation_Entfeuchtung + Kennfeld_Entfeuchtung[3][Index_Entfeuchtung - 1] * (1.0 - Interpolation_Entfeuchtung); // Ende - f_PID_Door(...) // Überhitzungsregelung // Temperatur Verdampferausgang PT1 // f_PT1.Vapourize(...) if (!Startup_finished) { Istwert_Temperatur_Verdampferausgang_PT1 = Istwert_Temperatur_Verdampferausgang; } else { Istwert_Temperatur_Verdampferausgang_PT1 += (Istwert_Temperatur_Verdampferausgang - Istwert_Temperatur_Verdampferausgang_PT1) / (60.0 * 4.0); } // Skalierung Überhitzung if (Istwert_Temperatur_Verdampferausgang < (Istwert_Temperatur + Sollwert_Ueberhitzung)) { Counter_Durchzug = MIN(Counter_Durchzug + sampling_time, 10.0); } else { // uj-todo; template for MAX // Counter_Durchzug = MAX(MAX(Counter_Durchzug-sampling_time,-10),0); } if (Counter_Durchzug >= 10.0) { Durchzug = true; } else if (Counter_Durchzug <= -10.0) { Durchzug = false; } double Skalierung_Ueberhitzung_PT1 = Skalierung_Ueberhitzung_Kennfeld_Max; // Magnetventil Kühlung // Stellgrad Kühlung if (Counter_Verdichter_aus > 60.0 && Counter_Verdichter_aus < 600.0) { Stellgrad_Kuehlventil = 1.0; } else if (Istwert_Temperatur > 120.0 || Counter_Kuehlung_Freigabe <= 0.0) { Stellgrad_Kuehlventil = 0.0; } else { Stellgrad_Kuehlventil = MAX(-Stellgrad_Kuehlung, 0.0) * Skalierung_Ueberhitzung_PT1 * Counter_Kuehlung_Freigabe; } // Ende - f_PT1.Vapourize(...) // PWM Generierung Kuehlventil // bool step(double Stellgrad,double sampling_time){ // f_PWMCoolingValve.Step(...) Kuehlventil = PWM_Kuehlventil.step(Stellgrad_Kuehlventil, sampling_time); // Magnetventil Entfeuchtung double T_Entfeuchtung; if (!Startup_finished) { T_Entfeuchtung = Istwert_Temperatur; } else if (Entfeuchtungsventil) { T_Entfeuchtung = limit(T_Entfeuchtung + ((Istwert_Temperatur - T_Entfeuchtung) * U_Entfeuchtung - P_Entfeuchtung) / (4.0 * C_Entfeuchtung), -30.0, Istwert_Temperatur); } else { T_Entfeuchtung = limit(T_Entfeuchtung + ((Istwert_Temperatur - T_Entfeuchtung) * U_Entfeuchtung) / (4.0 * C_Entfeuchtung), -30.0, Istwert_Temperatur); } // Stellgrad Entfeuchtung if (Istwert_Temperatur > 120.0 || Counter_Entfeuchtung_Freigabe <= 0.0) { Stellgrad_Entfeuchtungsventil = 0.0; } else { Stellgrad_Entfeuchtungsventil = MAX(-Stellgrad_Entfeuchtung, 0.0) * Skalierung_Entfeuchtungsventil * Counter_Entfeuchtung_Freigabe; } // Abtauzyklus bool Freigabe_Abtauzyklus = Istwert_Feuchte > Sollwert_Feuchte_Absolut + 2.5; if (!Freigabe_Abtauzyklus) { Counter_Freigabe_Abtauzyklus = 0.0; } else { Counter_Freigabe_Abtauzyklus += sampling_time; } double Skalierung_Abtauzyklus_Dauer = 0.0; ; if (Abtauzyklus_Pause > 0.0 && Abtauzyklus_Dauer > 0.0) { Skalierung_Abtauzyklus_Dauer = limit(Counter_Freigabe_Abtauzyklus / (10.0 * (Abtauzyklus_Pause + Abtauzyklus_Dauer) * 60.0), 1.0, 5.0); } if (Counter_Abtauzyklus > (Abtauzyklus_Pause + Abtauzyklus_Dauer * Skalierung_Abtauzyklus_Dauer) * 60.0) { Counter_Abtauzyklus = 0.0; } else if ((T_Entfeuchtung < 0.0 && Freigabe_Abtauzyklus) || Abtauzyklus) { Counter_Abtauzyklus += sampling_time; } else { Counter_Abtauzyklus = MAX(Counter_Abtauzyklus - sampling_time, 0.0); } Abtauzyklus = Counter_Abtauzyklus > Abtauzyklus_Pause * 60.0 && Abtauzyklus_Pause > 0.0; if (Abtauzyklus) { Stellgrad_Entfeuchtungsventil = 0.0; } // Ende -f_PWMCoolingValve.Step(...) // PWM Entfeuchtungsventil // f_PWMDeHumizeValve.Step(...) Entfeuchtungsventil = PWM_Entfeuchtungsventil.step( Stellgrad_Entfeuchtungsventil, sampling_time); // Druckausgleich vor Start Verdichter if (!Verdichter && Counter_Entfeuchtung_Freigabe > 5.0) { Entfeuchtungsventil = true; } // Heizung Kessel if (Freigabe_Heizung) { Stellgrad_HeizungKessel = MAX(Stellgrad_Heizung * Counter_Heizung_Freigabe, 0.0); } else { Stellgrad_HeizungKessel = 0.0; } // PWM Heizung Kessel HeizungKessel = PWM_Heizung_Kessel.step(Stellgrad_HeizungKessel, 0.25); // Betauungsschutz double Stellgrad_Betauungsschutz_MAX = limit( (90.0 + Stellgrad_Kuehlung_Mittelwert) / (90.0 - 80.0) * 100.0, 0.0, limit((Sollwert_Temperatur - 25.0) / (-20.0 - 25.0) * Betauungsschutz, 0.0, Betauungsschutz)); if (!Startup_finished) { Stellgrad_Betauungsschutz = 0.0; } // Tuerheizung Stellgrad_HeizungTuer = limit(Stellgrad_Tuer + Stellgrad_Betauungsschutz / 10.0, 0.0, 100.0); HeizungTuer = PWM_Heizung_Tuer.step(Stellgrad_HeizungTuer, 0.25); // Heizung Kesselrand Stellgrad_HeizungKesselrand = limit(Stellgrad_Tuer * limit(1.0 + Betauungsschutz / 100.0 * 2.0 * (90.0 + Stellgrad_Kuehlung_Mittelwert) / (90.0 - 80.0), 1.0, 2.0) + Stellgrad_Betauungsschutz, 0.0, 100.0); // Ende - f_PWMDeHumizeValve.Step(...) // PWM Kesselrand // Ende - f_PWMKesselRand.Step(...) HeizungKesselrand = PWM_Heizung_Kesselrand.step(Stellgrad_HeizungKesselrand, 0.25); // Ende - f_PWMKesselRand.Step(...) { // Binder Feuchtemodul // Sperrsignal Feuchtemodul bool Sperrsignal_Feuchte = false; // Gradient Feuchtemodul if (!Startup_finished) { Temperatur_Feuchtemodul_Gradient = 0; } else { Temperatur_Feuchtemodul_Gradient += ((Temperatur_Feuchtemodul - Temperatur_Feuchtemodul_alt) * 60.0 * 4.0 - Temperatur_Feuchtemodul_Gradient) / (4.0 * 10.0); } Sollwert_Temperatur_Feuchtemodul = Sollwert_Temperatur_Feuchtemodul_MIN + Stellgrad_Feuchtemodul_Mittelwert / 100.0 * (Sollwert_Temperatur_Feuchtemodul_MAX - Sollwert_Temperatur_Feuchtemodul_MIN); // Offset Stellgrad Feuchtemodul double Temperatur_Feuchtemodul_Standby = Sollwert_Temperatur_Feuchtemodul - (Stellgrad_Entfeuchtung_Mittelwert - 0.0) / (-100.0 - 0.0) * 60.0; double Standby_Feuchtemodul = limit((Temperatur_Feuchtemodul_Standby - Temperatur_Feuchtemodul) / 10.0 * 5.0, 0.0, 5.0); // Stellgrad Feuchtemodul Stellgrad_Feuchtemodul = limit( Stellgrad_Befeuchtung + 2.0 * limit(Stellgrad_Befeuchtung - Stellgrad_Feuchtemodul_PT1, -2.0, 2.0) + Stellgrad_Feuchtemodul_Nachfuellen, 0.0, 100.0); // Begrenzung Temperatur Feuchtemodul über Temperatur double Stellgrad_Feuchtemodul_MAX_Temperatur = limit( (Temperatur_Feuchtemodul_MAX - Temperatur_Feuchtemodul) / 40.0 * 100.0, 0.0, 100.0); double Temperatur_Feuchtemodul_Gradient_MAX = 10.0; if (Temperatur_Feuchtemodul < 90.0) { Temperatur_Feuchtemodul_Gradient_MAX = 10.0; } else { Temperatur_Feuchtemodul_Gradient_MAX = limit( 20.0 - (Temperatur_Feuchtemodul - (Temperatur_Feuchtemodul_MAX - 60.0)) / 60.0 * 20.0 - Stellgrad_Feuchtemodul_MAX / 100.0 * 10.0, 5.0, 20.0); } double Stellgrad_Feuchtemodul_MAX_adaptiv = 10.0; if (!Startup_finished) { Stellgrad_Feuchtemodul_MAX_adaptiv = 10.0; } else if (Temperatur_Feuchtemodul < 80.0) { Stellgrad_Feuchtemodul_MAX_adaptiv = 10.0; } else if (Stellgrad_Feuchtemodul + 20.0 > Stellgrad_Feuchtemodul_MAX_adaptiv && Stellgrad_Feuchtemodul_MAX_adaptiv < Stellgrad_Feuchtemodul_MAX_Temperatur && Temperatur_Feuchtemodul_Gradient < 2.0 * Temperatur_Feuchtemodul_Gradient_MAX && !Sperrsignal_Feuchte) { Stellgrad_Feuchtemodul_MAX_adaptiv = limit(Stellgrad_Feuchtemodul_MAX_adaptiv + 20.0 * limit((Temperatur_Feuchtemodul_Gradient_MAX - Temperatur_Feuchtemodul_Gradient) / Temperatur_Feuchtemodul_Gradient_MAX, -2.0, 1.0) / (60.0 * 4.0), 0.0, Stellgrad_Feuchtemodul_MAX_Temperatur); } else { Stellgrad_Feuchtemodul_MAX_adaptiv = limit(Stellgrad_Feuchtemodul_MAX_adaptiv - 5.0 / (60.0 * 4.0), 10.0, Stellgrad_Feuchtemodul_MAX_Temperatur); } // Begrenzung Stellgrad_Feuchtemodul Stellgrad_Feuchtemodul_MAX = MIN(Stellgrad_Feuchtemodul_MAX_Temperatur - 5.0, Stellgrad_Feuchtemodul_MAX_adaptiv + Stellgrad_Feuchtemodul_Boost); Stellgrad_Feuchtemodul = MIN(Stellgrad_Feuchtemodul, Stellgrad_Feuchtemodul_MAX); // Stellgrad Feuchtemodul Boost if (!Startup_finished || Temperatur_Feuchtemodul < 80.0) { Stellgrad_Feuchtemodul_Boost = 0.0; } else if (Stellgrad_Feuchtemodul < Stellgrad_Feuchtemodul_MAX_adaptiv - 10.0) { Stellgrad_Feuchtemodul_Boost = MIN(Stellgrad_Feuchtemodul_Boost + 10.0 / 60.0 * sampling_time, 2.0 * Stellgrad_Feuchtemodul_MAX_Temperatur); } else { Stellgrad_Feuchtemodul_Boost = MAX( Stellgrad_Feuchtemodul_Boost - (Stellgrad_Feuchtemodul + 10.0 - Stellgrad_Feuchtemodul_MAX_adaptiv) / 60.0 * sampling_time, 0.0); } if (!Startup_finished) { Stellgrad_Feuchtemodul_PT1 = Stellgrad_Feuchtemodul; } else if (is_valid(Stellgrad_Feuchtemodul_PT1)) { Stellgrad_Feuchtemodul_PT1 = 0.0; } else { Stellgrad_Feuchtemodul_PT1 = Stellgrad_Feuchtemodul_PT1 + (Stellgrad_Feuchtemodul - Stellgrad_Feuchtemodul_PT1) / (4.0 * 30.0); } // Nachfüllen Befeuchtungsmodul double Stellgrad_Nachfuellen_Temperatur = 0.0; double Skalierung_Nachfuellen_Temperatur_P_Anteil = 0.0; double Skalierung_Nachfuellen_Temperatur_D_Anteil = 0.0; if (!Startup_finished) { Stellgrad_Nachfuellen_Temperatur = 0.0; Skalierung_Nachfuellen_Temperatur_D_Anteil = 0.0; Skalierung_Nachfuellen_Temperatur_D_Anteil = 0.0; Skalierung_Nachfuellen_Temperatur_I_Anteil = 0.0; } else { Stellgrad_Nachfuellen_Temperatur = limit( MAX(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) * 2.0 + MIN(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) * 1.0, -20.0, 50.0); Skalierung_Nachfuellen_Temperatur_P_Anteil = limit( MAX(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) / 20.0 + MIN(Temperatur_Feuchtemodul - Sollwert_Temperatur_Feuchtemodul, 0.0) / 40.0, -0.2, 5.0); Skalierung_Nachfuellen_Temperatur_D_Anteil = limit(Temperatur_Feuchtemodul_Gradient / 10.0, -5.0, 5.0); Skalierung_Nachfuellen_Temperatur_I_Anteil = limit(Skalierung_Nachfuellen_Temperatur_I_Anteil + limit(Skalierung_Nachfuellen_Temperatur_P_Anteil + Skalierung_Nachfuellen_Temperatur_D_Anteil, -0.2, 25.0) * sampling_time / 1200.0, 0.0, 5.0); } double Stellgrad_Nachfuellen = 0.0; Stellgrad_Feuchtemodul_Nachfuellen = 0.0; if (Temperatur_Feuchtemodul > Temperatur_Feuchtemodul_MAX && Temperatur_Feuchtemodul_Gradient > 0.0) { Stellgrad_Nachfuellen = 20.0; Stellgrad_Feuchtemodul_Nachfuellen = 0.0; } else { Stellgrad_Nachfuellen = limit( ((Stellgrad_Feuchtemodul_PT1 - Stellgrad_Feuchtemodul_Nachfuellen) * (MAX(Skalierung_Nachfuellen_Temperatur_P_Anteil + Skalierung_Nachfuellen_Temperatur_D_Anteil, 0.0) + Skalierung_Nachfuellen_Temperatur_I_Anteil) + Stellgrad_Nachfuellen_Temperatur) * 2.0 * 7.9681 / Durchflussmenge_Einlassventil_Feuchtemodul, 0.0, 100.0); Stellgrad_Feuchtemodul_Nachfuellen = 0.5 * Stellgrad_Nachfuellen * Durchflussmenge_Einlassventil_Feuchtemodul / 60.0 * 4.19 * 75.0 / 600.0; } //(* Entleeren des Kessels *) bool Entleeren_Kessel = false; if (Startup_finished && Temperatur_Feuchtemodul < 70.0) { Entleeren_Kessel = Counter_Entleeren_Kessel < 60.0; Counter_Entleeren_Kessel += sampling_time; } else { Counter_Entleeren_Kessel = 0.0; Entleeren_Kessel = false; } //(* Abschlämmen des Kessels *) Abschlaemmintegral = Abschlaemmintegral + 0.1 * Durchflussmenge_Einlassventil_Feuchtemodul / Durchflussmenge_Abschlaemmventil_Feuchtemodul * Stellgrad_Nachfuellen / 100.0 * sampling_time; if (Entleeren_Kessel) { Abschlaemmventil = true; Stellgrad_Abschlaemmventil_zyklisch = 100.0; } else { Counter_Zyklus_Abschlaemmventil += sampling_time; if (Abschlaemmintegral > 0.25 && Temperatur_Feuchtemodul_Gradient < 0.0) { Abschlaemmventil = true; Stellgrad_Abschlaemmventil_zyklisch = 2.5; Counter_Zyklus_Abschlaemmventil = 0.0; Abschlaemmintegral -= 0.25; } else { Abschlaemmventil = false; if (Counter_Zyklus_Abschlaemmventil >= 10.0) { Stellgrad_Abschlaemmventil_zyklisch = 0.0; } } } // Stellgrad_Feuchtemodul = 2.0; // PWM Befeuchtungsmodul HeizungFeuchtemodul = PWM_Heizung_Feuchtemodul.step(Stellgrad_Feuchtemodul, 0.25); // PWM Nachfüllen Nachfuellen = PWM_Nachfuellen.step(Stellgrad_Nachfuellen, 0.25); // Abwassermanagement if (!Entleerbehaelter_Unten || !Entleerbehaelter_Oben || Entleeren_Kessel) { Counter_Nachlauf_Entleeren = 10.0; Counter_Pause_Entleeren += sampling_time; if (Counter_Pause_Entleeren > 30.0) { Counter_Pause_Entleeren = 0.0; } } else { Counter_Nachlauf_Entleeren = MAX(Counter_Nachlauf_Entleeren - sampling_time, 0.0); Counter_Pause_Entleeren = 0.0; } bool Entleeren_Pause = false; Entleeren = Counter_Nachlauf_Entleeren > 0.0; Entleeren_Pause = Counter_Pause_Entleeren > 27.0; Entleerpumpe = Entleeren && !Entleeren_Pause; if (!Startup_finished) { Zyklus_Entleeren_Mittelwert = 600.0; } else if (Entleeren && !Entleeren_alt) { Zyklus_Entleeren_Mittelwert = limit( Zyklus_Entleeren_Mittelwert + (Counter_Zyklus_Entleeren - Zyklus_Entleeren_Mittelwert) / 10.0, 10.0, 3600.0); Counter_Zyklus_Entleeren = 0.0; } else { Counter_Zyklus_Entleeren += sampling_time; } if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0) { Counter_Kuehlung_Freigabe = 0.0; } else { if (Stellgrad_Kuehlung < 0.0 || Stellgrad_Heizung < 2.0 || Counter_Tuer_geschlossen < 300.0) { Counter_Kuehlung_Freigabe = MIN(Counter_Kuehlung_Freigabe + sampling_time / 10.0, 1.0); } else { Counter_Kuehlung_Freigabe = MAX(Counter_Kuehlung_Freigabe - sampling_time / 300.0, 0.0); } } Freigabe_Kuehlung = Counter_Kuehlung_Freigabe >= 1.0 || (Freigabe_Kuehlung && Counter_Kuehlung_Freigabe > 0.0); // * Freigabe Kühlung *) // (* Freigabe Entfeuchtung *) if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0) { Counter_Entfeuchtung_Freigabe = 0.0; } else { if (Stellgrad_Entfeuchtung < 0.0 || Stellgrad_Befeuchtung < 2.0 || Counter_Tuer_geschlossen < 300.0) { Counter_Entfeuchtung_Freigabe = MIN(Counter_Entfeuchtung_Freigabe + sampling_time / 10.0, 10.0); } else { Counter_Entfeuchtung_Freigabe = MAX(Counter_Entfeuchtung_Freigabe - sampling_time / 300.0, 0.0); } } Freigabe_Entfeuchtung = Counter_Entfeuchtung_Freigabe >= 1.0 || (Freigabe_Entfeuchtung && Counter_Entfeuchtung_Freigabe > 0.0); // (* Freigabe Heizung *) if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0) { Counter_Heizung_Freigabe = 0.0; } else { if (Stellgrad_Heizung < 0.0 || Stellgrad_Kuehlung > -2.0 || Counter_Tuer_geschlossen < 300.0) { Counter_Heizung_Freigabe = MIN(Counter_Heizung_Freigabe + sampling_time / 10.0, 10.0); } else { Counter_Heizung_Freigabe = MAX(Counter_Heizung_Freigabe - sampling_time / 300.0, 0.0); } } Freigabe_Heizung = Counter_Heizung_Freigabe >= 1.0 || (Freigabe_Heizung && Counter_Heizung_Freigabe > 0.0); // (* Freigabe Befeuchtung *) if (Steuerkontakt_Standby || Istwert_Temperatur > 110.0) { Counter_Befeuchtung_Freigabe = 0.0; } else { if (Stellgrad_Befeuchtung < 0.0 || Stellgrad_Entfeuchtung > -2.0 || Counter_Tuer_geschlossen < 300.0) { Counter_Befeuchtung_Freigabe = MIN(Counter_Befeuchtung_Freigabe + sampling_time / 10.0, 10.0); } else { Counter_Befeuchtung_Freigabe = MAX(Counter_Befeuchtung_Freigabe - sampling_time / 300.0, 0.0); } } Freigabe_Befeuchtung = Counter_Befeuchtung_Freigabe >= 1.0 || (Freigabe_Befeuchtung && Counter_Befeuchtung_Freigabe > 0.0); // Verdichterabscaltung if (!Startup_finished) { Drehzahl_Verdichter_adaptiv = Drehzahl_Verdichter_MAX; } else if (Temperatursprung) { Drehzahl_Verdichter_adaptiv = MAX(Drehzahl_Verdichter_Kuehlung, Drehzahl_Verdichter_Entfeuchtung); } else if (is_valid(Stellgrad_Kuehlung)) { Drehzahl_Verdichter_adaptiv = limit(Drehzahl_Verdichter_adaptiv + (-Stellgrad_Kuehlung - 25.0) / 100.0 * (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN) / (4.0 * 600.0), Drehzahl_Verdichter_MIN, Drehzahl_Verdichter_MAX); } Drehzahl_Verdichter_Kuehlung = Drehzahl_Verdichter_MIN + (MAX(-Stellgrad_Kuehlung_Mittelwert, -Stellgrad_Kuehlung) - 30.0) / (90.0 - 30.0) * (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN); Drehzahl_Verdichter_Entfeuchtung = Drehzahl_Verdichter_MIN + 0.5 * (MAX(-Stellgrad_Entfeuchtung_Mittelwert, -Stellgrad_Entfeuchtung) - 50.0) / (90.0 - 50.0) * (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN); if (Verdichter) { Drehzahl_Verdichter = limit(MAX(Drehzahl_Verdichter_Kuehlung, MAX(Drehzahl_Verdichter_Entfeuchtung, Drehzahl_Verdichter_adaptiv)), Drehzahl_Verdichter_MIN, Drehzahl_Verdichter_MAX); } else { Drehzahl_Verdichter = 1000.0; } Stellgrad_Verdichter = Drehzahl_Verdichter / Drehzahl_Verdichter_MAX * 100.0 * (160.0 / 200.0); /* (* -------------------- *) (* Verflüssigerregelung *) (* -------------------- *) */ Verfluessiger = Verfluessiger && ((Drehzahl_Verdichter_adaptiv - Drehzahl_Verdichter_MIN) / ((Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN) < 0.30) && (-Stellgrad_Kuehlung_Mittelwert < 30.0) && (-Stellgrad_Entfeuchtung_Mittelwert < 60.0) || ((Drehzahl_Verdichter_adaptiv - Drehzahl_Verdichter_MIN) / (Drehzahl_Verdichter_MAX - Drehzahl_Verdichter_MIN) < 0.20) && (-Stellgrad_Kuehlung_Mittelwert < 20.0) && -Stellgrad_Entfeuchtung_Mittelwert < 50.0); }// Ende Feuchtemodul // ---------------------------------------- // Werte die auf Veränderung geprüft werden // ---------------------------------------- Sammelalarm_quittiert_alt = Sammelalarm_quittiert; Istwert_Temperatur_alt = Istwert_Temperatur; Regelabweichung_Temperatur_alt = Regelabweichung_Temperatur; Sollwert_Temperatur_alt = Sollwert_Temperatur; Istwert_Feuchte_alt = Istwert_Feuchte; Regelabweichung_Feuchte_alt_alt = Regelabweichung_Feuchte_alt; Regelabweichung_Feuchte_alt = Regelabweichung_Feuchte; Sollwert_Feuchte_alt = Sollwert_Feuchte; Durchzug_alt = Durchzug; Regelabweichung_Tuer_alt = Regelabweichung_Tuer; HeizungFeuchtemodul_alt = HeizungFeuchtemodul; Regelabweichung_Befeuchtung_alt_alt = Regelabweichung_Befeuchtung_alt; Regelabweichung_Entfeuchtung_alt = Regelabweichung_Entfeuchtung; // ---------------- // Rückgabewerte // ---------------- // F_Outputs out{}; binOut.bool_out01 = (std::abs((Sollwert_Temperatur - Istwert_Temperatur)) > Temperaturband); // du nutzt Temperaturband-Alarm // separat; hier nur Beispiel binOut.bool_out02 = (std::abs((Sollwert_Feuchte - Istwert_Feuchte)) > Feuchteband) && (!Befeuchtung_aus) && (!Entfeuchtung_aus); binOut.bool_out03 = Befeuchtung_aus || Entfeuchtung_aus; binOut.bool_out07 = (!Status_Uebertemperatur) && (!(std::abs(Istwert_Ueberwachungsregler - Istwert_Temperatur) > 20.0)); alarmOut.Startup = Startup_finished; binOut.bool_out09 = HeizungKessel; binOut.bool_out11 = HeizungTuer; binOut.bool_out12 = HeizungKesselrand; binOut.bool_out13 = Verfluessiger; binOut.bool_out14 = Nachfuellen; binOut.bool_out16 = Entleerpumpe; binOut.bool_out17 = HeizungFeuchtemodul; binOut.bool_out20 = Abschlaemmventil; binOut.bool_out18 = Kuehlventil; binOut.bool_out19 = Entfeuchtungsventil; binOut.bool_out21 = Verdichter; binOut.bool_out23 = !Sammelalarm_quittiert; analogOut.real_out01 = Istwert_Temperatur; analogOut.real_out02 = Istwert_Temperatur; analogOut.real_out04 = Istwert_Temperatur; analogOut.real_out05 = limit(Istwert_Feuchte, 0.0, 100.0); analogOut.real_out06 = limit(Istwert_Feuchte, 0.0, 100.0); analogOut.real_out07 = Sollwert_Feuchte; analogOut.real_out08 = limit(Istwert_Feuchte, 0.0, 100.0); analogOut.real_out09 = Stellgrad_HeizungKessel; analogOut.real_out10 = Stellgrad_Pumpe; analogOut.real_out11 = Stellgrad_HeizungTuer; analogOut.real_out12 = Stellgrad_HeizungKesselrand; analogOut.real_out13 = Stellgrad_Feuchtemodul; analogOut.real_out14 = Stellgrad_Abschlaemmventil_zyklisch; analogOut.real_out16 = Temperatur_Feuchtemodul; analogOut.Stellgrad_Feuchtemodul = Stellgrad_Feuchtemodul; analogOut.real_out18 = Stellgrad_Kuehlventil; analogOut.real_out19 = Stellgrad_Entfeuchtungsventil; analogOut.real_out20 = Stellgrad_Luefter; analogOut.real_out21 = Stellgrad_Verdichter; analogOut.real_out25 = Schaltwert_Uebertemperatur; analogOut.real_out26 = Schaltwert_Untertemperatur; analogOut.Stellgrad_Heizung = Stellgrad_Heizung; analogOut.Stellgrad_Kuehlung = Stellgrad_Kuehlung; analogOut.Stellgrad_Befeuchtung = Stellgrad_Befeuchtung; analogOut.Stellgrad_Entfeuchtung = Stellgrad_Entfeuchtung; analogOut.Counter_Tuer = Counter_Tuer_offen; // alarms (wie ST) alarmOut.alarm_01 = Bandalarm_Temperatur; alarmOut.alarm_02 = Bandalarm_Feuchte; alarmOut.alarm_03 = Tueralarm; alarmOut.alarm_04 = false; alarmOut.alarm_05 = false; alarmOut.alarm_06 = Alarm_Wasser_Befeuchtungsmodul && !Befeuchtung_aus; alarmOut.alarm_07 = Alarm_Abwasser_Befeuchtungsmodul; alarmOut.alarm_08 = (Alarm_Heizung_Befeuchtungsmodul || Alarm_PT100_Befeuchtungsmodul) && !Befeuchtung_aus; // alarm_09..alarm_15 sind im ST mit Selbsthaltung/Quittierung etc.: alarmOut.alarm_09 = (((Istwert_Temperatur_Tuer < -50.0) || (Istwert_Temperatur_Tuer > 120.0)) && Startup_finished) ||(alarm_09 && Sammelalarm_quittiert); alarmOut.alarm_10 = (std::abs(Istwert_Ueberwachungsregler - Istwert_Temperatur) > 20.0) || ((((Istwert_Ueberwachungsregler < -50.0) || (Istwert_Ueberwachungsregler > 120.0) && Startup_finished))) || (alarm_10 && Sammelalarm_quittiert); alarmOut.alarm_11 = Status_Uebertemperatur || StatusQuittierung_Uebertemperatur; alarmOut.alarm_12 = Status_Untertemperatur || StatusQuittierung_Untertemperatur; alarmOut.alarm_13 = (((Istwert_Temperatur_Verdampferausgang < -50.0) || (Istwert_Temperatur_Verdampferausgang > 120.0)) && Startup_finished) || (alarm_13 && Sammelalarm_quittiert); alarmOut.alarm_14 = (Counter_Wasserkanister_leer > 10.0 && Startup_finished) || (alarm_14 && Sammelalarm_quittiert); alarmOut.alarm_15 = ((analogInput.real_in11 > Sollwert_Feuchte_Max && !Befeuchtung_aus) || (analogInput.real_in11 < Sollwert_Feuchte_Min && !Entfeuchtung_aus)) || (alarm_15 && Sammelalarm_quittiert); // Selbsthaltung der Alarm-Bits (wie ST-OR alarm_x ...) alarm_09 = alarmOut.alarm_09; alarm_10 = alarmOut.alarm_10; alarm_13 = alarmOut.alarm_13; alarm_14 = alarmOut.alarm_14; alarm_15 = alarmOut.alarm_15; // return out; } private: // ===== ST: VAR CONSTANT ===== static constexpr double sampling_time = 0.25; 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}}}; // Zeitkonstanten etc. static constexpr double Tau_Heizung_Tv = 10.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; // ===== 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; bool Freigabe_Entfeuchtung = false; double Counter_Heizung_Freigabe = 0.0; bool Freigabe_Heizung = false; double Counter_Befeuchtung_Freigabe = 0.0; bool Freigabe_Befeuchtung = false; bool Abtauzyklus = false; double Counter_Zyklus_Entleeren = 0.0; double Drehzahl_Verdichter_Kuehlung = 0.0; double Drehzahl_Verdichter_Entfeuchtung = 0.0; double Drehzahl_Verdichter = 0.0; /*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{}; std::uint32_t Modus_Ueberwachungsregler{}; double Offset_Ueberwachungsregler{}; double Klasse_Ueberwachungsregler{}; bool Wasserkanister_leer{}; double Regler_Tuer_Tn = 700.0; double Regler_Tuer_Tv = 60.0; double Tau_Tuer_Tv = 60.0; 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 Sollwert_Temperatur_Feuchtemodul_MIN = 110.0; double Sollwert_Temperatur_Feuchtemodul_MAX = 130.0; 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{}; double Regler_Kuehlung_Tv = 5.0; double Tau_Kuehlung_Tv = 30.0; double Theta_I_Kuehlung = 1.0; // 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 Regelabweichung_Tuer_alt{}; double Abschlaemmintegral = 0.0; double Standby_Feuchtemodul = 0.0; double Regelabweichung_Befeuchtung_alt_alt = 0.0; double Regelabweichung_Entfeuchtung_alt = 0.0; double Durchflussmenge_Einlassventil_Feuchtemodul = 400.0; double Durchflussmenge_Abschlaemmventil_Feuchtemodul = 1500.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{}; // Reglerparameter double Regler_Heizung_Xp{}; double Regler_Kuehlung_Xp{}; double Regler_Befeuchtung_Xp{}; double Regler_Entfeuchtung_Xp{}; double Regler_Tuer_Xp{}; 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; // 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{}; const double Temperatur_Feuchtemodul_MAX = 200.0; // 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_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_Entfeuchten_I_Anteil_MIN = 0.0; double Drehzahl_Verdichter_MIN = 1800.0; double Drehzahl_Verdichter_MAX = 4500.0; double Drehzahl_Verdichter_adaptiv = 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: bool initialize(const char *configFilePath); void step(); void terminate(); private: #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