Files
BinderBeispielRegler/controller/Controller.hpp
2026-03-30 11:52:39 +02:00

2531 lines
99 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#ifdef BUILD_TARGET_SOM
#if defined(_WIN32)
#define BINDER_SIMULINK_API_EXPORT __declspec(dllexport)
#else
#define BINDER_SIMULINK_API_EXPORT __attribute__((visibility("default")))
#endif
#include "algorithm/ControllerBase.hpp"
#include "asio/SignalConnection.hpp"
#endif
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
#include <limits>
#include <memory>
#include <vector>
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<int>(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<std::uint32_t>(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<std::uint32_t>(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<std::uint32_t>(10 * 4)); StatusQuittierung_Uebertemperatur =
(Status_Uebertemperatur && Counter_Status_Uebertemperatur <
static_cast<std::uint32_t>(11 * 4)) || (StatusQuittierung_Uebertemperatur &&
Sammelalarm_quittiert);
if ( ((minUeberw < Schaltwert_Untertemperatur) ||
(Status_Untertemperatur && (minUeberw < Schaltwert_Untertemperatur
+ 1.0))) && (Klasse_Ueberwachungsregler >= 3.0) ) {
Counter_Status_Untertemperatur += 1;
} else {
Counter_Status_Untertemperatur = 0;
}
Status_Untertemperatur = (Counter_Status_Untertemperatur >=
static_cast<std::uint32_t>(10 * 4)); StatusQuittierung_Untertemperatur =
(Status_Untertemperatur && Counter_Status_Untertemperatur <
static_cast<std::uint32_t>(11 * 4)) || (StatusQuittierung_Untertemperatur &&
Sammelalarm_quittiert);
if (Status_Untertemperatur || StatusQuittierung_Untertemperatur) {
Sollwert_Temperatur = std::max(Sollwert_Temperatur,
Schaltwert_Untertemperatur);
}
if (Status_Uebertemperatur || StatusQuittierung_Uebertemperatur) {
Sollwert_Temperatur = std::min(Sollwert_Temperatur,
Schaltwert_Uebertemperatur);
}*/
// ------------------------
// Parametersatzumschaltung
// ------------------------
// f_SwitchParameterSet(...)
Index_Feuchte = static_cast<std::uint16_t>(
8 -
UTILITY_FUNCTIONS::real_to_int(
limit((Sollwert_Feuchte - 10.0) / (90.0 - 10.0) * 8.0, 0.0, 8.0) +
0.5));
Index_Temperatur =
static_cast<std::uint16_t>(UTILITY_FUNCTIONS::real_to_int(
limit((Sollwert_Temperatur - 10.0) / (90.0 - 10.0) * 8.0, 0.0,
8.0) +
0.5));
Index_Temperatur_ohne_Feuchte =
static_cast<std::uint16_t>(UTILITY_FUNCTIONS::real_to_int(
limit((Sollwert_Temperatur - (-20.0)) / (100.0 - (-20.0)) * 12.0,
0.0, 12.0) +
0.5));
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<std::array<double, 13>, 4> Kennfeld_Ueberhitzung{
{// 0: Temperatur
std::array<double, 13>{-20.0, -10.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0,
60.0, 70.0, 80.0, 90.0, 100.0},
// 1: Skalierung Min
std::array<double, 13>{0.01, 0.02, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7,
0.8, 0.9, 1.0, 1.0},
// 2: Skalierung Max
std::array<double, 13>{0.01, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
1.0, 1.0, 1.0},
// 3: Sollwert Überhitzung
std::array<double, 13>{-6.0, -8.0, -10.0, -8.0, -6.0, -8.0, -10.0, -12.0,
-16.0, -20.0, -24.0, -28.0, -32.0}}};
static constexpr std::array<std::array<double, 13>, 4> Kennfeld_Entfeuchtung{
{// 0: Temperatur
std::array<double, 13>{-20.0, -10.0, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0,
60.0, 70.0, 80.0, 90.0, 100.0},
// 1: Skalierung Entfeuchtung
std::array<double, 13>{0.08, 0.08, 0.08, 0.10, 0.12, 0.14, 0.16, 0.18,
0.20, 0.22, 0.24, 0.26, 0.28},
// 2: Abtauzyklus Pause
std::array<double, 13>{120.0, 120.0, 120.0, 120.0, 120.0, 90.0, 60.0,
60.0, 60.0, 0.0, 0.0, 0.0, 0.0},
// 3: Abtauzyklus Dauer
std::array<double, 13>{60.0, 60.0, 60.0, 30.0, 20.0, 10.0, 8.0, 4.0, 2.0,
0.0, 0.0, 0.0, 0.0}}};
// Kennfelder (nur die, die oben genutzt werden; den Rest kannst du genauso
// hinzufügen)
static constexpr std::array<double, 13> Kennfeld_Regler_Heizung_Xp{
0.2, 0.5, 0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
static constexpr std::array<double, 13> Kennfeld_Regler_Kuehlung_Xp{
0.1, 0.1, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.0};
static constexpr std::array<std::array<double, 9>, 9>
Kennfeld_Regler_Befeuchtung_Xp{
{std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02},
std::array<double, 9>{1.00, 0.54, 0.31, 0.18, 0.11, 0.07, 0.05, 0.03,
0.02}}};
static constexpr std::array<std::array<double, 9>, 9>
Kennfeld_Regler_Entfeuchtung_Xp{
{std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20},
std::array<double, 9>{1.00, 0.80, 0.60, 0.50, 0.40, 0.35, 0.30, 0.25,
0.20}}};
static constexpr std::array<std::array<double, 11>, 3>
Kennfeld_Sollwert_Feuchte_Limit{
{std::array<double, 11>{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100},
std::array<double, 11>{80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80},
std::array<double, 11>{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}};
// 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<appengine::state::IStateVariable> tempVariable_;
std::shared_ptr<appengine::state::IStateVariable> tempSetPointVariable_;
// TODO: bool_inXX / real_inXX / bool_outXX / real_outXX / alarm_XX als
// StateVariables holen (oder je nach AppEngine: arrays/IO mapping)
ClimateAlgorithm algo_{};
PT1 FILTERED_TEMP{};
PT1 FILTER_TUER{};
// Eingänge
std::shared_ptr<appengine::state::IStateVariable> const_duty_cycle_;
std::shared_ptr<appengine::state::IStateVariable> const_freq_;
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Oben_Config_;
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Unten_Config_;
std::shared_ptr<appengine::state::IStateVariable> Fuellstand_Config_;
std::shared_ptr<appengine::state::IStateVariable> SV_Tuer_Variable_;
std::shared_ptr<appengine::state::IStateVariable> SV_Verdampferausgang_;
std::shared_ptr<appengine::state::IStateVariable> SV_Befeuchtungsmodul_;
std::shared_ptr<appengine::state::IStateVariable> SV_Verdichter_on_;
std::shared_ptr<appengine::state::IStateVariable> Startup_;
std::shared_ptr<appengine::state::IStateVariable> CounterTuer_;
// ausgänge
std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
std::shared_ptr<appengine::state::IStateVariable> Heizung_Bef_Config_;
std::shared_ptr<appengine::state::IStateVariable> MV_Kuehlung_Config_;
std::shared_ptr<appengine::state::IStateVariable> Abschlaemmen_Config_;
std::shared_ptr<appengine::state::IStateVariable> Entleerpumpe_Config_;
std::shared_ptr<appengine::state::IStateVariable> Heizung_Kesselrand_Config_;
std::shared_ptr<appengine::state::IStateVariable>
Freigabe_Verfluessigerluefter_Config_;
std::shared_ptr<appengine::state::IStateVariable> Heizung_Innenraum_Config_;
std::shared_ptr<appengine::state::IStateVariable> Heizung_Tuer_Config_;
std::shared_ptr<appengine::state::IStateVariable> Uebertemperatur_Config_;
std::shared_ptr<appengine::state::IStateVariable> MV_Entfeuchtung_Config_;
std::shared_ptr<appengine::state::IStateVariable> MV_Druckluft_Config_;
std::shared_ptr<appengine::state::IStateVariable>
Ansteuerung_Wassereinlass_Config_;
std::shared_ptr<appengine::state::IStateVariable>
Ansteuerung_Verdichter_Config_;
std::shared_ptr<appengine::state::IStateVariable> Verdichter_Duty_Config;
std::shared_ptr<appengine::state::IStateVariable> Luefter_Innenraum_Config_;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Heizung;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Kuehlung;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Befeuchtung;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Entfeuchtung;
// Regelgrößen
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Temperatur_;
std::shared_ptr<appengine::state::IStateVariable> SV_Temperatur_Variable_;
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Feuchte_;
std::shared_ptr<appengine::state::IStateVariable> SV_Feuchte_Variable_;
// std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
};
extern "C" BINDER_SIMULINK_API_EXPORT ControllerBase *create();
#else
class Controller {
public:
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<appengine::state::IStateVariable> tempVariable_;
std::shared_ptr<appengine::state::IStateVariable> tempSetPointVariable_;
// TODO: bool_inXX / real_inXX / bool_outXX / real_outXX / alarm_XX als StateVariables holen
// (oder je nach AppEngine: arrays/IO mapping)
ClimateAlgorithm algo_{};
PT1 FILTERED_TEMP{} ;
PT1 FILTER_TUER{};
// Eingänge
std::shared_ptr<appengine::state::IStateVariable> const_duty_cycle_;
std::shared_ptr<appengine::state::IStateVariable> const_freq_;
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Oben_Config_;
std::shared_ptr<appengine::state::IStateVariable> Wasserstand_Unten_Config_;
std::shared_ptr<appengine::state::IStateVariable> Fuellstand_Config_;
std::shared_ptr<appengine::state::IStateVariable> SV_Tuer_Variable_;
std::shared_ptr<appengine::state::IStateVariable> SV_Verdampferausgang_;
std::shared_ptr<appengine::state::IStateVariable> SV_Befeuchtungsmodul_;
std::shared_ptr<appengine::state::IStateVariable> SV_Verdichter_on_;
std::shared_ptr<appengine::state::IStateVariable> Startup_;
std::shared_ptr<appengine::state::IStateVariable> CounterTuer_;
// ausgänge
std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
std::shared_ptr<appengine::state::IStateVariable> Heizung_Bef_Config_;
std::shared_ptr<appengine::state::IStateVariable> MV_Kuehlung_Config_;
std::shared_ptr<appengine::state::IStateVariable> Abschlaemmen_Config_;
std::shared_ptr<appengine::state::IStateVariable> Entleerpumpe_Config_;
std::shared_ptr<appengine::state::IStateVariable> Heizung_Kesselrand_Config_;
std::shared_ptr<appengine::state::IStateVariable> Freigabe_Verfluessigerluefter_Config_;
std::shared_ptr<appengine::state::IStateVariable> Heizung_Innenraum_Config_;
std::shared_ptr<appengine::state::IStateVariable> Heizung_Tuer_Config_;
std::shared_ptr<appengine::state::IStateVariable> Uebertemperatur_Config_;
std::shared_ptr<appengine::state::IStateVariable> MV_Entfeuchtung_Config_;
std::shared_ptr<appengine::state::IStateVariable> MV_Druckluft_Config_;
std::shared_ptr<appengine::state::IStateVariable> Ansteuerung_Wassereinlass_Config_;
std::shared_ptr<appengine::state::IStateVariable> Ansteuerung_Verdichter_Config_;
std::shared_ptr<appengine::state::IStateVariable> Verdichter_Duty_Config;
std::shared_ptr<appengine::state::IStateVariable> Luefter_Innenraum_Config_;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Heizung;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Kuehlung;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Befeuchtung;
std::shared_ptr<appengine::state::IStateVariable> SV_Stellgrad_Entfeuchtung;
// Regelgrößen
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Temperatur_;
std::shared_ptr<appengine::state::IStateVariable> SV_Temperatur_Variable_;
std::shared_ptr<appengine::state::IStateVariable> SV_Sollwert_Feuchte_;
std::shared_ptr<appengine::state::IStateVariable> SV_Feuchte_Variable_;
//std::vector<appengine::asio::SignalConnectionPtr> subscriptions_{};
#endif
};
#endif