# Reglerentwurf {#sec-entwurf}
Wir haben im letzten Unterrichtsblock den PID-Regler und seine Abwandlungen (P/PI/PD) kennengelernt, aber wir haben noch nicht darüber gesprochen, wie man die Reglerparameter einstellt. Um die Reglerparametrierung (wir sprechen auch vom *Reglerentwurf*) in systematischer Weise vorzunehmen, stehen verschiedene *Entwurfsverfahren* zur Verfügung.
Zu Beginn werden wir *Gütekriterien* kennenlernen, mit denen wir eine Regelung beurteilen können bzw. die wir für die Spezifikation der Anforderungen an eine Regelung verwenden können.
::: {.callout-important title="Ziele"}
- Du kennst Gütekriterien, um eine Regelung in Bezug auf das Führungsverhalten bzw. das Störverhalten beurteilen zu können.
- Du kannst einen P/PI/PD/PID-Regler anhand eines Entwurfsverfahrens für eine gegebene Regelstrecke parametrieren.
:::
## Gütekriterien
Im @sec-anforderungen haben wir die fünf Anforderungen an eine Regelung besprochen.
::: {.anf-list}
- Genauigkeit
- Schnelligkeit
- Dämpfung
- Stabilität
- Robustheit
:::
Diese Anforderungen können wir in quantitative Gütekriterien umformulieren, die wir für die Beurteilung einer Regelung heranziehen können.
### Gütekriterien für das Führungsverhalten
Für die Beurteilung einer Regelung sind primär die Genauigkeit, die Schnelligkeit und die Dämpfung massgeblich. Wir wollen die Fragen:
- Wie schnell wird der Sollwert erreicht?
- Gibt es eine bleibende Regelabweichung?
- Wie stark schwingt die Regelung?
mit einfach messbaren Grössen beantworten können, welche mittels der Führungssprungantwort bestimmt werden können (vgl. @fig-guete-f).
{#fig-guete-f}
Anhand der Führungssprungantwort können wir die folgenden Grössen bestimmen.
Anregelzeit $T_{cr}$
: Zeitdauer bis zum *erstmaligen* Eintreten der Regelgrösse in eine bestimmte Einschwingtoleranz $2 \cdot \Delta x_s$. Die Einschwingtoleranz (auch Fehlerschlauch oder Toleranzband genannt) wird üblicherweise auf den Sollwert bezogen (z. B. +/-10% vom Sollwert). Die Anregelzeit ist ein Mass für die Schnelligkeit der Regelung.
Ausregelzeit $T_{cs}$
: Zeitdauer bis zum *letztmaligen* Eintreten der Regelgrösse in die Einschwingtoleranz $2 \cdot \Delta x_s$ (danach verlässt die Regelgrösse die Einschwingtoleranz nicht mehr). Diese Kenngrösse ist ebenfalls ein Mass für die Schnelligkeit.
Überschwingweite $x_m$
: Maximalwert des Überschwingens der Regelgrösse über den Sollwert. Die Überschwingweite wird üblicherweise auf den Sollwert bezogen und in % angegeben. Die Überschwingweite ist ein Mass für die Dämpfung der Regelung.
Bleibende Regelabweichung $e_\infty$
: Abweichung zwischen Führungs- und Regelgrösse nach Abklingen des Einschwingvorgangs. Diese kann absolut oder relativ (bezogen auf den Sollwert in %) angegeben werden. Die bleibende Regelabweichung ist ein Mass für die (stationäre) Genauigkeit der Regelung.
### Gütekriterien für das Störverhalten
Für die Beurteilung des Störverhaltens werden die obigen Grössen in analoger Weise anhand einer Störsprungantwort ermittelt (vgl. @fig-guete-s).
{#fig-guete-s}
Anstelle von $x_m$ wird hier $x_{max}$ (Maximalwert der Regelgrösse als absolute Grösse) verwendet und anstelle von $e_\infty$ wird $x_\infty$ (stationärer Endwert der Regelgrösse) verwendet. Zusätzlich zu den ermittelten Werten muss immer auch angegeben werden, an welcher Stelle die Störgrösse eingreift.
## Entwurfsverfahren
Im letzten Unterrichtsblock haben wir die stetigen Regler (P/PI/PD/PID) kennengelernt und wissen bereits, mit welchen Kenngrössen (Parametern) diese beschrieben werden.
::: {.callout-note title="Proportionalbeiwert $K_P$"}
Um Verwechslungen auszuschliessen, verwenden wir im Folgenden $K_{PR}$ für den Proportionalbeiwert des Reglers (Reglerverstärkung) sowie $K_{PS}$ für den Proportionalbeiwert der Regelstrecke.
:::
| Regler | Proportionalbeiwert $K_{PR}$ (Verstärkung) | Nachstellzeit $T_i$ | Vorhaltezeit $T_d$ |
| :---: | :---: | :---: | :---: |
| P | <i class="bi bi-check"></i> | | |
| PI | <i class="bi bi-check"></i> | <i class="bi bi-check"></i> | |
| PD | <i class="bi bi-check"></i> | | <i class="bi bi-check"></i> |
| PID | <i class="bi bi-check"></i> | <i class="bi bi-check"></i> | <i class="bi bi-check"></i> |
Im Folgenden wollen wir verschiedene Verfahren anschauen (*Entwurfsverfahren* genannt), mit denen wir ermitteln können, wie wir die Reglerparameter für eine gegebene Regelstrecke einstellen müssen. Je besser man die Regelstrecke kennt, desto besser fällt i. Allg. auch die Reglerparametrierung bzw. das resultierende Regelverhalten aus. Man kann die Verfahren grob in die folgenden drei Kategorien einteilen.
| Regelstrecke <br>unbekannt | Regelstrecke <br>grob bekannt | Regelstrecke <br>genau bekannt |
| :--- | :--- | :--- |
| [Ziegler/Nichols (Schwingversuch)](#zn-i-schwingversuch) | [Ziegler/Nichols (Sprungantwort)](#zn-ii-sprungantwort-analyse) | [T-Summen-Regel](#entwurf-nach-der-t-summen-regel) |
| | [Chien/Hrones/Reswick](#entwurf-nach-chienhronesreswick-chr) | [Betragsoptimum](#entwurf-nach-dem-betragsoptimum) |
| | [Oppelt](#entwurf-nach-oppelt) | [numerische Optimierung](#entwurf-mittels-numerischer-optimierung) |
| | [T-Summen-Regel](#entwurf-nach-der-t-summen-regel) | |
Bevor wir die obigen Entwurfsverfahren betrachten, wollen wir uns kurz überlegen, welche Kombinationen von Reglern und Strecken geeignet bzw. eher ungeeignet sind. Als grobe Richtlinie kann man sich an die nachfolgenden Aussagen halten und @tbl-kombinationen konsultieren[^i_regler].
- Bei P-Strecken sollte der Regler einen I-Anteil aufweisen, wenn stationäre Genauigkeit gefordert ist.
- Bei I-Strecken sollte der Regler keinen I-Anteil aufweisen, ausser wenn es nötig ist, um z. B. bei Folgeregelungen allfällige Schleppfehler zu vermeiden.
- An I-Strecken ist ein D-Anteil im Regler hilfreich, da er zur Stabilisierung beiträgt.
- An Strecken ohne Speicher (z. B. reine P-Strecke oder reine Totzeit) ist ein D-Anteil nicht sinnvoll.
::: {#tbl-kombinationen tbl-colwidths="[20,50,6,6,6,6,6]"}
| | Streckentyp | P | I | PI | PD | PID |
| :--- | :--- | :-: | :-: | :-: | :-: | :-: |
| | P-Strecke (P) bzw. reine Totzeit (P-T~t~) | <span style="color:grey">−</span> | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:grey">−</span> | <span style="color:grey">−</span> |
| |Verzögerung 1. Ordnung (P-T~1~) | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:green">+</span> |
| |Verzögerung 1. Ordnung + Totzeit (P-T~1~-T~t~) | <span style="color:grey">−</span> | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:grey">−</span> | <span style="color:green">+</span> |
| |Verzögerung 2. Ordnung (P-T~2~) | <span style="color:green">+</span> | <span style="color:grey">−</span> | <span style="color:green">+</span> | <span style="color:grey">−</span> | <span style="color:green">+</span> |
| |Verzögerung höherer Ordnung (P-T~n~) | <span style="color:green">+</span> | <span style="color:grey">−</span> | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:green">+</span> |
| |ohne Ausgleich (I-T~1~) | <span style="color:green">+</span> | <span style="color:grey">−</span> | <span style="color:green">+</span> | <span style="color:green">+</span> | <span style="color:green">+</span> |
| |ohne Ausgleich[^doppelt_integrierend] (I~2~) | <span style="color:grey">−</span> | <span style="color:grey">−</span> | <span style="color:grey">−</span> | <span style="color:green">+</span> | <span style="color:green">+</span> |
Geeignete (+) bzw. ungeeignete (-) Regler-Strecken-Kombinationen
:::
### Entwurf nach Ziegler/Nichols (ZN)
Von Ziegler/Nichols wurden die beiden folgenden Verfahren entwickelt:
- [Entwurf anhand des Schwingversuchs](#entwurf-anhand-des-schwingversuchs)
- [Entwurf anhand der Sprungantwort](#entwurf-anhand-der-sprungantwort)
#### Entwurf anhand des Schwingversuchs {.unnumbered}
Diese Methode kommt ganz ohne Kenntnisse der Regelstrecke aus und liefert daher keine optimalen Ergebnisse. Dieses Verfahren stammt aus einer Zeit, in der die Regler analog ausgeführt wurden und noch keine Computer existierten. Heute wird es kaum noch angewendet (ausser für rudimentäre Regelungen/Hobby-Projekte etc.).
a) Im ersten Schritt wird der I- und D-Anteil deaktiviert (d. h. ein P-Regler verwendet) und mit einer geringen Verstärkung ein stabiles Regelverhalten erzeugt.
b) Nun wird die Verstärkung des P-Reglers schrittweise erhöht bis die Regelung in eine Dauerschwingung, d. h. eine ungedämpfte Schwingung gerät (wir bringen die Regelung also an die *Stabilitätsgrenze*). Diese Verstärkung $K_{PR\mathrm{,krit}}$ wird notiert und ebenso die Periodendauer der Schwingung $T_{\mathrm{krit}}$.
c) Mit den beiden Werten aus b) werden die Reglerparameter gemäss @tbl-znI bestimmt.
::: {#tbl-znI}
| | $K_{PR}$ | $T_i$ | $T_d$ |
| :---| :--- | :--- | :--- |
| **P** | $0.5 \cdot K_{PR\mathrm{,krit}}$ | | |
| **PI** | $0.45 \cdot K_{PR\mathrm{,krit}}$ | $0.85 \cdot T_{\mathrm{krit}}$ | |
| **PID** | $0.6 \cdot K_{PR\mathrm{,krit}}$ | $0.5 \cdot T_{\mathrm{krit}}$ | $0.12 \cdot T_{\mathrm{krit}}$ |
Einstellregeln nach Ziegler/Nichols (Schwingversuch)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:5em;">K_{PR\mathrm{,krit}}</span>
<input id="znI-kkrit" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:5em;">T_{\mathrm{krit}}</span>
<input id="znI-tkrit" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<select id="znI-type" class="calc-field">
<option value="P" selected>P</option>
<option value="PI">PI</option>
<option value="PID">PID</option>
</select>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="znI-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="znI-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="znI-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kkrit = document.getElementById("znI-kkrit");
var tkrit = document.getElementById("znI-tkrit");
var typeSel = document.getElementById("znI-type");
var outKpr = document.getElementById("znI-kpr");
var outTi = document.getElementById("znI-ti");
var outTd = document.getElementById("znI-td");
var factors = {
P: { kpr: 0.5, ti: null, td: null },
PI: { kpr: 0.45, ti: 0.85, td: null },
PID: { kpr: 0.6, ti: 0.5, td: 0.12 }
};
function fmt(v) {
if (isNaN(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function update() {
var f = factors[typeSel.value] || factors.P;
var kv = parseFloat(kkrit.value);
var tv = parseFloat(tkrit.value);
outKpr.value = fmt(f.kpr !== null && !isNaN(kv) ? f.kpr * kv : NaN);
outTi.value = fmt(f.ti !== null && !isNaN(tv) ? f.ti * tv : NaN);
outTd.value = fmt(f.td !== null && !isNaN(tv) ? f.td * tv : NaN);
}
kkrit.addEventListener("input", update);
tkrit.addEventListener("input", update);
typeSel.addEventListener("change", update);
update();
})();
</script>
```
#### Entwurf anhand der Sprungantwort {.unnumbered}
Bei dieser Methode nach Ziegler/Nichols werden die Reglereinstellungen von der Sprungantwort der Regelstrecke abgeleitet. Mittels Wendetangente (vgl. @nte-wt) werden dabei die Ersatzzeitkonstanten $T_e$ (Verzugszeit) und $T_b$ (Ausgleichszeit) bestimmt und dann anhand von @tbl-znII die Reglerparameter berechnet.
::: {#tbl-znII}
| | $K_{PR}$ | $T_i$ | $T_d$ |
| :---| :--- | :--- | :--- |
| **P** | $\dfrac{T_b}{K_{PS} \cdot T_e}$ | | |
| **PI** | $0.9 \cdot \dfrac{T_b}{K_{PS} \cdot T_e}$ | $3.3 \cdot T_e$ | |
| **PID** | $1.2 \cdot \dfrac{T_b}{K_{PS} \cdot T_e}$ | $2 \cdot T_e$ | $0.5 \cdot T_e$ |
Einstellregeln nach Ziegler/Nichols (Sprungantwort)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PS}</span>
<input id="znII-kps" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_b</span>
<input id="znII-tb" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_e</span>
<input id="znII-te" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<select id="znII-type" class="calc-field">
<option value="P" selected>P</option>
<option value="PI">PI</option>
<option value="PID">PID</option>
</select>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="znII-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="znII-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="znII-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kps = document.getElementById("znII-kps");
var tb = document.getElementById("znII-tb");
var te = document.getElementById("znII-te");
var typeSel = document.getElementById("znII-type");
var outKpr = document.getElementById("znII-kpr");
var outTi = document.getElementById("znII-ti");
var outTd = document.getElementById("znII-td");
var factors = {
P: { kpr: 1, ti: null, td: null },
PI: { kpr: 0.9, ti: 3.3, td: null },
PID: { kpr: 1.2, ti: 2, td: 0.5 }
};
function fmt(v) {
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function update() {
var f = factors[typeSel.value] || factors.P;
var kpsv = parseFloat(kps.value);
var tbv = parseFloat(tb.value);
var tev = parseFloat(te.value);
var base = (!isNaN(kpsv) && !isNaN(tbv) && !isNaN(tev) && kpsv !== 0 && tev !== 0) ? tbv / (kpsv * tev) : NaN;
outKpr.value = fmt(f.kpr !== null ? f.kpr * base : NaN);
outTi.value = fmt(f.ti !== null && !isNaN(tev) && tev !== 0 ? f.ti * tev : NaN);
outTd.value = fmt(f.td !== null && !isNaN(tev) && tev !== 0 ? f.td * tev : NaN);
}
kps.addEventListener("input", update);
tb.addEventListener("input", update);
te.addEventListener("input", update);
typeSel.addEventListener("change", update);
update();
})();
</script>
```
### Entwurf nach Chien/Hrones/Reswick (CHR)
Das Verfahren nach Chien/Hrones/Reswick basiert ebenfalls auf der Analyse der Sprungantwort und existiert für Strecken mit Ausgleich und Strecken ohne Ausgleich. Je nachdem, ob **Überschwingen** eher gewünscht wird oder nicht bzw. ob der Fokus auf dem **Führungs- oder Störverhalten** liegt, sind unterschiedliche Einstellregeln definiert.
#### Strecken mit Ausgleich {.unnumbered}
Mittels Wendetangente (vgl. @nte-wt) werden die Ersatzzeitkonstanten $T_e$ (Verzugszeit) und $T_b$ (Ausgleichszeit) bestimmt und dann anhand von @tbl-chrP die Reglerparameter berechnet.
::: {#tbl-chrP tbl-colwidths="[30,35,35]"}
| mit Überschwingen | | |
| :--- | :--- | :--- |
| | **Störverhalten** | **Führungsverhalten** |
| **P** | $K_{PR}=0.71\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ | $K_{PR}=0.71\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ |
| **PI** | $K_{PR}=0.71\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=2.3\cdot T_e$ | $K_{PR}=0.59\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=T_b$ |
| **PID** | $K_{PR}=1.2\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=2.3\cdot T_e$<br>$T_d=0.42\cdot T_e$ | $K_{PR}=0.95\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=1.35\cdot T_b$<br>$T_d=0.47\cdot T_e$ |
| ohne Überschwingen | | |
| :--- | :--- | :--- |
| | **Störverhalten** | **Führungsverhalten** |
| **P** | $K_{PR}=0.3\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ | $K_{PR}=0.3\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ |
| **PI** | $K_{PR}=0.59\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=4\cdot T_e$ | $K_{PR}=0.34\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=1.2\cdot T_b$ |
| **PID** | $K_{PR}=0.95\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=2.4\cdot T_e$<br>$T_d=0.42\cdot T_e$ | $K_{PR}=0.59\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$<br>$T_i=T_b$<br>$T_d=0.5\cdot T_e$ |
Einstellregeln nach Chien/Hrones/Reswick (Strecken mit Ausgleich)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PS}</span>
<input id="chrP-kps" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_b</span>
<input id="chrP-tb" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_e</span>
<input id="chrP-te" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;">
<select id="chrP-type" class="calc-field" style="width:11em;">
<option value="P" selected>P</option>
<option value="PI">PI</option>
<option value="PID">PID</option>
</select>
<select id="chrP-osc" class="calc-field" style="width:11em;">
<option value="mit" selected>mit Überschwingen</option>
<option value="ohne">ohne Überschwingen</option>
</select>
<select id="chrP-beh" class="calc-field" style="width:11em;">
<option value="stoer" selected>Störverhalten</option>
<option value="fuehr">Führungsverhalten</option>
</select>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="chrP-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="chrP-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="chrP-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kps = document.getElementById("chrP-kps");
var tb = document.getElementById("chrP-tb");
var te = document.getElementById("chrP-te");
var typeSel = document.getElementById("chrP-type");
var oscSel = document.getElementById("chrP-osc");
var behSel = document.getElementById("chrP-beh");
var outKpr = document.getElementById("chrP-kpr");
var outTi = document.getElementById("chrP-ti");
var outTd = document.getElementById("chrP-td");
var data = {
mit: {
stoer: {
P: { kpr: 0.71, ti: null, td: null },
PI: { kpr: 0.71, ti: { f: 2.3, b: false }, td: null },
PID: { kpr: 1.2, ti: { f: 2.3, b: false }, td: { f: 0.42, b: false } }
},
fuehr: {
P: { kpr: 0.71, ti: null, td: null },
PI: { kpr: 0.59, ti: { f: 1, b: true }, td: null },
PID: { kpr: 0.95, ti: { f: 1.35, b: true }, td: { f: 0.47, b: false } }
}
},
ohne: {
stoer: {
P: { kpr: 0.3, ti: null, td: null },
PI: { kpr: 0.59, ti: { f: 4, b: false }, td: null },
PID: { kpr: 0.95, ti: { f: 2.4, b: false }, td: { f: 0.42, b: false } }
},
fuehr: {
P: { kpr: 0.3, ti: null, td: null },
PI: { kpr: 0.34, ti: { f: 1.2, b: true }, td: null },
PID: { kpr: 0.59, ti: { f: 1, b: true }, td: { f: 0.5, b: false } }
}
}
};
function fmt(v) {
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function calcParam(spec, tev, tbv) {
if (!spec) return NaN;
var v = spec.b ? tbv : tev;
return (!isNaN(v) && v !== 0) ? spec.f * v : NaN;
}
function update() {
var f = data[oscSel.value][behSel.value][typeSel.value];
var kpsv = parseFloat(kps.value);
var tbv = parseFloat(tb.value);
var tev = parseFloat(te.value);
var base = (!isNaN(kpsv) && !isNaN(tbv) && !isNaN(tev) && kpsv !== 0 && tev !== 0) ? tbv / (kpsv * tev) : NaN;
outKpr.value = fmt(f.kpr !== null ? f.kpr * base : NaN);
outTi.value = fmt(calcParam(f.ti, tev, tbv));
outTd.value = fmt(calcParam(f.td, tev, tbv));
}
kps.addEventListener("input", update);
tb.addEventListener("input", update);
te.addEventListener("input", update);
typeSel.addEventListener("change", update);
oscSel.addEventListener("change", update);
behSel.addEventListener("change", update);
update();
})();
</script>
```
#### Strecken ohne Ausgleich {.unnumbered}
Für Strecken ohne Ausgleich wird der Integrierbeiwert $K_I$ und mittels angelegter Tangente die Verzugszeit $T_e$ bestimmt (vgl. @nte-wt-i) und damit anschliessend anhand der @tbl-chrI die Reglerparameter bestimmt. Da bei Strecken ohne Ausgleich bereits in der Regelstrecke ein I-Anteil enthalten ist, wird dieser im PI/PID-Regler für gutes Führungsverhalten deaktiviert (dies ist mit $T_i = \infty$ gemeint).
::: {#tbl-chrI tbl-colwidths="[30,35,35]"}
| mit Überschwingen | | |
| :--- | :--- | :--- |
| | **Störverhalten** | **Führungsverhalten** |
| **P** | $K_{PR}=0.71\cdot\dfrac{1}{K_{IS}\cdot T_e}$ | $K_{PR}=0.71\cdot\dfrac{1}{K_{IS}\cdot T_e}$ |
| **PI** | $K_{PR}=0.71\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=2.3\cdot T_e$ | $K_{PR}=0.59\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=\infty$ |
| **PID** | $K_{PR}=1.2\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=2\cdot T_e$<br>$T_d=0.42\cdot T_e$ | $K_{PR}=0.95\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=\infty$<br>$T_d=0.47\cdot T_e$ |
| ohne Überschwingen | | |
| :--- | :--- | :--- |
| | **Störverhalten** | **Führungsverhalten** |
| **P** | $K_{PR}=0.3\cdot\dfrac{1}{K_{IS}\cdot T_e}$ | $K_{PR}=0.3\cdot\dfrac{1}{K_{IS}\cdot T_e}$ |
| **PI** | $K_{PR}=0.59\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=4\cdot T_e$ | $K_{PR}=0.34\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=\infty$ |
| **PID** | $K_{PR}=0.95\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=2.4\cdot T_e$<br>$T_d=0.42\cdot T_e$ | $K_{PR}=0.59\cdot\dfrac{1}{K_{IS}\cdot T_e}$<br>$T_i=\infty$<br>$T_d=0.5\cdot T_e$ |
Einstellregeln nach Chien/Hrones/Reswick (Strecken ohne Ausgleich)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{IS}</span>
<input id="chrI-kis" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_e</span>
<input id="chrI-te" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;">
<select id="chrI-type" class="calc-field" style="width:11em;">
<option value="P" selected>P</option>
<option value="PI">PI</option>
<option value="PID">PID</option>
</select>
<select id="chrI-osc" class="calc-field" style="width:11em;">
<option value="mit" selected>mit Überschwingen</option>
<option value="ohne">ohne Überschwingen</option>
</select>
<select id="chrI-beh" class="calc-field" style="width:11em;">
<option value="stoer" selected>Störverhalten</option>
<option value="fuehr">Führungsverhalten</option>
</select>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="chrI-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="chrI-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="chrI-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kis = document.getElementById("chrI-kis");
var te = document.getElementById("chrI-te");
var typeSel = document.getElementById("chrI-type");
var oscSel = document.getElementById("chrI-osc");
var behSel = document.getElementById("chrI-beh");
var outKpr = document.getElementById("chrI-kpr");
var outTi = document.getElementById("chrI-ti");
var outTd = document.getElementById("chrI-td");
var data = {
mit: {
stoer: {
P: { kpr: 0.71, ti: null, td: null },
PI: { kpr: 0.71, ti: { f: 2.3 }, td: null },
PID: { kpr: 1.2, ti: { f: 2 }, td: { f: 0.42 } }
},
fuehr: {
P: { kpr: 0.71, ti: null, td: null },
PI: { kpr: 0.59, ti: "inf", td: null },
PID: { kpr: 0.95, ti: "inf", td: { f: 0.47 } }
}
},
ohne: {
stoer: {
P: { kpr: 0.3, ti: null, td: null },
PI: { kpr: 0.59, ti: { f: 4 }, td: null },
PID: { kpr: 0.95, ti: { f: 2.4 }, td: { f: 0.42 } }
},
fuehr: {
P: { kpr: 0.3, ti: null, td: null },
PI: { kpr: 0.34, ti: "inf", td: null },
PID: { kpr: 0.59, ti: "inf", td: { f: 0.5 } }
}
}
};
function fmt(v) {
if (v === Infinity) return "\u221e";
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function calcParam(spec, tev) {
if (spec === "inf") return Infinity;
if (!spec) return NaN;
return (!isNaN(tev) && tev !== 0) ? spec.f * tev : NaN;
}
function update() {
var f = data[oscSel.value][behSel.value][typeSel.value];
var ksv = parseFloat(kis.value);
var tev = parseFloat(te.value);
var base = (!isNaN(ksv) && !isNaN(tev) && ksv !== 0 && tev !== 0) ? 1 / (ksv * tev) : NaN;
outKpr.value = fmt(f.kpr !== null ? f.kpr * base : NaN);
outTi.value = fmt(calcParam(f.ti, tev));
outTd.value = fmt(calcParam(f.td, tev));
}
kis.addEventListener("input", update);
te.addEventListener("input", update);
typeSel.addEventListener("change", update);
oscSel.addEventListener("change", update);
behSel.addEventListener("change", update);
update();
})();
</script>
```
::: {.callout-note title="CHR-Verfahren in BORIS"}
Das CHR-Verfahren ist in <span class="cap">Boris</span> implementiert und kann direkt im Zeitverlaufsdiagramm (*→ PID-Entwurf*) durchgeführt werden. Zuerst werden mittels Wendetangente/Tangente automatisch $K_P$, $T_e$ und $T_b$ bzw. $K_I$ und $T_e$ bestimmt und danach können damit je nach Auswahl (mit/ohne Überschwingen, Führungs- oder Störverhalten) die Reglerparameter bestimmt und optional direkt in einen PID-Block übertragen werden. Zu beachten ist, dass von der Strecke eine saubere/vollständige Einheitssprungantwort vorliegt (Eingangssprung von 0 auf 1 bei $t=0$).
```{=html}
<video controls muted playsinline width="100%">
<source src="../images/videos/CHR_BORIS.mp4" type="video/mp4">
</video>
```
Wir wählen das CHR-Verfahren als unser *Standardverfahren*, d. h. sofern nichts anderes vermerkt/gefordert wird, kannst du jeweils dieses Verfahren anwenden.
:::
### Entwurf nach Oppelt
Das Verfahren nach Oppelt funktioniert sehr ähnlich wie das CHR-Verfahren. Es basiert ebenfalls auf den Ersatzzeitkonstanten der Regelstrecke (vgl. @nte-wt bzw. @nte-wt-i). Es wird häufig in der Chemietechnik eingesetzt, wo das Störverhalten im Vordergrund steht und führt deshalb zu einer eher geringen Dämpfung (also grossem Überschwingen bei einem Führungssprung).
::: {#tbl-chrO tbl-colwidths="[30,70]"}
| P-Strecken | |
| :--- | :--- |
| **P** | $K_{PR} = \dfrac{T_b}{K_{PS}\cdot T_e}$ |
| **PI** | $K_{PR} = 0.8\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ $\qquad$ $T_i = 3 \cdot T_e$ |
| **PD** | $K_{PR} = 1.2\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ $\qquad$ $T_d = 0.22\ldots0.5\cdot T_e$ |
| **PID** | $K_{PR} = 1.2\cdot\dfrac{T_b}{K_{PS}\cdot T_e}$ $\qquad$ $T_i = 2\cdot T_e$ $\qquad$ $T_d = 0.42\cdot T_e$ |
| I-Strecken | |
| :--- | :--- |
| **P** | $K_{PR} = \dfrac{0.5}{K_{IS}\cdot T_e}$ |
| **PI** | $K_{PR} = \dfrac{0.42}{K_{IS}\cdot T_e}$ $\qquad$ $T_i = 5.8\cdot T_e$ |
| **PD** | $K_{PR} = \dfrac{0.5}{K_{IS}\cdot T_e}$ $\qquad$ $T_d = 0.5\cdot T_e$ |
| **PID** | $K_{PR} = \dfrac{0.4}{K_{IS}\cdot T_e}$ $\qquad$ $T_i = 3.2\cdot T_e$ $\qquad$ $T_d = 0.8\cdot T_e$ |
Einstellregeln nach Oppelt (Strecken mit/ohne Ausgleich)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" id="opp-label-ps" style="display:inline-block;width:3em;">K_{PS}</span>
<span class="math inline" id="opp-label-is" style="display:none;width:3em;">K_{IS}</span>
<input id="opp-k" type="number" step="any" min="0" class="calc-field">
</div>
<div id="opp-tb-row" style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_b</span>
<input id="opp-tb" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_e</span>
<input id="opp-te" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;">
<select id="opp-strecke" class="calc-field" style="width:8em;">
<option value="p" selected>P-Strecke</option>
<option value="i">I-Strecke</option>
</select>
<select id="opp-type" class="calc-field" style="width:8em;">
<option value="P" selected>P</option>
<option value="PI">PI</option>
<option value="PD">PD</option>
<option value="PID">PID</option>
</select>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="opp-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="opp-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="opp-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var k = document.getElementById("opp-k");
var tb = document.getElementById("opp-tb");
var te = document.getElementById("opp-te");
var tbRow = document.getElementById("opp-tb-row");
var labelPs = document.getElementById("opp-label-ps");
var labelIs = document.getElementById("opp-label-is");
var streckeSel = document.getElementById("opp-strecke");
var typeSel = document.getElementById("opp-type");
var outKpr = document.getElementById("opp-kpr");
var outTi = document.getElementById("opp-ti");
var outTd = document.getElementById("opp-td");
var data = {
p: {
P: { kpr: 1, ti: null, td: null },
PI: { kpr: 0.8, ti: { f: 3 }, td: null },
PD: { kpr: 1.2, ti: null, td: { from: 0.22, to: 0.5 } },
PID: { kpr: 1.2, ti: { f: 2 }, td: { f: 0.42 } }
},
i: {
P: { kpr: 0.5, ti: null, td: null },
PI: { kpr: 0.42, ti: { f: 5.8 }, td: null },
PD: { kpr: 0.5, ti: null, td: { f: 0.5 } },
PID: { kpr: 0.4, ti: { f: 3.2 }, td: { f: 0.8 } }
}
};
function fmt(v) {
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function outStr(spec, tev) {
if (!spec) return "\u2013";
var v = isFinite(tev) && tev !== 0 ? tev : NaN;
if (isNaN(v)) return "\u2013";
if (spec.from !== undefined) return fmt(spec.from * v) + "\u2026" + fmt(spec.to * v);
return fmt(spec.f * v);
}
function update() {
var isP = streckeSel.value === "p";
var f = data[streckeSel.value][typeSel.value];
var kv = parseFloat(k.value);
var tbv = parseFloat(tb.value);
var tev = parseFloat(te.value);
var base;
if (isP) {
base = (!isNaN(kv) && !isNaN(tbv) && !isNaN(tev) && kv !== 0 && tev !== 0) ? tbv / (kv * tev) : NaN;
} else {
base = (!isNaN(kv) && !isNaN(tev) && kv !== 0 && tev !== 0) ? 1 / (kv * tev) : NaN;
}
outKpr.value = fmt(f.kpr !== null ? f.kpr * base : NaN);
outTi.value = outStr(f.ti, tev);
outTd.value = outStr(f.td, tev);
}
function onStrecke() {
var isP = streckeSel.value === "p";
tbRow.style.display = isP ? "" : "none";
labelPs.style.display = isP ? "" : "none";
labelIs.style.display = isP ? "none" : "inline-block";
update();
}
k.addEventListener("input", update);
tb.addEventListener("input", update);
te.addEventListener("input", update);
streckeSel.addEventListener("change", onStrecke);
typeSel.addEventListener("change", update);
update();
})();
</script>
```
### Entwurf nach der T-Summen-Regel
Dieses Verfahren basiert auf der *Summenzeitkonstante* $T_{\Sigma}$, d. h. der Summe der Zeitkonstanten der Regelstrecke. Wenn sämtliche Zeitkonstanten bekannt sind, kann die Summenzeitkonstante direkt berechnet werden.
$$
T_{\Sigma} = T_1 + T_2 + \ldots \qquad \mathsf{(inkl. allfälliger Totzeiten)}
$$
In vielen Fällen sind die Zeitkonstanten nicht direkt bekannt und es wird das folgende grafische Verfahren angewendet (vgl. @fig-tsumme). Die Summenzeitkonstante $T_{\Sigma}$ kann dort abgelesen werden, wo die beiden Flächen links bzw. rechts davon gerade gleich gross sind.
{#fig-tsumme}
Mit der Summenzeitkonstante $T_{\Sigma}$ können die Reglerparameter anhand von @tbl-tsumme bestimmt werden, wobei zwei Parametersätze (normal und schnell) vorliegen. Der schnellere Satz liefert ein schnelleres Führungsverhalten, jedoch auf Kosten der Dämpfung (höheres Überschwingen).
::: {#tbl-tsumme tbl-colwidths="[30,35,35]"}
| | normal | schnell |
| :--- | :--- | :--- |
| **P** | $K_{PR} = \dfrac{1}{K_{PS}}$ | |
| **PD** | $K_{PR} = \dfrac{1}{K_{PS}}$<br>$T_d = 0.33 \cdot T_{\Sigma}$ | |
| **PI** | $K_{PR} = \dfrac{0.5}{K_{PS}}$<br>$T_i = 0.5 \cdot T_{\Sigma}$ | $K_{PR} = \dfrac{1}{K_{PS}}$<br>$T_i = 0.7 \cdot T_{\Sigma}$ |
| **PID** | $K_{PR} = \dfrac{1}{K_{PS}}$<br>$T_i = 0.66 \cdot T_{\Sigma}$<br>$T_d = 0.167 \cdot T_{\Sigma}$ | $K_{PR} = \dfrac{2}{K_{PS}}$<br>$T_i = 0.8 \cdot T_{\Sigma}$<br>$T_d = 0.194 \cdot T_{\Sigma}$ |
Einstellregeln gemäss T-Summen-Regel
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PS}</span>
<input id="tsum-kps" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_{\Sigma}</span>
<input id="tsum-ts" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;">
<select id="tsum-variante" class="calc-field" style="width:8em;">
<option value="normal" selected>normal</option>
<option value="schnell">schnell</option>
</select>
<select id="tsum-type" class="calc-field" style="width:8em;">
<option value="P" selected>P</option>
<option value="PD">PD</option>
<option value="PI">PI</option>
<option value="PID">PID</option>
</select>
</div>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="tsum-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="tsum-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="tsum-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kps = document.getElementById("tsum-kps");
var ts = document.getElementById("tsum-ts");
var varianteSel = document.getElementById("tsum-variante");
var typeSel = document.getElementById("tsum-type");
var outKpr = document.getElementById("tsum-kpr");
var outTi = document.getElementById("tsum-ti");
var outTd = document.getElementById("tsum-td");
var data = {
normal: {
P: { kpr: 1, ti: null, td: null },
PD: { kpr: 1, ti: null, td: { f: 0.33 } },
PI: { kpr: 0.5, ti: { f: 0.5 }, td: null },
PID: { kpr: 1, ti: { f: 0.66 }, td: { f: 0.167 } }
},
schnell: {
P: { kpr: null, ti: null, td: null },
PD: { kpr: null, ti: null, td: null },
PI: { kpr: 1, ti: { f: 0.7 }, td: null },
PID: { kpr: 2, ti: { f: 0.8 }, td: { f: 0.194 } }
}
};
function fmt(v) {
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function paramStr(spec, tv) {
if (!spec) return "\u2013";
var v = isFinite(tv) && tv !== 0 ? tv : NaN;
if (isNaN(v)) return "\u2013";
return fmt(spec.f * v);
}
function update() {
var f = data[varianteSel.value][typeSel.value];
var kv = parseFloat(kps.value);
var tv = parseFloat(ts.value);
var base = (!isNaN(kv) && kv !== 0) ? 1 / kv : NaN;
outKpr.value = fmt(f.kpr !== null ? f.kpr * base : NaN);
outTi.value = paramStr(f.ti, tv);
outTd.value = paramStr(f.td, tv);
}
kps.addEventListener("input", update);
ts.addEventListener("input", update);
varianteSel.addEventListener("change", update);
typeSel.addEventListener("change", update);
update();
})();
</script>
```
### Entwurf nach dem Betragsoptimum
Dieses Verfahren ist für Strecken mit Ausgleich geeignet, die eine oder zwei **dominante Zeitkonstanten** aufweisen, d. h. eine oder zwei Zeitkonstanten, die deutlich grösser sind als die Summe der übrigen Zeitkonstanten $T_{\Sigma^*}$.
#### Eine dominante Zeitkonstante $T_1$ {.unnumbered}
Liegt eine dominante Zeitkonstante $T_1$ vor, gilt also
$$
T_1 \gg T_{\Sigma^*} \qquad \mathsf{mit} \qquad T_{\Sigma^*} = T_2 + T_3 + \ldots
$$
so kann der Regler anhand von @tbl-betrag1 parametriert werden.
::: {#tbl-betrag1 tbl-colwidths="[30,70]"}
| | Reglerparameter |
| :--- | :--- |
| **P** | $K_{PR} = \dfrac{T_1}{2 \cdot K_{PS} \cdot T_{\Sigma^*}}$ |
| **PI** | $K_{PR} = \dfrac{T_1}{2 \cdot K_{PS} \cdot T_{\Sigma^*}}$ $\qquad$ $T_i = T_1$ |
Einstellregeln nach dem Betragsoptimum (1 dominante Zeitkonstante)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PS}</span>
<input id="betrag1-kps" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_1</span>
<input id="betrag1-t1" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_{\Sigma^*}</span>
<input id="betrag1-ts" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<select id="betrag1-type" class="calc-field" style="width:6em;">
<option value="P" selected>P</option>
<option value="PI">PI</option>
</select>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="betrag1-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="betrag1-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="betrag1-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kps = document.getElementById("betrag1-kps");
var t1 = document.getElementById("betrag1-t1");
var ts = document.getElementById("betrag1-ts");
var typeSel = document.getElementById("betrag1-type");
var outKpr = document.getElementById("betrag1-kpr");
var outTi = document.getElementById("betrag1-ti");
var outTd = document.getElementById("betrag1-td");
var data = {
P: { kpr: 1, ti: null, td: null },
PI: { kpr: 1, ti: { f: 1, of: "t1" }, td: null }
};
function fmt(v) {
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function timeStr(spec, t1v, tsv) {
if (!spec) return "\u2013";
var v = spec.of === "t1" ? t1v : tsv;
if (!isFinite(v) || v === 0) return "\u2013";
return fmt(spec.f * v);
}
function update() {
var f = data[typeSel.value];
var kv = parseFloat(kps.value);
var t1v = parseFloat(t1.value);
var tsv = parseFloat(ts.value);
var base = (!isNaN(kv) && !isNaN(t1v) && !isNaN(tsv) && kv !== 0 && tsv !== 0) ? t1v / (2 * kv * tsv) : NaN;
outKpr.value = fmt(f.kpr !== null ? f.kpr * base : NaN);
outTi.value = timeStr(f.ti, t1v, tsv);
outTd.value = timeStr(f.td, t1v, tsv);
}
kps.addEventListener("input", update);
t1.addEventListener("input", update);
ts.addEventListener("input", update);
typeSel.addEventListener("change", update);
update();
})();
</script>
```
#### Zwei dominante Zeitkonstanten $T_1$ und $T_2$ {.unnumbered}
Liegen zwei dominante Zeitkonstanten $T_1$ und $T_2$ vor, gilt also
$$
T_1, T_2 \gg T_{\Sigma^*} \qquad \mathsf{mit} \qquad T_{\Sigma^*} = T_3 + T_4 + \ldots
$$
so kann der Regler anhand von @tbl-betrag2 parametriert werden.
::: {#tbl-betrag2 tbl-colwidths="[30,70]"}
| | Reglerparameter |
| :--- | :--- |
| **PI** | $K_{PR} = \dfrac{T_1^2 + T_2^2}{2 \cdot K_{PS} \cdot T_1 \cdot T_2}$ $\qquad$ $T_i = \dfrac{(T_1^2 + T_2^2) \cdot (T_1 + T_2)}{T_1^2 + T_1 \cdot T_2 + T_2^2}$ |
| **PID** | $K_{PR} = \dfrac{T_1}{2 \cdot K_{PS} \cdot T_{\Sigma^*}}$ $\qquad$ $T_i = T_1$ $\qquad$ $T_d = T_2$|
Einstellregeln nach dem Betragsoptimum (2 dominante Zeitkonstanten)
:::
```{=html}
<div style="display:flex;align-items:flex-start;gap:2em;border:1px solid #ccc;border-radius:6px;padding:0.6em 1.1em;margin:1em 0;font-family:'Source Sans Pro',sans-serif;">
<div style="display:flex;flex-direction:column;gap:0.5em;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PS}</span>
<input id="betrag2-kps" type="number" step="any" min="0" class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_1</span>
<input id="betrag2-t1" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_2</span>
<input id="betrag2-t2" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_{\Sigma^*}</span>
<input id="betrag2-ts" type="number" step="any" min="0" class="calc-field calc-pos">
</div>
</div>
<select id="betrag2-type" class="calc-field" style="width:6em;">
<option value="PI" selected>PI</option>
<option value="PID">PID</option>
</select>
<div style="display:flex;flex-direction:column;gap:0.5em;margin-left:auto;">
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">K_{PR}</span>
<input id="betrag2-kpr" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_i</span>
<input id="betrag2-ti" type="text" readonly class="calc-field">
</div>
<div style="display:flex;align-items:center;gap:0.6em;white-space:nowrap;">
<span class="math inline" style="display:inline-block;width:3em;">T_d</span>
<input id="betrag2-td" type="text" readonly class="calc-field">
</div>
</div>
</div>
<script>
(function () {
var kps = document.getElementById("betrag2-kps");
var t1 = document.getElementById("betrag2-t1");
var t2 = document.getElementById("betrag2-t2");
var ts = document.getElementById("betrag2-ts");
var typeSel = document.getElementById("betrag2-type");
var outKpr = document.getElementById("betrag2-kpr");
var outTi = document.getElementById("betrag2-ti");
var outTd = document.getElementById("betrag2-td");
var data = {
PI: {
kpr: function (v) {
if (!(isFinite(v.kv) && isFinite(v.t1v) && isFinite(v.t2v) && v.kv !== 0 && v.t1v !== 0 && v.t2v !== 0)) return NaN;
var a = v.t1v * v.t1v + v.t2v * v.t2v;
return a / (2 * v.kv * v.t1v * v.t2v);
},
ti: function (v) {
if (!(isFinite(v.t1v) && isFinite(v.t2v) && v.t1v !== 0 && v.t2v !== 0)) return NaN;
var a = v.t1v * v.t1v + v.t2v * v.t2v;
return a * (v.t1v + v.t2v) / (a + v.t1v * v.t2v);
},
td: null
},
PID: {
kpr: function (v) {
if (!(isFinite(v.kv) && isFinite(v.t1v) && isFinite(v.tsv) && v.kv !== 0 && v.t1v !== 0 && v.tsv !== 0)) return NaN;
return v.t1v / (2 * v.kv * v.tsv);
},
ti: function (v) {
return (isFinite(v.t1v) && v.t1v !== 0) ? v.t1v : NaN;
},
td: function (v) {
return (isFinite(v.t2v) && v.t2v !== 0) ? v.t2v : NaN;
}
}
};
function fmt(v) {
if (isNaN(v) || !isFinite(v)) return "\u2013";
var r = Math.round(v * 1e5) / 1e5;
return String(r);
}
function update() {
var f = data[typeSel.value];
var v = {
kv: parseFloat(kps.value),
t1v: parseFloat(t1.value),
t2v: parseFloat(t2.value),
tsv: parseFloat(ts.value)
};
outKpr.value = fmt(f.kpr ? f.kpr(v) : NaN);
outTi.value = fmt(f.ti ? f.ti(v) : NaN);
outTd.value = fmt(f.td ? f.td(v) : NaN);
}
kps.addEventListener("input", update);
t1.addEventListener("input", update);
t2.addEventListener("input", update);
ts.addEventListener("input", update);
typeSel.addEventListener("change", update);
update();
})();
</script>
```
```{=html}
<script>
(function () {
var fields = document.querySelectorAll("input[type=number].calc-pos");
for (var i = 0; i < fields.length; i++) {
fields[i].addEventListener("beforeinput", function (e) {
if (e.data && e.data.indexOf("-") !== -1) e.preventDefault();
});
fields[i].addEventListener("input", function () {
if (this.value !== "" && Number(this.value) < 0) this.value = "";
});
}
})();
</script>
```
### Entwurfsverfahren für schwingfähige Strecken
Für schwingfähige Strecken finden wir in @crashkurs kein Entwurfsverfahren. Schwingfähige Strecken werden üblicherweise im Frequenzbereich entworfen, in den wir erst im nächsten Regelungstechnik-Modul vorstossen. Damit wir trotzdem ein Verfahren für P-T~2S~-Strecken kennen, ist nachfolgend ein einfaches Verfahren aufgeführt.
Bei dem Verfahren versucht man die Schwingung der Strecke mit dem PID-Regler zu kompensieren, um idealerweise im Regelkreis P-T~1~-Verhalten zu erreichen. Die [P-T~2S~-Regelstrecke](#p-t2s-glied) wird bekanntlich mit der Kennkreisfrequenz $\omega_0$ und dem Dämpfungsgrad $D$ beschrieben. Um die erwähnte Kompensation zu erreichen, setzt man:
$$
T_i = \frac{2 \cdot D}{\omega_0} \qquad \mathsf{und} \qquad T_d = \frac{1}{2 \cdot D \cdot \omega_0}
$$
Die Reglerverstärkung $K_{PR}$ kann mit der nachfolgend aufgeführten Beziehung bestimmt werden, wobei $T_{RK}$ der Zeitkonstanten des gewünschten Regelverhaltens (\~P-T~1~) entspricht. Falls keine Vorgaben bestehen, kann für $T_{RK}$ initial $1/\omega_0$ gewählt werden und dann mittels Finetuning manuell optimiert werden.
$$
K_{PR} = \frac{T_i}{K_{PS} \cdot T_{RK}}
$$
### Entwurf mittels numerischer Optimierung
Die obigen Verfahren wurden z. T. vor langer Zeit entwickelt und sind limitiert in ihrer Anwendung. Mit dem Aufkommen von Computersimulationen bzw. numerischen Optimierungsverfahren können die Reglerparameter auch direkt anhand der Regelstrecke optimiert werden. Dabei wird ein bestimmtes Gütekriterium $Q$ definiert und anschliessend die Reglerparameter so lange angepasst, bis ein Optimum (Minimum) gefunden wurde.
$$
\min_{K_{PR}, T_i, T_d} \, Q
$$
Ein sinnvolles Gütekriterium für eine solche Optimierung wäre z. B. die Fläche zwischen Soll- und Istwertverlauf (diese entspricht in gewisser Weise der kumulierten Regelabweichung und wird als *Regelfläche* bezeichnet, vgl. @fig-reglerentwurf-opt). Wird diese Fläche minimiert, so erreichen wir folglich eine optimale Regelung. In der Regelungstechnik werden üblicherweise die nachfolgend aufgeführten Gütekriterien verwendet.
- Betragslineare Regelfläche **IAE** (*Integral of Absolute Error*)
$$
Q_{\mathrm{IAE}} = \int_0^\infty |e(t)| \, dt
$$
Die obige Beziehung sieht kompliziert aus, doch das Integral der Regelabweichung $|e(t)|$ über die Zeit entspricht genau der *Regelfläche* (Abweichung zwischen dem Soll- und Istverlauf). Da die Betragsfunktion $|\ldots|$ mathematisch ungünstige Eigenschaften aufweist, verwendet man stattdessen häufig die quadrierte Regelabweichung $e(t)^2$.
- Quadratische Regelfläche **ISE** (*Integral of Squared Error*)
$$
Q_{\mathrm{ISE}} = \int_0^\infty e(t)^2 \, dt
$$
Häufig möchte man Abweichungen stärker gewichten, wenn sie zeitlich später auftreten (vgl. bleibende Regelabweichung etc.). Darum gewichtet man die Regelfläche mit der Zeit und erhält die folgenden Gütekriterien:
- Zeitgewichtete betragslineare Regelfläche **ITAE** (*Integral of Time-weighted Absolute Error*)
$$
Q_{\mathrm{ITAE}} = \int_0^\infty t \cdot |e(t)| \, dt
$$
- Zeitgewichtete quadratische Regelfläche **ITSE** (*Integral of Time-weighted Squared Error*)
$$
Q_{\mathrm{ITSE}} = \int_0^\infty t \cdot e(t)^2 \, dt
$$
Wir werden uns nicht weiter mit dieser Methode beschäftigen, da wir die entsprechenden <span class="cap">Python</span>-Werkzeuge erst später kennenlernen werden. In <span class="cap">Boris</span> sind zwar gewisse Optimierungsverfahren implementiert, jedoch bietet das <span class="cap">Python</span>-Ökosystem deutlich mehr und flexiblere Möglichkeiten für solche Optimierungen.
In @fig-reglerentwurf-opt ist ein Beispiel für eine numerische Optimierung dargestellt, bei der ein PI-Regler an einer P-T~4~-Strecke optimiert wird, wobei das ITSE-Kriterium anhand der Führungssprungantwort minimiert wird.
{#fig-reglerentwurf-opt}
## Aufgaben {.unnumbered}
<button class="pdf-export"
data-target="aufgaben6"
data-filename="SYS_RE1_AUFG06.pdf"
aria-label="Aufgaben als PDF speichern"
title="Aufgaben als PDF speichern">
<img src="/images/icons/file-pdf.svg" alt="PDF herunterladen" width="24" height="24">
</button>
:::: {#aufgaben6}
::: {.callout-tip collapse="true" #ex-6-1}
### Aufgabe 6.1
Übungshalber soll das Entwurfsverfahren anhand des Schwingversuchs nach [Ziegler/Nichols](#entwurf-anhand-des-schwingversuchs) durchgeführt werden für eine P-T~3~-Regelstrecke mit $K_{PS} = 25$ und $T_1 = 3\,\mathrm{s}$, $T_2 = 2\,\mathrm{s}$ sowie $T_3 = 1\,\mathrm{s}$. Es soll damit ein PID-Regler parametriert werden.
Da wir die Regelstrecke genau kennen, würden wir dieses Verfahren in der Praxis natürlich nicht anwenden (dieses Verfahren ist ja genau für Fälle, in denen man die Regelstrecke nicht kennt). Es ist aber eine gute Übung, dieses Verfahren einmal anhand einer Simulation durchzuführen, da es das Thema *Stabilität* des Regelkreises schön behandelt.
::: {.callout-important collapse="true"}
### Lösung
Mit P-Regler und kleiner Verstärkung beginnen und dann Verstärkung schrittweise erhöhen bis Dauerschwingung resultiert.
{fig-align="center"}
Die eingestellte Verstärkung ist die kritische Verstärkung $K_{PR,krit}$ und die Periodendauer der Schwingung ist $T_{krit}$.
$$
K_{PR,krit} = 0.4
$$
$$
T_{krit} = 6.3 \, \mathrm{s}
$$
Reglerparametrierung gemäss Ziegler-Nichols (Schwingversuch) gemäss @tbl-znI:
$$
K_{PR} = 0.6 \cdot K_{PR,krit} = 0.24
$$
$$
T_i = 0.5 \cdot T_{krit} = 3.15 \, \mathrm{s}
$$
$$
T_d = 0.12 \cdot T_{krit} = 0.756 \, \mathrm{s}
$$
{fig-align="center"}
{fig-align="center"}
:::
:::
::: {.callout-tip collapse="true" #ex-6-2}
### Aufgabe 6.2
Führe das [Chien/Hrones/Reswick](#entwurf-nach-chienhronesreswick-chr)-Verfahren durch, um einen PID-Regler an einer P-T~2~-Strecke zu entwerfen. Die Regelstrecke ist durch die folgenden Parameter gegeben:
$$
𝐾_{PS} = 5 \qquad 𝑇_1 = 1.0\,\mathrm{s} \qquad 𝑇_2 = 0.5\,\mathrm{s}
$$
Der PID-Regler soll mit Fokus auf gutem Führungsverhalten entworfen werden und eine schnelle Regelung ermöglichen (also Überschwingen aufweisen). Simuliere die Führungssprungantwort und beurteile anschliessend die Regelung anhand der [Gütekriterien](#gütekriterien-für-das-führungsverhalten), wobei ein 10%-Toleranzband verwendet werden soll.
- Anregelzeit [s]
$$
T_{cr} =
$$
- Ausregelzeit [s]
$$
T_{cs} =
$$
- Überschwingweite [%]
$$
x_m =
$$
- Bleibende Regelabweichung
$$
e_\infty =
$$
::: {.callout-important collapse="true"}
### Lösung
Sprungantwort-Analyse (Wendetangente):
{fig-align="center"}
$$
K_{PS} = 5
$$
$$
T_e = 0.2 \, \mathrm{s}
$$
$$
T_b = 2.0 \, \mathrm{s}
$$
Bestimmung der Reglerparameter gemäss @tbl-chrP:
$$
K_{PR}=0.95 \cdot \dfrac{T_b}{K_{PS}\cdot T_e} = 1.9
$$
$$
T_i = 1.35 \cdot T_b = 2.7 \, \mathrm{s}
$$
$$
T_d=0.47 \cdot T_e = 0.094 \, \mathrm{s}
$$
{fig-align="center"}
{fig-align="center"}
- Anregelzeit [s]
$$
T_{cr} = 0.4 \, \mathrm{s}
$$
- Ausregelzeit [s]
$$
T_{cs} = 0.85 \, \mathrm{s}
$$
- Überschwingweite [%]
$$
x_m = 14 \, \%
$$
- Bleibende Regelabweichung
$$
e_\infty = 0
$$
:::
:::
::: {.callout-tip collapse="true" #ex-6-3}
### Aufgabe 6.3
Gegeben ist folgende P-T~3~-Regelstrecke:
$$
𝐾_{PS} = 12.75 \qquad 𝑇_1 = 5.25\,\mathrm{s} \qquad 𝑇_2 = 2.5\,\mathrm{s} \qquad 𝑇_3 = 0.75\,\mathrm{s}
$$
Baue den Regelkreis in <span class="cap">Boris</span> auf und entwerfe einen PID-Regler gemäss [T-Summen-Regel](#entwurf-nach-der-t-summen-regel). Stelle in einem Zeitverlaufsdiagramm die Führungssprungantwort dar, wobei die beiden Einstellungen (*normal* bzw. *schnell*) vergleichend dargestellt werden sollen.
::: {.callout-important collapse="true"}
### Lösung
$$
T_{\Sigma} = T_1 + T_2 + T_3 = 8.5 \, \mathrm{s}
$$
Die Reglerparametrierung erfolgt dann mittels @tbl-tsumme.
Normaler Reglerentwurf:
$$
K_{PR} = \frac{1}{K_{PS}} = 0.08
$$
$$
T_i = 0.66 \cdot T_{\Sigma} = 5.61
$$
$$
T_d = 0.167 \cdot T_{\Sigma} = 1.42
$$
Schneller Reglerentwurf:
$$
K_{PR} = \frac{2}{K_{PS}} = 0.16
$$
$$
T_i = 0.8 \cdot T_{\Sigma} = 6.8
$$
$$
T_d = 0.194 \cdot T_{\Sigma} = 1.65
$$
{fig-align="center"}
{fig-align="center"}
:::
:::
::::
[^i_regler]: Der Vollständigkeit halber ist in @tbl-kombinationen auch der I-Regler aufgeführt, den wir aber nie einsetzen werden. Wie zu sehen ist in der Tabelle, hat er gegenüber dem PI-Regler keine Vorteile.
[^doppelt_integrierend]: Wenn zwei I-Glieder in Reihe geschaltet werden, d. h. die Strecke zwei I-Glieder aufweist, sprechen wir von einer *doppelt integrierenden* Strecke oder I~2~-Strecke. Eine solche Strecke ist grundsätzlich instabil, kann mit einem D-Anteil im Regler aber stabilisiert werden. Wir werden uns in diesem Modul nicht mit solchen Strecken beschäftigen.