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:
Übrigends ist die hier vorgestellte Anwendung bei weitem nicht so zeit- und rechenintensiv wie allgemein angenommen ;)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); }
Gruß
mic







Zitieren


Lesezeichen