PID-Regler zur Steuerung der FHT8V über die FHT8i

Hallo Leute,

hier im Forum wurde schon so einiges zu dem Thema geschrieben. Daraus habe ich mal den „Basiscode“ eines PID-Regelers für die oben genannte Aufgabe geschrieben.

<?

//e = aktuelle Reglerabweichung -> Soll-Ist (oder umgekehrt?)
//ealt = vorherige Reglerabweichung
//esum = die Summe aller bisherigen Abweichungen e
//Ta = Rechenschrittweite (Abtastzeit)
//Kp = Verstärkungsfaktor Proportionalregler
//Ki = Verstärkungsfaktor Integralregler
//Kd = Verstärkungsfaktor Differenzialregler
//y = Antwort -> muss im Bereich zwischen 0-100 sein
// esum = esum + e
// y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta
// ealt = e
$Kp=5;
$Kd=0;
$Ki=0;
$Script = IPS_GetScript($IPS_SELF);
$Ta=time() - $Script['LastExecute'];
echo "Zeitdifferenz: " .$Ta. " ";

//aktuelle Regelabweichung bestimmen
$e = GetValueFloat(28056 /*[Raum-Temperaturen\Büro Joachim\Soll Temperatur]*/ )- GetValueFloat(40847 /*[Raum-Temperaturen\Büro Joachim\Temperatur]*/ );
echo "Regelabweichung: ".$e." ";

// Die Summe aller vorherigen Regelabweichungen bestimmen
$esum = (GetValueFloat(43568 /*[Raum-Temperaturen\Büro Joachim\Summe Regelabweichungen]*/ )) + $e;
echo "Summe Regelabweichungen: ".$esum." ";
SetValueFloat(43568 /*[Raum-Temperaturen\Büro Joachim\Summe Regelabweichungen]*/ , $esum);

// Die vorherige Regelabweichung ermitteln
$ealt = GetValueFloat(19069 /*[Raum-Temperaturen\Büro Joachim\Vorherige Regelabweichung]*/ );
// Die Regelgröße nun errechnen

$y = ($Kp * $e + $Ki * $Ta * $esum + $Kd * ($e - $ealt) / $Ta);
echo "Neue Regelgrößen: ".$y." ";
SetValueInteger(37838  /*[Raum-Temperaturen\Büro Joachim\Heizungs-Stellelement]*/, $y);

// Vorherige Regelabweichung durch jetzige ersetzen
SetValueFloat(19069 /*[Raum-Temperaturen\Büro Joachim\Vorherige Regelabweichung]*/ , $e);


?>

Am Ende muss ja eine Zahl zwischen 0 und 100 rauskommen, die dann an den Stellantrieb gesendet wird.
Dazu meine Frage: Hat jemand von Euch schon Erfahrungen für „passende“ Werte für Kp, Kd und Ki?:confused:

Joachim

Hallo Leute,

wegen dem nahende Ende der Heizsaison kann ich derzeit nicht so viel weiterkalibrieren. Aber vom Prinzip her läuft der Code jetzt so, wie ich ihn hier poste. Ich denke an den Verstärkungsfaktoren könnte noch eine weitere Verbesserung erfolgen, da denke ich aber auch, dass diese Parameter auch schon sehr raumabhängig sein können.

<?

//e = aktuelle Reglerabweichung -> Soll-Ist
//ealt = vorherige Reglerabweichung
//esum = die Summe aller bisherigen Abweichungen e
//Ta = Rechenschrittweite (Abtastzeit)
//Kp = Verstärkungsfaktor Proportionalregler
//Ki = Verstärkungsfaktor Integralregler
//Kd = Verstärkungsfaktor Differenzialregler
//y = Antwort -> muss im Bereich zwischen 0-100 sein
// esum = esum + e
// y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta
// ealt = e
$Kp=5;
$Kd=0;
$Ki=2.5;
$Script = IPS_GetScript($IPS_SELF);
$Ta=Round((time() - $Script['LastExecute'])/60,0);
echo "Zeitdifferenz: " .$Ta. " ";

//aktuelle Regelabweichung bestimmen
$e = GetValueFloat(28056 /*[Raum-Temperaturen\Büro Joachim\Soll Temperatur]*/ )- GetValueFloat(40847 /*[Raum-Temperaturen\Büro Joachim\Temperatur]*/ );
echo "Regelabweichung: ".$e." ";

// Die Summe aller vorherigen Regelabweichungen bestimmen
If ((getValueinteger(37838 /*[Raum-Temperaturen\Büro Joachim\Heizungs-Stellelement]*/ ) == 0) and ($e < 0))
	// Die Negativ-Werte sollen nicht weiter aufsummiert werden, wenn der Stellmotor schon auf 0 ist
	{
   $esum = (GetValueFloat(43568 /*[Raum-Temperaturen\Büro Joachim\Hilfsvariablen\Summe Regelabweichungen]*/ ));
   }
