Files
BinderBeispielRegler/controller/Controller.h
2026-04-04 22:32:01 +02:00

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