Hallo Dosenfans,
die Regelungsfragen sind recht ordentlich geklärt worden. Die ersten Sprungantworten hatte ich ereignisgesteuert aufgenommen – es wurden hundert Interrupts an einem Motor erfasst, das waren anfangs 25 und sind jetzt 50 Umdrehungen. In den letzten Tagen (sprich nach etlichen unbefriedigenden Auslegungsversuchen) habe ich stattdessen isochrone Messungen durchgeführt: alle 1,0 ms (sprich: 20*50 µs) wurde der jeweils aktuelle Messwert für eine halbe Umdrehung der Motorwelle gespeichert. Diese Messungen scheinen mir aussagekräftiger zu sein. Im ersten Fall bekomme ich den ersten Messwert (vermutlich) dann, wenn der erste Interrupt erfasst wird. Im zweiten Fall werden Messwerte im Stillstand erfasst, danach wird die vollständige Anlaufphase des Motors dargestellt.
................Bild hier
In diesem Diagramm wurde die Kurvensteigung mit der Wendetangente (schwarze Linie) bestimmt und daraus die Verzugszeit Tu und die Ausgleichszeit Tg. Die blaue Linie stellt eine weniger glaubhafte Wendetangente dar aufgrund einer sehr toleranten Auswertung. Danach wurde genau nach „Kochbuch“ im RNWiki: Dimensionierung nach Einstellregeln gearbeitet. Aus dem früher vorgestellten Speedtest (hier, weiter oben) wurde Kp mit 0,2 = 1/5 bestimmt. Aus den Zeiten Tu und Tg bzw. Tn und Tv wurde mit den Formeln im Wiki „Einstellregeln nach Ziegler/Nichols“ die Parameter für den PID-Regler bestimmt: Ki = 1/30 und Kd = 1/3.
Beim Aufbau meines Codes bin ich nach dem Motto vorgegangen: klau schau wem – und habe als Vorlage wieder das RNWiki genommen sowie ein Codebeispiel von waste für einen PD-Regler für Linienfolger. Mein Code sieht danach so aus:
Code:
// =================================================================================
// === Regelungsroutine für Motor 12 =============================================
// Die gemessene Zeitdifferenz Iz_diff0 zwischen zwei Encoderinterrupts wird zur
// Regelung verwendet. Es gibt pro halbe Umdrehung einen Interrupt/Zeitwert.
void rgl_mo_12(void) // Regelung für Motor 12 mit 2 Interr pro Umdr.
{
if (sspeed12 <= 10) // Soll überhaupt gefahren werden?
{
OCR0B = 0; // Unter 10 mm/s soll nicht gefahren werden
return;
}
tupsi12 = Iz_diff0; // Übernahme Interruptabstand in Regelung
ndrz12 = sspeed12; // Nenn = Solldrehzahl = Soll-speed
sei(); // Erlaube Interrupts ##### nested Interrupts
ix12 = 8300 / tupsi12; // => Ist-Geschwindigkeit in mm/s
ie_mot12 = ndrz12 - ix12; // Vergleich => Regelabweichung
if (tupsi12 > 500) {tupsi12 = 500;} // Begrenze auf 500
isum12 += ie_mot12;
if (isum12 < -1000) { isum12 = -1000;}
if (isum12 > 1000) { isum12 = 1000;}
iyp12 = ie_mot12 / Kp12; // P-Anteil berechnen, Kptheor = 0,25 !!
iyi12 = isum12 / Ki12; // I-Anteil berechnen
iyd12 = (ie_mot12 - ie_alt12) / Kd12; // D-Anteil berechnen
iy12 = iyp12 + iyi12 + iyd12; // Gesamtkorrektur PID berechnet
if ( iy12 < 0 ) { iy12 = 0;} // Stellwert (PWM) begrenzen
if ( iy12 > 255 ) { iy12 = 255;}
OCR0B = iy12; // Ansteuerung der PWM direkt
return;
}
// =================================================================================
und das MiniD0 läuft damit sehr schön (Danke Sternthaler, danke waste). Ach so: die Begrenzung der tupsi auf +- 500 und die von iesum auf +- 1000 ist aufgrund von Tests erfolgt. Hohe Werte von iesum führten zu deutlichen Störungen bei positiven und sehr auffallend bei negativen Beschleunigungen. Mit den genannten Eingrenzungen sieht der Lauf glatt und gut aus.
Leider fehlt immer noch einiges: Abweichungen an einem Motor führen zu bleibenden Winkelfehlern der zurückgelegten Spur und zu große PWM-Werte für einen Motor werden nicht gleich zum Abbremsen bzw. verringerter Sollwertvorgabe des anderen Motors benutzt. Beide Dinge sind für eine saubere Odometrie notwendig. Da muss ich wieder ne Weile auf Tauchstation.
Ein bisschen Legende:
vgmm ... Vorgabegeschwindigkeit in mm/s, vgmm12 ... für Motor12
sspeed ... Sollspeed, die eigentliche Führungsgröße/Sollwert W der Reglerschleife
Iz_diff0 ... Zeitdifferenz zwischen zwei Interrupts durch den Encoder am Motor 12 (ist gleich "Motor 0")
ix12 ... Der "eigentliche" Istwert X der Reglerschleife = Wert von Motor12.
Lesezeichen