Forum: Mikrocontroller und Digitale Elektronik PID Regler verbessern


von Denny (Gast)


Lesenswert?

Hallo.
Ich habe einen PD-Regler programmiert.
Er dient dazu, einen kleinen Dauermagneten unter einer Spule in der 
Schwebe zu halten.
1
'+----------------------------------------------------------------------------+'
2
'| Titel             :     Endarbeit: "Schwebender Magnet"                    |'
3
'+----------------------------------------------------------------------------+'
4
'| Funktion          :     Der Magnet schwebt unter einer Spule.              |'
5
'| Anschlüsse        :     PB1=PWM; PC0=ADC; PD2=RC5; PB0=LED                 |'
6
'+----------------------------------------------------------------------------+'
7
'| Name              :     Weinberg Denny                                     |'
8
'| E-Mail Adresse    :     Denny_Weinberg@hotmail.com                         |'
9
'+----------------------------------------------------------------------------+'
10
11
12
'|---------------------------------Controller---------------------------------|'
13
$regfile = "m8def.dat"                                      'ATmega8
14
$crystal = 14745600                                         'Quarzfrequenz (Extern); Standart: 14745600
15
$baud = 230400                                              'Funktionierende Baudrate; Standart: 230400
16
17
$hwstack = 100
18
$swstack = 100
19
$framesize = 100                                            'Freier Speicherplatz für Variablen...
20
21
22
'|---------------------------------Variablen----------------------------------|'
23
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten
24
25
Dim Istwert As Integer                                      'Analoge Spannung des Hallsensors
26
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
27
Dim Lastistewert As Integer                                 'Istwert der letzten Messung
28
Dim Delta As Integer                                        'Die Veränderung der Spannung des Hallsensors während eines Zyklus
29
Dim Kp As Integer                                           'Die Dämpfung des Magneten
30
Dim Ki As Integer
31
Dim Kd As Integer
32
Dim P As Integer
33
Dim I As Integer
34
Dim D As Integer
35
Dim Sollwert As Integer
36
37
Dim Rs232nummer As Byte                                     'ASCII-Code die seriell ankommen
38
Dim Zeichen As String * 5                                   'Seriell ankommende Zeichen
39
Dim Anfangsbuchstabe As String * 1                          'Hilfsbuchstabe bei Änderungen
40
Dim Endwert As String * 4                                   'Der wirkliche Wert der benötigt wird
41
Dim Zeichengroesse As Byte                                  'Hilfsvariable um das erste Zeichen herauszufiltern
42
43
Dim Impulslaenge As Word
44
Dim Rc5bitnummer As Byte
45
Dim Tempdaten As Word
46
Dim Befehl As Byte
47
Dim Empfangsfehler As Byte
48
Dim Wiederholen_erlaubt As Bit
49
Dim Letzter_befehl As Byte
50
Dim Rc5timervorgabe As Byte
51
Dim Interruptvektor As Bit
52
53
54
'|--------------------------------Konfiguration-------------------------------|'
55
Declare Sub Rc5()
56
Declare Sub Regelung_berechnen()                            'Unterprogramm um die Variablen zu Regelung_Berechnen
57
Declare Sub Regelung_auswerten()                            'Unterprogramm um die berechneten Werte auszuwerten
58
Declare Sub Rc5_berechnen()                                 'Unterprogramm, um den RC5-Code zu berechnen
59
Declare Sub Rc5_auswerten()                                 'Unterprogramm, um den RC5-Code auszuwerten
60
61
Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler
62
63
Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation
64
65
On Urxc Isr_rs232                                           'Interrupt der seriellen schnittstelle
66
Enable Urxc                                                 'Interrupt der seriellen schnittstelle einschalten
67
68
Config Timer0 = Timer , Prescale = 8
69
On Ovf0 Isr_timer0
70
Enable Timer0
71
72
Rc5timervorgabe = 26                                        'Impulslänge bei RC5 1,778ms --> 8000 Überlaufe / Sekunde
73
Timer0 = Rc5timervorgabe
74
75
Config Int0 = Rising                                        'Externer Interrupt; Steigende Flanke
76
77
Reset Ddrd.2                                                'Ausgang des Infrarormodules
78
Set Portd.2                                                 'Pullup ein
79
80
On Int0 Isr_int0
81
Enable Int0
82
83
Enable Interrupts                                           'Interrupts einschalten
84
85
86
'|-----------------------------Eingänge und Ausgänge--------------------------|'
87
Set Ddrb.0                                                  'Freier Pin (LED)
88
89
90
'|--------------------------------Einstellungen-------------------------------|'
91
Set Eingeschaltet                                           'Einschalten
92
93
Kd = 255                                                    '255
94
Kp = 1
95
Sollwert = 120                                              '120
96
97
Set Portb.0                                                 'LED Einschalten
98
99
Set Wiederholen_erlaubt                                     'Damit man eine Taste gedrückt halten kann
100
101
102
'|--------------------------------Hauptprogramm-------------------------------|'
103
Do
104
    Call Rc5
105
106
    If Eingeschaltet = 1 Then
107
       Start Adc
108
          Istwert = Getadc(0)                               'Analoge Spannung des Hallsensors messen
109
       Stop Adc
110
111
       Call Rc5                                             'Sonst bekommt er nicht alle RC5-Codes mit
112
113
       Call Regelung_berechnen                              'Werte Berechnen
114
115
       Call Rc5
116
117
       Call Regelung_auswerten                              'Werte Auswerten (begrenzen)
118
    Else
119
       Pulsweite = 0
120
    End If
121
122
    Pwm1a = Pulsweite                                       'Spulenstrom regeln
123
Loop
124
125
126
'|--------------------------------Alles mit RC5-------------------------------|'
127
Sub Rc5()
128
    If Interruptvektor = 1 Then
129
       Call Rc5_berechnen
130
131
       If Rc5bitnummer = 14 Then
132
          Call Rc5_auswerten
133
       End If
134
135
       Impulslaenge = 0
136
       Interruptvektor = 0
137
    End If
138
End Sub
139
140
141
'|-------------------------------Werte Berechnen------------------------------|'
142
Sub Regelung_berechnen()
143
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt
144
145
    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255
146
147
    Delta = Istwert - Sollwert
148
149
    P = Delta * Kp
150
151
    'I
152
153
    Delta = Istwert - Lastistewert                          'Istwertsveränderung Berechnen
154
    D = Delta * Kd                                          'Dämpfung hinzurechnen
155
156
    Pulsweite = D + P                                       'Pulsweite Berechnen
157
End Sub
158
159
160
'|----------------------------------Auswerten---------------------------------|'
161
Sub Regelung_auswerten()
162
    If Istwert > 0 Then
163
       If Pulsweite > 255 Then Pulsweite = 255              'Begrenzungen der Pulsweite einhalten