else
	{
	$esum = (GetValueFloat(43568 /*[Raum-Temperaturen\Büro Joachim\Hilfsvariablen\Summe Regelabweichungen]*/ )) + $e;
	}

echo "Summe Regelabweichungen: ".$esum." ";
SetValueFloat(43568 /*[Raum-Temperaturen\Büro Joachim\Hilfsvariablen\Summe Regelabweichungen]*/ , $esum);

// Die vorherige Regelabweichung ermitteln
$ealt = GetValueFloat(19069 /*[Raum-Temperaturen\Büro Joachim\Hilfsvariablen\Vorherige Regelabweichung]*/ );
// Die Regelgröße nun errechnen

echo "Produkt Kp * e = : ".$Kp * $e." ";
echo "Produkt Ki * Ta * esum = : ".$Ki * $Ta * $esum." ";
$y = ($Kp * $e + $Ki * $Ta * $esum + $Kd * ($e - $ealt) / $Ta);

// Vorherige Regelabweichung durch jetzige ersetzen
SetValueFloat(19069 /*[Raum-Temperaturen\Büro Joachim\Hilfsvariablen\Vorherige Regelabweichung]*/, $e);

//$NeuerWert = GetValueInteger(37838 /*[Raum-Temperaturen\Büro Joachim\Heizungs-Stellelement]*/ ) + (abs($e)/10*$y);
$NeuerWert = $y;

If ($NeuerWert < 0)
	{
	$NeuerWert = 0;
	}
elseif ($NeuerWert > 100)
	{
	$NeuerWert = 100;
	}
echo "Neue Regelgrößen: ".$NeuerWert." ";
SetValueInteger(37838 /*[Raum-Temperaturen\Büro Joachim\Heizungs-Stellelement]*/ , $NeuerWert);
//Umskalierung auf 0-255 und Errechnung des HEXwertes
$Sendewert = dechex(Round(($NeuerWert * 2.55)));
echo "Gerundeter Wert: ".Round(($NeuerWert * 2.55))." ";
echo "Gesendeter Wert: ".$Sendewert;
$Sendewert = "0x$Sendewert";
echo $Sendewert;
HID_SendEvent(22578 /*[Stellmotorsender]*/, 0, chr(0x01).chr($Sendewert).chr(0x02));

?>

Gesteuert wird der FHT8i über den FHT8i der über Helmuts (Super-MuFi-)Adapter angeschlossen ist, also bei Fragen zur Hardware sich vertrauensvoll an ihn wenden!:slight_smile:

Das Skript wird derzeit im 5-Minuten-Intervall aufgerufen.

Freue mich nun auf eine rege Diskussion…

Joachim

Ist es eine Option in den MultiTrupa-Kontroller keine 1Wire Temperatursensoren-Abfrage einzubauen, sondern die 8-fach Temperaturmessung von den 8 möglichen Funksensoren des WDE1 Systemes zu integrieren?

Zur Erinnerung: Das WDE1 System erfasst bis zu 8 Temp/Feuchte Sensoren per Funk.

Man könnte auch die PI(D)-Regelung des oben geposteten Scriptes in den Kontroller bringen und einfach nur die Sollwerte und die Werte für P und I per USB - HID -Parameter in den Kontroller bringen.

Der Kontroller arbeitet dann vollkommen autark und steuert so die max.4- Funkventile in Abhängkeit von den Funksensoren.

Hallo Joachim,

