So, hier mal die vorerst finale Version des Linienfolgers (der jetzt meiner Meinung nach sehr schön funktioniert!). Das hier hat sich noch geändert:
- Die BackLEDs leuchten alle 100 Prozesszyklen kurz auf und zeigen so die Zyklengeschwindigkeit an. Der hat nämlich echt Probleme gemacht und das "Wackeln" auf Geraden verursacht. Nachdem der Code deutlich abgespeckt wurde (z.B. werden die Taster jetzt auch nur noch alle 100 Zyklen abgefragt) läuft der Asuro deutlich besser und stabiler seine Bahnen ab!
- Kubische Abhängigkeit und verschiedene Fuzzyregler ausprobiert. Hat alles nix gebracht, quadratisch scheint hier echt die beste Lösung (BISHER) zu sein. Beim kubischen kann man auch gleich einen "Schalter" einbauen und für eine *gescheite* Fuzzyregelung ist der Prozessor nicht ausreichend schnell - und damit kommts wieder zum Wackeln.
- Die Formel wurde über den Jordan geschickt und ersetzt. Die einzige Benutzerangabe ist jetzt noch der maximale Helligkeitsunterschied. Funzt viel besser und ist leichter verständlich. Der Rest wird intern erledigt.
Ich hab das Proggi auch mal auf einer nachgebauten Bahn von der letzten Roboliga laufen lassen und da hat er nach ein zwei Probeläufen (mit verschiedenen Tastern) mit Bravur bestanden.
Ziehts euch rein (oder auch nicht) und gebt mir eure Meinung. Ich denk mal, *jetzt* ist das Thema wirklich abgehandelt!
Code:
/* Quadratisch abhängiger Linienfolger vorerst finale Version
vmax = maximal negative und maximal positive Motorgeschwindigkeit;
imaxinit sollte etwa dem maximalen Helligkeitsunterschied der Liniendioden entsprechen
(z.B. Wert hell = 130, Wert dunkel = 30 -> imaxinit = 100)
Im Programmablauf kann dieser Wert (der das korrekte Folgen der Strecke am meisten
beeinflusst) noch über die Kollisionstaster angepasst werden:
Sw0 -> imaxinit -20 (mehr enge Kurven)
sw1 -> imaxinit -10
Sw2 -> imaxinit (Standard)
Sw3 -> imaxinit +10
Sw4 -> imaxinit +20
Sw5 -> imaxinit +40 (langgezogene Kurven, viele Geraden)
Die Schalter werden ausgelesen, wenn die BackLEDs aufleuchten!
Die StatusLED zeigt an, ob sich die Linie links oder rechts der Mittelstellung befindet.
Die BackLEDs leuchten alle 100 Zyklen kurz auf und zeigen so die Prozessorlast an.
pay.c 12.08.2005
*/
#include "asuro.h"
#include <stdlib.h>
#define vmax 120
#define imaxinit 100
long i;
char flag = 0, sw, sR, sL;
int lineData[2], imax = imaxinit, speedLeft, speedRight;
void Line (void)
{
speedRight = ((((-i*abs(i))/50)+100) * vmax)/100;
speedLeft = ((((i*abs(i))/50)+100) * vmax)/100;
if (speedLeft > vmax) speedLeft=vmax;
if (speedRight > vmax) speedRight=vmax;
if (speedRight < 0) {MotorDir (FWD,RWD); sR=-speedRight;sL=speedLeft;}
else if (speedLeft < 0) {MotorDir (RWD,FWD); sL=-speedLeft;sR=speedRight;}
else {MotorDir(FWD,FWD);sL=speedLeft;sR=speedRight;}
MotorSpeed(sL,sR);
}
int main(void)
{
Init();
FrontLED(ON);
for (i = 0; i < 0xFF; i++) LineData(lineData);
for(;;) {
if (flag>=99) {flag=0; BackLED(ON,ON);
sw = PollSwitch();
sw = (sw+PollSwitch())/2;
sw = (sw+PollSwitch())/2; //sicheres Auslesen der Schalter!!
if (sw > 0)
imax=imaxinit-20;
if (sw > 1)
imax=imaxinit-10;
if (sw > 2)
imax=imaxinit;
if (sw > 4)
imax=imaxinit+10;
if (sw > 8)
imax=imaxinit+20;
if (sw > 16)
imax=imaxinit+40;
}
else {flag++;BackLED(OFF,OFF);}
LineData(lineData);
i = ((lineData[0] - lineData[1])*100)/imax;
if (i>100) i=100;
if (i<-100) i=-100;
if (i > 0) StatusLED(GREEN);
else StatusLED(RED);
Line();
//if (lineData[0] < 40 && lineData[1] < 40) {Encoder_Init();Go(50,150);Turn(180);}
}
}
Lesezeichen