164
       If Pulsweite < 0 Then Pulsweite = 0                  'Begrenzungen der Pulsweite einhalten
165
166
       Lastistewert = Istwert                               'LastIstewert setzen
167
    Else                                                    'Wenn der Magnet falsch rum hängt wird er umgedreht
168
       Pulsweite = 255
169
    End If
170
End Sub
171
172
'|----------------------------------Berechnen---------------------------------|'
173
Sub Rc5_berechnen()
174
    Select Case Impulslaenge
175
       Case Is > 1500:                                      '-> startimpuls, nach empgfangsfehler muss immer erst ein solcher kommen.
176
          Rc5bitnummer = 1
177
          Tempdaten = 1
178
          Empfangsfehler = 0
179
       Case 26 To 29:                                       '-> große Länge: vorher 0, jetzt 1 + 0
180
          If Empfangsfehler = 0 Then
181
             Shift Tempdaten , Left                         'hinzufügen einer 0
182
             Incr Tempdaten                                 'umwandeln in 1
183
             Shift Tempdaten , Left                         'hinzufügen einer 0
184
             Incr Rc5bitnummer                              'bei Kombination '10' fehlt ein Impuls
185
          End If
186
       Case 19 To 22:                                       '-> mittlere Länge: vorher 1, jetzt 1 + 0 oder vorher 0 jetzt 1
187
          If Empfangsfehler = 0 Then
188
             Shift Tempdaten , Left                         'hinzufügen einer 0
189
             Incr Tempdaten                                 'umwandeln in 1
190
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
191
                Shift Tempdaten , Left                      'hinzufügen einer 0
192
                Incr Rc5bitnummer                           'bei Kombination '10' fehlt ein Impuls
193
             End If
194
          End If
195
       Case 12 To 15:                                       '-> kleine Länge     --> gleicher Wert wie vorher
196
          If Empfangsfehler = 0 Then
197
             Shift Tempdaten , Left , 1                     'hinzufügen einer 0
198
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
199
                Incr Tempdaten                              'umwandeln in 1
200
             End If
201
          End If
202
       Case Is > 400:                                       'aber kleiner 1500, dann war's eine Pause zwischen Befehlen beim Dauerdrücken
203
          If Empfangsfehler = 1 Or Wiederholen_erlaubt = 1 Then
204
             Rc5bitnummer = 1
205
             Tempdaten = 1
206
             Empfangsfehler = 0
207
          End If
208
       Case Else
209
         Empfangsfehler = 1
210
    End Select
211
End Sub
212
213
'|----------------------------------Auswerten---------------------------------|'
214
Sub Rc5_auswerten()
215
    Befehl = Tempdaten And &B00111111                       'Überflüssige Bits herausfiltern
216
    If Befehl < 64 Then
217
       If Wiederholen_erlaubt = 1 Or Befehl <> Letzter_befehl Then
218
          Letzter_befehl = Befehl
219
          Select Case Befehl
220
             Case 3
221
                Sollwert = Sollwert + 10
222
             Case 6
223
                Sollwert = Sollwert - 10
224
             Case 9
225
                Toggle Eingeschaltet
226
          End Select
227
228
          Befehl = 0
229
       End If
230
    End If
231
End Sub
232
233
234
'|--------------------Interrupt der seriellen Schnittstelle-------------------|'
235
Isr_rs232:
236
    Rs232nummer = Inkey()                                   'ASCII-Code einlesen
237
238
    Select Case Rs232nummer
239
       Case 13                                              'RS232Nummer 13 ist das Enter, das gesendet wird, wenn alles gesendet ist
240
          Select Case Zeichen
241
             Case "EIA"
242
                 Print Eingeschaltet                        'Zurücksenden, ob das Gerät eingeschaltet ist
243
             Case "POS"
244
                 Print Istwert                              'Istwert zurücksenden
245
             Case "SOL"
246
                 Print Sollwert                             'Sollwert zurücksenden
247
             Case "AUS"
248
                 Reset Eingeschaltet                        'Ausschalten
249
             Case "EIN"
250
                 Set Eingeschaltet                          'Einschalten
251
             Case "PB0"
252
                 Toggle Portb.0                             'LED Umschalten
253
             Case "P0E"
254
                 Set Portb.0                                'PortB.0 Einschalten
255
             Case "P0A"
256
                 Reset Portb.0                              'PortB.0 Ausschalten
257
             Case "KP"
258
                 Print Kp
259
             Case "KI"
260
                 Print Ki
261
             Case "KD"
262
                 Print Kd
263
             Case Else
264
                 Zeichengroesse = Len(zeichen) - 1          'Zeichengröße, um den Endwert herauszufinden
265
266
                 Anfangsbuchstabe = Left(zeichen , 1)       'Anfangsbuchstabe rausschneiden
267
                 Endwert = Right(zeichen , Zeichengroesse)  'Endwert rausschneiden
268
269
                 Select Case Anfangsbuchstabe
270
                   Case "S"
271
                        Sollwert = Val(endwert)             'Es wurde der Sollwert gesendet
272
                   Case "KP"
273
                        Kp = Val(endwert)                   'Es wurde die Dämpfung gesendet
274
                   Case "KI"
275
                        Ki = Val(endwert)
276
                   Case "KD"
277
                        Kd = Val(endwert)
278
                 End Select
279
          End Select
280
281
          Zeichen = ""                                      'Zeichen zurücksetzen
282
       Case Else
283
          Zeichen = Zeichen + Chr(rs232nummer)              'Nächstes zeichen hinzusetzen
284
    End Select
285
Return                                                      'Ins Hauptprogramm zurückspringen
286
287
288
'|----------------------Interrupt des Timer0 (Überlauf)-----------------------|'
289
Isr_timer0:
290
   Timer0 = Rc5timervorgabe
291
   Incr Impulslaenge
292
   If Impulslaenge > 65000 Then                             'Überlauf von Impulslaenge verhindern (nach 65535 kommt 0),
293
                                                             'damit Start (Impulslaenge > 500) sicher erkannt wird
294
      Impulslaenge = 1501
295
   End If
296
Return
297
298
'|--------------------Interrupt des externen Pins PIND.2----------------------|'
299
Isr_int0:                                                   'RC5 Impuls erkannt
300
   Incr Rc5bitnummer
301
   Interruptvektor = 1
302
Return
303
'|----------------------------------The End-----------------------------------|'

Es geht hauptsächlich um den Sub "Regelung_berechnen".
Ich möchte jetzt noch einen I-Anteil ins Programm integrieren.

Könnt ihr mir bitte erklären, wie ich das mache und welche Auswirkungen 
das genau hat??

P.S.: Die Regelung funktioniert sehr gut, allerdings gibt es immer eine 
Regeldifferenz (Magnet schwebt nie an der Sollwertstelle) und die 
funktionierende Hubhöhe ist nicht gerade groß.