ich benutze zwar nicht Helmuts super-duper Kontroller, sondern „nur“ den seriellen Adapter mit Bascom Code (vielen Dank Helmut) aber das funktioniert auch wunderbar.
Ich experimentiere seit etwa 6 Wochen mit verschiedenen Reglertypen und Parametern und bin bisher zu folgendem Ergebniss gekommen:

  1. Im Prinzip reicht der P-Regler. Er ist mit dem entsprechenden Kp schnell und präzise, hat aber eine kleine WAF Besonderheit: Bei Erreichen der Solltemperatur ist das Ventil zu und der Heizkörper wird kalt. Nun noch ein bischen Fremdwärme durch Sonne oder Fernseher/Beamer und er bleibt kalt. Und 21° mit kalter Heizung fühlen sich kälter an, als 21° mit warmer Heizung.

  2. Den PID Regler habe ich sofort wieder verworfen, da der D-Anteil bei mir extrem viele und merkwürdige Ventilbewegungen verursacht hat - vielleicht waren aber auch nur mein Parameter murks.

  3. Der gute Kompromiss ist für mich der PI-Regler. Ich stoppe das Integrieren aber nicht nur bei geschlossenem Ventil, sondern auch bei voll geöffnetem Ventil. Da ich viele Räume mit Fenstern nach Süden und Südwesten habe, begrenze ich esum auf einen Max und Min Wert, damit die Heizung bei Fremdwärme nicht allzu träge reagiert.

  4. Ein normaler Thermostat hat eine Regelautonomie von 2K, d.h. 1K unter Solltemperatur ist er auf und 1K über Solltemperatur zu. Mit der Formel für den P-Regler ergibt das ein Kp von 50. Die besseren Thermostate liegen bei 1K, was einem Kp von 100 entspricht.

  5. Meine Stellmotoren gehen bei y=0 in eine 5% Frostschutzstellung, daher ist mein kleinster Wert für y nicht 0 sondern 1.

  6. Ich bin schon seit Jahren dabei, meinen Altbau Stück für Stück auf den energetisch neusten Stand zu bringen und habe einen bunten Mischmasch von Räumen mit guter und weniger guter Isolierung, alten und neuen Fenstern. Dementsprechend reagieren die Räume auch unterschiedlich, wenn überall die gleichen Reglerparameter verwendet werden. Ich habe deshalb mein Reglerscript so angepasst, dass es jeden Morgen mit offenen Ventilen ohne Regelung startet, die Verzugszeit und Ausgleichszeit beim Aufheizen bestimmt und daraus die Parameter Kp und Ki berechnet, dann umschaltet auf einen P-Regler mit festen Parametern, der die Ventile langsam zufährt und anschließend auf den PI-Regler schaltet, wenn der P-Regler die Ventile zu weit schließen würde. Das klingt vielleicht oversized, aber das direkte Umschalten von der Parameterbestimmung mit offenen Ventilen auf den PI-Regler hatte zur Folge, dass die Brennerregelung die Heizung erstmal abgeschaltet hat, wenn alle Ventile mehr oder weniger zeitgleich von 100% auf 20-30% runtergefahren wurden. Das spielt jetzt keine Rolle mehr, aber bei Temperaturen um und unter Null wirds dann wieder etwas kälter in der Wohnung.

$Status = GetValueString(56027 /*[Wetter\Heizung]*/);
$Parameterbestimmung = GetValueString(38608 /*[Wohnzimmer\Heizung\Parameterbestimmung]*/);
$Wochentag = date ("w");
$Uhrzeit = date("H:i");
$Zeitstring = GetValueString(39161 /*[Zeit\Datum/Zeit]*/);
$Solltemperatur = GetValueFloat(38985 /*[Wohnzimmer\Heizung\Solltemperatur]*/);
$Isttemperatur = GetvalueFloat(50695 /*[Wohnzimmer\S 2001-ID Wohnzimmer\Temperatur]*/);
$Starttemperatur = GetValueFloat(29142 /*[Wohnzimmer\Heizung\Starttemperatur]*/);
$Tu = GetValueFloat(13052 /*[Wohnzimmer\Heizung\Tu - Verzugszeit]*/);
$Tg = GetValueFloat(20705 /*[Wohnzimmer\Heizung\Tg - Ausgleichszeit]*/);
$Kp = GetValueFloat(18350 /*[Wohnzimmer\Heizung\Kp - Proportionalbeiwert]*/);
$Ki = GetValueFloat(43863 /*[Wohnzimmer\Heizung\Ki - Integralbeiwert]*/);
$esum = GetValueFloat(34279 /*[Wohnzimmer\Heizung\esum - Integralanteil]*/);
$ealt = GetValueFloat(22624 /*[Wohnzimmer\Heizung\ealt]*/);
$y = GetValueFloat(15174 /*[Wohnzimmer\Heizung\Ventilposition]*/);
$Zieltemperatur = GetValueFloat(14264 /*[Wohnzimmer\Heizung\Zieltemperatur]*/);
$Pp = 0;
$Py = 0;
$Regelungsart = GetValueString(37358 /*[Wohnzimmer\Heizung\Regelungsart]*/);

// wöchentliche Entkalkungsfahrt Stellmotor 1

If ($Wochentag == 6 AND $Uhrzeit == '06:00') {    												// Samstag Morgen 6:00
    $str=chr(5).chr(255).chr(13); 																	// Befehl(Entkalkungsfahrt Motor 1).Daten(nach Fahrt voll öffnen).chr(13) ist CR als Abschluß der Sequence
	 COMPort_SendText (38228 /*[Serial Port]*/ ,$str);
	 SetValueString(15479 /*[Wohnzimmer\Heizung\Letzte Entkalkungsfahrt]*/, $Zeitstring);
};

