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
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