Mit freundlichen Grüßen.
Denny

von Heiko (Gast)


Lesenswert?

Moin,

hab ich gerade ein deja vu oder hast du das vor ein paar Tagen schonmal 
gepostet?

Zu deinen Fragen:

Denny schrieb:
> Ich möchte jetzt noch einen I-Anteil ins Programm integrieren.
> Könnt ihr mir bitte erklären, wie ich das mache und welche Auswirkungen
> das genau hat??

Die genauen Auswirkungen sind schwierig zu erklären und mit deinen 
Angaben nicht zu bestimmen - besonders, weil dein Regelkreis hochgradig 
nichtlinear ist.

Wie du das machst... naja, im kontinuierlichen w(t) = k_I * 
int(e(tau)*dtau,tau=0..t). Ein Mikrocontroller kann jetzt nicht mit 
kontinuierlicher Zeit rechnen, damit wird aus dem infinitesimal kleinen 
dtau ein T (Abtastperiode), die Funktion e(t) ist ohnehin nur zu 
bestimmten Zeiten e(kT) bekannt, das kann man kurz als e_k schreiben, 
und das Integral wird wieder zu einer Summe (aus der die Integration 
schließlich mal hergeleitet wurde. Zusammengefasst also w_k=k_I * 
summe(e(jT)*T,j=0..k) = k_I  T  summe(e_j,j=0..k).

Nun ist diese Summe etwas zu aufwändig, um sie bei jedem Schritt zu 
berechnen - also muss man sie vereinfachen. Das geht auch ganz toll, 
denn summe(e_j,j=0..k)=summe(e_j,j=0..k-1)+e_k oder auch kurz sum_k = 
sum_(k-1) + e_k.

Zusammengefasst: w_k = k_I  T  sum_k und sum_k = sum(k-1) + e_k

Denny schrieb:
> P.S.: Die Regelung funktioniert sehr gut, allerdings gibt es immer eine
> Regeldifferenz (Magnet schwebt nie an der Sollwertstelle)

Dagegen sollte ein I-Anteil helfen.

Denny schrieb:
> und die funktionierende Hubhöhe ist nicht gerade groß.

Das ist bei einem linearen Regler an einem nichtlinearen, instabilen 
System zu erwarten. Besser wird das nur mit einem anderem 
Regelverfahren...

MfG, Heiko

von Denny (Gast)


Lesenswert?

Ich verstehe.
Ich werde es heute versuchen.

Heiko schrieb:
> Das ist bei einem linearen Regler an einem nichtlinearen, instabilen
> System zu erwarten. Besser wird das nur mit einem anderem
> Regelverfahren...
Was meinst Du mit einem anderen Regelverfahren??

Danke schon Mal für die gute Hilfe!

von TestX .. (xaos)


Lesenswert?

> Was meinst Du mit einem anderen Regelverfahren??

es gibt noch was anderes als dieses standard kinderkram pid zeugs...
kannst mal bei wiki unter nichtlinearen reglern suchen, wird aber 
wesentlich komplexer

von Heiko (Gast)


Lesenswert?

Denny schrieb:
> Was meinst Du mit einem anderen Regelverfahren??

Es gibt auch noch andere Regler als PID-Regler. Manche davon sind besser 
für nichtlineare Systeme geeignet. Mit Details kenne ich mich aber nicht 
aus.

MfG, Heiko

von Denny (Gast)


Lesenswert?

Das mit dem I-Anteil funktioniert noch nicht so gut.
1
'+----------------------------------------------------------------------------+'
2
'| Titel               :     Endarbeit: "Schwebender Magnet"                  |'
3
'+----------------------------------------------------------------------------+'
4
'| Funktion            :     Der Magnet schwebt unter einer Spule.            |'
5
'| Anschlüsse          :     PB1=PWM; PC0=ADC; PD2=RC5; PB0=LED               |'
6
'+----------------------------------------------------------------------------+'
7
'| Name                :     Weinberg Denny                                   |'
8
'| E-Mail Adresse      :     Denny_Weinberg@hotmail.com                       |'
9
'+----------------------------------------------------------------------------+'
10
11
'+----------------------------------------------------------------------------+'
12
'| PID-Regler          :                                                      |'
13
'|                                                                            |'
14
'| RC5-Empfang         :                                                      |'
15
'|                                                                            |'
16
'| RS232-Schnittstelle :                                                      |'
17
'+----------------------------------------------------------------------------+'
18
19
20
'|---------------------------------Controller---------------------------------|'
21
$regfile = "m8def.dat"                                      'ATmega8
22
$crystal = 14745600                                         'Quarzfrequenz (Extern); Standart: 14745600
23
$baud = 230400                                              'Funktionierende Baudrate; Standart: 230400
24
25
$hwstack = 100
26
$swstack = 100
27
$framesize = 100                                            'Freier Speicherplatz für Variablen...
28
29
30
'|---------------------------------Variablen----------------------------------|'
31
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten
32
33
Dim Istwert As Integer                                      'Analoge Spannung des Hallsensors
34
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
35
Dim Lastistewert As Integer                                 'Istwert der letzten Messung
36
Dim Delta As Single                                         'Die Veränderung der Spannung des Hallsensors während eines Zyklus
37
Dim Kp As Single                                            'Die Dämpfung des Magneten
38
Dim Ki As Single
39
Dim Kd As Single
40
Dim P As Single
41
Dim I As Single
42
Dim D As Single
43
Dim Integrator As Integer
44
Dim Sollwert As Single
45
46
Dim Rs232nummer As Byte                                     'ASCII-Code die seriell ankommen
47
Dim Zeichen As String * 10                                  'Seriell ankommende Zeichen
48
Dim Anfangsbuchstabe As String * 2                          'Hilfsbuchstabe bei Änderungen
49
Dim Endwert As String * 8                                   'Der wirkliche Wert der benötigt wird
50
Dim Zeichengroesse As Byte                                  'Hilfsvariable um das erste Zeichen herauszufiltern
51
52
Dim Impulslaenge As Word
53
Dim Rc5bitnummer As Byte
54
Dim Tempdaten As Word
55
Dim Befehl As Byte
56
Dim Empfangsfehler As Byte
57
Dim Wiederholen_erlaubt As Bit
58
Dim Letzter_befehl As Byte
59
Dim Rc5timervorgabe As Byte
60
Dim Interruptvektor As Bit
61
62
63
'|--------------------------------Konfiguration-------------------------------|'
64
Declare Sub Rc5()
65
Declare Sub Regelung_berechnen()                            'Unterprogramm um die Variablen zu Regelung_Berechnen
66
Declare Sub Regelung_auswerten()                            'Unterprogramm um die berechneten Werte auszuwerten
67
Declare Sub Rc5_berechnen()                                 'Unterprogramm, um den RC5-Code zu berechnen
68
Declare Sub Rc5_auswerten()                                 'Unterprogramm, um den RC5-Code auszuwerten
69
70
Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler
71
72
Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation
73
74
On Urxc Isr_rs232                                           'Interrupt der seriellen schnittstelle
75
Enable Urxc                                                 'Interrupt der seriellen schnittstelle einschalten
76
77
Config Timer0 = Timer , Prescale = 8
78
On Ovf0 Isr_timer0
79
Enable Timer0
80
81
Rc5timervorgabe = 26                                        'Impulslänge bei RC5 1,778ms --> 8000 Überlaufe / Sekunde
82
Timer0 = Rc5timervorgabe
83
84
Config Int0 = Rising                                        'Externer Interrupt; Steigende Flanke
85
86
Reset Ddrd.2                                                'Ausgang des Infrarormodules
87
Set Portd.2                                                 'Pullup ein
88
89
On Int0 Isr_int0
90
Enable Int0
91
92
Enable Interrupts                                           'Interrupts einschalten
93
94
95
'|-----------------------------Eingänge und Ausgänge--------------------------|'
96
Set Ddrb.0                                                  'Freier Pin (LED)
97
98
99
'|--------------------------------Einstellungen-------------------------------|'
100
Set Eingeschaltet                                           'Einschalten
101
102
Kd = 255                                                    '255
103
Ki = 0.7
104
Kp = 1
105
Sollwert = 120                                              '120
106
107
Set Portb.0                                                 'LED Einschalten
108
109
Set Wiederholen_erlaubt                                     'Damit man eine Taste gedrückt halten kann
110
111
112
'|--------------------------------Hauptprogramm-------------------------------|'
113
Do
114
    Call Rc5
115
116
    If Eingeschaltet = 1 Then
117
       Start Adc
118
          Istwert = Getadc(0)                               'Analoge Spannung des Hallsensors messen
119
       Stop Adc
120
121
       Call Rc5                                             'Sonst bekommt er nicht alle RC5-Codes mit
122
123
       Call Regelung_berechnen                              'Werte Berechnen
124
125
       Call Rc5
126
127
       Call Regelung_auswerten                              'Werte Auswerten (begrenzen)
128
    Else
129
       Pulsweite = 0
130
    End If
131
132
    Pwm1a = Pulsweite                                       'Spulenstrom regeln
133
Loop
134
135
136
'|--------------------------------Alles mit RC5-------------------------------|'
137
Sub Rc5()
138
    If Interruptvektor = 1 Then
139
       Call Rc5_berechnen
140
141
       If Rc5bitnummer = 14 Then
142
          Call Rc5_auswerten
143
       End If
144
145
       Impulslaenge = 0
146
       Interruptvektor = 0
147
    End If
148
End Sub
149
150
151
'|-------------------------------Werte Berechnen------------------------------|'
152
Sub Regelung_berechnen()
153
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt
154
155
    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255
156
157
    Delta = Istwert - Sollwert
158
    P = Delta * Kp
159
160
    I = Delta * 0.005
161
    I = I * Ki
162
    If Pulsweite <= 1 Then
163
    Else
164
       If Pulsweite < 1023 Then Integrator = Integrator + I
165
    End If
166
167
    Incr Integrator
168
    If Integrator < -1023 Then Integrator = -1023           'Begrenzung der Ausgangsgröße
169
    If Integrator > 1023 Then Integrator = 1023
170
    If Ki < 0.01 Then Integrator = 0
171
172
    Delta = Istwert - Lastistewert                          'Istwertsveränderung Berechnen
173
    D = Delta * Kd                                          'Dämpfung hinzurechnen
174
175
    Pulsweite = D + P                                       'Pulsweite Berechnen
176
    Pulsweite = Pulsweite + Integrator
177
End Sub
178
179
180
'|----------------------------------Auswerten---------------------------------|'
181
Sub Regelung_auswerten()
182
    If Istwert > 0 Then
183
       If Pulsweite > 255 Then Pulsweite = 255              'Begrenzungen der Pulsweite einhalten
184
       If Pulsweite < 0 Then Pulsweite = 0                  'Begrenzungen der Pulsweite einhalten
185
186
       Lastistewert = Istwert                               'LastIstewert setzen
187
    Else                                                    'Wenn der Magnet falsch rum hängt wird er umgedreht
188
       Pulsweite = 255
189
    End If
190
End Sub
191
192
'|----------------------------------Berechnen---------------------------------|'
193
Sub Rc5_berechnen()
194
    Select Case Impulslaenge
195
       Case Is > 1500:                                      '-> startimpuls, nach empgfangsfehler muss immer erst ein solcher kommen.
196
          Rc5bitnummer = 1
197
          Tempdaten = 1
198
          Empfangsfehler = 0
199
       Case 26 To 29:                                       '-> große Länge: vorher 0, jetzt 1 + 0
200
          If Empfangsfehler = 0 Then
201
             Shift Tempdaten , Left                         'hinzufügen einer 0
202
             Incr Tempdaten                                 'umwandeln in 1
203
             Shift Tempdaten , Left                         'hinzufügen einer 0
204
             Incr Rc5bitnummer                              'bei Kombination '10' fehlt ein Impuls
205
          End If
206
       Case 19 To 22:                                       '-> mittlere Länge: vorher 1, jetzt 1 + 0 oder vorher 0 jetzt 1
207
          If Empfangsfehler = 0 Then
208
             Shift Tempdaten , Left                         'hinzufügen einer 0
209
             Incr Tempdaten                                 'umwandeln in 1
210
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
211
                Shift Tempdaten , Left                      'hinzufügen einer 0
212
                Incr Rc5bitnummer                           'bei Kombination '10' fehlt ein Impuls
213
             End If
214
          End If
215
       Case 12 To 15:                                       '-> kleine Länge     --> gleicher Wert wie vorher
216
          If Empfangsfehler = 0 Then
217
             Shift Tempdaten , Left , 1                     'hinzufügen einer 0
218
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
219
                Incr Tempdaten                              'umwandeln in 1
220
             End If
221
          End If
222
       Case Is > 400:                                       'aber kleiner 1500, dann war's eine Pause zwischen Befehlen beim Dauerdrücken
223
          If Empfangsfehler = 1 Or Wiederholen_erlaubt = 1 Then
224
             Rc5bitnummer = 1
225
             Tempdaten = 1
226
             Empfangsfehler = 0
227
          End If
228
       Case Else
229
         Empfangsfehler = 1
230
    End Select
231
End Sub
232
233
'|----------------------------------Auswerten---------------------------------|'
234
Sub Rc5_auswerten()
235
    Befehl = Tempdaten And &B00111111                       'Überflüssige Bits herausfiltern
236
    If Befehl < 64 Then
237
       If Wiederholen_erlaubt = 1 Or Befehl <> Letzter_befehl Then
238
          Letzter_befehl = Befehl
239
          Select Case Befehl
240
             Case 3
241
                Sollwert = Sollwert + 10
242
             Case 6
243
                Sollwert = Sollwert - 10
244
             Case 9
245
                Toggle Eingeschaltet
246
          End Select
247
248
          Befehl = 0
249
       End If
250
    End If
251
End Sub
252
253
254
'|--------------------Interrupt der seriellen Schnittstelle-------------------|'
255
Isr_rs232:
256
    Rs232nummer = Inkey()                                   'ASCII-Code einlesen
257
258
    Select Case Rs232nummer
259
       Case 13                                              'RS232Nummer 13 ist das Enter, das gesendet wird, wenn alles gesendet ist
260
          Select Case Zeichen
261
             Case "EIA"
262
                 Print Eingeschaltet                        'Zurücksenden, ob das Gerät eingeschaltet ist
263
             Case "POS"
264
                 Print Istwert                              'Istwert zurücksenden
265
             Case "SOL"
266
                 Print Sollwert                             'Sollwert zurücksenden
267
             Case "AUS"
268
                 Reset Eingeschaltet                        'Ausschalten
269
             Case "EIN"
270
                 Set Eingeschaltet                          'Einschalten
271
             Case "PB0"
272
                 Toggle Portb.0                             'LED Umschalten
273
             Case "P0E"
274
                 Set Portb.0                                'PortB.0 Einschalten
275
             Case "P0A"
276
                 Reset Portb.0                              'PortB.0 Ausschalten
277
             Case "KP"
278
                 Print Kp
279
             Case "KI"
280
                 Print Ki
281
             Case "KD"
282
                 Print Kd
283
             Case Else
284
                 Zeichengroesse = Len(zeichen) - 2          'Zeichengröße, um den Endwert herauszufinden
285
286
                 Anfangsbuchstabe = Left(zeichen , 2)       'Anfangsbuchstabe rausschneiden
287
                 Endwert = Right(zeichen , Zeichengroesse)  'Endwert rausschneiden
288
289
                 Select Case Anfangsbuchstabe
290
                   Case "SO"
291
                        Sollwert = Val(endwert)             'Es wurde der Sollwert gesendet
292
                   Case "KP"
293
                        Kp = Val(endwert)                   'Es wurde die Dämpfung gesendet
294
                   Case "KI"
295
                        Ki = Val(endwert)
296
                   Case "KD"
297
                        Kd = Val(endwert)
298
                 End Select
299
          End Select
300
301
          Zeichen = ""                                      'Zeichen zurücksetzen
302
       Case Else
303
          Zeichen = Zeichen + Chr(rs232nummer)              'Nächstes zeichen hinzusetzen
304
    End Select
305
Return                                                      'Ins Hauptprogramm zurückspringen
306
307
308
'|----------------------Interrupt des Timer0 (Überlauf)-----------------------|'
309
Isr_timer0:
310
   Timer0 = Rc5timervorgabe
311
   Incr Impulslaenge
312
   If Impulslaenge > 65000 Then                             'Überlauf von Impulslaenge verhindern (nach 65535 kommt 0),
313
                                                             'damit Start (Impulslaenge > 500) sicher erkannt wird
314
      Impulslaenge = 1501
315
   End If
316
Return
317
318
'|--------------------Interrupt des externen Pins PIND.2----------------------|'
319
Isr_int0:                                                   'RC5 Impuls erkannt
320
   Incr Rc5bitnummer
321
   Interruptvektor = 1
322
Return
323
'|----------------------------------The End-----------------------------------|'

Für die Zeit habe ich einfach mal 0.005 genommen und Ki ist 0.7.
Zuerst schwingt der Magnet sehr stark und dann nach einigen Sekunden 
schwebt er an seiner Position.
Manchmal fängt er wieder heftig an zu schwingen, kriegt sich aber wieder 
ein.
Der Sollwert ist 120 und die Schwebeposition ist ungefähr 130.
Was soll ich für Werte eingeben, dass es besser funktioniert??

von Stefan (Gast)


Lesenswert?

Die bleibende Regelabweichung spricht nicht grade für den Regler ... vor 
allem wenn er einen I-Anteil enthalten soll. Die Schwingneigung deutet 
auf zu geringe Dämpfung hin. Mach auch Kr mal kleiner.

Gruß!

von Stefan (Gast)


Lesenswert?

Edit: Ich meinte Kp.

von Heiko (Gast)


Lesenswert?

Denny schrieb:
> Was soll ich für Werte eingeben, dass es besser funktioniert??

Weiß ich doch auch nicht. Kennst du die Systemparameter? Dann such dir 
ein Reglerentwurfsverfahren (Eigenwertvorgabe, Ziegler-Nichols, 
Kessler...) aus und mach.

Wenn nicht: Erstmal Systemparameter bestimmen...

MfG, Heiko

von G. B. (garyb)


Lesenswert?

Hallo...

wenn es mit der Theorie nicht so hinhaut.... Faustregel.

1) I und D -Anteil zu null setzen..
    KI = 0 oder TI=9999999999
    KD = 0
