PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Geschwindigkeitsregelung mit PI-Regler



asuro_oli
28.02.2007, 20:45
Hallo Zusammen!

Ich bin zur Zeit dabei, eine Geschwindigkeitsregelung für meinen ASURO zu programmieren. Ich habe mir überlegt einen PI-Regler dafür zu verwenden. Den Istwert der Geschwindigkeit berechne ich aus dem Zeitabstand von 2 schwarz-weiß Wechseln am Odometriesensor (ich benutze die Sensorscheiben mit jeweils 4 schwarzen und 4 weißen Feldern). Mein derzeitiges Programm für die Regelung funktioniert noch nicht wirklich gut. Hier ist einmal der derzeitige Stand:



/************************************************** *******************
**
** Geschwindigkeitsregelung mit PI-Regler
**
************************************************** *******************/

#include "asuro.h"
#include <stdlib.h>

volatile unsigned char count36kHz;
volatile unsigned long timebase;
unsigned long takte;
float w, x, e, y, kp, ki, ta, esum[2];
unsigned char speedLeft, speedRight;
unsigned long zeit[2];

void ReglerLinks(void)
{
takte = (timebase*256) + count36kHz - zeit[0]; //Anzahl der Takte zwischen 2 sw-Wechsel
zeit[0] = (timebase*256) + count36kHz;

x = 104615.0/(float)takte; //Berechnung der aktuellen Geschwindigkeit in mm/s, Wert 104615 durch Rechnungen ermittelt
e = w - x;
esum[0] = esum[0] + e;
y = kp*e + ki*ta*esum[0]; //Berechnung der Stellgröße

if(y<0) y = 0;
if(y>255) y = 255;

speedLeft = (int)y;
MotorSpeed(speedLeft,speedRight);
}

void ReglerRechts(void)
{
takte = (timebase*256) + count36kHz - zeit[1]; //Anzahl der Takte zwischen 2 sw-Wechsel
zeit[1] = (timebase*256) + count36kHz;

x = 104615/(float)takte; //Berechnung der aktuellen Geschwindigkeit, Wert 104615 durch Rechnungen ermittelt
e = w - x;
esum[1] = esum[1] + e;
y = kp*e + ki*ta*esum[1]; //Berechnung der Stellgröße

if(y<0) y = 0;
if(y>255) y = 255;

speedRight = (int)y;
MotorSpeed(speedLeft,speedRight);
}


int main (void)
{
unsigned int daten[2];
unsigned char flagl, flagr;

Init();

MotorDir(FWD,FWD);
MotorSpeed(200,200);

kp = 5.0; //Verstärkungswert für Proportionalkomponente
ki = 100.0; //Verstärkungswert für Integralkomponente
ta = 0.001; //Abtastzeit

w = 350.0; //Sollwert der Geschwindigkeit in mm/s

OdometrieData(daten);
OdometrieData(daten);

if(daten[0]>600) flagl = TRUE;
else flagl = FALSE;

if(daten[1]>600) flagr = TRUE;
else flagr = FALSE;

zeit[0] = (timebase*256) + count36kHz;
zeit[1] = (timebase*256) + count36kHz;

while(1)
{
OdometrieData(daten);

if(daten[0]<600 && flagl==TRUE)
{
flagl = FALSE;
ReglerLinks();
}

if(daten[0]>600 && flagl==FALSE)
{
flagl = TRUE;
ReglerLinks();
}

if(daten[1]<600 && flagr==TRUE)
{
flagr = FALSE;
ReglerRechts();
}

if(daten[1]>600 && flagr==FALSE)
{
flagr = TRUE;
ReglerRechts();
}
}

return 0;
}


Ich habe mit Regelungstechnik noch nicht ganz soviel praktische Erfahrung. Ist ein Programm in der Art überhaupt prinzipiell möglich? Ein großes Problem ist für mich das Festlegen der Reglerparameter. Wie kann ich die Reglerparameter am besten bestimmen?

Für Berichtigungen, Hilfe und Verbesserungsvorschläge wäre ich sehr dankbar. Vielleicht haben von euch ja auch schon einige eine Geschwindigkeitsregelung für den ASURO programmiert. Vielleicht könntet ihr euren Quellcode dafür ja auch hier zur Verfügung stellen.

