Hi Leute, also ich bin grad dabei, einen PI Regler zu programmieren. Möchte nämlich die Geschwindigkeit regeln, die aktuelle Drehzahl lässt sich nicht ohne eure Hilfe schon sehr gut bestimmen. Also wie der Regler funktioniert, weiß ich, hab aber bezüglich Realisierung noch ein paar Fragen und zwar: 1) Begrenzung der Stellgröße: Die Stellgröße ist ja der Reglerausgang und Regelstrecke-Eingang. Stimmt es, dass die die maximale Geschwindigkeit meines Motors darstellt? Also wenn ich max. Drehzahl von 3000 hab, muss die Stellgröße einfach auf int-Wert 3000 begrenzen? 2) Was ist mit dem Windup? Das ist doch dafür da, damit mir mein I-Anteil nicth abhaut, oder? Wie begrenze ich denn den I-Anteil? 3) Offset beim P-Anteil, brauch ich den? txs
Kartoffel wrote: > Hi Leute, > also ich bin grad dabei, einen PI Regler zu programmieren. > Möchte nämlich die Geschwindigkeit regeln, die aktuelle Drehzahl lässt > sich nicht ohne eure Hilfe schon sehr gut bestimmen. > Also wie der Regler funktioniert, weiß ich, hab aber bezüglich > Realisierung noch ein paar Fragen und zwar: > 1) Begrenzung der Stellgröße: > Die Stellgröße ist ja der Reglerausgang und Regelstrecke-Eingang. jep. > Stimmt es, dass die die maximale Geschwindigkeit meines Motors > darstellt? Kommt drauf an was Deine Steuergröße und Deine Regelgröße ist ! Ich denke mal die Drehzahl soll geregelt werden, dann ist die Eingangsgröße bespielsweise das PWM Tastverhältnis. > Also wenn ich max. Drehzahl von 3000 hab, muss die Stellgröße einfach > auf > int-Wert 3000 begrenzen? s.o. > 2) Was ist mit dem Windup? Das ist doch dafür da, damit mir mein > I-Anteil nicth abhaut, oder? Wie begrenze ich denn den I-Anteil? jep. Schalte die "Integration" einfach in Bereichen ab, die weit von der Sollgröße weg sind (denn da ist der P - Anteil schon groß genug, Beispiel: Aktuelle Drehzahl 1000 U/min .... neuer Sollwert: 2500 U/min ... Die Integration darf aber erst "loslegen", wenn der Absolutbetrag von (Soll - Ist) eine bestimmten Wert unterschreitet. Z.B. 500) > 3) Offset beim P-Anteil, brauch ich den? Mir ist nicht ganz klar, was Du mit Offset meinst, aber normalerweise macht der integrelle Anteil ja den stationären Regelfehler weg ... > txs Grüße, Michael
Also meine Regelstrecke ist ein Motor mit einem Encoder. Der Motor wird mittels PWM angetrieben, PWM erzeuge ich selbst, ich poste einfach meinen Code:
1 | //****************************************************************************
|
2 | // @Function void CC2_vInit(void)
|
3 | //
|
4 | //----------------------------------------------------------------------------
|
5 | // @Description This is the initialization function of the CAPCOM2 function
|
6 | // library. It is assumed that the SFRs used by this library
|
7 | // are in its reset state.
|
8 | //
|
9 | //----------------------------------------------------------------------------
|
10 | // @Returnvalue None
|
11 | //
|
12 | //----------------------------------------------------------------------------
|
13 | // @Parameters None
|
14 | //
|
15 | //----------------------------------------------------------------------------
|
16 | // @Date 21.11.2007
|
17 | //
|
18 | //****************************************************************************
|
19 | |
20 | // USER CODE BEGIN (Init,1)
|
21 | |
22 | // USER CODE END
|
23 | |
24 | void CC2_vInit(void) |
25 | {
|
26 | // USER CODE BEGIN (Init,2)
|
27 | |
28 | // USER CODE END
|
29 | |
30 | /// -----------------------------------------------------------------------
|
31 | /// Configuration of CAPCOM2 Control:
|
32 | /// -----------------------------------------------------------------------
|
33 | /// - the contents of the port register is changed by the CAPCOM2 unit
|
34 | /// - staggered mode is disabled
|
35 | |
36 | CC2_IOC = 0x0004; // load CAPCOM2 I/O control register |
37 | |
38 | /// -----------------------------------------------------------------------
|
39 | /// Configuration of CAPCOM2 Timer 7:
|
40 | /// -----------------------------------------------------------------------
|
41 | /// - timer 7 works in timer mode
|
42 | /// - prescaler factor is 1
|
43 | /// - timer 7 run bit is set
|
44 | |
45 | /// -----------------------------------------------------------------------
|
46 | /// Configuration of CAPCOM2 Timer 8:
|
47 | /// -----------------------------------------------------------------------
|
48 | /// - timer 8 works in timer mode
|
49 | /// - prescaler factor is 1
|
50 | /// - timer 8 run bit is reset
|
51 | |
52 | |
53 | CC2_T78CON = 0x0000; // load CAPCOM2 timer 7 and timer 8 |
54 | // control register
|
55 | |
56 | CC2_T7 = 0xFCE0; // load CAPCOM2 timer 7 register |
57 | |
58 | CC2_T7REL = 0xFCE0; // load CAPCOM2 timer 7 reload register |
59 | |
60 | CC2_T8 = 0x0000; // load CAPCOM2 timer 8 register |
61 | |
62 | CC2_T8REL = 0x0000; // load CAPCOM2 timer 8 reload register |
63 | |
64 | /// -----------------------------------------------------------------------
|
65 | /// Configuration of the used CAPCOM2 Timer Port Pins:
|
66 | /// -----------------------------------------------------------------------
|
67 | |
68 | |
69 | /// -----------------------------------------------------------------------
|
70 | /// Configuration of the used CAPCOM2 Timer Interrupts:
|
71 | /// -----------------------------------------------------------------------
|
72 | /// Tmr7 service request node configuration:
|
73 | /// - Tmr7 interrupt priority level (ILVL) = 10
|
74 | /// - Tmr7 interrupt group level (GLVL) = 1
|
75 | /// - Tmr7 group priority extension (GPX) = 0
|
76 | |
77 | CC2_T7IC = 0x0069; |
78 | |
79 | |
80 | |
81 | /// -----------------------------------------------------------------------
|
82 | /// Configuration of the used CAPCOM2 Channel 16:
|
83 | /// -----------------------------------------------------------------------
|
84 | /// - channel 16 is disabled
|
85 | |
86 | CC2_CC16 = 0x0000; // load CAPCOM2 channel 16 register |
87 | |
88 | /// -----------------------------------------------------------------------
|
89 | /// Configuration of the used CAPCOM2 Channel 17:
|
90 | /// -----------------------------------------------------------------------
|
91 | /// - channel 17 is disabled
|
92 | |
93 | CC2_CC17 = 0x0000; // load CAPCOM2 channel 17 register |
94 | |
95 | /// -----------------------------------------------------------------------
|
96 | /// Configuration of the used CAPCOM2 Channel 18:
|
97 | /// -----------------------------------------------------------------------
|
98 | /// - channel 18 is disabled
|
99 | |
100 | CC2_CC18 = 0x0000; // load CAPCOM2 channel 18 register |
101 | |
102 | /// -----------------------------------------------------------------------
|
103 | /// Configuration of the used CAPCOM2 Channel 19:
|
104 | /// -----------------------------------------------------------------------
|
105 | /// - channel 19 is disabled
|
106 | |
107 | CC2_CC19 = 0x0000; // load CAPCOM2 channel 19 register |
108 | |
109 | /// -----------------------------------------------------------------------
|
110 | /// Configuration of the used CAPCOM2 Channel 20:
|
111 | /// -----------------------------------------------------------------------
|
112 | /// - channel 20 is disabled
|
113 | |
114 | CC2_CC20 = 0x0000; // load CAPCOM2 channel 20 register |
115 | |
116 | /// -----------------------------------------------------------------------
|
117 | /// Configuration of the used CAPCOM2 Channel 21:
|
118 | /// -----------------------------------------------------------------------
|
119 | /// - channel 21 is disabled
|
120 | |
121 | CC2_CC21 = 0x0000; // load CAPCOM2 channel 21 register |
122 | |
123 | /// -----------------------------------------------------------------------
|
124 | /// Configuration of the used CAPCOM2 Channel 22:
|
125 | /// -----------------------------------------------------------------------
|
126 | /// - channel 22 is disabled
|
127 | |
128 | CC2_CC22 = 0x0000; // load CAPCOM2 channel 22 register |
129 | |
130 | /// -----------------------------------------------------------------------
|
131 | /// Configuration of the used CAPCOM2 Channel 23:
|
132 | /// -----------------------------------------------------------------------
|
133 | /// - channel 23 is disabled
|
134 | |
135 | CC2_CC23 = 0x0000; // load CAPCOM2 channel 23 register |
136 | |
137 | /// -----------------------------------------------------------------------
|
138 | /// Configuration of the used CAPCOM2 Channel 24:
|
139 | /// -----------------------------------------------------------------------
|
140 | /// - channel 24 is disabled
|
141 | |
142 | CC2_CC24 = 0x0000; // load CAPCOM2 channel 24 register |
143 | |
144 | /// -----------------------------------------------------------------------
|
145 | /// Configuration of the used CAPCOM2 Channel 25:
|
146 | /// -----------------------------------------------------------------------
|
147 | /// - channel 25 is disabled
|
148 | |
149 | CC2_CC25 = 0x0000; // load CAPCOM2 channel 25 register |
150 | |
151 | /// -----------------------------------------------------------------------
|
152 | /// Configuration of the used CAPCOM2 Channel 26:
|
153 | /// -----------------------------------------------------------------------
|
154 | /// - channel 26 is disabled
|
155 | |
156 | CC2_CC26 = 0x0000; // load CAPCOM2 channel 26 register |
157 | |
158 | /// -----------------------------------------------------------------------
|
159 | /// Configuration of the used CAPCOM2 Channel 27:
|
160 | /// -----------------------------------------------------------------------
|
161 | /// - channel 27 is disabled
|
162 | |
163 | CC2_CC27 = 0x0000; // load CAPCOM2 channel 27 register |
164 | |
165 | /// -----------------------------------------------------------------------
|
166 | /// Configuration of the used CAPCOM2 Channel 28:
|
167 | /// -----------------------------------------------------------------------
|
168 | /// - compare mode 2: interrupt only
|
169 | /// - CC28 allocated to CAPCOM2 timer 7
|
170 | /// - single event mode is disabled
|
171 | |
172 | |
173 | CC2_CC28 = 0xFF00; // load CAPCOM2 channel 28 register |
174 | |
175 | /// -----------------------------------------------------------------------
|
176 | /// Configuration of the used CAPCOM2 Channel 29:
|
177 | /// -----------------------------------------------------------------------
|
178 | /// - channel 29 is disabled
|
179 | |
180 | CC2_CC29 = 0x0000; // load CAPCOM2 channel 29 register |
181 | |
182 | /// -----------------------------------------------------------------------
|
183 | /// Configuration of the used CAPCOM2 Channel 30:
|
184 | /// -----------------------------------------------------------------------
|
185 | /// - compare mode 2: interrupt only
|
186 | /// - CC30 allocated to CAPCOM2 timer 7
|
187 | /// - single event mode is disabled
|
188 | |
189 | |
190 | CC2_CC30 = 0xFE00; // load CAPCOM2 channel 30 register |
191 | |
192 | /// -----------------------------------------------------------------------
|
193 | /// Configuration of the used CAPCOM2 Channel 31:
|
194 | /// -----------------------------------------------------------------------
|
195 | /// - channel 31 is disabled
|
196 | |
197 | CC2_CC31 = 0x0000; // load CAPCOM2 channel 31 register |
198 | |
199 | CC2_M4 = 0x0000; // load CAPCOM2 mode register 4 |
200 | CC2_M5 = 0x0000; // load CAPCOM2 mode register 5 |
201 | CC2_M6 = 0x0000; // load CAPCOM2 mode register 6 |
202 | CC2_M7 = 0x0606; // load CAPCOM2 mode register 7 |
203 | |
204 | CC2_DRM = 0x0000; // load CAPCOM2 double-register mode register |
205 | |
206 | CC2_SEM = 0x0000; // load CAPCOM2 single event mode register |
207 | |
208 | CC2_SEE = 0x0000; // load CAPCOM2 single event enable register |
209 | |
210 | CC2_OUT = 0x0000; // load CAPCOM2 compare output register |
211 | |
212 | /// -----------------------------------------------------------------------
|
213 | /// Configuration of the used CAPCOM2 Channel Port Pins:
|
214 | /// -----------------------------------------------------------------------
|
215 | |
216 | |
217 | /// -----------------------------------------------------------------------
|
218 | /// Configuration of the used CAPCOM2 Channels Interrupts:
|
219 | /// -----------------------------------------------------------------------
|
220 | /// CC28 service request node configuration:
|
221 | /// - CC28 interrupt priority level (ILVL) = 10
|
222 | /// - CC28 interrupt group level (GLVL) = 2
|
223 | /// - CC28 group priority extension (GPX) = 0
|
224 | |
225 | CC2_CC28IC = 0x006A; |
226 | |
227 | |
228 | /// CC30 service request node configuration:
|
229 | /// - CC30 interrupt priority level (ILVL) = 10
|
230 | /// - CC30 interrupt group level (GLVL) = 3
|
231 | /// - CC30 group priority extension (GPX) = 0
|
232 | |
233 | CC2_CC30IC = 0x006B; |
234 | |
235 | |
236 | |
237 | CC2_T78CON_T7R = 1; // set CAPCOM2 timer 7 run bit |
238 | |
239 | // USER CODE BEGIN (Init,3)
|
240 | |
241 | // USER CODE END
|
242 | |
243 | } // End of function CC2_vInit |
244 | |
245 | |
246 | //****************************************************************************
|
247 | // @Function void CC2_viTmr7(void)
|
248 | //
|
249 | //----------------------------------------------------------------------------
|
250 | // @Description This is the interrupt service routine for the CAPCOM2 timer
|
251 | // 7. It is called when overflow of the timer 7 register
|
252 | // occurs.
|
253 | // Please note that you have to add application specific code
|
254 | // to this function.
|
255 | //
|
256 | //----------------------------------------------------------------------------
|
257 | // @Returnvalue None
|
258 | //
|
259 | //----------------------------------------------------------------------------
|
260 | // @Parameters None
|
261 | //
|
262 | //----------------------------------------------------------------------------
|
263 | // @Date 21.11.2007
|
264 | //
|
265 | //****************************************************************************
|
266 | |
267 | // USER CODE BEGIN (Tmr7,1)
|
268 | |
269 | // USER CODE END
|
270 | |
271 | void CC2_viTmr7(void) interrupt CC2_T7INT using RB_LEVEL10 |
272 | {
|
273 | // USER CODE BEGIN (Tmr7,2)
|
274 | P7_P4=0; |
275 | P7_P5=1; |
276 | P7_P6=0; |
277 | P7_P7=1; |
278 | // USER CODE END
|
279 | |
280 | } // End of function CC2_viTmr7 |
281 | |
282 | |
283 | //****************************************************************************
|
284 | // @Function void CC2_viCC28(void)
|
285 | //
|
286 | //----------------------------------------------------------------------------
|
287 | // @Description This is the interrupt service routine for the CAPCOM2
|
288 | // register CC28. If the content of the corresponding compare
|
289 | // timer (configurable) equals the content of the
|
290 | // capture/compare register CC28 or if a capture event occurs
|
291 | // at the associated port pin, the interrupt request flag is
|
292 | // set and an interrupt is triggered (only if enabled).
|
293 | // Please note that you have to add application specific code
|
294 | // to this function.
|
295 | //
|
296 | //----------------------------------------------------------------------------
|
297 | // @Returnvalue None
|
298 | //
|
299 | //----------------------------------------------------------------------------
|
300 | // @Parameters None
|
301 | //
|
302 | //----------------------------------------------------------------------------
|
303 | // @Date 21.11.2007
|
304 | //
|
305 | //****************************************************************************
|
306 | |
307 | // USER CODE BEGIN (CC28,1)
|
308 | |
309 | // USER CODE END
|
310 | |
311 | void CC2_viCC28(void) interrupt CC2_CC28INT using RB_LEVEL10 |
312 | {
|
313 | // USER CODE BEGIN (CC28,2)
|
314 | P7_P4=1; |
315 | P7_P5=0; |
316 | |
317 | // USER CODE END
|
318 | |
319 | } // End of function CC2_viCC28 |
320 | |
321 | |
322 | //****************************************************************************
|
323 | // @Function void CC2_viCC30(void)
|
324 | //
|
325 | //----------------------------------------------------------------------------
|
326 | // @Description This is the interrupt service routine for the CAPCOM2
|
327 | // register CC30. If the content of the corresponding compare
|
328 | // timer (configurable) equals the content of the
|
329 | // capture/compare register CC30 or if a capture event occurs
|
330 | // at the associated port pin, the interrupt request flag is
|
331 | // set and an interrupt is triggered (only if enabled).
|
332 | // Please note that you have to add application specific code
|
333 | // to this function.
|
334 | //
|
335 | //----------------------------------------------------------------------------
|
336 | // @Returnvalue None
|
337 | //
|
338 | //----------------------------------------------------------------------------
|
339 | // @Parameters None
|
340 | //
|
341 | //----------------------------------------------------------------------------
|
342 | // @Date 21.11.2007
|
343 | //
|
344 | //****************************************************************************
|
345 | |
346 | // USER CODE BEGIN (CC30,1)
|
347 | |
348 | // USER CODE END
|
349 | |
350 | void CC2_viCC30(void) interrupt CC2_CC30INT using RB_LEVEL10 |
351 | {
|
352 | // USER CODE BEGIN (CC30,2)
|
353 | P7_P6=1; |
354 | P7_P7=0; |
355 | |
356 | // USER CODE END
|
357 | |
358 | } // End of function CC2_viCC30 |
359 | |
360 | |
361 | |
362 | |
363 | // USER CODE BEGIN (CC2_General,10)
|
364 | |
365 | // USER CODE END
|
Ich versteh irgendwie nicht, was meine Stellgröße in diesem Fall ist und wohin ich mit der soll.....
Die Stellgroesse ist die Zahl, die ausm Regler kommt und ins Stellglied reingeht. Beim PWM-Stellglied ist das demnach die Pulsbreite. Die maximale Stelgroesse ist daher die Zahl, bei der der anschlag erreicht wird. Das ist bei einem 8Bit PWM 255, bei einem 10bit PWM 1023 usw. Ich hab den code nicht angeschaut.
@sechsminuszwei: also meine Pulsantwort wird so bestimmt: am Anfang ist das PWM-Signal =1, ein Timer läuft mit. Wenn der Inhalt des Timers mit dem Inhalt des Compare-Registers übereinstimmt, setz ich PMW auf "0", wenn der Timer abgelaufen ist, wieder auf "1" usw. Also um die Pulsbreite zu beeinflussen, könnte ich so vorgehen: Pulsbreite= Registerinhalt des Compare_Registers -Startwert vom Timer Pulsbreite= Stellgröße Registerinhalt des Compare_Registers= Stellgröße+Startwert vom Timer oder?
Ach ja, noch ne andere Frage: da meine Pulsbreite aus der Differenz zweier 16-Bit REgister berechnet wird,heißt es für mich, dass ich die Stellgröße auf 65536 begrenzen soll?
> Pulsbreite= Stellgröße
Richtig. Da die 16bit hat --> 0 - 65535
Du musst aber noch die Größen umrechnen !!
Du hast die Drehzahl als Regelgröße und die Pulsbreite als Stellgröße.
Da die beiden Wertemässig nicht zusammen passen musst Du vorher ein
sogenanntes Command - Shaping machen:
Mach einfach mal ein paar Testläufe, mit stationären Zuständen, damit Du
die Größenordungen ein wenig abschätzen kannst !
z.B.
PWM Tastverhältnis --> Drehzahl
10% (6553) --> 400 U/min
20% (13107) --> 600 U/min
30% (19660) --> 900 U/min
...
Du hast oben geschrieben, daß Deine max. Drehzahl rund 3000 U/min ist.
Somit sind 0 U/min 0% und 3000U/min 100%. Jetzt musst Du nur noch die
Prozente anpassen (Command Shaping) und die Reglerparameter tunen.
Regeldifferenz DeltaU = (Soll - Ist)
Stellgröße (PWM Tastverhältnis) = Kp * DeltaU + Ki * Integral (DeltaU)
Das Integral kannst Du entweder als Euler vorwärts, oder auch mit Trapez
rechnen.
Den Anti - Windup kannst du im ersten Versuch wie folgt machen:
if (DeltaU < Limit)
Stellgröße (PWM Tastverhältnis) = Kp * DeltaU;
else
Stellgröße (PWM Tastverhältnis) = Kp * DeltaU + Ki * Integral (DeltaU)
Grüße,
Michael
@(mmike) Also das PWM-Tastverhältnis ist ja das Verhältnis zwischen pos. und neg. Periode. Heißt bei 50% dreht sich der Motor überhaupt nicht, weil der Mittelwert =0 ist. Wieso hab ich dann bei 3000U-> 100%? Versteh ich net. Wieso ich die Umdrehungen in Prozente umwandeln soll, hab ich auch nicht verstanden :-(
Kartoffel wrote: > @(mmike) > Also das PWM-Tastverhältnis ist ja das Verhältnis zwischen pos. und neg. > Periode. Wie positiv und negativ ? PWM sieht bei mir so aus ----- ----- ----- _| |_____| |_____| |___ HIGH LOW HIGH LOW HIGH + LOW = Periode bei 50 % => HIGH = LOW = Periode / 2 > Heißt bei 50% dreht sich der Motor überhaupt nicht, weil der > Mittelwert =0 ist. ?? > Wieso hab ich dann bei 3000U-> 100%? Versteh ich net. 100% ensprechen Deiner Maximaldrehzahl. 0% ist wenn sich nix dreht! Oder läuft das Ding auch rückwärts ? > Wieso ich die Umdrehungen in Prozente umwandeln soll, hab ich auch nicht > verstanden :-( Um die Sachen aneinander anzupassen (Command Shaping). Denn Dein PWM geht ja von 0 - 65535 und die Drehzahl sicher nicht von 0 - 65535 sondern z.B. von 0 - 3000 Grüße, Michael
Wie ich bisher gelesen habe willst du den Motor nur Drehzahlregeln? Welche Last soll er denn treiben können? Das Problem ist, das die Drehzahl auch mit der Belastung abfällt und du daher eine U UND I Regelung machen müsstest, ums ganz genau zu haben... Aber Last und Zweck wären ganz interessant!
Kartoffel wrote: > Hi Leute, > also ich bin grad dabei, einen PI Regler zu programmieren. Wieso neu erfinden? -> Codesammlung > 1) Begrenzung der Stellgröße: > Die Stellgröße ist ja der Reglerausgang und Regelstrecke-Eingang. > Stimmt es, dass die die maximale Geschwindigkeit meines Motors > darstellt? jap, bzw. könntest du den Motor auch bis zu einen gewissen Grad "schneller" drehen lassen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.