2) KP langsam erhöhen bis man merkt das der Regler instabil wird.
   -> einfach mal schubsen...
      dabei stelle ich mir im Moment die Frage wie du die Postion 
bestimmst??
3) KP ca. 30% zurück stellen und den I-Anteil langsam erhöhen, bis
   das System ausreichend schnell ein den Bereich einschwingt den du dir
   vorstellst.

Den D-Anteil braucht man eigentlich nur wenn du schnelle Reaktionen 
brauchst,
aber in der Regel heizt du damit die Schwingneigung deines Reglers sehr 
an.

kleine Regel
P - gibt Power
I - gibt die PräzIsion
D - den SpeeD

;O)
Nicht sehr akademisch, aber vielleicht hilfts.
Gruss
Gary

von Denny (Gast)


Angehängte Dateien:

Lesenswert?

G. B. schrieb:
> KP langsam erhöhen bis man merkt das der Regler instabil wird.
Er ist die ganze Zeit instabil.
Ohne den Kd-Anteil geht es gar nicht.

G. B. schrieb:
> dabei stelle ich mir im Moment die Frage wie du die Postion
Die Position wird mit einem HAL815 gemessen.
Unten ist der Istwert 255 und oben (oder Magnet ganz weg) ist 0.

von Denny (Gast)