// Berechnung Parameter des Tages

If (($Wochentag >= 1 AND $Wochentag <= 5) AND													// Montag und Freitag
	 $Status == 'Heizbetrieb' AND
	 $Uhrzeit == '05:40') {																				// Start Heizbetrieb
	 SetValueString(38608 /*[Wohnzimmer\Heizung\Parameterbestimmung]*/, 'aktiv');    // Parameterbestimmung aktivieren, Regelung ausschalten
	 SetValueFloat(29142 /*[Wohnzimmer\Heizung\Starttemperatur]*/, $Isttemperatur);  // Startwert für Parameter setzen
    $str=chr(1).chr(255).chr(13);                                                   //Befehl(Motor 1).voll öffnen.chr(13) ist CR als Abschluß der Sequence
	 COMPort_SendText (38228 /*[Serial Port]*/ , $str);
	 SetValueFloat(13052 /*[Wohnzimmer\Heizung\Tu - Verzugszeit]*/, 0);              // alle nötigen Parameter erstmal auf Null
	 SetValueFloat(20705 /*[Wohnzimmer\Heizung\Tg - Ausgleichszeit]*/, 0);
	 SetValueFloat(34279 /*[Wohnzimmer\Heizung\esum - Integralanteil]*/, 0);
	 SetValueFloat(22624 /*[Wohnzimmer\Heizung\ealt]*/, 0);
	 SetValueFloat(14264 /*[Wohnzimmer\Heizung\Zieltemperatur]*/, 0);
    SetValueString(37358 /*[Wohnzimmer\Heizung\Regelungsart]*/, 'Aufheizen');
	 return;
};

If (($Wochentag < 1 OR $Wochentag > 5) AND														// Sonntag und Samstag
	  $Status == 'Heizbetrieb' AND
	  $Uhrzeit == '06:30') {			  																// Start Heizbetrieb
     SetValueString(38608 /*[Wohnzimmer\Heizung\Parameterbestimmung]*/, 'aktiv');   // Parameterbestimmung aktivieren, Regelung ausschalten
	  SetValueFloat(29142 /*[Wohnzimmer\Heizung\Starttemperatur]*/, $Isttemperatur); // Startwert für Parameter setzen
  	  $str=chr(1).chr(255).chr(13); 																	//Befehl(Motor 1).voll öffnen.chr(13) ist CR als Abschluß der Sequence
	  COMPort_SendText (38228 /*[Serial Port]*/ , $str);
     SetValueFloat(13052 /*[Wohnzimmer\Heizung\Tu - Verzugszeit]*/, 0);             // alle nötigen Parameter erstmal auf Null
     SetValueFloat(20705 /*[Wohnzimmer\Heizung\Tg - Ausgleichszeit]*/, 0);
     SetValueFloat(34279 /*[Wohnzimmer\Heizung\esum - Integralanteil]*/, 0);
     SetValueFloat(22624 /*[Wohnzimmer\Heizung\ealt]*/, 0);
     SetValueFloat(14264 /*[Wohnzimmer\Heizung\Zieltemperatur]*/, 0);
     SetValueString(37358 /*[Wohnzimmer\Heizung\Regelungsart]*/, 'Aufheizen');
     return;
};

If ($Status == 'Heizbetrieb' AND
	 ($Isttemperatur - $Starttemperatur) >= 0.1 AND												// Bedingung Verzugszeit
	 $Tu == 0 AND
	 $Parameterbestimmung == 'aktiv') {
    $updatezeit = IPS_GetVariable(38608 /*[Wohnzimmer\Heizung\Parameterbestimmung]*/);
	 $updatezeit = $updatezeit['VariableUpdated'];												// holen der Startzeit Heizbetrieb
	 $Tu = round((time() - $updatezeit) / 60);													// Berechnung Verzugszeit
    SetValueFloat(13052 /*[Wohnzimmer\Heizung\Tu - Verzugszeit]*/, $Tu);
};

If ($Status == 'Heizbetrieb' AND
	 $Tg == 0 AND
	 $Parameterbestimmung == 'aktiv' AND
	 $Zieltemperatur == 0) {
	 $Zieltemperatur = $Starttemperatur + (0.63 * ($Solltemperatur-$Starttemperatur));// Berechnung Zieltemperatur für Ausgleichszeit
    If ($Zieltemperatur >= $Solltemperatur ) {$Zieltemperatur = $Solltemperatur;};   // größer als Solltemperatur geht nicht
	 SetValueFloat(14264 /*[Wohnzimmer\Heizung\Zieltemperatur]*/, $Zieltemperatur);
};

