Code:
	Stand 14.Dezember 2006 00:16 Uhr
Version 1.3
--------------------------------------------
Asuroprojekt: Der Weg durch das Labyrinth
Asuroname: Odysseus I
Gruppe: S. Gessulat, M. SchŸmann, J. Uecker
--------------------------------------------
EinrŸckung nach Horstman
Unterfunktionen alphabetisch geordnet
--------------------------------------------
Aufgrund von Compilerproblemen werden an
vielen Stellen while-Schleifen statt
for-Schleifen verwendet
--------------------------------------------
Aufgrund eines Lštfehlers sind die Dreh-
richtungen der Motoren invertiert, fŸr
VorwŠrtsbetrieb ist MotorDir(RWD) zu setzen,
fŸr RŸckwŠrtsbetrieb MotorDir(FWD)
--------------------------------------------
Versionshistory:
1.0:
- Alle notwendigen Funktionen sind
  implementiert, sind getestet und 
  funktionieren
1.1:
- Linienverfolgung wurde verbessert (ist 
  jetzt sowohl schneller, als auch genauer 
  -> kleine Toleranz eingefŸhrt)
- Kommentare wurden Ÿberarbeitet
1.2:
- Ausgabefunktion wurde entschlankt und
  durch effizienteren Code verbessert
  (ca. 10 pages weniger)
- Kommentare Ÿberarbeitet und vereinheitlicht
- Komplettes Programm durchkommentiert
1.3:
- PrŠsentationsreif
---------------------------------------------
Funktionen im Überblick:
  Name ------------ Ÿbergebene Parameter -- Status ----	Zustand ------- Testzustand