Lesenswert?

Sorry, dass ich nicht alles auf Anhieb versteh.
Ich bin noch ein Anfänger.

Mit den Werten:
Kp = 0.6
Kd = 100
Ki = 0.7 oder 0

Schwebt der Magnet sehr ruhig.
Allerdings ist der Istwert 200 bei einem Sollwert von 120.
Versteh ich nicht...

von G. B. (garyb)


Lesenswert?

Nur mal noch als Tip das Thema ist nicht ganz neu bzw. wird wegen des
Show-Effekts - denn man gerne mit nimmt - häufig gemacht.

Beitrag "Schwebende Kugel"

Zum Thema Einstellregeln... mein Tip war sehr pauschal und basiert
auf Erfahrung mit Antriebsregelungen. Die Anderen vor mir hatten aber
schon recht... genaue Angaben kann man nur mit einem Streckenmodel 
machen.

Dabei hilft dir aber auch das Web einfach mal nach "Regelung schwebender 
Magnet" eingeben.

Zu der Regelabweichung die du nun siehst, fällt mir im Moment nur 
folgendes ein:
a) Hast du Begrenzungen in deinem Regler überschritten - z.B. I-Anteil.
b) Hast du eine evtl. irgendwo in der Rechnung eine "Normierung", so das 
der
   Regler gar nicht die Differenz sieht.