If ($Status == 'Heizbetrieb' AND
	 $Isttemperatur >= $Zieltemperatur AND															// Bedingung Ausgleichszeit
	 $Tg == 0 AND
	 $Parameterbestimmung == 'aktiv') {
	 $updatezeit = IPS_GetVariable(13052 /*[Wohnzimmer\Heizung\Tu - Verzugszeit]*/);
	 $updatezeit = $updatezeit['VariableUpdated'];												// Beginn Ausgleichzeit ist Ende Verzugszeit
	 $Tg = round((time() - $updatezeit) / 60);													// Berechnung Ausgleichszeit
    SetValueFloat(20705 /*[Wohnzimmer\Heizung\Tg - Ausgleichszeit]*/, $Tg);			
    $Kp = 0.35 * 100/($Solltemperatur - $Starttemperatur)* $Tg / $Tu;					// Berechnung Proportionalbeiwert
    If ($Kp <= 50 ) {$Kp = 50;};  			                                          // Minimum für Kp
	 SetValueFloat(18350 /*[Wohnzimmer\Heizung\Kp - Proportionalbeiwert]*/, $Kp);		// nach Chien/Hrones/Reswick ohne Überschwingen
    $Ki = $Kp / (1.2 * $Tg);                                                        // Berechnung Integralbeiwert
	 If ($Ki >= 3 ) {$Ki = 3;};																		// Maximum für Ki
    SetValueFloat(43863 /*[Wohnzimmer\Heizung\Ki - Integralbeiwert]*/, $Ki);
    SetValueString(38608 /*[Wohnzimmer\Heizung\Parameterbestimmung]*/, 'fertig');	// Abschluß Parameterbestimmung, Aktivierung der Regelung
    SetValueString(37358 /*[Wohnzimmer\Heizung\Regelungsart]*/, 'Übergang - P-Regler');
};

// Regelung
If ($Parameterbestimmung == 'fertig' AND $Status == 'Heizbetrieb') {
	 $e = $Solltemperatur - $Isttemperatur; 					      							// Regelabweichung
	 SetValueFloat(31526 /*[Wohnzimmer\Heizung\e - Regelabweichung]*/, $e);
	 If ( $y > 1 AND $y < 100 ) {            		               							// Anti Wind Up Hold
	 	 $esum = $esum + $e;												   							// Integration I-Anteil
	 	 If ($esum <= -35 ) {$esum = -35;};                                           // Untere Begrenzung I-Anteil
	 	 If ($esum >= 35 ) {$esum = 35;};                                             // Obere Begrenzung I-Anteil
	 	 SetValueFloat(34279 /*[Wohnzimmer\Heizung\esum - Integralanteil]*/, $esum);
	 };		                                        
    $p = $Kp * $e;   																					// Proportionalanteil PI-Regler
	 SetValueFloat(54772 /*[Wohnzimmer\Heizung\p - Proportionalanteil]*/, $p);
	 $Pp = 100 * $e;                                                     				// Proportionalanteil P-Regler mit Kp=100 für Übergang
	 $i = $Ki * 2 * $esum;   																			// Integralanteil PI-Regler
	 SetValueFloat(30501 /*[Wohnzimmer\Heizung\i - Integralanteil]*/, $i);
	 $y = $p + $i; 																						// Stellgröße in % PI-Regler
	 $Py = $Pp;                                                        					// Stellgröße P-Regler Übergang
	 SetValueFloat(36158 /*[Wohnzimmer\Heizung\Stellgröße]*/, $y);
	 SetValueFloat(22624 /*[Wohnzimmer\Heizung\ealt]*/, $e);
	 If ($Py > $y AND $Regelungsart == 'Übergang - P-Regler') {$y = $Py;}            // P-Regler macht langsamer 'zu', Heizung arbeitet kontinuierlicher
	 elseif ($Py <= $y AND $Regelungsart == 'Übergang - P-Regler') {SetValueString(37358 /*[Wohnzimmer\Heizung\Regelungsart]*/, 'PI-Regler');}; // bei gleicher Stellgröße Umschalten auf PI-Regler
	 If ($y <= 0 ) {$y = 1;};		 													   			// untere Begrenzung Stellgröße - y=0 heißt Frostschutz 5%
	 If ($y > 100 ) {$y = 100;};										   							// obere Begrenzung Stellgröße
	 SetValueFloat(15174 /*[Wohnzimmer\Heizung\Ventilposition]*/, $y);
	 $Ventilposition = (round($y * 2.55));                      							// Prozentwerte in 0-255 umrechnen
	 $str=chr(1).chr($Ventilposition).chr(13); 			   	   							// Befehl(Motor 1).Daten.chr(13) ist CR als Abschluß der Sequence
	 COMPort_SendText (38228 /*[Serial Port]*/ , $str);
};


