Hallo

Der RP6 ist einfach zu fett für den engen RN-Kurs:

Bild hier   Bild hier   Bild hier  
http://www.youtube.com/watch?v=h7bdUD3mJfg
http://www.youtube.com/watch?v=sm3WrykPj4M
http://www.youtube.com/watch?v=3r_m2rGgXLk


Aber als Test für mein Projekt reicht mir das erstmal. Andere Anwendungen wären z.B. Objekt-, Muster- und Hindernisserkennung, Barcodelesen, Abstandsmessung (mit Laserpointer) und möglicherweise auch Licht-/IR-Kommunikation. Vielleicht fällt mir noch was nettes ein, vorerst bleibe ich mal beim Liniensuchen. Hier noch der Code:

Code:
// RP6 folgt einer Linie die mit der Kamera erkannt wird           26.9.2008 mic

#include "RP6RobotBaseLib.h"

#define mitte 1550

// Achtung! Die PWM-Werte werden hier OHNE Rampe verändert!
void setMotorPWM(uint8_t power_links, uint8_t power_rechts)
{
extern uint8_t mleft_ptmp, mright_ptmp;

	if(power_links > 210) power_links = 210;
	if(power_rechts > 210) power_rechts = 210;
	mleft_power=mleft_ptmp=power_links;
	mright_power=mright_ptmp=power_rechts;

	OCR1BL = power_links;
	OCR1AL = power_rechts;

	if(power_links || power_rechts)
		TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
	else
		TCCR1A = 0;
}

uint8_t get_line(void)
{
	uint8_t i;
	cli();
		// auf Bildanfang warten
	do { i=0; while (ADCH > 30); while (ADCH < 50) i++; } while (i < 40);
	// die ersten 50 Zeilen überlesen
	i=50; while (i--) { while (ADCH > 30); while (ADCH < 50); }
	// warten auf hell-dunkel-Übergang
	i=0; while (ADCH > 100) i++;
	sei();
	return(i);
}

int main(void)
{
	uint8_t linie;
	uint16_t i, servo=mitte, dummy;

	initRobotBase();
	extIntOFF(); // schaltet den E_INT1-Port auf Eingang für den ADC
	//powerON();

// ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4 (E_INT1)
	ADMUX = (1<<REFS1) | (1<<REFS0)  | (1<<ADLAR) | 4;
// setze free running triggern
	SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// kein Interupt, Wandler einschalten, prescaller /2
	ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (0<<ADPS1)  | (1<<ADPS0);
// Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen
	ADCSRA |= (1<<ADATE) | (1<<ADIF);
// Initialisierung starten
	ADCSRA |= (1<<ADSC);
// und noch die wohl eher unnötige Initiallesung
	while (!(ADCSRA & (1<<ADIF)));
	ADCSRA |= (1<<ADIF);
	
	// SCL (Pin10) auf Ausgang und Low zur Servoansteuerung
	DDRC |= 1;
	PORTC &= ~1;
	setMotorDir(BWD,BWD);
	//setMotorPWM(100,100);

	while (1)
	{
		linie=get_line(); // linke Kante der Linie suchen

   	if((linie > 0) && (linie < 70)) // Linie im "Bild"?
   	{
			if(linie > 36 && servo <mitte+800) servo+=(linie-35)*2; // Servoposition
			if(linie < 34 && servo >mitte-1000) servo-=(35-linie)*2; // korrigieren

			i=servo; // Servo blockierend auf Position stellen
			cli();
			PORTC |= 1;
			while(i--) dummy ^= i;
			PORTC &= ~1;
			sei();
			i=15000;
			while(i--) dummy ^= i;
			
			if(servo < mitte) setMotorPWM(100, 100-(mitte-servo)/10);
			if(servo > mitte) setMotorPWM(100-(servo-mitte)/10, 100);

			if(servo < mitte-300)
			{
				setMotorDir(BWD,FWD);
				setMotorPWM(100, (mitte-servo)/10);
			}
			else if(servo > mitte+300)
			{
				setMotorDir(FWD,BWD);
				setMotorPWM((servo-mitte)/10, 100);
			}
			else setMotorDir(BWD,BWD);

		} // else setMotorPWM(0,0);
	}
	return(0);
}
Übrigends ist die hier vorgestellte Anwendung bei weitem nicht so zeit- und rechenintensiv wie allgemein angenommen ;)

Gruß

mic