Sorry wenn ich nun so pauschal bleibe, aber ich müsste mich selbst 
reinwühlen um dir mehr sagen zu können. Evtl. gibt es ja jemanden der 
das schon selber gemacht hat.

von G. B. (garyb)


Lesenswert?

> Ki = 0.7 oder 0

sorry das hab ich erst im Nachgang gelesen, nun ja wenn KI=0 das gleiche 
Ergebniss liefert wie KI=0.7 dann tippe ich schwer darauf das du dein
I-Anteil entweder überläuft oder gar nicht funktioniert.

dazu vielleicht einfach mal nach
http://www.rn-wissen.de/index.php/Regelungstechnik#PID-Regler
schauen

von Denny (Gast)


Lesenswert?

Ja ich habe eben gemerkt, dass mein I-Anteil völlig falsch berechnet 
wird.
Ich probiere gerade das hin zu bekommen.

von Denny (Gast)


Lesenswert?

Das ist irgendwie komisch:
1
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt
2
3
    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255
4
5
    Delta = Istwert - Sollwert
6
    P = Delta * Kp
7
8
    Esum = Esum + Delta
9
    If Esum > 255 Then Esum = 255
10
    If Esum < -255 Then Esum = -255
11
    I = Esum
12
    I = I * Ki
13
14
    Delta = Istwert - LetzterIstwert                          'Istwertsveränderung Berechnen
15
    D = Delta * Kd                                          'Dämpfung hinzurechnen
16
17
    Pulsweite = P + D
18
    Pulsweite = Pulsweite + I

Wenn ich Ki = 0 einstelle, Sollte der I-Anteil immer 0 sein.
Dann funktioniert aber die ganze Regelung nicht mehr.
Wenn ich jetzt aber anstatt "Pulsweite = Pulsweite + I" "Pulsweite = 
Pulsweite" schreibe, funktioniert alles.
Wie kann das sein!?

von G. B. (garyb)


Lesenswert?

Hallo Denny,

mit diesem Schnipsel kann ich leider auch nichts anfangen...
Vorschlag...
Implementiere den PID-Regler erst einmal in einer
eigenen Funktion und nimm den ganzen Normierungskram da raus.
Dann kannst du deinen Regler auch "offline" testen.
Die notwendigen Normierungen kannst du schlieslich vorher bzw.
nachher machen.
Wenn du dann noch Probleme mit dem Regler haben solltest, dann
poste nur diesen Code-Teil mit konkreter Testsequenz....
und nicht immer deinen ganzen Interpreter ;O) - den zwar
sterben für Bildschirmseiten keine Bäume, aber der Leser steht dafür
zwischen selbigen (Wald).

Viel Erfolg,
Gary

von G. B. (garyb)


Lesenswert?

Denny schrieb:
> Wenn ich jetzt aber anstatt "Pulsweite = Pulsweite + I" "Pulsweite =
> Pulsweite" schreibe, funktioniert alles.
> Wie kann das sein!?

mit dem was ich da lesen kann... nein

von Denny (Gast)


Lesenswert?

So jetzt habe ich mal alles rausgeschmissen.

1
'|---------------------------------Controller---------------------------------|'
2
$regfile = "m8def.dat"                                      'ATmega8
3
$crystal = 14745600                                         'Quarzfrequenz (Extern); Standart: 14745600
4
$baud = 230400                                              'Funktionierende Baudrate; Standart: 230400
5
6
$hwstack = 100
7
$swstack = 100
8
$framesize = 100                                            'Freier Speicherplatz für Variablen...
9
10
11
'|---------------------------------Variablen----------------------------------|'
12
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten
13
14
Dim Istwert As Integer                                      'Analoge Spannung des Hallsensors
15
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
16
Dim Letzteristwert As Integer                               'Istwert der letzten Messung
17
Dim Delta As Integer                                        'Die Veränderung der Spannung des Hallsensors während eines Zyklus
18
Dim Esum As Integer
19
Dim Kp As Single                                            'Die Dämpfung des Magneten
20
Dim Ki As Single
21
Dim Kd As Integer
22
Dim P As Single
23
Dim I As Single
24
Dim D As Integer
25
Dim Sollwert As Integer
26
27
28
'|--------------------------------Konfiguration-------------------------------|'
29
Declare Sub Regelung_berechnen()                            'Unterprogramm um die Variablen zu Regelung_Berechnen
30
Declare Sub Regelung_auswerten()                            'Unterprogramm um die berechneten Werte auszuwerten
31
32
Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler
33
34
Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation
35
36
37
'|--------------------------------Einstellungen-------------------------------|'
38
Set Eingeschaltet                                           'Einschalten
39
40
Kd = 255                                                    '255
41
Ki = 0
42
Kp = 1
43
Sollwert = 120                                              '120
44
45
46
'|--------------------------------Hauptprogramm-------------------------------|'
47
Do
48
    If Eingeschaltet = 1 Then
49
       Start Adc
50
          Istwert = Getadc(0)                               'Analoge Spannung des Hallsensors messen
51
       Stop Adc
52
53
       Call Regelung_berechnen                              'Werte Berechnen
54
55
       Call Regelung_auswerten                              'Werte Auswerten (begrenzen)
56
    Else
57
       Pulsweite = 0
58
    End If
59
60
    Pwm1a = Pulsweite                                       'Spulenstrom regeln
61
Loop
62
63
64
'|-----------------------------------Regelung---------------------------------|'
65
Sub Regelung_berechnen()
66
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt
67
    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255
68
69
    Delta = Istwert - Sollwert                              'Proportionalanteil
70
    P = Delta * Kp
71
72
    Esum = Esum + Delta                                     'Integralanteil
73
    If Esum > 1023 Then Esum = 1023
74
    If Esum < -1023 Then Esum = -1023