Danke schonmal im voraus!

Schöne Grüße, Oli

damaltor
01.03.2007, 16:01
bitte such mal im forum. klick oben auf suche, dann gibst du "regelung" ein und klickst in der liste links auf "| | | - Asuro". dann hast du schonmal 17 ergebnisse.

waste
01.03.2007, 19:01
Hallo Oli,

wie ich sehe, hast du bereits Anleihen aus meinem Programm und dem RN-Wissen genommen. Was mir als erstes auffällt, ist die zu kurze Abtastzeit. Die kann nicht mit der Wirklichkeit übereinstimmen, dürfte aber nicht dein Problem sein, da man es mit ki wieder ausmerzen kann. Hast du eine Möglichkeit, die Abtastzeit nachzumessen, Oszi oder so?

Eine empirische Bestimmung der Reglerparameter ist wegen der Odometrie sehr schwierig, weil sich mit der Geschwindigkeit die Totzeit im Regelkreis mit ändert. Je langsamer die Geschwindigkeit, umso seltener kommen Signale vom Odometriesensor. Dadurch ändert sich die Totzeit, was eine optimale Dimensionierung schwierig macht. Entweder man macht eine adaptive Regelung oder man dimensioniert es für die langsamste Geschwindigkeit, was allerdings nicht so optimal ist.

Dein Problem kann aber auch in der Hardware des Asuro liegen. Der Odometriesensor ist sehr empfindlich auf Umgebungslicht. Hast du schon ausgeschlossen, dass es daran liegt?

Gruß Waste

asuro_oli
01.03.2007, 21:33
hI Waste!

Erstmal danke für deine Antwort. Ja, habe mich an deinem Programm orientiert. Stimmt, die Abtastzeit ist wohl sehr unrealistisch. Ich habe erstmal einfach irgendwelche werte eingegeben und getestet, ohne mir bisher große gedanken dazu zu machen. Die Änderung der Totzeit mit der Geschwindigkeit des ASUROS leuchtet mir ein. Wie würde man überhaupt bei einer empirischen Ermittlung der Reglerparameter vorgehen? Und was meinst du genau mit einer adaptiven Regelung?

Ein Oszilloskop hab ich hier leider nicht zur Hand. Die Hardware meines ASUROs hab ich bis jetzt nur durch die Fixierung der Zahnräder modifiziert. Dadurch ist die Auswertung der Odometrie schon deutlich angenehmer geworden. Abdeckungen über den Sensoren habe ich nicht, ich betreibe den Asuro aber auch nur unter konstanten und relativ dunklen Lichtverhältnissen. Daran kann es also wahrscheinlich auch nicht liegen.

Wäre nett wenn du nochmal antworten würdest.

Grüße, Oli

waste
01.03.2007, 23:08
Die Abtastzeit kannst du auch ohne Oszi messen. Im Programm wird ja schon die Zeit der sw-Wechsel gemessen. Genauso kannst du auch die Zeit für einen Zyklus messen und auf das Hyperterminal ausgeben.

Die empirische Parametrierung ist nicht einfach, weil man die Geschwindigkeit durch Beobachtung schlecht beurteilen kann. Da bleibt nur die Möglichkeit den Asuro die Geschwindigkeit selbst messen zu lassen, speichern und dann auszulesen. So kann man sich dann die Sprungantwort ansehen und daraus Rückschlüsse ziehen. Natürlich muss dazu die Odometrie sauber funktionieren.

Eine adaptive Regelung ist die Anpassung der Reglerparameter an z.B. die Geschwindigkeit. Die Geschwindigkeit wird ja vorgegeben, also kann man auch darauf hin Parameter anpassen. Meistens braucht man nur einen Parameter mitändern und auch nur linear.

Beschreib mal, was mit deinem Programm noch nicht so gut läuft?

Gruß Waste