// Anregungen/Todo:
// - Meßwerte über mehrere Intervalle mitteln
// - dynamic anti wind up probieren

// PI-Regler reicht
// D-Anteil des PID-Reglers führt zu viel zu großen und unnützen Ventilbewegungen bei Temperaturänderung

Man kann das bestimmt auch eleganter programmieren, aber ich bin leider nicht der PHP-Profi.

Ach so, der FHT8i ist gerade für 10€ im Angebot.

Viele Grüße

Stephan

Sehr interessant,
habe mit gelesen und auch ich weiß, dass der D-Anteil unbedeutend ist.

Bessere Regler sind immer die PI_Regler.

Schön wäre auch zu erfahren, wie man eine selbst adaptierende Regelung hin bekommt.

Vielen Dank für die Erläuterung.
PS. FHT8i im Angebot und TH555 beim großen C für 5 Euro!!

Der erste Schritt zur selbst adaptierenden Regelung ist die eigenständige Bestimmung der Reglerparameter. Leider geht das nur zu Laufzeitbeginn, da nur beim Aufheizen die Brennerregelung eine Zeitlang nicht aktiv ist und man eine „fast echte“ Sprungantwort der Regelstrecke bekommt.

Für die Parameteränderung während der Laufzeit gibt es viele Ansätze. Z.B durch Einprägung einer kurzen Störgröße und der Analyse/Ermittlung der neuen Parameter. Dafür ist das System Heizung aber viel zu träge und außerdem pfuscht einem die Brennerregelung immer ins Handwerk.
Eine andere Möglichkeit wären vorgefertigte Ereignisstabellen (die man aber erst füttern muss) anhand derer man die Parameter ändert.

Man könnte also die Wettersymbole und Temperatur seiner Lieblingswetterseite für die Mittagszeit auswerten und beschließen, dass man bei morgentlichen Zimmertemperaturen nahe am Soll durch gezieltes Zusteuern der Ventile das Schnellaufheizen verhindert, da die Sonne tagsüber genügend Energie liefern wird.
Wie stellt man aber sicher, dass auch in den Räumen ohne diese Mittagssonne ein vernüftiges Raumklime herrscht?

Man könnte ein Toleranzband für die Temperatur festlegen und bei längerem Über- oder Unterschreiten die Werte für Kp anpassen. Wie unterscheidet man dann echtes Überschwingen von Fremdwärmeeinfluss??

Wer beruftätig ist und die Temperatur bei Abwesenheit wieder etwas absenkt, könnte die automatische Parameterbestimmung bei jedem größeren positiven Sollwertsprung erneut durchführen. Welchen Einfluss hat dann die Brennerregelung, da es sich hier nicht um einen echten Kaltstart handelt? Inwiefern beeinflussen sich die Räume gegenseitig, wenn nicht alle Türen geschlossen sind?

Man könnte die Zeiten mitloggen, die ein Raum, nach Abschalten der Heizung, benötigt, bis er sich auf eine Minimumwohlfühltemperatur abgekühlt hat. In Abhängigkeit von der Außentemperatur könnte man dann einzelne Räume schon Abschalten, bevor die Heizung regulär ausgeht.

Wenn man denn direkten Zugriff auf die Brennersteuerung hätte, könnte man auf diese Weise auch die Startzeiten variabel gestalten.
Oder die Regelung von Außen-/Vorlauftemperatursteuerung auf echte Wärmebedarfs-/Rücklauftemperatursteuerung umstricken.
Es hat also nicht zufällig irgendjemand eine Buderus W002 Schalteinheit im Regal liegen und dafür keine Verwendung mehr???

Aber Joachim hat recht, die Zeit für Experimente in diesem Winter neigt sich rapide dem Ende entgegen - aber der nächste Winter kommt bestimmt.

Grüße
Stephan

Hallo Leute,

ich freue mich sehr, dass die Diskussion endlich mal in Gange gekommen ist!:slight_smile:

Ich habe bei Dir tolle Ansätze entdeckt, u.a. die wöchentlichen Entkalkungsfahrt und ganz besonders hat mich die tägliche Neuberechnung der Verstärkungsfaktoren beeindruckt - auch wenn ich auf die Schnelle das Prinzip noch nicht 100% verstanden habe, ich muss mich dazu mal mit den Code intensicver auseinandersetzen.