75
    I = Esum * Ki
76
    'If I < 0.01 Then I = 0
77
78
    Delta = Istwert - Letzteristwert                        'Differenzialanteil
79
    D = Delta * Kd
80
81
    Pulsweite = P + D
82
    Pulsweite = Pulsweite + I
83
End Sub
84
85
86
'|----------------------------------Auswerten---------------------------------|'
87
Sub Regelung_auswerten()
88
    If Istwert > 0 Then
89
       If Pulsweite > 255 Then Pulsweite = 255              'Begrenzungen der Pulsweite einhalten
90
       If Pulsweite < 0 Then Pulsweite = 0                  'Begrenzungen der Pulsweite einhalten
91
92
       Letzteristwert = Istwert                             'LetzterIstwert setzen
93
    Else                                                    'Wenn der Magnet falsch rum hängt wird er umgedreht
94
       Pulsweite = 255
95
    End If
96
End Sub

Wie man sehen kann ist Ki auf 0 eingestellt.
Normalerweise müsste der Magnet jetzt schweben, wenn auch an der 
falschen Position.
Es tut sich aber gar nichts.
Wenn ich nun schreibe Pulsweite = Pulsweite + 0 anstatt Pulsweite = 
Pulsweite + I (I-Faktor sollte jetzt 0 sein) funktioniert alles.

Das ist doch nicht normal!
Was mache ich falsch??

von G. B. (garyb)


Lesenswert?

Hallo Danny...
funktioniert, funktioniert nicht... ist ja schön, aber
was kommt den da an Zahlen rein und raus?
Generier dir doch einfach mal nen Sprung als Testsignal.. und vergiss 
deine Hardware erst einmal.

Auserdem berechnest du den D-Anteil falsch.. es müsste sinngemäß so 
lauten
D = ( (Delta - Delta_alt)/TA) * KD
wenn du die Abtastzeit in KD ziehst
D = (Delta - Delta_alt) * KD

Gruss,
Gary

von Gast2 (Gast)


Lesenswert?

Ich habe die Ta mal aus dem Spiel gelassen, damit ich nicht noch mit 
Kommazahlen arbeiten muss.
Sie ist ja eh konstant.
Desshalb ist mein Kd auch so groß.

Den I-Anteil habe ich mittlerweile aufgegeben...
Es geht ja auch so.

von G. B. (garyb)


Lesenswert?

Dein D-Anteil war aber auch kein D-Anteil.. was du hast sind zwei 
P-Regler
parallel geschalten.

von Gast2 (Gast)


Lesenswert?

Hm
Komischerweise funktioniert es aber.
Ich schau mir es in den nächsten Tagen mal an...

von Karl H. (kbuchegg)


Lesenswert?

Gast2 schrieb:
> Hm
> Komischerweise funktioniert es aber.

Das heißt nicht viel.

Testen kann immer nur das Vorhandensein eines Fehlers nachweisen, nie 
dessen Fehlen. Wenn etwas scheinbar so funktioniert wie vorgesehen, kann 
das auch eine glückliche Fügung sein.

von Gast2 (Gast)


Lesenswert?

Ich habe den Code nun angepasst.
1
Sub Regelung_berechnen()
2
    'Weil der Sensor die halbe Spannung in einer Richtung angibt
3
    Istwert = Istwert - 512
4
    'Der Wert geht bis 512, die Pulsweitemodulation arbeitet aber bis 255
5
    '--> Wert durch 2 teilen
6
    Shift Istwert , Right , 1
7
8
    'Proportionalanteil ausrechnen
9
    Regeldifferenz = Istwert - Sollwert
10
    P = Regeldifferenz * Kp
11
12
    'Differenzialanteil ausrechnen
13
    'Es wurde auf Ta verzichtet
14
    D = Regeldifferenz - Regeldifferenz_alt
15
    D = D * Kd
16
17
    'Alte Regeldifferenz speichern
18
    Regeldifferenz_alt = Regeldifferenz
19
20
    'Anteile zusammenrechnen
21
    Stellgroesse = P + D
22
End Sub
Das Ergebnis ist genau das gleiche.

Ich verstehe das mit dem I-Anteil nicht ganz.
Ich habe bereits viel versucht, komme aber nicht an das gewünschte 
Ergebnis.
Könnte ihr den I-Anteil bitte in diesen Codeschnipsel einbauen??

Vielen Dank!
Denny

von gary (Gast)


Lesenswert?

Wir sind doch hier in einem Do-It-Yourself-Forum und nicht bei 
Make-It-For-Me :O)

Beitrag "PID-Regler mit anti-Windup"

Gruss,
Gary

von Gast2 (Gast)


Lesenswert?

1
'|---------------------------PD-Regelung: berechnen---------------------------|'
2
Sub Regelung_berechnen()
3
    'Weil der Sensor die halbe Spannung in einer Richtung angibt
4
    Istwert = Istwert - 512
5
    'Der Wert geht bis 512, die Pulsweitemodulation arbeitet aber bis 255
6
    '--> Wert durch 2 teilen
7
    Shift Istwert , Right , 1
8
9
    'Proportionalanteil ausrechnen
10
    Regeldifferenz = Istwert - Sollwert
11
    P = Kp * Regeldifferenz
12
13
    'Regelungsdifferenzen addieren
14
    Regelungsdifferenzsumme = Regelungsdifferenzsumme + Regeldifferenz
15
    If Regelungsdifferenzsumme > 30000 Then
16
       Regelungsdifferenzsumme = 30000
17
    Elseif Regelungsdifferenzsumme < -30000 Then
18
       Regelungsdifferenzsumme = -30000
19
    End If
20
    I = Ki * Regelungsdifferenzsumme
21
    I = I / 500
22
23
    'Differenzialanteil ausrechnen
24
    'Es wurde auf Ta verzichtet
25
    D = Regeldifferenz - Regeldifferenz_alt
26
    D = Kd * D
27
28
    'Alte Regeldifferenz speichern
29
    Regeldifferenz_alt = Regeldifferenz
30
31
    'Anteile zusammenrechnen
32
    Stellgroesse = P + D
33
    Stellgroesse = Stellgroesse + I
34
End Sub
Leider schwebt der Magnet immer noch nicht an der Sollwertstelle.

von Karl H. (kbuchegg)


Lesenswert?

Warum

    I = I / 500

Du hast ein Ki. Wenn du einen Faktor brauchst, dann sollte der dort 
drinn mit enthalten sein.

Die 30000 für den Antiwindup: Hast du die empirisch ermittelt?

Generell: Wenn du eine Möglichkeit hast, der Regelung zuzusehen, dann 
solltest du die nutzen. Ideal wäre ein LCD, auf dem man sich die Werte 
für P, D und I ausgeben lassen kann. In deinem Fall ist natürlich der I 
Wert interessant. Wenn die Regelung funktioniert, müsste I im Laufe der 
Zeit immer kleiner werden, bis 0 erreicht wird (das zeigt an, dass die 
Sollposition erreicht ist)