asuro_oli
02.03.2007, 17:41
Also, ich habe den I-Anteil der Regelung jetzt mal komplett herausgenommen und eine Proportionalverstärkung von 15 eingestellt. Das Ergebnis war eigentlich recht gut. Mein Asuro fuhr ziemlich geradeaus, allerdings noch mit einem kleinen rechtsdrift. Das war bei mittelhellem Umgebungslicht. Bei kompletter Dunkelheit fährt mein Asuro bei den gleichen einstellungen eine schwache linkskurve. Er macht also das gegenteil. Ich kann ihn jetzt also per lichtschalterdruck etwas steuern :) Nein, aber spaß beiseite. das bedeutet doch, dass die odometriesensoren bei mir zu stark durch das umgebungslicht beeinflusst werden oder? ich werde da mal eine abdeckung anbringen und sie dann nochmal genau durchmessen.

Waste, du meintest ja, ich sollte die geschwindigkeit mit dem asuro messen, speichern und dann auslesen. Aber wie kann ich werte während der fahrt messen und speichern und dann nach der fahrt ausgeben lassen?

Gruß, Oli

waste
02.03.2007, 18:42
Ich habe mal dein Programm in meinen Asuro geladen und ausprobiert. Also bei mir fährt der schön gleichmäßig und geradeaus. Da vermute ich schon noch die Probleme bei deiner Odometrie. Ich hatte ja bei meinem Asuro auch lange gekämpft, bis es einigermaßen lief.
Meine damaligen Erkenntnisse:
Das axiale Spiel darf nicht größer als 0.1 - 0.2mm sein.
Das Zahnrad darf nicht rattern, sonst gibt es Schwingungen, die die Auswertung stören. Abhilfe ist schmieren. Das Rattern hört man deutlich. Aus dem Grund habe ich auch eine Hysterese bei der Auswertung eingefügt.
Der Schwellwert ist vermutlich bei jedem Asuro unterschiedlich. Bei meinem ist er 600, bei anderen kann er 500 oder 700 sein.
Gegen die Umgebungslichtempfindlichkeit hilft eigentlich nur abdecken.

Ein Beispielprogramm zum "messen, speichern und auslesen" siehe Codefenster:

Waste

/************************************************** *****************************
*
* Description: Aufnahme der Beschleunigung
*
************************************************** ***************************/
#include "asuro.h"
#include <stdlib.h>
volatile unsigned char count36kHz;
volatile unsigned long timebase;

int main(void)
{
unsigned char i, wegr, flagr;
unsigned int data[2], zeit[99];

Init();
for (i = 0; i < 90; i++) zeit[i]=0;
MotorDir(BREAK,BREAK);
MotorSpeed(255,255);
OdometrieData(data);
OdometrieData(data);
if (data[1] < 600) flagr = FALSE; // Flag setzen
else flagr = TRUE;
MotorDir(FWD,FWD);
timebase=0;count36kHz=0;
wegr=0;
zeit[wegr]=(timebase*256)+count36kHz;
while(timebase<90){
OdometrieData(data); // messe Reflexscheibe
if ((data[1] < 550) && (flagr == TRUE)) {flagr = FALSE; wegr++; zeit[wegr]=(timebase*256)+count36kHz;}
if ((data[1] > 650) && (flagr == FALSE)) {flagr = TRUE; wegr++; zeit[wegr]=(timebase*256)+count36kHz;}
if (timebase==50) MotorSpeed(0,0);
}
StatusLED(RED);
MotorDir(BREAK,BREAK);
while (!PollSwitch());
for (i = 0; i < 90; i++)
{
PrintInt(i); PrintInt(zeit[i]); SerWrite("\n\r",2);
}
while(1);
return 0;
}

asuro_oli
03.03.2007, 10:58
Danke erstmal für dein Beispielprogramm für die Aufnahme der Beschleunigung! Dann werde ich mich jetzt erstmal mit der Abdeckung der Odometriesensoren befassen und den Schwellwert neu bestimmen, um dort mögliche Fehlerquellen auszuschließen.

Mich würde nochmal interessieren, mit welchen Reglerparametern du mein Programm getestet hast?

Gruß Oli

waste
03.03.2007, 14:34
Mich würde nochmal interessieren, mit welchen Reglerparametern du mein Programm getestet hast?
Ich habe dein obiges Programm compiliert und geladen, so wie es ist, also ohne Änderungen.

Waste