Die Berechnung der Verstärkungsfaktoren ist sicherlich ein ganz wichtiger Punkt. Aber wie weit liegt diese Regelung besser oder schlechter als die des alten Dreh-Thermostates oder der Regelung durch das FHT80b?

Ein weiterer (positiver) Gesichtspunkt ist doch auf jeden Fall, dass ich bei Abwesenheit die Räume zentral (also durch IPS) heruntersteuern kann und auch bei geöffneten Fenster (sofern ein Kontakt vorhanden ist) den Heizkörper komplett herunterfahren kann…

Ich denke wir sind auf dem richtigem Weg…:wink:

Joachim

Nachtrag: Habe mir die 10€-Aktion nicht entgehen lassen, und noch mal vier Bausätze bestellt - da kommt dann wieder Arbeit auf Helmut zu! :wink:

Die Regelung ist definitiv besser als die normalen Thermostate. Ich habe mich schon immer darüber geärgert, dass der Thermostat auf 20° steht und ich bei 23° immer noch einen warmen Heizkörper habe. Das gibt es jetzt nicht mehr und schneller warm wird es morgens auch.

Die FHT80b kenne ich nicht. Ich wollte mir neben dem Temp-Sensor nicht noch eine weiße Kiste in jedes Zimmer hängen - wirklich hübsch sind die nämlich nicht.

Grüße

Stephan

…Stephan - ich merke wir verstehen uns, die Motivation ist bei mir sehr ähnlich gelagert…:wink:

Ich wollte auch die FHT80b nicht in die Zimmer hängen, Temperaturmessung läuft bei mir über 1-Wire.

Joachim

Hallo Stephan,

ich habe noch mal eine Frage: Hast Du mal mitgeloggt, wie sich die Verstärkungsfaktoren an den verschiedenen Tagen verändert haben?
Gibt es da ein „von-bis“? Einen Durchschnittswert?

Joachim

Es ist schon wieder viel zu spät - die untere Grenze habe ich auf 50 gesetzt, um nicht schlechter zu sein als ein normaler Thermostat und der obere Wert war wahrscheinlich noch nie über 120, nagel mich da aber bitte nicht fest. Im Augenblick bin ich, bis auf einen Raum, überall bei 50. Ich kann das loggen ja mal einschalten.

Grüße
Stephan

Hallo Leute,

ich habe jetzt diverse Anregungen aus Stephans Skript mit eingebaut und den Code nach einem Tipp von Rainer etwas „aufgeräumt“:

//e = aktuelle Reglerabweichung -> Soll-Ist
//ealt = vorherige Reglerabweichung
//esum = die Summe aller bisherigen Abweichungen e
//y = Antwort -> muss im Bereich zwischen 0-100 sein
//esum = esum + e
//y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta
//ealt = e
$Kp=5; //Kp = Verstärkungsfaktor Proportionalregler
$Ki=2.5; //Ki = Verstärkungsfaktor Integralregler
$Kd=0; //Kd = Verstärkungsfaktor Differenzialregler
$Script = IPS_GetScript($IPS_SELF);
$Ta=Round((time() - $Script['LastExecute'])/60,0); //Ta = Rechenschrittweite (Abtastzeit)

// Objekt-ID der genutzten Variablen, Sensoren und Aktoren
$SollTemperatur = 54918 /*[Raum-Temperaturen\Büro Ania\Soll Temperatur]*/;  //*[Raum-Temperaturen\Büro Ania\Soll Temperatur]*/
$IstTemperatur = 15617 /*[Raum-Temperaturen\Büro Ania\Temperatur]*/;  //*[Raum-Temperaturen\Büro Ania\Temperatur]*/
$HeizungsStellelement = 39465 /*[Raum-Temperaturen\Büro Ania\Heizungs-Stellelement]*/;  //*[Raum-Temperaturen\Büro Ania\Heizungs-Stellelement]*/
$SummeRegelabweichungen = 33897 /*[Raum-Temperaturen\Büro Ania\Hilfsvariablen\Summe Regelabweichungen]*/;  //*[Raum-Temperaturen\Büro Ania\Hilfsvariablen\Summe Regelabweichungen]*/
$VorherigeRegelabweichung = 33459 /*[Raum-Temperaturen\Büro Ania\Hilfsvariablen\Vorherige Regelabweichung]*/;  //*[Raum-Temperaturen\Büro Ania\Hilfsvariablen\Vorherige Regelabweichung]*/
$TagDesMonats = 10856 /*[Sonstige Daten\Sonstige Variablen\Sonstige Variablen\Tag des Monats]*/; //*[Sonstige Daten\Sonstige Variablen\Sonstige Variablen\Tag des Monats]*/
$AktuelleUhrzeit = 37001 /*[Sonstige Daten\Sonstige Variablen\Sonstige Variablen\Aktuelle Uhrzeit]*/; //*[Sonstige Daten\Sonstige Variablen\Sonstige Variablen\Aktuelle Uhrzeit]*/
$Stellmotorsender = 22578 /*[Stellmotorsender]*/; //*[Stellmotorsender]*/
$StellmotorAdresseDaten = "0x02";
$StellmotorAdresseEntkalkung = "0x06";

