PID20 - Der PID-Regler: Unterschied zwischen den Versionen
John (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
(Ersetzung von Forum-Links mit Vorlage Link2Forum) |
||
(34 dazwischenliegende Versionen von 7 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{ | {{Infobox Modul | ||
|Name=PID20 | |||
|ModPurpose=Regler nach P-I-D Algorithmus | |||
|ModType=d | |||
|ModCmdRef=PID20 | |||
|ModForumArea=Automatisierung | |||
|ModTechName=98_PID20.pm | |||
|ModOwner=John ({{Link2FU|806|Forum}} / [[Benutzer Diskussion:John|Wiki]]) | |||
}} | |||
'''PID20''' ist ein Modul, das nach dem P-I-D Algorithmus einen Regler realisiert. | '''PID20''' ist ein Modul, das nach dem P-I-D Algorithmus einen Regler realisiert. | ||
== Projekt-Status == | == Projekt-Status == | ||
Das | Das Modul ist seit dem 26.03.2014 Bestandteil von FHEM. | ||
== Features == | == Features == | ||
* einstellbarer Bewertungs-/ | * einstellbarer Bewertungs-/Berechnungszyklus | ||
* Überwachung des Istwert-Gebers über dessen Zeitstempel (Sensorausfall) | * Überwachung des Istwert-Gebers über dessen Zeitstempel (Sensorausfall) | ||
* Skalierbarkeit der Ausgabehäufigkeit an das Stellglied über Zeit und Mindeständerung | * Skalierbarkeit der Ausgabehäufigkeit an das Stellglied über Zeit und Mindeständerung | ||
* Zwangsausgabe an das Stellglied nach Ablauf eines einstellbaren Zeitintervalls | * Zwangsausgabe an das Stellglied nach Ablauf eines einstellbaren Zeitintervalls | ||
* Notstellung des Stellgliedes, falls Istwert-Geber ausgefallen ist | * Notstellung des Stellgliedes, falls Istwert-Geber ausgefallen ist | ||
* Begrenzung des | * Begrenzung des Stellbereichs nach oben und unten | ||
* Festlegung der Nachkommastellen (0..5) des Ausgabewertes zum Stellglied | * Festlegung der Nachkommastellen (0..5) des Ausgabewertes zum Stellglied | ||
* Festlegen einer minimalen Regelabweichung, ab der der Regler aktiv wird | * Festlegen einer minimalen Regelabweichung, ab der der Regler aktiv wird | ||
* Festlegen des Reading-Namens für den Sollwert | * Festlegen des Reading-Namens für den Sollwert | ||
* Festlegen des Reading-Namens für den Istwert | * Festlegen des Reading-Namens für den Istwert | ||
* Invertierung des | * Invertierung des Reglerwirksinns | ||
* Festlegen der minimalen Aktualisierungsrate der Readings | * Festlegen der minimalen Aktualisierungsrate der Readings | ||
* Festlegen der Proportionalitätskonstanten P,I,D | * Festlegen der Proportionalitätskonstanten P,I,D | ||
== | == Thread im Forum == | ||
{{Link2Forum|Topic=17067|Message=111615|LinkText=Diskussion zu PID20 im Forum}} | |||
=== Define === | === Define === | ||
<code> | :<code>define <name> PID20 sensor[:reading[:regexp]] actor:cmd</code> | ||
</code> | |||
=== Attribute === | === Attribute === | ||
Zeile 35: | Zeile 38: | ||
! Parameter !! Wertebereich !! Default !! Beschreibung | ! Parameter !! Wertebereich !! Default !! Beschreibung | ||
|- | |- | ||
|pidActorValueDecPlaces||[0..5]||0||Anzahl der | |pidActorValueDecPlaces||[0..5]||0||Anzahl der Nachkommastellen für Ausgabewert zu Aktor | ||
|- | |- | ||
|pidActorInterval||uint||180||minimale Wartezeit in Sekunden, bis eine neue Ausgabe an das Stellglied erfolgen kann | |pidActorInterval||uint||180||minimale Wartezeit in Sekunden, bis eine neue Ausgabe an das Stellglied erfolgen kann | ||
Zeile 56: | Zeile 59: | ||
|pidCalcInterval||uint||60||Berechnungszyklus in Sekunden, nach dem die PID-Berechnung durchgeführt wird. | |pidCalcInterval||uint||60||Berechnungszyklus in Sekunden, nach dem die PID-Berechnung durchgeführt wird. | ||
|- | |- | ||
|pidDeltaTreshold|| | |pidDeltaTreshold||pos. float||0||wenn die Regeldifferenz(delta) kleiner als pidDeltaThreshold, dann wird der Regler eingefroren (state=idle) | ||
|- | |- | ||
|pidDesiredName||string||desired||Name für das Reading, das den Sollwert für den Regler aufnehmen soll | |pidDesiredName||string||desired||Name für das Reading, das den Sollwert für den Regler aufnehmen soll | ||
Zeile 71: | Zeile 74: | ||
|- | |- | ||
|pidFactor_I||pos. float||0 | |pidFactor_I||pos. float||0.25||Proportionalitätskonstante für I-Anteil | ||
|- | |- | ||
Zeile 99: | Zeile 102: | ||
* delta, die aktuelle Regeldifferenz | * delta, die aktuelle Regeldifferenz | ||
* desired (Name ist variabel), der Sollwert | * desired (Name ist variabel), der Sollwert | ||
* measured (Name ist variabel), der aktuelle Wert vom | * measured (Name ist variabel), der aktuelle Wert vom Istwert-geber | ||
* p_p, der P-Anteil des Ausgabewertes für das Stellglied | * p_p, der P-Anteil des Ausgabewertes für das Stellglied | ||
* p_i, der I-Anteil des Ausgabewertes für das Stellglied | * p_i, der I-Anteil des Ausgabewertes für das Stellglied | ||
Zeile 106: | Zeile 109: | ||
'''delta''' | '''delta''' | ||
<code> | |||
:<code>delta = desired - measured (also Sollwert-Istwert)</code> | |||
</code> | |||
'''actuation''' | '''actuation''' | ||
:<code>actuation = actuationCalc</code> | |||
jedoch begrenzt durch pidActorLimitLower und pidActorLimitUpper und formatiert via pidActorValueDecPlaces | |||
'''actuationCalc''' | '''actuationCalc''' | ||
Der Ausgabewert für das Stellglied wird wie folgt berechnet | Der Ausgabewert für das Stellglied wird wie folgt berechnet | ||
:<code>actuationCalc = p_p + p_i + p_d</code> | |||
<code> | |||
</code> | |||
'''state''' | '''state''' | ||
Zeile 138: | Zeile 135: | ||
| idle || Berechnung ist inaktiv | | idle || Berechnung ist inaktiv | ||
|- | |- | ||
| processing || Berechnung ist | | processing || Berechnung ist aktiv, Normalbetrieb | ||
|- | |- | ||
| alarm || Ausnahmezustand, z.B. Timout des Istwert-Gebers | | alarm || Ausnahmezustand, z.B. Timout des Istwert-Gebers | ||
|} | |} | ||
== Inbetriebnahme == | == Inbetriebnahme == | ||
* PID20 definieren, hier mit HMS100TF als Istwert-Geber für die Temperatur und ein MAX-Thermostat als Stellglied; Auslegung für eine Fußbodenheizung (sehr träge) | |||
* PID20 definieren, hier mit HMS100TF als | :<code>define PID.FUBO PID20 DG.BAD.TF:temperature HT.FUBO:maxValveSetting</code> | ||
< | ** <sensor> = "DG.BAD.TF": Name des Istwert-Geber s (HMS100TF) | ||
** "DG.BAD.TF": Name des | ** <reading> = "temperature": das Reading vom HMS100TF, das die Temperatur liefert | ||
** "temperature": das Reading vom HMS100TF, das die Temperatur liefert | ** <regexp> = nicht definiert, wir können also direkt den Wert des Readings verwenden | ||
** "HT.FUBO" : Name des MAX-Thermostats, das als Stellglied verwendet wird | ** <actor> = "HT.FUBO" : Name des MAX-Thermostats, das als Stellglied verwendet wird | ||
** "maxValveSetting" : Das | ** <cmd> = "maxValveSetting" : Das Kommando mit dem PID20 die Stellausgabe realisieren soll | ||
:Letztlich wird mit <actor> und <cmd> Folgendes ausgeführt: | |||
::<code>set <actor> <cmd> <setting-value></code> | |||
< | |||
'''Zusätzlich noch einige Attribute anpassen:''' | |||
< | * die Ausgabehäufigkeit an das Stellglied auf 15 Minuten begrenzen | ||
:<code>attr PID.FUBO pidActorInterval 900</code> | |||
< | * nur dann einen Wert an das Stellglied ausgeben, wenn die Differenz zum Altwert >= 5% | ||
:<code>attr PID.FUBO pidActorTreshold 5</code> | |||
< | * Nachommastellen für das Stellglied festlegen; MAX-Thermostate erlauben nur Werte ohne Nachkommastellen | ||
:<code>attr PID.FUBO pidActorValueDecPlaces 0</code> | |||
< | * I-Faktor festlegen; Überlegung: bei einer Regelabweichung von 1 Grad, soll der I-Anteil um 0.2% pro Minute inkrementieren/dekrementieren | ||
:<code>attr PID.FUBO pidFactor_I 0.2</code> | |||
* P-Faktor festlegen; Überlegung:Bei einer Regel-Abweichung von 1 Grad, soll der P-Anteil +/-50% betragen | |||
:<code>attr PID.FUBO pidFactor_P 50</code> | |||
* Häufigkeit der Events begrenzen: Die Readings werden im Intervall von "pidCalcInterval" aktualisiert. Die damit erzeugten Events kann man mit den Standard-Mechanismen von FHEM begrenzen. Hier wird festgelegt, dass die Readings nur dann einen Event feuern, wenn diese sich tatsächlich ändern. Der Wert hinter dem Doppelpunkt, gibt die Mindeständerung an. Fehlt dieser, feuert jede Änderung einen Event. | |||
:<code>attr PID.FUBO event-on-change-reading actuation:1,actuationCalc:0.5,delta:0.2,desired,measured:0.2,p_d:0.1,p_i:1.0,p_p:1.0</code> | |||
* Events feuern, wenn sich über lange Zeit ein Reading nicht ändert: wenn sich z.B. desired über Stunden nicht ändert, so wird kein einziger Event gefeuert. Mit nachfolgender Einstellung erreicht man, dass ein Event auch dann erzeugt wird, wenn sich das Reading nach einer festgelegten Zeit nicht ändert(sinnvoll für Charts, hier z.B. alle 30 Minuten) | |||
:<code>attr PID.FUBO event-min-interval actuation:1800,actuationCalc:1800,delta:1800,desired:1800,measured:1800,p_d:1800,p_i:1800,p_p:1800</code> | |||
'''Chart einrichten''' | |||
Es ist für das Einstellen der Regel-Faktoren (P,I,D) überaus hilfreich, das Verhalten über die Zeit aufzuzeichnen, um das Verhalten objektiv beurteilen zu können. | |||
;Zunächst ein Filelog einrichten | |||
:define PID.FUBO.File FileLog ./log/PID.FUBO-%Y.log PID\.FUBO | |||
:attr PID.FUBO.File logtype text | |||
Danach ein Chart definieren, angelehnt an folgendes Beispiel: | |||
[[Datei:13_12_03_PID_ChartDef.png]] | |||
Zeile 166: | Zeile 183: | ||
== Hintergrund-Informationen == | == Hintergrund-Informationen == | ||
=== list <pid-name> === | === list <pid-name> === | ||
< | <pre> | ||
Internals: | Internals: | ||
DEF DG.BAD.TF PID.Actor:state | DEF DG.BAD.TF PID.Actor:state | ||
Zeile 220: | Zeile 237: | ||
room PID | room PID | ||
verbose 4 | verbose 4 | ||
</pre> | |||
</ | |||
=== Anti-WindUp-Strategie === | === Anti-WindUp-Strategie === | ||
Der integrale Anteil des PID-Reglers wird ohne Gegenmassnahmen auch dann weiter integriert, | Der integrale Anteil des PID-Reglers wird ohne Gegenmassnahmen auch dann weiter integriert, wenn das Stellglied bereits an seine Grenzen gestossen ist. Dies hat den Nachteil, dass nach einer Reduzierung der Regeldifferenz lange Wartezeiten entstehen können, bis das Stellglied reagiert. Dies nennt man den WindUP-Effekt. Hierzu wurde die folgende Strategie entwickelt: | ||
wenn das Stellglied bereits an seine Grenzen gestossen ist. | |||
Dies hat den Nachteil, dass nach einer Reduzierung der Regeldifferenz lange Wartezeiten entstehen können, bis das | |||
Stellglied reagiert. | |||
Dies nennt man den WindUP-Effekt. | |||
Hierzu wurde die folgende Strategie entwickelt: | |||
[[Datei:13 10 20 PID Windup.png|WindUP]] | [[Datei:13 10 20 PID Windup.png|WindUP]] | ||
Zeile 235: | Zeile 246: | ||
Sobald das rechnerische Stellsignal (Ventilstellung Calc=actuationCalc) die obere Grenze des Stellgliedes überschreitet (pidActorLimitUpper) oder die untere Grenze unterschreitet (pidActorLimitLower), wird die Integration des I-Anteils eingefroren. | Sobald das rechnerische Stellsignal (Ventilstellung Calc=actuationCalc) die obere Grenze des Stellgliedes überschreitet (pidActorLimitUpper) oder die untere Grenze unterschreitet (pidActorLimitLower), wird die Integration des I-Anteils eingefroren. | ||
'''Am Beispiel:''' | |||
An Position L1 überschreitet der rechnerische Ausgabewert des Stellgliedes die obere Grenze (100%). Der I-Anteil verändert sich nicht mehr bis zur Position L2. Hier unterschreitet der Ausgabewert die obere Grenze, der I-Anteil kann wieder verändert werden. | |||
An Position L1 überschreitet der rechnerische Ausgabewert des Stellgliedes die obere Grenze (100%). | |||
Der I-Anteil verändert sich nicht mehr bis zur Position L2. Hier unterschreitet der | |||
obere Grenze, der I-Anteil kann wieder verändert werden. | |||
== Fragen und Antworten == | == Fragen und Antworten == | ||
=== Wie kann ich den I-Anteil (p_i) im Regler auf 0 setzen ? === | |||
Dies ist nach folgender Anweisung möglich: | |||
<pre>set <Pid-Name> restart <p_p + p_d></pre> | |||
=== Temperatur im Raum steigt nicht oder stark verzögert, was kann ich tun? === | |||
==== 1. Fehlerquelle: Heizsystem ist nicht ausreichend entlüftet ==== | |||
In diesem Fall behindern die Luftblasen im System den Durchfluss des Heizmediums. | |||
Der Heizkörper erwärmt sich nur teilweise oder "gluckert". Hier ist das Entlüften der Heizkörper angesagt. | |||
Natürlich können sich die Gasblasen an anderer Stelle befinden. Normalerweise sorgen automatische Entlüfter dafür, dass das Gas entweichen kann. | |||
Aber auch diese "verkalken" im Lauf der Zeit. | |||
==== 2. Fehlerquelle: Totzone beim Stellglied ==== | |||
Der Temperaturanstieg erfolgt erst ab einer bestimmten Ventilöffnung von xy%. | |||
Der PID-Regler geht davon aus, dass jede Änderung des Stellausgangs auf die Regelgröße wirkt (also bei Ventil weiter öffnen, wird mehr Wärme abgegeben). | |||
Ist dies nicht der Fall, wird der PID über die Zeit (I-Anteil) das Ventil weiter öffnen. Allerdings vergeht hierbei Zeit und damit leidet die Regelgüte. | |||
Es ist also wichtig die Totzone zu ermitteln und im Attribut pidActorLimitLower zu hinterlegen. | |||
==== 3. Fehlerquelle: Hydraulische Fehlanpassung ==== | |||
Wenn einzelne Heizkreise einen sehr kleinen hydraulischen Widerstand aufweisen, kann es passieren, dass Heizkreise mit höherem Widerstand zeitweise unterversorgt sind. | |||
Erst wenn die gut versorgten Heizkreise die Ventile schließen (Soll-Temperatur ist erreicht), werden die Heizkreise mit hohem Widerstand ausreichend versorgt. | |||
Dies kann man dank FHEM sehr gut über die Charts nachvollziehen. | |||
Es ist regelungstechnisch, ökologisch und energetisch absolut sinnvoll geregelte Hocheffizienz-Pumpen im Heizkreis einzusetzen. Diese sorgen für konstanten Druck im Hauptstrang bei sehr geringen Energiebedarf. | |||
Man kann gezielt den hydraulischen Widerstand einzelner Thermostate erhöhen, indem man deren maximale Ventilöffnung begrenzt. | |||
Dies erreicht man durch Reduzieren des Wertes pidActorLimitUpper. Dies ist gleichbedeutend mit der Erhöhung des hydraulischen Widerstandes durch voreinstellbare Heizungsventile beim hydraulischen Abgleich. | |||
== Weblinks == | == Weblinks == | ||
* {{Link2Forum|Topic=15060|LinkText=Initialer Forumseintrag zur Überarbeitung des PID-Moduls}} | |||
* | |||
* [http://de.wikipedia.org/wiki/Regler Wikipedia Regler] | * [http://de.wikipedia.org/wiki/Regler Wikipedia Regler] | ||
[[Kategorie:Glossary]] | [[Kategorie:Glossary]] | ||
[[Kategorie:Regelungstechnik]] | [[Kategorie:Regelungstechnik]] |
Aktuelle Version vom 19. März 2017, 20:49 Uhr
PID20 | |
---|---|
Zweck / Funktion | |
Regler nach P-I-D Algorithmus | |
Allgemein | |
Typ | Gerätemodul |
Details | |
Dokumentation | EN / DE |
Support (Forum) | Automatisierung |
Modulname | 98_PID20.pm |
Ersteller | John (Forum / Wiki) |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
PID20 ist ein Modul, das nach dem P-I-D Algorithmus einen Regler realisiert.
Projekt-Status
Das Modul ist seit dem 26.03.2014 Bestandteil von FHEM.
Features
- einstellbarer Bewertungs-/Berechnungszyklus
- Überwachung des Istwert-Gebers über dessen Zeitstempel (Sensorausfall)
- Skalierbarkeit der Ausgabehäufigkeit an das Stellglied über Zeit und Mindeständerung
- Zwangsausgabe an das Stellglied nach Ablauf eines einstellbaren Zeitintervalls
- Notstellung des Stellgliedes, falls Istwert-Geber ausgefallen ist
- Begrenzung des Stellbereichs nach oben und unten
- Festlegung der Nachkommastellen (0..5) des Ausgabewertes zum Stellglied
- Festlegen einer minimalen Regelabweichung, ab der der Regler aktiv wird
- Festlegen des Reading-Namens für den Sollwert
- Festlegen des Reading-Namens für den Istwert
- Invertierung des Reglerwirksinns
- Festlegen der minimalen Aktualisierungsrate der Readings
- Festlegen der Proportionalitätskonstanten P,I,D
Thread im Forum
Define
define <name> PID20 sensor[:reading[:regexp]] actor:cmd
Attribute
Parameter | Wertebereich | Default | Beschreibung |
---|---|---|---|
pidActorValueDecPlaces | [0..5] | 0 | Anzahl der Nachkommastellen für Ausgabewert zu Aktor |
pidActorInterval | uint | 180 | minimale Wartezeit in Sekunden, bis eine neue Ausgabe an das Stellglied erfolgen kann |
pidActorThreshold | uint | 1 | Notwendige minimale Änderung zum Altwert der Stellgliedausgabe, damit diese erneut erfolgt |
pidActorErrorAction | [freeze, errorPos] | freeze | legt das Verhalten der Ausgabe zum Stellglied fest, wenn der Istwert nicht innerhalb von <pidSensorTimeout> aktualisiert wurde (Sensor-Ausfall) freeze: Position des Stellgliedes beibehalten |
pidActorErrorPos | int | 0 | Diese Position ist einzunehmen, wenn pidActorErrorAction auf errorPos steht und der Istwert-Geber ausgefallen ist. |
pidActorKeepAlive | uint | 1800 | Spätestens nach dieser Zeit erfolgt eine Zwangsausgabe an das Stellglied
(wenn PID nicht disabled und nicht stopped) |
pidActorLimitLower | float | 0 | untere Begrenzung für das Stellglied |
pidActorLimitUpper | float | 100 | obere Begrenzung für das Stellglied |
pidCalcInterval | uint | 60 | Berechnungszyklus in Sekunden, nach dem die PID-Berechnung durchgeführt wird. |
pidDeltaTreshold | pos. float | 0 | wenn die Regeldifferenz(delta) kleiner als pidDeltaThreshold, dann wird der Regler eingefroren (state=idle) |
pidDesiredName | string | desired | Name für das Reading, das den Sollwert für den Regler aufnehmen soll |
pidMeasuredName | string | measured | Name für das Reading, das den Istwert für den Regler aufnehmen soll |
pidSensorTimeout | uint | 3600 | Zeitlimit in Sekunden, nach dessen Überschreitung der Ausfall des Istwert-Gebers anzunehmen ist |
pidReverseAction | [0,1] | 0 | Umgekehrter Wirksinn des Reglers |
pidUpdateInterval | uint | 300 | Zeitlimit in Sekunden, nach der ein Zwangsupdate der Readings erfolgen muss (Kurvendarstellung). |
pidFactor_P | pos. float | 25 | Proportionalitätskonstante für P-Anteil |
pidFactor_I | pos. float | 0.25 | Proportionalitätskonstante für I-Anteil |
pidFactor_D | pos. float | 0 | Proportionalitätskonstante für D-Anteil |
disable | [0,1] | 0 | Freigabe/Sperren des Reglers |
Setter
desired
- Funktion: Sollwert einstellen
- Name des Setters kann vom Anwender über das Attribute "pidDesiredName" definiert werden
start
- PID nimmt den Betrieb wieder auf, es werden P-, I- und D-Anteil vor dem Stop übernommen
stop
- PID geht in den Zustand stopped; alles wird praktisch eingefroren
restart
- arbeitet zunächst wie Start, jedoch gibt man an, mit welchen Prozentwert der Stellausgang anfangs stehen soll
Readings
- actuation liefert den tatsächlichen Ausgabewert an das Stellglied
- actuationCalc liefert den internen Rechenwert des Ausgabewertes für das Stellglied(ohne Begrenzung)
- delta, die aktuelle Regeldifferenz
- desired (Name ist variabel), der Sollwert
- measured (Name ist variabel), der aktuelle Wert vom Istwert-geber
- p_p, der P-Anteil des Ausgabewertes für das Stellglied
- p_i, der I-Anteil des Ausgabewertes für das Stellglied
- p_d, der D-Anteil des Ausgabewertes für das Stellglied
- state, der Betriebszustand des Reglers
delta
delta = desired - measured (also Sollwert-Istwert)
actuation
actuation = actuationCalc
jedoch begrenzt durch pidActorLimitLower und pidActorLimitUpper und formatiert via pidActorValueDecPlaces
actuationCalc
Der Ausgabewert für das Stellglied wird wie folgt berechnet
actuationCalc = p_p + p_i + p_d
state
state | Erläuterung |
---|---|
disabled | PID-Instanz ist inaktiv |
initializing | Modul wurde initialisiert |
idle | Berechnung ist inaktiv |
processing | Berechnung ist aktiv, Normalbetrieb |
alarm | Ausnahmezustand, z.B. Timout des Istwert-Gebers |
Inbetriebnahme
- PID20 definieren, hier mit HMS100TF als Istwert-Geber für die Temperatur und ein MAX-Thermostat als Stellglied; Auslegung für eine Fußbodenheizung (sehr träge)
define PID.FUBO PID20 DG.BAD.TF:temperature HT.FUBO:maxValveSetting
- <sensor> = "DG.BAD.TF": Name des Istwert-Geber s (HMS100TF)
- <reading> = "temperature": das Reading vom HMS100TF, das die Temperatur liefert
- <regexp> = nicht definiert, wir können also direkt den Wert des Readings verwenden
- <actor> = "HT.FUBO" : Name des MAX-Thermostats, das als Stellglied verwendet wird
- <cmd> = "maxValveSetting" : Das Kommando mit dem PID20 die Stellausgabe realisieren soll
- Letztlich wird mit <actor> und <cmd> Folgendes ausgeführt:
set <actor> <cmd> <setting-value>
Zusätzlich noch einige Attribute anpassen:
- die Ausgabehäufigkeit an das Stellglied auf 15 Minuten begrenzen
attr PID.FUBO pidActorInterval 900
- nur dann einen Wert an das Stellglied ausgeben, wenn die Differenz zum Altwert >= 5%
attr PID.FUBO pidActorTreshold 5
- Nachommastellen für das Stellglied festlegen; MAX-Thermostate erlauben nur Werte ohne Nachkommastellen
attr PID.FUBO pidActorValueDecPlaces 0
- I-Faktor festlegen; Überlegung: bei einer Regelabweichung von 1 Grad, soll der I-Anteil um 0.2% pro Minute inkrementieren/dekrementieren
attr PID.FUBO pidFactor_I 0.2
- P-Faktor festlegen; Überlegung:Bei einer Regel-Abweichung von 1 Grad, soll der P-Anteil +/-50% betragen
attr PID.FUBO pidFactor_P 50
- Häufigkeit der Events begrenzen: Die Readings werden im Intervall von "pidCalcInterval" aktualisiert. Die damit erzeugten Events kann man mit den Standard-Mechanismen von FHEM begrenzen. Hier wird festgelegt, dass die Readings nur dann einen Event feuern, wenn diese sich tatsächlich ändern. Der Wert hinter dem Doppelpunkt, gibt die Mindeständerung an. Fehlt dieser, feuert jede Änderung einen Event.
attr PID.FUBO event-on-change-reading actuation:1,actuationCalc:0.5,delta:0.2,desired,measured:0.2,p_d:0.1,p_i:1.0,p_p:1.0
- Events feuern, wenn sich über lange Zeit ein Reading nicht ändert: wenn sich z.B. desired über Stunden nicht ändert, so wird kein einziger Event gefeuert. Mit nachfolgender Einstellung erreicht man, dass ein Event auch dann erzeugt wird, wenn sich das Reading nach einer festgelegten Zeit nicht ändert(sinnvoll für Charts, hier z.B. alle 30 Minuten)
attr PID.FUBO event-min-interval actuation:1800,actuationCalc:1800,delta:1800,desired:1800,measured:1800,p_d:1800,p_i:1800,p_p:1800
Chart einrichten
Es ist für das Einstellen der Regel-Faktoren (P,I,D) überaus hilfreich, das Verhalten über die Zeit aufzuzeichnen, um das Verhalten objektiv beurteilen zu können.
- Zunächst ein Filelog einrichten
- define PID.FUBO.File FileLog ./log/PID.FUBO-%Y.log PID\.FUBO
- attr PID.FUBO.File logtype text
Danach ein Chart definieren, angelehnt an folgendes Beispiel:
Hintergrund-Informationen
list <pid-name>
Internals: DEF DG.BAD.TF PID.Actor:state NAME PID.PID NR 616 NTFY_ORDER 50-PID.PID STATE processing TYPE PID Readings: 2013-10-20 17:13:41 actuation 97 2013-10-20 17:21:42 actuationCalc 97.2079999999999 2013-10-20 17:21:42 delta 0.199999999999999 2013-10-20 17:13:41 desired 22 2013-10-20 17:13:41 measured 21.8 2013-10-20 17:21:42 p_d 0 2013-10-20 17:21:42 p_i 92.2079999999999 2013-10-20 17:21:42 p_p 4.99999999999998 2013-10-20 17:21:42 state processing Helper: actor PID.Actor actorCommand state actorErrorAction freeze actorErrorPos 0 actorInterval 300 actorKeepAlive 1800 actorLimitLower 0 actorLimitUpper 100 actorThreshold 4 actorTimestamp 2013-10-20 17:13:41 actorValueDecPlaces 0 calcInterval 60 deltaGradient 0 deltaOld 0.199999999999999 deltaOldTS 2013-10-20 17:18:07 deltaTreshold 0 desiredName desired disable 0 factor_D 0 factor_I 0.25 factor_P 25 isWindUP 0 measuredName measured reading temperature regexp ([\d\.]*) reverseAction 0 sensor DG.BAD.TF sensorTimeout 3600 updateInterval 600 Attributes: pidActorInterval 300 pidActorTreshold 4 pidActorValueDecPlaces 0 room PID verbose 4
Anti-WindUp-Strategie
Der integrale Anteil des PID-Reglers wird ohne Gegenmassnahmen auch dann weiter integriert, wenn das Stellglied bereits an seine Grenzen gestossen ist. Dies hat den Nachteil, dass nach einer Reduzierung der Regeldifferenz lange Wartezeiten entstehen können, bis das Stellglied reagiert. Dies nennt man den WindUP-Effekt. Hierzu wurde die folgende Strategie entwickelt:
Sobald das rechnerische Stellsignal (Ventilstellung Calc=actuationCalc) die obere Grenze des Stellgliedes überschreitet (pidActorLimitUpper) oder die untere Grenze unterschreitet (pidActorLimitLower), wird die Integration des I-Anteils eingefroren.
Am Beispiel:
An Position L1 überschreitet der rechnerische Ausgabewert des Stellgliedes die obere Grenze (100%). Der I-Anteil verändert sich nicht mehr bis zur Position L2. Hier unterschreitet der Ausgabewert die obere Grenze, der I-Anteil kann wieder verändert werden.
Fragen und Antworten
Wie kann ich den I-Anteil (p_i) im Regler auf 0 setzen ?
Dies ist nach folgender Anweisung möglich:
set <Pid-Name> restart <p_p + p_d>
Temperatur im Raum steigt nicht oder stark verzögert, was kann ich tun?
1. Fehlerquelle: Heizsystem ist nicht ausreichend entlüftet
In diesem Fall behindern die Luftblasen im System den Durchfluss des Heizmediums.
Der Heizkörper erwärmt sich nur teilweise oder "gluckert". Hier ist das Entlüften der Heizkörper angesagt.
Natürlich können sich die Gasblasen an anderer Stelle befinden. Normalerweise sorgen automatische Entlüfter dafür, dass das Gas entweichen kann.
Aber auch diese "verkalken" im Lauf der Zeit.
2. Fehlerquelle: Totzone beim Stellglied
Der Temperaturanstieg erfolgt erst ab einer bestimmten Ventilöffnung von xy%.
Der PID-Regler geht davon aus, dass jede Änderung des Stellausgangs auf die Regelgröße wirkt (also bei Ventil weiter öffnen, wird mehr Wärme abgegeben).
Ist dies nicht der Fall, wird der PID über die Zeit (I-Anteil) das Ventil weiter öffnen. Allerdings vergeht hierbei Zeit und damit leidet die Regelgüte.
Es ist also wichtig die Totzone zu ermitteln und im Attribut pidActorLimitLower zu hinterlegen.
3. Fehlerquelle: Hydraulische Fehlanpassung
Wenn einzelne Heizkreise einen sehr kleinen hydraulischen Widerstand aufweisen, kann es passieren, dass Heizkreise mit höherem Widerstand zeitweise unterversorgt sind.
Erst wenn die gut versorgten Heizkreise die Ventile schließen (Soll-Temperatur ist erreicht), werden die Heizkreise mit hohem Widerstand ausreichend versorgt.
Dies kann man dank FHEM sehr gut über die Charts nachvollziehen.
Es ist regelungstechnisch, ökologisch und energetisch absolut sinnvoll geregelte Hocheffizienz-Pumpen im Heizkreis einzusetzen. Diese sorgen für konstanten Druck im Hauptstrang bei sehr geringen Energiebedarf.
Man kann gezielt den hydraulischen Widerstand einzelner Thermostate erhöhen, indem man deren maximale Ventilöffnung begrenzt.
Dies erreicht man durch Reduzieren des Wertes pidActorLimitUpper. Dies ist gleichbedeutend mit der Erhöhung des hydraulischen Widerstandes durch voreinstellbare Heizungsventile beim hydraulischen Abgleich.