Waste,
ich habe Deinen Code leicht modifiziert, da Dein Programm bei mir keiner Linie folgte.
Folgende Aenderungen habe ich vorgenommen:
1.) die Variablen drest, xsum und xalt in MAIN, da diese Variablen sonst nicht initialisiert werden
2.) Linedata mit LED off zur Initialisierung von doff in MAIN, da bei mir die LED beim Ein- und Ausschalten in FollowLine zu traege ist und scheinbar immer an bleibt.
3.) Implementierung mit Lib Ver. 2.70
Das war's. Nun folgt mein Asuro brav der Linie und der PID-Regler ist viel sensibler als der einfache P-Regelkreis!
Ich habe noch eine Frage:
Ich verstehe die Logik beim abbremsen nicht.
Links von der Linie (rechts bremsen)ist der Code:
Links dagegenspeedRight = speed - y; // rechts abbremsen
Kannst Du mir das mal erklaeren. Besten Dank im voraus.speedLeft = speed + y; // links abbremsen
Hier ist der neue Code:
Code:/******************************************************************************* * * Description: Asuro Linienverfolgung mit PID-Regler * Version 1: Korrektur auf beide Motoren verteilt * Author: Waste 26.8.05 * * Version 2: initialization of parameters in Main, measurement with LED off in Main * Author: irobot22587 11.03.2007 * *****************************************************************************/ #include "c:/WinAVR/avr/include/asuro.h" // ver 2.70 unsigned char speed; int speedLeft,speedRight; unsigned int lineData[2]; int x, xalt, don, doff, kp, kd, ki, yp, yd, yi, drest, y, y2, isum; void FollowLine (void) { unsigned char leftDir = FWD, rightDir = FWD; LineData(lineData); // Messung mit LED ON don = (lineData[0] - lineData[1]); x = don - doff; // Regelabweichung isum += x; if (isum > 16000) isum =16000; //Begrenzung um Überlauf zu vermeiden if (isum < -16000) isum =-16000; yi = isum/625 * ki; //I-Anteil berechnen yd = (x - xalt)*kd; // D-Anteil berechnen und mit yd += drest; // nicht berücksichtigtem Rest addieren if (yd > 255) drest = yd - 255; // merke Rest else if (yd < -255) drest = yd + 255; else drest = 0; if (isum > 15000) BackLED(OFF,ON); // nur zur Diagnostik else if (isum < -15000) BackLED(ON,OFF); else BackLED(OFF,OFF); yp = x*kp; // P-Anteil berechnen y = yp + yi + yd; // Gesamtkorrektur y2 = y/2; // Aufteilung auf beide Motoren xalt = x; // x merken speedLeft = speedRight = speed; MotorDir(FWD,FWD); if ( y > 0) { // nach rechts StatusLED(GREEN); speedLeft = speed + y2; // links beschleunigen if (speedLeft > 255) { speedLeft = 255; // falls Begrenzung y2 = speedLeft - speed; // dann Rest rechts berücksichtigen } y = y - y2; speedRight = speed - y; // rechts abbremsen if (speedRight < 0) { speedRight = 0; } } if ( y < 0) { // nach links StatusLED(RED); speedRight = speed - y2; // rechts beschleunigen !!!was speed - y2!! if (speedRight > 255) { speedRight = 255; // falls Begrenzung y2 = speed - speedRight; // dann Rest links berücksichtigen !!was speed - speedRight!! } y = y - y2; speedLeft = speed + y; // links abbremsen !! was speed + y!!! if (speedLeft < 0) { speedLeft = 0; } } leftDir = rightDir = FWD; if (speedLeft < 20) leftDir = BREAK; // richtig bremsen if (speedRight < 20) rightDir = BREAK; MotorDir(leftDir,rightDir); MotorSpeed(abs(speedLeft),abs(speedRight)); } int main(void) { unsigned char sw; Init(); MotorDir(FWD,FWD); StatusLED(GREEN); speed = 150; kp = 3; ki = 10; kd = 70; // Regler Parameter kd enthält bereits Division durch dt drest=0; isum=0; xalt=0; sw=0; /* sw = PollSwitch(); if (sw & 0x01) {ki=20;} if (sw & 0x02) {speed = 200;} if (sw & 0x04) speed = 100; if (sw & 0x08) kd = 35; if (sw & 0x10) kd = 70; if (sw & 0x20) kd = 140; */ FrontLED(OFF); Msleep(50); LineData(lineData); // Messung mit LED OFF doff = (lineData[0] - lineData[1]); // zur Kompensation des Umgebungslicht FrontLED(ON); Msleep(100); speedLeft = speed; speedRight = speed+25; while(1){ FollowLine(); } return 0; }







Zitieren

Lesezeichen