PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Vorsteuerung bei PID-Regler



BoGe-Ro
01.11.2010, 11:19
Hallo Forum,

eigentlich ist die Frage eher allgemein, anstatt auf Bascom bezogen.
Aber, da ich in Bascom programmiere und eben für das Bascom-Programm Hilfe benötige poste ich es hier.

Ich habe in einem Bascom-Programm eine Function PID-Regler welche die Heizleistung für eine Temperaturregelung ausgibt.



Function Pid_regler(byval _text As String) As Byte
Local _y As Single , _x As Single , _e As Single , _pid As Single , _pwm As Byte
Local _kp As Single , _ki As Single , _kd As Single
Local _proportionalteil As Single , _integralteil As Single , _differentialteil As Single
Local _esum As Single , _ealt As Single
Local _betrag_e As Word
Local _schwelle As Word
Local _esum_startwert As Single
Local _integralteil_startwert As Single
Local _pwm_max As Byte
Const _ta = 1 'Abtastintervall

Select Case _text
Case "L":
Sreg.7 = 0
_pwm = Ocr1a
_y = T_ist_luft
Sreg.7 = 1
_x = Prog_temperatur_luft
_kp = Kp_l
_ki = Ki_l
_kd = Kd_l
_esum = Esum_luft
_ealt = Ealt_luft
_schwelle = Schwelle_l
_pwm_max = P_l_ueberw

'Annahme lineare Kennlinie
'P_heizung_luft=0 bei T_soll=20°C
'P_heizung_luft=85 bei T_soll=80°C
'bei _e=0 => P-Anteil=0 => Heizleistung wird durch I-Anteil bestimmt
'
'_integralteil = 0,0142 * ( T soll ) - 28,333
'_esum = _integralteil / (_ki * _ta) - e*Kp
_integralteil = T_ist_luft * 0.0142
_integralteil = _integralteil - 28.333
'Help_single = _x - _y
'Help_single = Help_single * _kp
'_integralteil = _integralteil - Help_single
If _integralteil < 0 Then _integralteil = 0
_integralteil_startwert = _integralteil
_esum_startwert = _integralteil / _ki



Case "K":
Sreg.7 = 0
_pwm = Ocr1b
_y = T_ist_kondensat
Sreg.7 = 1
_x = Prog_temperatur_kondensat
_kp = Kp_k
_ki = Ki_k
_kd = Kd_k
_esum = Esum_kondensat
_ealt = Ealt_kondensat
_schwelle = Schwelle_k
_pwm_max = P_k_hzg_max

End Select

_e = _x - _y 'Regelfehler
_betrag_e = Abs(_e)

If _betrag_e > _schwelle Then
If _e > 0 Then _pwm = 255 Else _pwm = 0 'Vollaussteuerung
_esum = _esum_startwert 'Vorgabe I_Anteil
Else

If _pwm > 0 And _pwm < _pwm_max Then _esum = _esum + _e
_proportionalteil = _kp * _e 'Proportionalteil berechnen

_integralteil = _ki * _ta 'Integralteil berechnen
_integralteil = _integralteil * _esum

_differentialteil = _e - _ealt 'Differentialglied berechnen
_differentialteil = _differentialteil * _kd
_differentialteil = _differentialteil / _ta

_pid = _proportionalteil + _integralteil 'Alle Glieder zusammenfassen
_pid = _pid + _differentialteil

_ealt = _e

If _pid <= 255 And _pid >= 0 Then
_pid = Round(_pid)
_pwm = _pid
Else
If _pid > 255 Then _pwm = 255 Else _pwm = 0
End If
End If

'(
Sreg.7 = 0
Print Zeit_string ; Spc(2) ; Zaehler_long ; Spc(2) ;
Help_string = Str(t_ist_luft) : Help_string = Format(help_string , "00.00")
Print Help_string ; Spc(1);
Help_string = Str(prog_temperatur_luft) : Help_string = Format(help_string , "00.00")
Print Help_string ; Spc(1);
_e = _e / 100
Help_string = Fusing(_e , "#.##")
Print Help_string ; Spc(2);
Print Ausgabe(_proportionalteil) ; Spc(1) ; Ausgabe(_integralteil) ; Spc(1) ; Ausgabe(_integralteil_startwert) ; Spc(2) ; Ausgabe(_pid) ; Spc(2) ; P_l_soll ; Spc(2) ; N_l_soll
Sreg.7 = 1
')
Select Case _text
Case "L":
Esum_luft = _esum
Ealt_luft = _ealt
Case "K":
Esum_kondensat = _esum
Ealt_kondensat = _ealt
End Select
Pid_regler = _pwm 'Ausgang
End Function



