Hallo mare_crisium,
oh kopfschüttel,
klar einen senkrechten Vektor kann man ja genau so ausrechnen. (Ist ganz einfach, wenn man einen gut erkläten Tritt in den Hintern bekommt.)
Mit den Einheiten bin ich einverstanden. Auch bei uns läßt sich der Küchentisch noch locker in cm ausdrücken, ohne den "unsigned char"-Bereich zu verlassen.
Mit den Rr und Rl bzw. N(rl) und n(rl) komme ich zu dieser Uhrzeit noch nicht klar. Im Moment sehe ich in (1) nur, dass du (PI * Rr / Nr) ausklammerst aus den beiden Geschwindigkeiten vr und vl. Weiters Grübeln ist da bei mir angesagt.
Zielpositions-Abweichung: Gut gebrüllt Löve. Ähh, gut erklärt. Ist mir nun auch klar geworden. Danke.
Zum Reglungskonzept im Asuro kann ich nur auf den Beitrag von waste hier hinweisen. Den von waste erstellten Code kann man sehr schön als allround-Code nutzen. Das Geheimnis bleibt natürlich in den PID-Parametern für die entsprechende Aufgabe.
Hier ist mal meine aktuelle Version vom Regelcode:
Code:
/*****************************************************************************
FUNKTION: MotorPID
Aufgabe: Funktion zur Reglung der Motoren.
Diese Funktion bzw. die eigendliche Berechnung fuer die
Reglung wurde im Forum unter www.roboternetz.de von waste
entwickelt.
Von Sternthaler ist die Moeglichkeit hinzugefuegt, die
Reglerberechnung fuer unterschiedliche Regelaufgaben zu
nutzen.
Die Parameter steuern, welche Sensoren zur Reglung benutzt
werden sollen. Zum einen koennen es die Liniensensoren sein
um eine Linienverfolgung zu realisieren, zum anderen kann
der Regler zur Ueberwachung der Raddecoder genutzt werden.
Parameter:
*****************************************************************************/
unsigned char MotorPID (
unsigned char regler,
char speed,
int links,
int rechts)
{
int LWert = 0, RWert = 0;
int absLinks = 0, absRechts = 0;
float faktor;
static int x, x1, x2, x3, x4;
static int xalt, drest, isum;
int kp = 0, kd = 0, ki = 0;
int yp, yd, yi, y, y2;
int LSpeed, RSpeed;
unsigned char LDir, RDir;
unsigned char use_regler = TRUE;
switch (regler)
{
case PID_LINIE:
links = rechts = 1; // erzwingt vorwaertsfahrt
LineData (); // Liniensensoren
LWert = sens.linie [LINKS_DUNKEL] - sens.linie [RECHTS_DUNKEL];
RWert = sens.linie [LINKS_HELL] - sens.linie [RECHTS_HELL];
/* DIESE PARAMETER WURDEN VON waste IM FORUM UNTER
https://www.roboternetz.de
ENTWICKELT.
*/
kp = 5; // Parameter kd enthält bereits Division durch dt
ki = 5;
kd = 70;
break;
case PID_ODOMETRIE:
if (links == 0 || rechts == 0)
use_regler = FALSE;
else
{
absLinks = abs (links);
absRechts = abs (rechts);
/* Odometrie-Zaehler so justieren, dass fuer eine Kurvenfahrt
die Tic-Anzahl auf beiden Seiten identisch aussehen.
Die Seite auf der weniger Tic's zu fahren sind wird auf die
hoehere Anzahl 'hochgerechnet'.
*/
if (absLinks < absRechts)
{
faktor = (float)absRechts / (float)absLinks;
LWert = sens.rad_tik [LINKS] * faktor;
RWert = sens.rad_tik [RECHTS];
}
else
{
faktor = (float)absLinks / (float)absRechts;
LWert = sens.rad_tik [LINKS];
RWert = sens.rad_tik [RECHTS] * faktor;
}
/* Diese Parameter wurden von Sternthaler durch probieren ermittelt.
*/
kp = 65;
ki = 6;
kd = 90;
}
break;
}
LSpeed = (int)(speed - hw.motor_diff / 2); //Wunschgeschwindigkeit vorgeben
RSpeed = (int)(speed + hw.motor_diff / 2); //Hardware beruecksichtigen
if (use_regler == TRUE)
{
/* AB HIER IST DIE BERECHNUNG VON waste IM FORUM UNTER
https://www.roboternetz.de
ENTWICKELT WORDEN.
*/
x1 = RWert - LWert; // Regelabweichung
x = (x1 + x2 + x3 + x4) / 4; // Filtert die 4 letzten Werte
x4 = x3; x3 = x2; x2 = x1; // Pipe ueber die letzten 4 Werte
isum += x; // I-Anteil berechnen
if (isum > 16000) isum = 16000; // Begrenzung: Überlauf vermeiden
if (isum < -16000) isum = -16000;
yi = isum / 625 * ki;
yd = (x - xalt) * kd; // D-Anteil berechnen und mit nicht
yd += drest; // berücksichtigtem Rest addieren
if (yd > 255) drest = yd - 255; // Eventuellen D-Rest merken
else if (yd < -255) drest = yd + 255;
else drest = 0;
yp = x * kp; // P-Anteil berechnen
y = yp + yi + yd; // Gesamtkorrektur
y2 = y / 2; // Aufteilung auf beide Motoren
xalt = x; // x merken
if (y > 0) // Abweichung nach rechts
{
LSpeed += y2; // links beschleunigen
if (LSpeed > 255) // wenn Wertebereich ueberschritten
{
y2 += (LSpeed - 255); // dann Rest rechts berücksichtigen
LSpeed = 255; // und Begrenzen
}
RSpeed -= y2; // rechts abbremsen
if (RSpeed < 0) // Auch hier Wertebereich
{
RSpeed = 0; // beruecksichtigen
}
}
if (y < 0) // Abweichung nach links
{
RSpeed -= y2; // rechts beschleunigen
if (RSpeed > 255) // wenn Wertebereich ueberschritten
{
y2 -= (RSpeed - 255); // dann Rest links berücksichtigen
RSpeed = 255; // und Begrenzen
}
LSpeed += y2; // links abbremsen
if (LSpeed < 0) // Auch hier Wertebereich
{
LSpeed = 0; // beruecksichtigen
}
}
}
/* Und wieder (fast) waste
*/
if (links >0) LDir = FWD; else if (links <0) LDir = RWD; else LDir = BREAK;
if (rechts>0) RDir = FWD; else if (rechts<0) RDir = RWD; else RDir = BREAK;
if (LSpeed < 20) LDir = BREAK; // richtig bremsen
if (RSpeed < 20) RDir = BREAK;
MotorDir ( LDir, RDir);
MotorSpeed (abs (LSpeed), abs (RSpeed));
return 0;
}
Ist so angepasst, dass sowohl der ehemalige von waste programmierte Zweck zur Linienverfolgung, als auch eine Reglung für ein Geradeausfahren, nun möglich sind. Klar, der Aufrufer muss ein abgestimmtes Timing haben, sonst stimmen die zeitabhängigen PID-Parameter nicht zur Regelungsaufgabe. Da waste im 2ms-Raster rechnete, sollte das Ding halt alle 2ms aufgerufen werden.
Aktuell geht es in dieser Version nicht, dass beide Regler gleichzeitig nutzbar sind, da innerhalb der Funktion die genuzten static-Variablen nur einmal vorhanden sind. Erzeugt man ein Array für die Variablen mit Variable/Parameter regler als Index, sollte das auch erledigt sein.
Ich sehe gerade, dass noch ein bisschen 'Beiwerk' fehlt.
- Variable hw.motor_diff kann mit 0 ersetzt werden.
- Variablen sens.linie[0-3] sind die automatisch im Interrupt ermittelten Messwerte der Liniensensoren für links/Rechts Hell-/Dunkelmessung
- Variablen sens.rad_tik[0-1] sind die, auch im Interrupt, ermittelten Hell-/Dunkelwechsel an den Odometriescheiben.
(Bei Bedarf poste ich den kompletten Code)
Mal sehen, wann wir google mit einem Asuro auf dem Mond überraschen 
Eine Gute Nacht wünscht Sternthaler
Lesezeichen