+ Ausgabe			*feld					komplett	funktioniert	ist getestet
+ Blink				void					komplett	funktioniert	ist getestet
+ BodenTest			&motorl,&motorr			komplett	funktioniert	ist getestet
+ Dreh90			richtung(LEFT/RIGHT)	komplett	funktioniert	ist getestet
+ Fahren			richtung(FWD/RWD/BREAK)	komplett	funktioniert	ist getestet
+ Koltest			void					komplett	funktioniert	ist getestet
+ LichtTest			&schwarz,&weiss			komplett	funktioniert	ist getestet
+ LinieAusrichten	richtung(LEFT/RIGHT)	komplett	funktioniert	ist getestet
+ LinieFinden		void					komplett	funktioniert	ist getestet
+ LinieVerfolgen	distanz(int)			komplett	funktioniert	ist getestet
- LinieLaenge		-						verworfen	ungenau			verworfen
- LinieVerfolgen	distanz, Richtung		verworfen	nicht mšglich	technisch nicht Umsetzbar
- Notfall			-						-			-				verworfen Zeitmangel
- Steht				-						-			-				verworfen Zeitmangel
---------------------------------------------
To-Do List:
- Quellcode optimieren
- Quellcode sŠubern
- Kommentare Ÿberarbeiten
---------------------------------------------
*/
//--- Funktionsdeklarationen ----------------
void Ausgabe( void );
void Blink( void );
void BodenTest( int *motorl, int *motorr );
void Dreh90(unsigned char richtung);
void Fahren( unsigned char richtung);
void KolTest( void );
void LichtTest( int *schwarz, int *weiss );
void LinieAusrichten( unsigned char richtung );
int LinieFinden( void );
int LinieVerfolgen( int distanz);
//------------------------------------------
//--- Globale Variablen --------------------
int motorr = 110; 				// Variablen fŸr die Motorwerte - mšglichst kleine Werte 
int motorl = 110; 				// Werden nochmal angepasst durch Bodentest();
int schwarz = 100;				// Variablen fŸr die Lichtwerte
int weiss = 923;				// Werden nochmal angepasst durch Lichtmessen();
int lageplan[4][3];
//------------------------------------------
int main( void )
{	
//--- Initialisierung ----------------------
	
	Init();							// Initialisieren
	int x,y;						// vorher anlegen, sonst kommt es zu Compilerfehlern
	for( x=0; x<4; x++ )			// Array mit Nullen vollschreiben
		for( y=0; y<3; y++ )
			lageplan[x][y]= 0;
	lageplan[3][2]=1;
	BodenTest(&motorl, &motorr);	// Werte fŸr motorr und motorl anpassen
	LichtTest(&schwarz, &weiss);	// Werte fŸr schwarz und weiss anpassen
//------------------------------------------
/* 
Asuro zeigt durch Blinken an, dass die 
Messungen abgeschlossen sind und Wartet 
auf Startbefehl (Tasterdruck)
*/
//--- Beginn der Hauptroutine --------------
	int i=2;								// fŸr Operationen mit den Reihen (0 bis 2 = 3)
	int j;									// fŸr Operationen mit den Spalten 
	
	Msleep(500);							// Kurz warten vor dem Start
	Fahren(RWD);							// losfahren
	Msleep(2000);							// nur kurz bis ins Labyrinth
	
	Encoder_Init();							// Encoder resetten fŸr die Turnfunktion
	Encoder_Set(0,0);						// auf 0 setzen
	Turn(30,110);							// halblinks einschlagen um die Linie besser zu finden
	Fahren(RWD);							// Weiterfahren
	LinieFinden();							// Liniefinden
	
	// Reihenschleife
	
	while(i>=0)								// sind alle 3 Linien schon durchlaufen? Wenn nicht
	{	if((2!=i)&&(lageplan[i+1][0]))		// PrŸfen, dass er nicht am Ende ist UND ob er ganz links ist
		{	LinieAusrichten(RIGHT);			// Wenn ja, dann nach rechts ausrichten
			LinieVerfolgen(300);			// kurz fahren um gerade zu stehen
			Dreh90(LEFT);					// Wieder senkrecht zur Linie
			Fahren(FWD);					// ZurŸcksetzen
			LinieFinden();					// bis zur Linie
		}
		LinieAusrichten(LEFT);				// nach Links ausrichten
		LinieVerfolgen(1500);				// bis zum linken Ende der Linie fahren
		Dreh90(RIGHT);						// nach rechts drehen
		
		// Spaltenschleife
		
		j=0;								// in jeder Reihe auf nullsetzen j steht fŸr die Spalten
		while(j<3)							// Alle drei Spalten durchlaufen
		{	Msleep(500);					// kurz warten
			Fahren(RWD);					// Geradeausfahren
			if(LinieFinden())				// kucken ob eine Linie oder eine Wand kommt ( Linie = 1)
			{	lageplan[i][j]=1;			// Wenn Linie kommt, ist dort ein Durchgang, merken
				j=42;						// aus der Spalten-Schleife in die nŠchste Reihe
			}else							// keine Liniegefunden -> Wand
			{	Fahren(FWD);				// zurŸcksetzen
				Msleep(100);				// kurz warten
				LinieFinden();				// ZurŸckfahren bis zur Linie
				LinieAusrichten(RIGHT);		// Nach rechts ausrichten
				LinieVerfolgen(350);		// In die nŠchste Spalte fahren
				Dreh90(LEFT);				// zur Wand (oder Durchgang) hin ausrichten
				j++;						// Spaltencounter erhšhen, und die Schleife nochmal durchlaufen
			}
		}
		i--;								
	}
	Blink();
//------------------------------------------
/* 
Asuro zeigt durch Blinken an, dass er den
Schatz gefunden hat. Er wartet auf Taster-
druck und gibt dann den Weg aus.
*/
	Ausgabe();
	while(1){};		// Sicher ist sicher!
}
//--- Definition der Unterfunktionen ---------------------------------------------------------------------
//--- Ausgabe ------------------------------
// Ausgabe berechnet den kŸrzesten Weg aus 
// lageplan, und sendet die Daten an den 
// EmpfŠnger
void Ausgabe( void )
{
	KolTest();										// Wartet auf Tastendruck
	//--- Daten ausgeben -----------------------
	
	SerWrite("  ------------\r\n",16);				// Rahmen oben
	int i, j;										// vorher deklarieren
	for( i=0; i<3; i++)								// fŸr alle drei Reihen
	{	SerWrite(" | ",3);							// Rahmen rechts
		for( j=0; j<3; j++ )						// fŸr alle drei Spalten
		{	PrintInt(lageplan[i][j]);				// Daten ausgeben ( 0 = Wand, 1 = Durchgang)
			if (j != 2) SerWrite( " - ",3);			// Platzhalter setzen (nur 2)
		}
		SerWrite("  |\r\n",5);						// Rahmen rechts
	}
	SerWrite("  ------------\r\n",16);				// Rahmen unten
	SerWrite(" \r\n",3);							// Eine Leerzeile zur Übersicht
	
	//--- Grafische Ausgabe der Koordinaten ----
	//--------- 1. Zeile ------------------------
	j=0;											// Schleifenparameter rŸcksetzen
	while(j<3)				
	{	if(lageplan[0][j])							// Wenn Ziel an Stelle J
			SerWrite(" Ziel ",6);					// Ziel schreiben		
		else										// sonst
			SerWrite("      ",6);					// Leerzeichen
		j++;										// Schleifenparameter erhšhen			
	}
	SerWrite("\r\n",2);								// Sprung zur nŠchsten Zeile
	//--------- 2. bis 7. Zeile -----------------
	i=0;											// Šußeren Schleifenparameter rŸcksetzen
	while(i<3)
	{	j=0;										// inneren Schleifenparameter rŸcksetzen
	//--------- 2. / 4. / 6. Zeile---------------	
		while(j<3)											
		{	if(lageplan[i][j])						// Wenn Tor an dieser Stelle
			SerWrite("+  .  ",6);					// Tor zeichnen
		else										// Sonst
			SerWrite("+-----",6);					// Wand zeichnen
		j++;										// Inneren Schleifenparameter erhšhen
		}
		SerWrite("+\r\n",3);						// Letztes WandstŸck zeichnen und zur nŠchsten Zeile
	//--------- 3. / 5. / 7. Zeile---------------
		SerWrite("|",1);							// WandstŸck zeichnen 
		if((lageplan[i][1] & lageplan[i+1][0]) || (lageplan[i][0] & lageplan[i+1][1]))	
					SerWrite("  .......        ",17);// Weg von der Mitte nach links oder umgekehrt	
		else														
		if((lageplan[i][2] & lageplan[i+1][1]) || (lageplan[i][1] & lageplan[i+1][2]))
			SerWrite("        .......  ",17);		// Weg von der Mitte nach rechts oder umgekehrt
		else
		if((lageplan[i][0] & lageplan[i+1][2]) || (lageplan[i][2] & lageplan[i+1][0]))	
			SerWrite("  .............  ",17);		// Weg von links nach rechts oder umgekehrt
		else												
		{	j=0;									// inneren Schleifenparameter rŸcksetzen
			while(j<3)
			{	if(lageplan[i][j] & lageplan[i+1][j])// Wenn Zwei Tore Ÿbereinander an Stelle j
					SerWrite("  .  ",5);			// Spur zeichnen
				else								// Sonst
					SerWrite("     ",5);			// Leerzeichen
				if(j<2)								// Zweimal
					SerWrite(" ",1);				// FŸllzeichen
				j++;								// inneren Schleifenparameter erhšhen
			}
		}
		SerWrite("|\r\n",3);						// WandstŸck zeichnen und zur nŠchsten Zeile
	i++;											// Äußeren Schleifenparameter erhšhen
	}
	//--------- 8. + 9. Zeile -------------------	
	SerWrite("+-----+-----+  .  +\r\n",21);			// Erste Wand sieht immer gleich aus
	SerWrite("             Start\r\n",20);			// Start ist auch immer an der gleichen Stelle
}
//------------------------------------------
//--- Blink --------------------------------
// Blinkt um wichtige Stationen im Programm
// anzuzeigen
void Blink( void )
{	
	int i = 0;				// Schleifenparameter anlegen
	while(i<3)				// Es soll 3 mal geblinkt werden. 
	{	BackLED( ON, OFF );	// Die BackLEDs wechseln sich im 200-Milisekundentakt ab.
		Msleep(200);
		BackLED( OFF, ON );
		Msleep(200);
		i++;
	}
	BackLED( OFF, OFF );	// fertig geblinkt - BackLEDs aus.
}
//------------------------------------------
//--- BodenTest ----------------------------
// Ermittelt (anhand der Encoder) Motorwerte
// zum geradeausfahren
void BodenTest( int *motorl, int *motorr )	// Call by Reference Zugriff
{												
	int rechts=0;							// Variablen fŸr die Encoderwerte initialisieren
	int links=0;							// werden in der While-Schleife fŸr die if Abfragen benštigt
	int dif=0;								// als Differenz von links und rechts
	int da = 42;							// fŸr D. Adams - honoris causae 
	while( 42 == da )
	{	MotorDir(RWD,RWD);					// Motor auf vorwŠrts stellen
		StatusLED(RED);						// StatusLED rot
		if(rechts < links)					// PrŸft ob das rechte Rad weniger gefahren ist als das Linke
			*motorr+=1;						// Wenn ja: Motorwert fŸr rechts erhšhen
		else if(rechts > links)				// PrŸft ob das rechte Rad mehr gefahren ist als das Linke
			*motorl+=1;						// Wenn ja: Motorwert fŸr links erhšhen
		Encoder_Init();						// Encoder neu starten
		Encoder_Set(0,0);					// und resetten
		MotorSpeed(*motorl,*motorr);		// Motorwerte einsetzen und damit...
		Msleep(1000);						// 1 Sekunden fahren
		MotorSpeed(0,0);					// Stoppen
		rechts = encoder[RIGHT];			// Encoder rechts auslesen
		links = encoder[LEFT];				// Encoder links auslesen
		dif = rechts - links;				// Differenz wird berechnet
		if(0 == dif)						// Wenn beide RŠder gleichweit gefahren sind 
			da=0;							// -> aus der While springen
		Msleep(300);						// Kurz warten um durchdrehende RŠder zu verhindern
		StatusLED(GREEN);					// GrŸnes Licht fŸr den RŸckwertsgang
		MotorDir(FWD,FWD);					// Motor auf rŸckwŠrts stellen
		MotorSpeed(*motorl,*motorr);		// Die aktuellen Motorwerte benutzen
		Msleep(1075);						// die gleiche Strecke zurŸckzufahren (dauert etwas lŠnger)
		MotorSpeed(0,0);					// Stoppen
		Msleep(300);						// Kurz warten um Hochstarts zu verhindern
	}
	Blink();								// Signalisiert, dass er Fertig ist
	KolTest();								// Wartet auf nŠchsten Schritt
}
//------------------------------------------
//-- Dreh90 --------------------------------
// Dreht sich um 90 Grad in die Ÿbergebene
// Richtung
void Dreh90(unsigned char richtung)
{	
	Encoder_Init();			// Encoder resetten
	Encoder_Set(0,0);		// auf 0 setzen
	if( LEFT==richtung )	// richtung prŸfen
		Turn(79,100);		// nach links drehen
	else
		Turn(-79,100);		// nach rechts drehen
}
//------------------------------------------
//--- Fahren -------------------------------
// FŠhrt geradeaus in die Ÿbergebene
// Richtung. Benutzt dazu die ermittelten
// Motorwerte motorl und motorr
void Fahren( unsigned char richtung)// FŠhrt vorwŠrts/rŸckwerts - MotorstŠrke unabhŠngig skalierbar
{	
	MotorDir(richtung,richtung);		// Richtung einstellen
	MotorSpeed( motorl, motorr );		// Motorspeed einstellen
}
//------------------------------------------
//--- KolTest ------------------------------
// PrŸft alle 50 Milisekunden ob die
// Schalter gedrŸckt sind und springt dann
// wieder zurŸck in die †bergeordnete 
// Funktion
void KolTest( void )
{	
	switched=0;			// switched ist die Variable des RŸckgabewertes der Sensoren
	StartSwitch();		// Startet die Sensorenabfrage
	while(!switched)	// Wartet solange bis ein Tastendruck kommt.
	{	Msleep(50);		// Hier wird StartSwitch() bzw. den Sensoren etwas Zeit gegeben
	}
}
//------------------------------------------
//--- LichtTest ----------------------------
// Ermittelt Werte fŸr schwarz und weiss
// Damit diese an die aktuellen Licht-
// verhŠltnisse angepasst sind
void LichtTest( int *schwarz, int *weiss )		// Call by Refernce Zugriff
{												
	// Auf Schattenwurf des ASURO achten!
	unsigned int data[2];						// Array fŸr Lichtwerte anlegen
	FrontLED(ON);								// FrontLED fŸr den Messvorgang anstellen
	StatusLED(GREEN);							// Dem Benutzer anzeigen, dass der Asuro startbereit ist
	Msleep(300);
	KolTest();									// Auf Benutzer warten
	StatusLED(RED);
	int i=0;									// Vorher anlegen sonst kommt es zu Compilerfehlern
	while(i<5)									// Misst 5 mal die Werte fŸr Schwarz
	{	LineData(data);							// um besonders gute Messwerte zu erhalten
		Msleep(50);
		*schwarz = *schwarz+( (data[0]+data[1]) /2);
		i++;
	}
	*schwarz = (*schwarz/5);					
	StatusLED(GREEN);							// Dem Benutzer anzeigen, dass der Asuro startbereit ist
	Msleep(1000);
	KolTest();									// Auf Benutzer warten
	StatusLED(RED);
	i=0;										// Schleifenparameter rŸcksetzen
	while(i<5)									// Misst 5 mal die Werte fŸr Weiss 
	{	LineData(data);							// um besonders gute Messwerte zu erhalten
		Msleep(50);
		*weiss = *weiss+( (data[0]+data[1]) /2);
		i++;
	}
	*weiss = (*weiss/5);						
	StatusLED(GREEN);							// Test erfolgreich
	*schwarz=*schwarz+40;						// Toleranz von 40 (empirisch ermittelt)
	*weiss=*weiss-200;							// Toleranz von 200 (empirisch ermittelt)
	FrontLED(OFF);								// Licht aus -> Strom sparen
	Blink();									// Signalisiert, dass er fertig ist
	KolTest();									// Wartet auf nŠchsten Schritt
}
//------------------------------------------
//--- LinieAusrichten ----------------------
// Richtet sich in eine bestimmte Richtung
// auf der Linie aus, wenn er vorher
// Senkrecht zu ihr gestanden hat.
// Im Gegensatz zu Turn sucht er sich
// wircklich die Linie
void LinieAusrichten( unsigned char richtung )
{	
	MotorDir(RWD,RWD);				// Stellt Motorrichtung ein, sicher ist sicher
	MotorSpeed(motorl,motorr);		// FŠhrt ein StŸck nach vorne
	Msleep(150);					// FŸr 150ms
	if ( LEFT == richtung )			// Wenn er sich nach Links ausrichten soll
		MotorSpeed(0, motorr);		// Dreht er sich nach links
	else if ( RIGHT == richtung )	// Wenn er sich nach rechts ausrichten soll
		MotorSpeed(motorl,0);		// dreht er sich nach rechts
	Msleep(250);					// Warten damit LinieFinden nicht sofort losgeht
	LinieFinden();					// Dreht sich Solange bis er die Linie wiedergefunden hat
}
//------------------------------------------
//--- LinieFinden --------------------------
// BehŠlt solange den vorherigen Zustand
// bis er entweder eine Linie oder eine Wand
// findet und gibt einen dementsprechenden
// RŸckgabewert
// Linie = 1
// Wand = 0
int LinieFinden( void )
{	
	FrontLED(ON);									// Licht an, damit was gemessen werden kann
	StatusLED(RED);									// StatusLED rot
	unsigned int data[2];							// Array anlegen fŸr die Liniensensorwerte
	switched=0;										// switched, Variable des RŸckgabewertes der Sensoren 
	StartSwitch();									// Startet die Sensorenabfrage
	while(!switched)								// Wartet solange bis ein Tastendruck kommt.
	{	LineData(data);								// holt sich die Liniensensorwerte
		if( schwarz > data[0] || schwarz > data[1])	// Vergleicht beide Werte mit Schwarzwert
		{	MotorSpeed(0,0);						// Stopp
			StatusLED(GREEN);
			FrontLED(OFF);	
			return 1;								// und Sprung aus der Schleife 1 zurŸck
		}
	}
	MotorSpeed(0,0);								// Wand -> Stopp
	StatusLED(GREEN);								// StatusLED grŸn
	FrontLED(OFF);									// Licht aus -> Strom sparen
	return 0;										// ZurŸckgeben, dass er gegen eine Wand gefahren ist
}
//------------------------------------------
//--- LinieVerfolgen -----------------------
// Verfolgt eine Linie Ÿber eine angegebene
// Distanz, oder bricht ab, wenn die Linie
// endet oder, er sie verloren hat und gibt
// entsprechende Werte zurŸck
// Linie verloren = 0
// Linie nicht verloren = 1
// RŸckgabewerte werden im Hauptprogramm
// nicht mehr ausgewertet, diente zum Testen
int LinieVerfolgen( int distanz)
{	
	int count = 0;									// Einen Counter mit 0 initialisieren.
	unsigned int data[2];							// Array fŸr Liniensensorwerte anlegen
	FrontLED(ON);									// Licht vorne an, damit etwas gemessen werden kann
	
	MotorDir(RWD,RWD);								// Motor vorwŠrts stellen. Sicher ist Sicher
	
	Encoder_Init();									// Encoder wird neu gestartet
	Encoder_Set(0,0);								// und geresettet
	while(count < distanz)							// Abbruchbedingung Distanz zuende
	{	count++;									// Counter zŠhlt hoch
		LineData(data);								// Lichtwerte werden gemessen
		if(data[0] > weiss && data[1] > weiss)	    // Hier wird ŸberprŸft, ob Linie verloren
		{	MotorSpeed(0,0);						// Falls das der Fall ist, Stop
			return 1;								// und Fehlermeldung ans Hauptprogramm
		}
		
		if(data[0]>data[1]&&(data[0]-data[1])>10)	// Links ist es heller als rechts? Toleranz 10
		{	MotorSpeed(motorl,0);					// nach rechts steuern
			Msleep(5);								// ein wenig Zeit geben
		}else 
		if(data[0]<data[1]&&(data[1]-data[0])>10)	// rechts ist es heller als links? Toleranz 10
		{	MotorSpeed(0,motorr);					// nach links steuern				
			Msleep(5);								// ein wenig Zeit geben
		}else										// sonst fŠhrt er gerade auf der Linie
		{	MotorSpeed(motorl,motorr);				// Motorenwerte auf "gerade fahren"
			Msleep(5);
		}
	}
	MotorSpeed(0,0);								// Distanz ist erreicht. Stop
	StatusLED(GREEN);								// StatusLED GrŸn
	FrontLED(OFF);									// Licht aus -> Strom sparen
	return 0;				
}
 
Lesezeichen