Hierbei habe ich eine Temperatur-Schwelle definiert, unter welcher die Heizung voll gesteuert wird und innerhalb der Schwelle soll der Regler greifen.

Weiterhin versuche ich mit esum_startwert eine Heizleistung zu ermitteln, welche unmittelbar nach überschreiten der Schwelle den I-Anteil des PID-Reglers füttern soll, um schon eine anähernde Heizleistung vorzugeben.

Leider bin ich mit dieser Lösung ziemlich unzufrieden und würde gern wissen, wie man eine "Vorsteuerung" richtig realisiert.


besten Dank

BoGe-Ro

Besserwessi
01.11.2010, 17:49
Solange der Regler nur eine konstante Temperatur halten soll, braucht man eigentlich keine Vorsteuerung. Da reicht der Integralanteil eigentlich aus. Sinnvoll ist die Vorsteuerung nach meiner Erfahrung dann, wenn man einem vorgegeben relativ steilen Temperaturprofil folgen will. Da kommt dann zusätzlich zur Heizleistung noch Leistung auf Grund des aktuellen Profils dazu. Dabei ist die Temperatur nicht so wichtig, sondern mehr der Sollwert der Steigung und ggf. auch die Nähe zu einem Wechsel in der Steigung. Wenn man will kann man die Parameter dazu aus direkt aus der Wärmekapazität berechnen.

Den Übergang zwischen der heurisctischen 2 Punktregelung und der PWM Regelung würde ich so machen, das sich ein glatter Übergang ergibt, gerade so als hätte man den Zustand der extremen Leistung auch mit dem PID-Regler erreicht. Den Wert für das Integral also so wählen das man beim Übergang in den PID-regler auch wieder an der Grenze der maximalen Leistung ist.

BoGe-Ro
02.11.2010, 20:03
Hallo,

sicherlich ist der Begriff Vorsteuerung an der Stelle mit dem was ich meine verkehrt - ich war wirklich mies in Regelungstechnik.

Jedenfalls genau diesen Übergang zwischen Steuerung und Regelung mein ich - un die nächste Zeit danach.

Also, ich hab ursprünglich eine Systemidentifikation durchgeführt und mit den Werten über Ziegler-Nichols die Werte für einen PI-Regler bestimmt.

Den D-Anteil hab ich aussen vor gelassen, da es hauptsächlich Reaktionen auf das Messwertrauschen gab und sich auch nur für Ta=1s auswirkten.

Nun will ich mit relativ schwacher zur Verfügung stehender Heizleistung 20 Liter Wasser aufheizen, hierbei werden relativ schwache Anforderungen an die Genauigkeit gestellt.

Leider seh ich hierbei, dass der I-Anteil erst sehr sehr langsam zum tragen kommt, die ohnehin geringe Heizleistung also anfangs nichtmal ganz zum Tragen kommt.

Daher die Idee, unterhalb der Schwelle die Heizung voll anzusteuern.
Bei Erreichen der Schwelle, schalte ich auf Regelung um und lade die Variable e_sum mit dem Wert vor, welchen ich aus vorherigen Tests ermittelt hab.

Meiner Meinung nach ist dieser Wert der, der später zum Halten der Sollspannung notwendig ist.

Nun habe ich durch die Steuerung der Heizleistung beinah die Soll-Temperatur, schalte um auf Regelung und geb dem I-Anteil (über e_sum) den Wert, der "genau der richtige" sein sollte und sehe, dass sich in nächster Zeit der I-Anteil nach unten integriert und sich danach erst wieder langsam hochhechelt.

Auf ein Folgen eines Temperaturprofils kommt es wirklich nicht an, aber gerade dieses erste Einschwingen , oder eher des ersten Teils des Einschwingen möcht ich beschleunigen


Gruß BoGe-Ro