Auch sollte man im Auge haben, ob es physikalisch überhaupt möglich ist, 
die Sollposition zu erreichen. Wenn dein Hubmagnet nicht in der Lage ist 
den schwebenden Magneten in seiner aktuellen Position noch höher zu 
heben, dann versagt die beste Regelung. Sprich: Mehr als Vollgas 
(Vollstrom) kann der Hubmagnet nicht geben. Reicht das nicht aus, den 
schebenden Magneten gegen die Schwerkraft noch weiter zu heben, dann 
kann sich deine Regelung brausen gehen. In dem Fall müsste man im I Wert 
erkennen, dass er sich nie aus seiner Anti-Windup Position herausbewegt, 
sprich ständig 30000 liefert.

von Gast2 (Gast)


Lesenswert?

Kd: 255
Kp: 1
Ki: 5

Jetzt schwebt der Magnet bei einem Sollwert von 80 so um den Wert 125.

I bleibt die ganze Zeit konstant auf 37.
Fällt euch da irgendwas auf??

von Karl H. (kbuchegg)


Lesenswert?

Gast2 schrieb:
> Kd: 255
> Kp: 1
> Ki: 5
>
> Jetzt schwebt der Magnet bei einem Sollwert von 80 so um den Wert 125.
>
> I bleibt die ganze Zeit konstant auf 37.
> Fällt euch da irgendwas auf??

Was macht Stellgroesse ?
Was machen P und D

Wenn I die ganze Zeit auf 37 bleibt, dann sollte doch Stellgroesse 
eigentlich immer größer und größer werden, wenn sich P und D nicht 
verändern (D sollte sowie so 0 sein, weil es ja keine Differenz gibt)

von Gast2 (Gast)


Lesenswert?

P = ungefähr 50
D = 0 (manchmal -255 oder 255)
I = 37

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger schrieb:

> Wenn I die ganze Zeit auf 37 bleibt, dann sollte doch Stellgroesse
> eigentlich immer größer und größer werden,

Denkfehler von mir.

Aber wenn I bei 37 bleibt bedeutet das ja letztendlich, dass 
Regeldifferenz zu 0 geworden ist.

Wekche Datentypen hast du eigentlich? Kann sich eine Regeldifferenz von 
125-80 überhaupt dahingehend auswirken, dass Regeldifferenzsumme noch 
größer wird?

von Gast2 (Gast)


Lesenswert?

Die Regeldifferenz ist immer so ungefähr 50...

von Karl H. (kbuchegg)


Lesenswert?

Gast2 schrieb:
> Die Regeldifferenz ist immer so ungefähr 50...


Das müsste sich dann aber hier
1
    Regelungsdifferenzsumme = Regelungsdifferenzsumme + Regeldifferenz
2
    If Regelungsdifferenzsumme > 30000 Then
3
       Regelungsdifferenzsumme = 30000
4
    Elseif Regelungsdifferenzsumme < -30000 Then
5
       Regelungsdifferenzsumme = -30000
6
    End If
7
    I = Ki * Regelungsdifferenzsumme
8
    I = I / 500
so auswirken, dass Regelungsdifferenzsumme immer größer wird und als 
folge davon I ebenfalls größer wird.

Jetzt gilt es herauszufinden, warum dem nicht so ist :-)

Die Datentypen von Regelungsdifferenzsumme und I sind zunächst 
interessant, um die Eigenschaften der Variablen zu kennen.

von Gast2 (Gast)


Lesenswert?

Ich habe Ki (unnötig denk ich gerade) und I jetzt als Long definiert.
Es scheint jetzt zu funktionierten.
Ki = 5
Sollwert = 80
Istwert = 90 bis 100 ungefähr.

Bei Sollwert = 150 ist der Istwert 150! yeah :-)

Also funktioniert es jetzt nur wenn der Magnet etwas mehr unten Schwebt.
Wenn er höher Schwebt, fängt er an zu zittern und erreicht den Sollwert 
nicht ganz.

von Karl H. (kbuchegg)


Lesenswert?

Gast2 schrieb:
> Ich habe Ki (unnötig denk ich gerade) und I jetzt als Long definiert.
> Es scheint jetzt zu funktionierten.
> Ki = 5
> Sollwert = 80
> Istwert = 90 bis 100 ungefähr.
>
> Bei Sollwert = 150 ist der Istwert 150! yeah :-)
>
> Also funktioniert es jetzt nur wenn der Magnet etwas mehr unten Schwebt.
> Wenn er höher Schwebt, fängt er an zu zittern und erreicht den Sollwert
> nicht ganz.

Schau dir wieder die Regelabweichungswerte an. Jetzt könnte es sein, 
dass du schon in die Begrenzung kommst. Eventuell hilft hier spielen mit 
den Werten für Kp und Ki

Auch durch die Division durch 500 verlierst du was.

Wenn da alles Ganzzahlen sind, dann läufst du auch in folgendes Problem:
 1/3 + 1/3 + 1/3 -> 0 !!!

Hier könnte es helfen, alle Werte mal 10 (*) zu nehmen, damit 1 
Kommastelle bis zur Addition erhalten bleibt und die erst nach der 
Summation der Einzelglieder abzuschneiden.

(*) oder mal 2 oder 4 oder 8. Auf jeden Fall eine 2-er Potenz. Dann 
dividiert es sich schneller.

von Gast2 (Gast)


Lesenswert?

Ich verstehe nicht ganz was das mit Kommastellen zu tun hat...

von Karl H. (kbuchegg)


Lesenswert?

Gast2 schrieb:
> Ich verstehe nicht ganz was das mit Kommastellen zu tun hat...


    I = Ki * Regelungsdifferenzsumme
    I = I / 500

Ki war 5
Du dividierst durch 500

Nehmen wir einfasch mal an, Regelungsdifferenzsumme wäre 99

   I = 5 * 99     = 495
   I = I / 500    = 495 / 500 = 0


rein mathematisch ist aber 99 * 5 / 500 = 0.99 also nahezu 1

-> Obwohl eine Regeldifferenz von 99 Einheiten besteht, wird der I Wert 
mit 0 errechnet und damit diese Regeldifferenz nicht mehr ausgeglichen.

von Gast2 (Gast)


Lesenswert?

Verstehe.
Ich werde es anpassen.

Ich habe in der Zwischenzeit einige Messungen gemacht und eine 
Excelkennlinie angefertigt.
Sinnlos oder sinnvoll darüber kann man streiten - jedenfalls geht das 
sehr einfach mit VisualBasic und RS232.

http://www4.pic-upload.de/10.03.10/vqt57ab45pk7.png

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.