echo "Zeitdifferenz: " .$Ta. " ";
//aktuelle Regelabweichung bestimmen
$e = GetValueFloat($SollTemperatur)- GetValueFloat($IstTemperatur);
echo "Regelabweichung: ".$e." ";

// Die Summe aller vorherigen Regelabweichungen bestimmen
If ((GetValueInteger($HeizungsStellelement) == 0) and ($e < 0))
	// Die Negativ-Werte sollen nicht weiter aufsummiert werden, wenn der Stellmotor schon auf 0 ist
	{
   $esum = (GetValueFloat($SummeRegelabweichungen));
   }
elseif ((GetValueInteger($HeizungsStellelement) == 100) and ($e > 0))
	// Die Positiv-Werte sollen nicht weiter aufsummiert werden, wenn der Stellmotor schon auf 100 ist
	{
   $esum = (GetValueFloat($SummeRegelabweichungen));
   }
else
	{
	$esum = (GetValueFloat($SummeRegelabweichungen)) + $e;
	}

echo "Summe Regelabweichungen: ".$esum." ";
SetValueFloat($SummeRegelabweichungen, $esum);

// Die vorherige Regelabweichung ermitteln
$ealt = GetValueFloat($VorherigeRegelabweichung);
// Die Regelgröße nun errechnen

echo "Produkt Kp * e = : ".$Kp * $e." ";
echo "Produkt Ki * Ta * esum = : ".$Ki * $Ta * $esum." ";

//Schutzmechanismus falls Skript innerhalb einer Minute zweimal ausgeführt wird
If ($Ta < 1)
{
$Ta = 1;
}

// Die Berechnung des neuen Regelwertes
$y = ($Kp * $e + $Ki * $Ta * $esum + $Kd * ($e - $ealt) / $Ta);

// Vorherige Regelabweichung durch jetzige ersetzen
SetValueFloat($VorherigeRegelabweichung, $e);

$NeuerWert = $y;

If ($NeuerWert < 0)
	{
	$NeuerWert = 0;
	}
elseif ($NeuerWert > 100)
	{
	$NeuerWert = 100;
	}
echo "Neue Regelgrößen: ".$NeuerWert." ";
SetValueInteger($HeizungsStellelement, $NeuerWert);
//Umskalierung auf 0-255 und Errechnung des HEXwertes
$Sendewert = dechex(Round(($NeuerWert * 2.55)));
echo "Gerundeter Wert: ".Round(($NeuerWert * 2.55))." ";
echo "Gesendeter Wert: ".$Sendewert;
$Sendewert = "0x$Sendewert";
echo $Sendewert." ";

// Stellwert senden
If ((GetValueInteger($TagDesMonats) == 1) and (GetValueString($AktuelleUhrzeit) == "08:00"))
{
//mit der monatliche Entkalkungsfahrt
HID_SendEvent($Stellmotorsender, 0, chr($StellmotorAdresseEntkalkung).chr($Sendewert).chr(0x02));
echo "Entkalkungsfahrt Büro Ania durchgeführt";
}
else
{
//nur Stellwert ändern
HID_SendEvent($Stellmotorsender, 0, chr($StellmotorAdresseDaten).chr($Sendewert).chr(0x02));
}

//Akustisches Low-Bat-Signal (wird an alle Aktoren gesendet)
If (GetValueString($AktuelleUhrzeit) == "22:00")
{
// nach 22.00 Uhr sperren
HID_SendEvent($Stellmotorsender, 0, chr(0x22).chr(0x00).chr(0x02));
}

If (GetValueString($AktuelleUhrzeit) == "08:00")
{
// nach 08.00 Uhr freigeben
HID_SendEvent($Stellmotorsender, 0, chr(0x21).chr(0x00).chr(0x02));
}

Jetzt mit dabei:

  • Eine monatliche Entkalkungsfahrt, jeweils am 01. des Monats um 8:00 Uhr
  • Unterdrückung des Bat-Low-Signals zwischen 22:00 und 8:00 Uhr
  • Keine weitere Vergrößerung des I-Anteils, wenn der Antrieb schon auf 100% steht
  • Zusammenfassung und Benennung der erforderlichen Variablen, Sensoren und Aktoren im Programmkopf

Joachim