jeffrey
02.11.2010, 20:34
Hallo,
also ich versteh auch deinen code nicht ganz, habe ihn aber auch nur kurz angeschaut ;-) warum ziehst du vom integralteil noch etwas ab?
wie wäre es anstatt mit einer reglerumschaltung mit paramteränderunge von kp und ki? habe ich auch schon so gehandhabt. einfach bei weitem abstand vom sollwert den regler stärker anziehen?
wenn du es bei klassischem pi lassen möchtest, würde ich es so probieren:
heizen mit vollgas bis zur hälfte, oder so, dann damit es einen glatten übergang gibt, i_init=p_max-kp*e
mfg jeffrey

BoGe-Ro
04.11.2010, 14:41
erstmal herzlichen Dank für die Antworten.

mein Fehler war selbsgemacht, der Teil, der den Initialisierungswert für den I-Anteil ausrechnet wurde immer durchgeführt, nicht nur ausserhalb der Schwelle wo der Regler arbeiten soll.

Dies hab ich nun geändert und die Initialisierung für "beide" Regler mit reingenommen und nun gehts.

die Funktion schaut nun so aus:



Function Pid_regler(byval _text As String) As Byte
Local _y As Single , _x As Single , _e As Single , _pid As Single , _pwm As Byte
Local _kp As Single , _ki As Single , _kd As Single
Local _proportionalteil As Single , _integralteil As Single , _differentialteil As Single
Local _esum As Single , _ealt As Single
Local _betrag_e As Word
Local _schwelle As Word
Local _pwm_max As Byte
Local _p_typ As Byte
Local _t_typ As Word
Local _m As Single , _n As Single
Const _ta = 1 'Abtastintervall

Select Case _text
Case "L":
Sreg.7 = 0
_pwm = Ocr1a
_y = T_ist_luft
Sreg.7 = 1
_x = Prog_temperatur_luft
_kp = Kp_l
_ki = Ki_l
_kd = Kd_l
_esum = Esum_luft
_ealt = Ealt_luft
_schwelle = Schwelle_l
_pwm_max = P_l_ueberw

_p_typ = P_l_typ 'typische Heizleistung bezogen auf
_t_typ = T_l_typ 'typische Lufttemperatur


Case "K":
Sreg.7 = 0
_pwm = Ocr1b
_y = T_ist_kondensat
Sreg.7 = 1
_x = Prog_temperatur_kondensat
_kp = Kp_k
_ki = Ki_k
_kd = Kd_k
_esum = Esum_kondensat
_ealt = Ealt_kondensat
_schwelle = Schwelle_k
_pwm_max = P_k_hzg_max

_p_typ = P_k_typ 'typische Heizleistung bezogen auf
_t_typ = T_k_typ 'typische Kondensattemperatur


End Select

_e = _x - _y 'Regelfehler
_betrag_e = Abs(_e)

If _betrag_e > _schwelle Then
Help_single = _t_typ - 2000 'delta T
_m = _p_typ / Help_single 'Anstieg Heizsteuerung

Help_single = _m * _t_typ
_n = _p_typ - Help_single 'Abschnitt Heizsteuerung

_integralteil = _m * _x
_integralteil = _integralteil + _n

If _integralteil < 0 Then _integralteil = 0
_esum = _integralteil / _ki 'Vorgabe I-Anteil

If _e > 0 Then _pwm = 255 Else _pwm = 0 'Vollaussteuerung

Else

If _pwm > 0 And _pwm < _pwm_max Then _esum = _esum + _e

_proportionalteil = _kp * _e 'Proportionalteil berechnen

_integralteil = _ki * _ta 'Integralteil berechnen
_integralteil = _integralteil * _esum

_differentialteil = _e - _ealt 'Differentialglied berechnen
_differentialteil = _differentialteil * _kd
_differentialteil = _differentialteil / _ta

_pid = _proportionalteil + _integralteil 'Alle Glieder zusammenfassen
_pid = _pid + _differentialteil

_ealt = _e

If _pid <= 255 And _pid >= 0 Then
_pid = Round(_pid)
_pwm = _pid
Else
If _pid > 255 Then _pwm = 255 Else _pwm = 0
End If
End If

Select Case _text
Case "L":
Esum_luft = _esum
Ealt_luft = _ealt
Case "K":
Esum_kondensat = _esum
Ealt_kondensat = _ealt
End Select
Pid_regler = _pwm
End Function


das Subtrahieren bei Integralteil kommt aus der Kennlinie.
Ich möchte ja erst bei einer Solltemperatur über 20°C losheizen - also geht die Heizleistungskurve nicht durch Null, sondern hat einen Achsenabschnitt.


Gruß BoGe-Ro