- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 4 von 4

Thema: Linienverfolgung für Asuro

  1. #1

    Linienverfolgung für Asuro

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo Ich habe ein mittelschweres Problem.
    Ich habe ein Linienverfolgungsprogramm für mein Asuro doch bekomme es nicht zum Anhalten. Ich habe es schon mit der Sleep Funktion und mit nem break versucht aber nix hilft.
    Der Asuro fährt immer weiter die Linie entlang ohne irgendwie anzuhalten.
    Könnt ihr mir Helfen?[/b]

  2. #2
    Moderator Robotik Einstein Avatar von damaltor
    Registriert seit
    28.09.2006
    Ort
    Milda
    Alter
    37
    Beiträge
    4.063
    dafür ist ein linienverfolgeprogramm da.
    -was genau ist das probem? wenn er anhalten soll, dann mach ihn aus.
    -wie sieht dein code aus? poste mit em [code]button und beschreibe, was passieren soll.
    -geh vor allem auf die funktionsweise des programms ein und sage, WAS an WELCHER STELLE passiert bzw nicht passiert, und WAS an WELCHER STELLE passieren sollte.
    Read... or die.
    ff.mud.de:7600
    Bild hier  

  3. #3
    Ich habe ja ein Linienprogramm.
    Mein Asuro soll die Linie entlang fahren und soll am Ende umkehren und die Linie wider zurück fahre.
    Mein Quell Code für die Linien Verfolgung:
    Code:
    #include "asuro.h"
    #include <stdlib.h>
    
    unsigned char speed;
    int speedLeft,speedRight;
    unsigned int lineData[2],zeit=0;
    int x, xalt, don, doff, kp, kd, ki, yp, yd, yi, drest, y, y2, isum;
    int x1, x2, x3, x4;
    
    void FollowLine (void)
    {
    unsigned char leftDir = FWD, rightDir = FWD;
    	FrontLED(OFF);
    	LineData(lineData);						// Messung mit LED OFF
    	doff = (lineData[0] - lineData[1]);	// zur Kompensation des Umgebungslicht
    	FrontLED(ON);
    	LineData(lineData);						// Messung mit LED ON
    	don = (lineData[0] - lineData[1]);	
    	x1 = don - doff;						// Regelabweichung
    	x = (x1+x2+x3+x4)/4;					//Filter
    	x4=x3; x3=x2; x2=x1;
    	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
    		if (speedRight > 255) {
    			speedRight = 255;				// falls Begrenzung
    			y2 = speed - speedRight;		// dann Rest links berücksichtigen
    		}
    		y = y - y2;
    		speedLeft = speed + y;				// links abbremsen
    		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 = 5; ki = 5; kd = 70;		// Regler Parameter kd enthält bereits Division durch dt
    	sw = PollSwitch();
    	if (sw & 0x01)
    		{ki=5;}
    	if (sw & 0x02)
    		{speed = 200;}
    	if (sw & 0x04)
    		speed = 255;
    	if (sw & 0x08)
    		kd = 35;
    	if (sw & 0x10)
    		kd = 70;
    	if (sw & 0x20)
    		kd = 140;
    	FrontLED(ON);
    	LineData(lineData);
    	speedLeft = speedRight = speed;
    	while(1){
    		FollowLine();
    		StatusLED(GREEN);	// zeigt durchlauf der Schleaife
    		FollowLine();
    		StatusLED(RED);
    zeit++;
    if(zeit>100) break;	//
     
    	}
    	MotorSpeed(0,0);
    	
        return 0;
    }
    Mit der Status LED wollte ich anzeigen lassen ob er die Schleife auch wirklich durchläuft.
    Macht er auch.
    Blos mit dem break Befehl das funktioniert nicht.
    Wie gesagt mit Sleep habe ich es auch schon probiert aber das ging auch nicht.
    Ich weis jetzt auch nicht mehr.

  4. #4
    Moderator Robotik Einstein Avatar von damaltor
    Registriert seit
    28.09.2006
    Ort
    Milda
    Alter
    37
    Beiträge
    4.063
    also was mir spontan auffällt, ist dass die main funktion nur ein einziges mal durchlaufen wird, wenigstens der teil mit den tastern. ist das absicht? warum? wofür sind die tasterabfragen da? eine einfache abfrage der PollSwitch.Funktion, ganz besonders kurz nach dem einschalten, ist sehr ungenau. meist werden falsche werte zurückgeliefert. verschiedene lösungen: mehrfahce abfragen, kurze pause davor (Sleep(216) ist etwa 3 ms), den kondensator bei den tastern (ich glaub c6) entfernen..

    vielleicht schaffst du es, eine funktion LinieVerloren() zu schreiben, die durch kurzes, vorsichtiges hin- und herdrehen prüft, ob noch eine linie vorhanden ist. wenn ja, dann wieder FollowLine(), wenn nein, dann so lange drehen bis die linie wieder vorhanden ist.
    in der while schleife würde dann sowas stehen:
    Code:
    StatusLED(GREEN);
    FollowLine();
    StatusLED(RED);
    LinieVerloren();
    dann weisst du, wenn die lampe grün ist, dann folgt er ihr ein stück, und wenn sie rot ist, prüft er ob sie nicht schon zu ende ist.
    die funktion LinieVerloren() müsste
    - den asuro eine FESTE zeit nach LINKS drehen, und dann wieder zurück, und prüfen ob in dieser zeit der RECHTE fototransistor einen sehr niedrigen wert geliefert hat (also über die linie gekommen ist).
    - dann den asuro die GLEICHE ZEIT nach RECHTS drehn und dann prüfen, ob auch der LINKE fototransistor die linie "gesehen" hat (doppelte abfrage, ich weiss, aber doppelt hält besser =)
    - wenn offensichtlich eine linie vorhanden ist, dann kann die funktion verlassen werden, in der while(1) schleife wird ja dann wieder FollowLine aufgerufen.
    - wenn keine linie mehr vorhanden ist, dann muss der asuro sich so lange drehen, BIS wieder eine linie vorhanden ist. dann wird die schleife beendet, und mit FollowLine wird zurückgefahren.

    wenn es dir nur darum geht, aus der while(1) schleife rauszukommen, dann mach doch einfach while(zeit<100) hin. sowie zeit>100 ist, wird die schleife dann beendet.
    ABER:
    vor dem return(0); muss dann nochmal while(1); hin (mit dem semikolon), damit das programm nie "beendet" wird. es kann sonst passieren, dass alte code-inhalte des speichers ausgeführt werden. der asuro sollte am ende, wenn er seine aufgabe erledigt hat, immer in einer while(1); schleife "eingefangen" werden.

    Die Sleep-Funktion lässt den asuro einfach einige millisekunden den aktuellen zustand beibehalten, wenn er fährt, dann fährt er weiter, wenn er steht, dann bleibt er stehen. sie hat nichts mit "schlafen" im sinne von "anhalten" zu tun. die zeit, die er während dieser funktion nichts (neues) macht kannst du so ausrechnen:
    Sleep(x);
    x=anzahl der 72000stel sekunden
    also z.B. Sleep(216) ist:
    216*(1/72000)=216/72000=3/1000 also 3 tausendstel sekunden(millisekunden)

    allerdings darf der wert in der funktion 255 nicht übersteigen. um also eine sekunde zu warten, würde folgendes gehn:
    for(i=0;i<500;i++)
    {Sleep(144)}
    er wartet dann 500*144*1/72000 sekunden, also 1000 millísekunden, also eine sekunde. (aber auch nur ungefähr... eine sekunde reine wartezeit, plus "rechenzeit").

    alternative:

    lade dir die neue asuro lib runter, mit der funktion Msleep() kannst einfach die anzahl der zu wartenden millisekunden angeben.
    Read... or die.
    ff.mud.de:7600
    Bild hier  

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test